diff --git a/lib/Db/TimelineWrite.php b/lib/Db/TimelineWrite.php index 30ded7e8..9dff2b74 100644 --- a/lib/Db/TimelineWrite.php +++ b/lib/Db/TimelineWrite.php @@ -86,7 +86,7 @@ class TimelineWrite // Check if need to update $query = $this->connection->getQueryBuilder(); - $query->select('fileid', 'mtime', 'mapcluster', 'orphan') + $query->select('fileid', 'mtime', 'mapcluster', 'orphan', 'lat', 'lon') ->from('memories') ->where($query->expr()->eq('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT))) ; @@ -176,15 +176,15 @@ class TimelineWrite } // Store location data - $lat = null; - $lon = null; + $lat = \array_key_exists('GPSLatitude', $exif) ? (float) $exif['GPSLatitude'] : null; + $lon = \array_key_exists('GPSLongitude', $exif) ? (float) $exif['GPSLongitude'] : null; + $oldLat = $prevRow ? (float) $prevRow['lat'] : null; + $oldLon = $prevRow ? (float) $prevRow['lon'] : null; $mapCluster = $prevRow ? (int) $prevRow['mapcluster'] : -1; - if (\array_key_exists('GPSLatitude', $exif) && \array_key_exists('GPSLongitude', $exif)) { - $lat = (float) $exif['GPSLatitude']; - $lon = (float) $exif['GPSLongitude']; + if ($lat || $lon || $oldLat || $oldLon) { try { - $mapCluster = $this->mapGetCluster($mapCluster, $lat, $lon); + $mapCluster = $this->mapGetCluster($mapCluster, $lat, $lon, $oldLat, $oldLon); } catch (\Error $e) { $logger = \OC::$server->get(LoggerInterface::class); $logger->log(3, 'Error updating map cluster data: '.$e->getMessage(), ['app' => 'memories']); diff --git a/lib/Db/TimelineWriteMap.php b/lib/Db/TimelineWriteMap.php index 4233fd46..a64c1306 100644 --- a/lib/Db/TimelineWriteMap.php +++ b/lib/Db/TimelineWriteMap.php @@ -17,14 +17,23 @@ trait TimelineWriteMap * Get the cluster ID for a given point. * If the cluster ID changes, update the old cluster and the new cluster. * - * @param int $prevCluster The current cluster ID of the point - * @param float $lat The latitude of the point - * @param float $lon The longitude of the point + * @param int $prevCluster The current cluster ID of the point + * @param null|float $lat The latitude of the point + * @param null|float $lon The longitude of the point + * @param null|float $oldLat The old latitude of the point + * @param null|float $oldLon The old longitude of the point * * @return int The new cluster ID */ - protected function mapGetCluster(int $prevCluster, float $lat, float $lon): int + protected function mapGetCluster(int $prevCluster, $lat, $lon, $oldLat, $oldLon): int { + // Just remove from old cluster if the point is no longer valid + if (null === $lat || null === $lon) { + $this->mapRemoveFromCluster($prevCluster, $oldLat, $oldLon); + + return -1; + } + // Get all possible clusters within CLUSTER_DEG radius $query = $this->connection->getQueryBuilder(); $query->select('id', 'lat', 'lon') @@ -51,7 +60,7 @@ trait TimelineWriteMap // If no cluster found, create a new one if ($minId <= 0) { - $this->mapRemoveFromCluster($prevCluster, $lat, $lon); + $this->mapRemoveFromCluster($prevCluster, $oldLat, $oldLon); return $this->mapCreateCluster($lat, $lon); } @@ -63,7 +72,7 @@ trait TimelineWriteMap // If the file was previously in a different cluster, // remove it from the first cluster and add it to the second - $this->mapRemoveFromCluster($prevCluster, $lat, $lon); + $this->mapRemoveFromCluster($prevCluster, $oldLat, $oldLon); $this->mapAddToCluster($minId, $lat, $lon); return $minId; @@ -135,9 +144,9 @@ trait TimelineWriteMap * @param float $lat The latitude of the point * @param float $lon The longitude of the point */ - private function mapRemoveFromCluster(int $clusterId, float $lat, float $lon): void + private function mapRemoveFromCluster(int $clusterId, $lat, $lon): void { - if ($clusterId <= 0) { + if ($clusterId <= 0 || null === $lat || null === $lon) { return; } diff --git a/lib/Db/TimelineWritePlaces.php b/lib/Db/TimelineWritePlaces.php index 25c68358..cee252d5 100644 --- a/lib/Db/TimelineWritePlaces.php +++ b/lib/Db/TimelineWritePlaces.php @@ -13,12 +13,31 @@ trait TimelineWritePlaces /** * Add places data for a file. + * + * @param int $fileId The file ID + * @param null|float $lat The latitude of the file + * @param null|float $lon The longitude of the file */ - protected function updatePlacesData(int $fileId, float $lat, float $lon): void + protected function updatePlacesData(int $fileId, $lat, $lon): void { // Get GIS type $gisType = \OCA\Memories\Util::placesGISType(); + // Check if valid + if ($gisType <= 0) return; + + // Delete previous records + $query = $this->connection->getQueryBuilder(); + $query->delete('memories_places') + ->where($query->expr()->eq('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT))) + ; + $query->executeStatement(); + + // Just remove from if the point is no longer valid + if (null === $lat || null === $lon) { + return; + } + // Construct WHERE clause depending on GIS type $where = null; if (1 === $gisType) { @@ -47,13 +66,6 @@ trait TimelineWritePlaces $result = $this->connection->executeQuery($sql); $rows = $result->fetchAll(); - // Delete previous records - $query = $this->connection->getQueryBuilder(); - $query->delete('memories_places') - ->where($query->expr()->eq('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT))) - ; - $query->executeStatement(); - // Insert records foreach ($rows as $row) { $query = $this->connection->getQueryBuilder(); diff --git a/src/components/Metadata.vue b/src/components/Metadata.vue index 942b2bf8..ce707fab 100644 --- a/src/components/Metadata.vue +++ b/src/components/Metadata.vue @@ -158,7 +158,7 @@ export default defineComponent({ } list.push({ - title: this.address || this.t("memories", "Unknown coordinates"), + title: this.address || this.t("memories", "No coordinates"), subtitle: this.address ? [] : [this.t("memories", "Click edit to set location")], diff --git a/src/components/modal/EditLocation.vue b/src/components/modal/EditLocation.vue index b163b965..93890b96 100644 --- a/src/components/modal/EditLocation.vue +++ b/src/components/modal/EditLocation.vue @@ -2,6 +2,13 @@
{{ loc }} {{ dirty ? "*" : "" }} + +
+ +
+
+ +
- +
@@ -54,7 +61,9 @@ const NcTextField = () => import("@nextcloud/vue/dist/Components/NcTextField"); const NcListItem = () => import("@nextcloud/vue/dist/Components/NcListItem"); import NcLoadingIcon from "@nextcloud/vue/dist/Components/NcLoadingIcon"; -import Magnify from "vue-material-design-icons/Magnify.vue"; +import MagnifyIcon from "vue-material-design-icons/Magnify.vue"; +import CloseIcon from "vue-material-design-icons/Close.vue"; +import UndoIcon from "vue-material-design-icons/UndoVariant.vue"; type NLocation = { osm_id: number; @@ -70,7 +79,9 @@ export default defineComponent({ NcTextField, NcListItem, NcLoadingIcon, - Magnify, + MagnifyIcon, + CloseIcon, + UndoIcon, }, props: { @@ -95,36 +106,41 @@ export default defineComponent({ if (this.lat && this.lon) { return `${this.lat.toFixed(6)}, ${this.lon.toFixed(6)}`; } - return this.t("memories", "Unknown coordinates"); + return this.t("memories", "No coordinates"); }, }, mounted() { - const photos = this.photos as IPhoto[]; - - let lat = 0, - lon = 0, - count = 0; - for (const photo of photos) { - const exif = photo.imageInfo?.exif; - if (!exif) { - continue; - } - - if (exif.GPSLatitude && exif.GPSLongitude) { - lat += Number(exif.GPSLatitude); - lon += Number(exif.GPSLongitude); - count++; - } - } - - if (count > 0) { - this.lat = lat / count; - this.lon = lon / count; - } + this.reset(); }, methods: { + reset() { + this.dirty = false; + const photos = this.photos as IPhoto[]; + + let lat = 0, + lon = 0, + count = 0; + for (const photo of photos) { + const exif = photo.imageInfo?.exif; + if (!exif) { + continue; + } + + if (exif.GPSLatitude && exif.GPSLongitude) { + lat += Number(exif.GPSLatitude); + lon += Number(exif.GPSLongitude); + count++; + } + } + + if (count > 0) { + this.lat = lat / count; + this.lon = lon / count; + } + }, + search() { if (this.loading || this.searchBar.length === 0) { return; @@ -151,6 +167,12 @@ export default defineComponent({ }); }, + clear() { + this.dirty = true; + this.lat = 0; + this.lon = 0; + }, + select(option: NLocation) { this.dirty = true; this.lat = Number(option.lat); @@ -160,7 +182,7 @@ export default defineComponent({ }, result() { - if (!this.dirty || !this.lat || !this.lon) { + if (!this.dirty) { return null; } @@ -180,9 +202,18 @@ export default defineComponent({ .lat-lon { padding: 4px; + > span { user-select: all; } + + > .action { + float: right; + margin-left: 2px; + > * { + cursor: pointer; + } + } } .osm-attribution {