Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(web): coordinate input for asset location #11291

Merged
merged 1 commit into from
Jul 23, 2024

Conversation

michelheusschen
Copy link
Contributor

Adds input fields for latitude and longitude to the change location modal. The coordinate inputs will update while picking a location on the map and vice versa. It will allow input of the 0 coordinate, even though the server doesn't support it.

coordinates-input

@jrasm91 jrasm91 merged commit 7d3db11 into main Jul 23, 2024
22 checks passed
@jrasm91 jrasm91 deleted the feat/web-coordinate-input-asset-location branch July 23, 2024 12:01
@waclaw66
Copy link
Contributor

Could be input fields background color consolidated within this dialog?

obrazek

@ajpanton
Copy link
Contributor

Having two separate fields for latitude and longitude makes it difficult to copy-paste between images, in case you want to assign multiple photos to the same location.

I have a few suggestions:

  • One combined field that takes a comma separated latitude,longitude coordinate.
  • A checkbox to change between two separate and one combined input field, and remember this setting for the next photo.
  • Two separate fields, but implement pasting such that if you paste a comma separated coordinate, it gets pasted separately into the fields. Also add a small copy button that copies the current coordinates as a comma separated latitude,longitude coordinate.
  • Two separate fields, but have both a copy and a paste button that copies and pastes both values at the same time. Could be implemented together with the previous suggestion.

@waclaw66
Copy link
Contributor

Having two separate fields for latitude and longitude makes it difficult to copy-paste between images, in case you want to assign multiple photos to the same location.

I have a few suggestions:

* One combined field that takes a comma separated latitude,longitude coordinate.

* A checkbox to change between two separate and one combined input field, and remember this setting for the next photo.

* Two separate fields, but implement pasting such that if you paste a comma separated coordinate, it gets pasted separately into the fields. Also add a small copy button that copies the current coordinates as a comma separated latitude,longitude coordinate.

* Two separate fields, but have both a copy and a paste button that copies and pastes both values at the same time. Could be implemented together with the previous suggestion.

Smart parsing from single field would be very helpful.
Common GPS notations:
40.6895917, -74.0444797
40.6895917N, 74.0444797W
40°41'22"N, 74°02'40"W
40°41.3755'N, 74°2.6688'W

Separator could be , or (space) if no other space occurs.

@Fmstrat
Copy link

Fmstrat commented Aug 9, 2024

This single-field method would also make it much easier to grab coordinates from common apps like Google Maps, OsmAnd, and gpx.studio.

@ITensEI
Copy link

ITensEI commented Aug 17, 2024

I made a script that I inject into the page using Code-Injector extension to allow GPS coordinates to be pasted into the Latitude input field in the format Lat,Long (40.6895917, -74.0444797). The script automatically splits the coordinates and inserts them into the corresponding Latitude and Longitude fields.

I often use Google Maps to get these coordinates—just right-click on the map, select the coordinates, and they'll be copied to your clipboard, ready to paste. Alternatively, you can also extract the coordinates directly from the URL string.

Make sure to add your Immich instance URL below

const logStyle = "background: yellow; color: black; font-weight: bold;";
let modalProcessed = false;

// Check if the current URL contains the required IP address
if (window.location.href.includes("YOUR-IMMICH-INSTANCE-URL")) {
    // Create a MutationObserver to observe changes in the DOM
    const observer = new MutationObserver((mutationsList) => {
        for (let mutation of mutationsList) {
            if (mutation.type === "childList") {
                // Check if the modal has been added by targeting aria-modal="true"
                const modalElement = document.querySelector('[aria-modal="true"]');
                const latitudeInput = document.querySelector('input[id^="latitude-input-id"]');

                if (modalElement && latitudeInput && !modalProcessed) {
                    console.log("%cGPS SPLIT%c Modal detected", logStyle, "");
                    // Add event listeners to the inputs when the modal is detected
                    addPasteEventListeners();
                    modalProcessed = true;
                }

                // Optionally, reset the flag when the modal is closed
                if (!modalElement) {
                    modalProcessed = false;
                }
            }
        }
    });

    // Start observing the document for changes
    observer.observe(document.body, { childList: true, subtree: true });
}

function addPasteEventListeners() {
    document.querySelectorAll('input[id^="latitude-input-id"]').forEach((input) => {
        // Check if the event listener has already been added
        if (!input.dataset.listenerAdded) {
            console.log("%cGPS SPLIT%c Adding event listener to:", logStyle, "", input);
            input.addEventListener("paste", handlePaste);
            // Mark this input as having the listener added
            input.dataset.listenerAdded = true;
        }
    });
}

// Function to handle the paste event
function handlePaste(event) {
    console.log("%cGPS SPLIT%c Paste event", logStyle, "", event);
    // Prevent the default paste behavior
    event.preventDefault();

    // Get the pasted data
    let pastedData = event.clipboardData.getData("text");

    // Check if the pasted data contains GPS coordinates
    if (pastedData.includes(",")) {
        // Split the coordinates at the comma and trim any whitespace
        let [latitude, longitude] = pastedData.split(",").map((coord) => coord.trim());

        // Set the value of the latitude input
        event.target.value = latitude;

        // Trigger input and change events on the latitude input
        event.target.dispatchEvent(new Event('input', { bubbles: true }));

        // Find the adjacent longitude input and set its value
        let longitudeInputId = event.target.id.replace("latitude-input-id", "longitude-input-id");
        let longitudeInput = document.getElementById(longitudeInputId);

        if (longitudeInput) {
            longitudeInput.value = longitude;
            // Trigger input and change events on the longitude input
            longitudeInput.dispatchEvent(new Event('input', { bubbles: true }));
        }
    } else {
        // If the pasted data does not contain a comma, insert it directly into the target input
        event.target.value = pastedData.trim();
        // Trigger input and change events on the input
        event.target.dispatchEvent(new Event('input', { bubbles: true }));
    }
}

@michelheusschen
Copy link
Contributor Author

@ITensEI thanks for the script. I've made some adjustments and opened a PR for it #11866

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants