Use activity title from GPX file when present

This commit is contained in:
Niklas Deutschmann 2026-04-12 12:58:21 +02:00
parent 6afd7a5dad
commit d4427ebd85
3 changed files with 46 additions and 14 deletions

View file

@ -378,10 +378,16 @@ public class ActivityFileService {
byte[] rawFile, byte[] rawFile,
ProcessingOptions options ProcessingOptions options
) throws JsonProcessingException { ) throws JsonProcessingException {
// Generate title if not provided String activityTitle;
String activityTitle = title != null && !title.isBlank() if (title != null && !title.isBlank()) {
? title activityTitle = title;
: ActivityFormatter.generateActivityTitle(parsedData.getStartTime(), parsedData.getActivityType()); } else if (parsedData.getTitle() != null) {
// Try to use title from input file
activityTitle = parsedData.getTitle();
} else {
// Generate title if not provided
activityTitle = ActivityFormatter.generateActivityTitle(parsedData.getStartTime(), parsedData.getActivityType());
}
// Default to PUBLIC if visibility not specified // Default to PUBLIC if visibility not specified
Activity.Visibility activityVisibility = visibility != null ? visibility : Activity.Visibility.PRIVATE; Activity.Visibility activityVisibility = visibility != null ? visibility : Activity.Visibility.PRIVATE;

View file

@ -80,8 +80,12 @@ public class GpxParser {
// Calculate duration // Calculate duration
parsedData.setTotalDuration(Duration.between(firstPoint.getTimestamp(), lastPoint.getTimestamp())); parsedData.setTotalDuration(Duration.between(firstPoint.getTimestamp(), lastPoint.getTimestamp()));
// Extract activity type from metadata // Extract activity type and title from metadata
extractActivityType(doc, parsedData); Optional<Element> track = getFirstTrack(doc);
if (track.isPresent()) {
extractActivityType(track.get(), parsedData);
extractActivityTitle(track.get(), parsedData);
}
// Determine timezone from first GPS coordinate // Determine timezone from first GPS coordinate
determineTimezone(parsedData); determineTimezone(parsedData);
@ -111,6 +115,8 @@ public class GpxParser {
} }
} }
/** /**
* Extracts track points from GPX document. * Extracts track points from GPX document.
*/ */
@ -245,21 +251,40 @@ public class GpxParser {
} }
} }
/** /*
* Extracts activity type from GPX metadata. * Returns the first <trk> element from the GPS XML
*/ */
private void extractActivityType(Document doc, ParsedActivityData parsedData) { private Optional<Element> getFirstTrack(Document doc) {
NodeList tracks = doc.getElementsByTagName("trk"); NodeList tracks = doc.getElementsByTagName("trk");
if (tracks.getLength() == 0) { if (tracks.getLength() == 0) {
tracks = doc.getElementsByTagNameNS("*", "trk"); tracks = doc.getElementsByTagNameNS("*", "trk");
} }
if (tracks.getLength() > 0) { return tracks.getLength() > 0 ? Optional.of((Element) tracks.item(0)) : Optional.empty();
Element track = (Element) tracks.item(0); }
String type = getElementText(track, "type");
if (type != null) { /**
parsedData.setActivityType(mapGpxTypeToActivityType(type)); * Extracts activity type from GPX metadata.
*/
private void extractActivityType(Element track, ParsedActivityData parsedData) {
String type = getElementText(track, "type");
if (type != null) {
parsedData.setActivityType(mapGpxTypeToActivityType(type));
}
}
/**
* Extracts activity title from GPX metadata.
*/
private void extractActivityTitle(Element track, ParsedActivityData parsedData) {
String title = getElementText(track, "name");
if (title != null) {
String shortenedTitle = title;
if (title.length() > 255) {
log.debug("Activity title was shortened to 255 characters: {}", title);
shortenedTitle = title.substring(0, 255);
} }
parsedData.setTitle(shortenedTitle);
} }
} }

View file

@ -30,6 +30,7 @@ public class ParsedActivityData {
private BigDecimal elevationGain; private BigDecimal elevationGain;
private BigDecimal elevationLoss; private BigDecimal elevationLoss;
private Activity.ActivityType activityType = Activity.ActivityType.OTHER; private Activity.ActivityType activityType = Activity.ActivityType.OTHER;
private String title;
private ActivityMetricsData metrics; private ActivityMetricsData metrics;
private String sourceFormat; // "FIT" or "GPX" private String sourceFormat; // "FIT" or "GPX"
private Boolean indoor = false; // Indicates if this is an indoor activity private Boolean indoor = false; // Indicates if this is an indoor activity