Get activity title from uploaded file, if it is present #7

Merged
kabupatix merged 4 commits from 8-use-activity-name-from-file into main 2026-04-13 10:12:38 +02:00
3 changed files with 46 additions and 14 deletions
Showing only changes of commit d4427ebd85 - Show all commits

View file

@ -378,10 +378,16 @@ public class ActivityFileService {
byte[] rawFile,
ProcessingOptions options
) throws JsonProcessingException {
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
String activityTitle = title != null && !title.isBlank()
? title
: ActivityFormatter.generateActivityTitle(parsedData.getStartTime(), parsedData.getActivityType());
activityTitle = ActivityFormatter.generateActivityTitle(parsedData.getStartTime(), parsedData.getActivityType());
}
// Default to PUBLIC if visibility not specified
Activity.Visibility activityVisibility = visibility != null ? visibility : Activity.Visibility.PRIVATE;

View file

@ -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<Element> 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,22 +251,41 @@ 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");
if (tracks.getLength() == 0) {
tracks = doc.getElementsByTagNameNS("*", "trk");
}
if (tracks.getLength() > 0) {
Element track = (Element) tracks.item(0);
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);
}
}
/**

View file

@ -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