From d4427ebd85ba4b2bf919631fda69a5bb5add590c Mon Sep 17 00:00:00 2001 From: Niklas Deutschmann Date: Sun, 12 Apr 2026 12:58:21 +0200 Subject: [PATCH] Use activity title from GPX file when present --- .../fitpub/service/ActivityFileService.java | 14 ++++-- .../net/javahippie/fitpub/util/GpxParser.java | 45 ++++++++++++++----- .../fitpub/util/ParsedActivityData.java | 1 + 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/main/java/net/javahippie/fitpub/service/ActivityFileService.java b/src/main/java/net/javahippie/fitpub/service/ActivityFileService.java index dcd60f7..060d0f6 100644 --- a/src/main/java/net/javahippie/fitpub/service/ActivityFileService.java +++ b/src/main/java/net/javahippie/fitpub/service/ActivityFileService.java @@ -378,10 +378,16 @@ public class ActivityFileService { byte[] rawFile, ProcessingOptions options ) throws JsonProcessingException { - // Generate title if not provided - String activityTitle = title != null && !title.isBlank() - ? title - : ActivityFormatter.generateActivityTitle(parsedData.getStartTime(), parsedData.getActivityType()); + String activityTitle; + if (title != null && !title.isBlank()) { + activityTitle = title; + } 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 Activity.Visibility activityVisibility = visibility != null ? visibility : Activity.Visibility.PRIVATE; diff --git a/src/main/java/net/javahippie/fitpub/util/GpxParser.java b/src/main/java/net/javahippie/fitpub/util/GpxParser.java index 0900af8..a06dc51 100644 --- a/src/main/java/net/javahippie/fitpub/util/GpxParser.java +++ b/src/main/java/net/javahippie/fitpub/util/GpxParser.java @@ -80,8 +80,12 @@ public class GpxParser { // Calculate duration parsedData.setTotalDuration(Duration.between(firstPoint.getTimestamp(), lastPoint.getTimestamp())); - // Extract activity type from metadata - extractActivityType(doc, parsedData); + // Extract activity type and title from metadata + Optional track = getFirstTrack(doc); + if (track.isPresent()) { + extractActivityType(track.get(), parsedData); + extractActivityTitle(track.get(), parsedData); + } // Determine timezone from first GPS coordinate determineTimezone(parsedData); @@ -111,6 +115,8 @@ public class GpxParser { } } + + /** * Extracts track points from GPX document. */ @@ -245,21 +251,40 @@ public class GpxParser { } } - /** - * Extracts activity type from GPX metadata. + /* + * Returns the first element from the GPS XML */ - private void extractActivityType(Document doc, ParsedActivityData parsedData) { + private Optional getFirstTrack(Document doc) { NodeList tracks = doc.getElementsByTagName("trk"); if (tracks.getLength() == 0) { tracks = doc.getElementsByTagNameNS("*", "trk"); } - if (tracks.getLength() > 0) { - Element track = (Element) tracks.item(0); - String type = getElementText(track, "type"); - if (type != null) { - parsedData.setActivityType(mapGpxTypeToActivityType(type)); + return tracks.getLength() > 0 ? Optional.of((Element) tracks.item(0)) : Optional.empty(); + } + + /** + * 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); } } diff --git a/src/main/java/net/javahippie/fitpub/util/ParsedActivityData.java b/src/main/java/net/javahippie/fitpub/util/ParsedActivityData.java index 12ff347..a64811a 100644 --- a/src/main/java/net/javahippie/fitpub/util/ParsedActivityData.java +++ b/src/main/java/net/javahippie/fitpub/util/ParsedActivityData.java @@ -30,6 +30,7 @@ public class ParsedActivityData { private BigDecimal elevationGain; private BigDecimal elevationLoss; private Activity.ActivityType activityType = Activity.ActivityType.OTHER; + private String title; private ActivityMetricsData metrics; private String sourceFormat; // "FIT" or "GPX" private Boolean indoor = false; // Indicates if this is an indoor activity