Repository navigation
FIX: POI: load the saved list once and skip duplicate entries - #3799
Autonomost wants to merge 6 commits into
Conversation
Every page that subscribes to POI.POIModified (FlightData and FlightPlanner) triggered a load of poi.txt from the event's add accessor, so each start doubled the in-memory list, and the next save wrote the doubled list back. After a few sessions the map shows stacks of identical markers; one affected poi.txt had 1280 lines for 16 distinct points. Load the file on the first subscription only. LoadFile now skips an entry whose position and name are already held, so loading a file twice or a file that already contains duplicates cannot pile markers up, and when duplicates were skipped the saved file is rewritten clean, which repairs existing installs on their next start. Malformed lines are ignored instead of throwing out of the loader. Verified on a real 1280-line poi.txt: the first start rewrote it to 16 lines and the markers are no longer stacked.
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Address import-file rewriting and POI loading/subscriber initialization issues.
Review effort: Lite
Findings: 1
Open (2)
What changed in this PR
Updates POI loading to prevent duplicate markers and clean malformed or repeated entries.
Changes:
- Loads the saved POI file once.
- Deduplicates entries and ignores malformed records.
- Rewrites cleaned POI data.
| File | Summary |
|---|---|
Utilities/POI.cs |
Updates POI loading, deduplication, and persistence behavior. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…ry page Follow-up to loading the saved list once: - The saved file was marked loaded before it was read, so a failed read (the file held open by a virus scanner, a sync client or another instance) was never retried, and the next add, edit or delete saved the list without its POIs over the file. It is now marked loaded only after a successful read or when there is no file, a failed read is retried on the next subscription, and the list is not written to the file until the file has been read. - The file is opened read only and shared. File.Open(path, FileMode.Open) asks for read/write access with no sharing, which fails whenever another program has the file open. - The duplicate repair ran inside LoadFile, so importing a file with Load file saved the merged list to poi.txt whenever the import contained a duplicate. The repair now only runs for the saved file. - Duplicates are matched on the position as the file stores it (15 significant digits), so a point placed on the map matches the same point read back from a saved file. - Pages draw POIs only when POIModified fires, and with the file loaded once only the first page to subscribe was redrawn; the Plan page showed no POIs until one changed. A page subscribing later now draws the list.
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
Review effort: Lite
Findings: 1
Open (4)
pnt.Tagis treated as a string here. IfPointLatLngAlt.Tagis typed asobject(common in map… · New This catch swallows all exceptions and returnsfalsewith no diagnostic signal. Since a failed… · Newitemsis an array, soitems.Lengthshould be used instead ofitems.Count().Count()adds… · New The comment says this matches the position \"as SaveFile writes it\" (15 significant digits), but… · New
Resolved since last review (2)
…d the duplicate key Review follow-ups: - A saved file that cannot be read at startup is now logged (with the exception) instead of failing silently, and so is a page handler or the duplicate repair throwing during the first load. The retry on the next subscription is unchanged. - SaveFile and the duplicate key both call CoordText for the latitude and longitude, so the key is exactly the text the file holds on whichever runtime formats the doubles, and the two cannot drift apart. The comment no longer claims a fixed 15 digits; that is only what .NET Framework's default format gives. - items.Length instead of items.Count() on the split line.
|
@meee1 feel free to give it another review. |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
An unresolved critical issue may mark inaccessible files as loaded and overwrite them.
Review effort: Lite
Findings: 1
Open (1)
Resolved since last review (4)
pnt.Tagis treated as a string here. IfPointLatLngAlt.Tagis typed asobject(common in map… The comment says this matches the position \"as SaveFile writes it\" (15 significant digits), but…itemsis an array, soitems.Lengthshould be used instead ofitems.Count().Count()adds… This catch swallows all exceptions and returnsfalsewith no diagnostic signal. Since a failed…
File.Exists returns false both for a missing file and for one the process cannot read, so an inaccessible poi.txt was marked loaded and the next add, edit or delete would have written the list over it. LoadSaved now opens the file and treats only FileNotFoundException and DirectoryNotFoundException as "no saved file"; any other failure is logged and retried on the next subscription, with the file left unwritten until then, as for a locked file.
Picks up a489d27, which fixes the Mavlink.cs syntax errors that have failed every CI run of this PR since 2026-09-30, and the commits since. No conflicts; the PR's own changes are untouched.
|
Merged upstream master (694628a) into the branch as 4580a2e. It brings a489d27, which fixes the Mavlink.cs syntax errors behind every red CI run here since 2026-09-30 (the last run on a2c8df1 had 890 of them, all in Mavlink.cs, none in POI.cs), plus the commits since. No conflicts; the PR's own change is untouched, and the branch builds on Windows (MissionPlanner.csproj, Release). |
|
@meee1 this should be good to go. |


Every page that subscribes to POI.POIModified (FlightData and FlightPlanner) triggered a load of poi.txt from the event's add accessor, so each start doubled the in-memory list, and the next save wrote the doubled list back. After a few sessions the map shows stacks of identical markers; one affected poi.txt had 1280 lines for 16 distinct points.
The saved file is now read on the first subscription only, and a page that subscribes later draws the list already held. LoadFile skips an entry whose position and name are already held, so loading a file twice, or a file that already contains duplicates, cannot pile markers up. When the saved file held duplicates it is rewritten clean at startup, which repairs existing installs on their next start. Malformed lines are ignored instead of throwing out of the loader.
The second commit addresses review:
File.Open(path, FileMode.Open)asks for read/write access with no sharing, which fails whenever another program has the file open.The third commit logs a failed startup read and the two failure paths after it, uses
items.Length, and givesSaveFileand the duplicate key one sharedCoordTexthelper so the key is always exactly the text the file holds.The fourth commit (after the merge of master) stops relying on
File.Existsto decide that there is no saved file:File.Existsis also false for a file the process cannot read, which would have marked an inaccessible poi.txt as loaded and let the next edit write over it. Only "not found" now counts as no file; any other read failure is logged and retried on the next subscription, with the file left unwritten until then.The first commit was verified on a real 1280-line poi.txt: the first start rewrote it to 16 lines and the markers are no longer stacked. The review changes are covered by unit tests in our fork (locked file read again on the next subscription, failed read not overwritten, file open in another program, unreadable file not overwritten, import leaves both files alone, re-import after placing a point, later page drawn). They need InternalsVisibleTo on the main assembly, so they are not included here.