remove the timestamps and improve the script by showing youtube titles instead of links and show the thumbnails too


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>YouTube Notes App</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
            background-color: #f4f4f4;
        }
        h1, h2 {
            color: #333;
        }
        .form-section {
            background-color: #fff;
            padding: 20px;
            border-radius: 5px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            margin-bottom: 30px;
        }
        input[type="text"], textarea, input[type="time"] {
            width: 100%;
            padding: 10px;
            margin-top: 5px;
            margin-bottom: 15px;
            border: 1px solid #ccc;
            border-radius: 4px;
            box-sizing: border-box;
        }
        label {
            font-weight: bold;
        }
        button {
            background-color: #4CAF50;
            color: white;
            padding: 10px 20px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
        }
        button:hover {
            background-color: #45a049;
        }
        #videoList {
            list-style-type: none;
            padding: 0;
        }
        #videoList li {
            padding: 10px;
            background-color: #fff;
            margin-bottom: 5px;
            cursor: pointer;
            border: 1px solid #ddd;
            border-radius: 4px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        #videoList li:hover {
            background-color: #ececec;
        }
        #videoDisplay {
            display: flex;
            flex-wrap: wrap;
            gap: 20px;
        }
        #videoContainer, #notesContainer {
            flex: 1 1 45%;
            background-color: #fff;
            padding: 15px;
            border-radius: 5px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        }
        iframe {
            width: 100%;
            height: 300px;
            border: none;
            border-radius: 4px;
        }
        .notes-section {
            margin-top: 15px;
        }
        .note-item {
            background-color: #f9f9f9;
            padding: 10px;
            margin-bottom: 10px;
            border-left: 4px solid #4CAF50;
            border-radius: 3px;
            position: relative;
        }
        .note-timestamp {
            font-weight: bold;
            color: #555;
        }
        .note-content {
            margin-top: 5px;
        }
        .note-actions {
            position: absolute;
            top: 10px;
            right: 10px;
        }
        .note-actions button {
            background-color: transparent;
            border: none;
            color: #888;
            cursor: pointer;
            margin-left: 5px;
            font-size: 14px;
        }
        .note-actions button:hover {
            color: #333;
        }
        @media (max-width: 768px) {
            #videoContainer, #notesContainer {
                flex: 1 1 100%;
            }
        }
    </style>
</head>
<body>

    <h1>YouTube Notes App</h1>

    <!-- Section to Add Video URL -->
    <div class="form-section">
        <h2>Add YouTube Video</h2>
        <form id="addVideoForm">
            <label for="videoURL">YouTube Video URL:</label>
            <input type="text" id="videoURL" name="videoURL" placeholder="Enter YouTube URL" required>
            <button type="submit">Add Video</button>
        </form>
    </div>

    <!-- Section to Add Notes -->
    <div class="form-section" id="addNoteSection" style="display:none;">
        <h2>Add Notes</h2>
        <form id="addNoteForm">
            <label for="selectedVideo">Selected Video:</label>
            <input type="text" id="selectedVideo" name="selectedVideo" readonly>

            <label for="noteContent">Notes:</label>
            <textarea id="noteContent" name="noteContent" rows="4" placeholder="Enter your notes here..." required></textarea>

            <label for="noteTimestamp">Timestamp (optional, format hh:mm:ss):</label>
            <input type="text" id="noteTimestamp" name="noteTimestamp" placeholder="00:00:00" pattern="^([0-1]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$">

            <button type="submit">Add Note</button>
        </form>
    </div>

    <h2>Saved Videos</h2>
    <ul id="videoList">
        <!-- Video items will be populated here -->
    </ul>

    <div id="videoDisplay">
        <!-- Embedded video and notes will appear here -->
        <div id="videoContainer" style="display:none;">
            <h2>Video</h2>
            <div id="playerWrapper">
                <div id="videoPlayer"></div>
            </div>
        </div>
        <div id="notesContainer" style="display:none;">
            <h2>Notes</h2>
            <div class="notes-section" id="notesSection">
                <!-- Notes will be populated here -->
            </div>
        </div>
    </div>

    <script>
        // Function to extract YouTube Video ID from URL
        function getYouTubeID(url) {
            const regex = /(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/(?:watch\?(?:.*&)?v=|embed\/)|youtu\.be\/)([^\s&?]+)/;
            const match = url.match(regex);
            return match ? match[1] : null;
        }

        // Retrieve videos from localStorage or initialize empty array
        function getVideos() {
            const videos = localStorage.getItem('videos');
            return videos ? JSON.parse(videos) : [];
        }

        // Save videos array to localStorage
        function saveVideos(videos) {
            localStorage.setItem('videos', JSON.stringify(videos));
        }

        // Add a new video
        function addVideo(url) {
            const videoID = getYouTubeID(url);
            if (!videoID) {
                alert('Please enter a valid YouTube URL.');
                return;
            }
            const videos = getVideos();
            // Check for duplicates
            let video = videos.find(video => video.id === videoID);
            if (video) {
                alert('This video is already added.');
                return;
            }
            video = { id: videoID, url: url, notes: [] };
            videos.push(video);
            saveVideos(videos);
            renderVideoList();
            document.getElementById('addVideoForm').reset();
        }

        // Add a new note to a video
        function addNote(videoID, content, timestamp) {
            const videos = getVideos();
            const video = videos.find(v => v.id === videoID);
            if (!video) return;
            if (content.trim() !== "") {
                video.notes.push({ content: content.trim(), timestamp: timestamp });
                saveVideos(videos);
                renderVideoList();
                if (currentDisplayedVideo === videoID) {
                    displayVideo(videoID);
                }
                document.getElementById('addNoteForm').reset();
                alert('Note added successfully!');
            }
        }

        // Render the list of saved videos
        function renderVideoList() {
            const videos = getVideos();
            const videoList = document.getElementById('videoList');
            videoList.innerHTML = '';
            videos.forEach(video => {
                const li = document.createElement('li');
                li.innerHTML = `
                    <span>${sanitizeHTML(video.url)}</span>
                    <div>
                        <button data-id="${video.id}" class="viewButton">View</button>
                        <button data-id="${video.id}" class="deleteButton" title="Delete">🗑️</button>
                    </div>
                `;
                videoList.appendChild(li);
            });

            // Attach event listeners to the newly added buttons
            const viewButtons = document.querySelectorAll('.viewButton');
            viewButtons.forEach(button => {
                button.addEventListener('click', () => displayVideo(button.getAttribute('data-id')));
            });

            const deleteButtons = document.querySelectorAll('.deleteButton');
            deleteButtons.forEach(button => {
                button.addEventListener('click', (e) => {
                    e.stopPropagation();
                    deleteVideo(button.getAttribute('data-id'));
                });
            });
        }

        // Display the selected video and its notes
        let currentDisplayedVideo = null;
        let player;
        let playerReady = false;

        function displayVideo(id) {
            const videos = getVideos();
            const video = videos.find(v => v.id === id);
            if (!video) return;

            currentDisplayedVideo = id;

            const videoContainer = document.getElementById('videoContainer');
            const notesContainer = document.getElementById('notesContainer');
            const notesSection = document.getElementById('notesSection');

            // Load the video using the YouTube IFrame API
            if (playerReady) {
                player.loadVideoById(video.id);
            } else {
                // If player isn't ready yet, wait until it is
                window.addEventListener('playerReady', () => {
                    player.loadVideoById(video.id);
                }, { once: true });
            }

            // Populate notes
            notesSection.innerHTML = '';

            video.notes.forEach((note, index) => {
                const noteDiv = document.createElement('div');
                noteDiv.className = 'note-item';

                const timestampLink = note.timestamp ? `<span class="note-timestamp"><a href="#" data-id="${id}" data-time="${convertTimeToSeconds(note.timestamp)}">${note.timestamp}</a></span>` : `<span class="note-timestamp">N/A</span>`;
                noteDiv.innerHTML = `
                    <div class="note-content">${sanitizeHTML(note.content)}</div>
                    ${timestampLink}
                    <div class="note-actions">
                        <button onclick="window.editNote('${id}', ${index})">✏️</button>
                        <button onclick="window.deleteNote('${id}', ${index})">🗑️</button>
                    </div>
                `;
                // Clicking timestamp links to that time in video
                if (note.timestamp) {
                    noteDiv.querySelector('a').addEventListener('click', (e) => {
                        e.preventDefault();
                        seekVideo(convertTimeToSeconds(note.timestamp));
                    });
                }
                notesSection.appendChild(noteDiv);
            });

            videoContainer.style.display = 'block';
            notesContainer.style.display = 'block';

            // Show the Add Note section
            const addNoteSection = document.getElementById('addNoteSection');
            addNoteSection.style.display = 'block';
            document.getElementById('selectedVideo').value = video.url;

            // Scroll to video display
            videoContainer.scrollIntoView({ behavior: 'smooth' });
        }

        // Seek the video to specified time
        function seekVideo(timeInSeconds) {
            if (playerReady && player && typeof player.seekTo === 'function') {
                player.seekTo(timeInSeconds, true);
                player.playVideo();
            } else {
                alert('Player is not ready yet. Please try again shortly.');
            }
        }

        // Delete a video
        function deleteVideo(id) {
            if (!confirm("Are you sure you want to delete this video and all its notes?")) return;
            let videos = getVideos();
            videos = videos.filter(video => video.id !== id);
            saveVideos(videos);
            renderVideoList();
            // Clear video display if deleted video was displayed
            if (currentDisplayedVideo === id) {
                player.stopVideo();
                document.getElementById('videoContainer').style.display = 'none';
                document.getElementById('notesContainer').style.display = 'none';
                document.getElementById('addNoteSection').style.display = 'none';
                currentDisplayedVideo = null;
            }
        }

        // Edit a note
        function editNote(videoId, noteIndex) {
            const videos = getVideos();
            const video = videos.find(v => v.id === videoId);
            if (!video) return;
            const note = video.notes[noteIndex];
            const newContent = prompt("Edit your note:", note.content);
            if (newContent !== null) {
                let newTimestamp = note.timestamp;
                if (note.timestamp) {
                    newTimestamp = prompt("Edit timestamp (hh:mm:ss):", note.timestamp);
                } else {
                    newTimestamp = prompt("Add timestamp (hh:mm:ss) or leave blank:", "");
                }
                // Validate timestamp format if provided
                if (newTimestamp && !/^([0-1]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$/.test(newTimestamp.trim())) {
                    alert('Invalid timestamp format. Please use hh:mm:ss or mm:ss.');
                    return;
                }
                video.notes[noteIndex] = { content: newContent.trim(), timestamp: newTimestamp ? newTimestamp.trim() : "" };
                saveVideos(videos);
                renderVideoList();
                if (currentDisplayedVideo === videoId) {
                    displayVideo(videoId);
                }
            }
        }

        // Delete a note
        function deleteNote(videoId, noteIndex) {
            const videos = getVideos();
            const video = videos.find(v => v.id === videoId);
            if (!video) return;
            if (confirm("Are you sure you want to delete this note?")) {
                video.notes.splice(noteIndex, 1);
                saveVideos(videos);
                renderVideoList();
                if (currentDisplayedVideo === videoId) {
                    displayVideo(videoId);
                }
            }
        }

        // Simple sanitization to prevent XSS
        function sanitizeHTML(str) {
            const temp = document.createElement('div');
            temp.textContent = str;
            return temp.innerHTML;
        }

        // Handle Add Video form submission
        document.getElementById('addVideoForm').addEventListener('submit', function(e) {
            e.preventDefault();
            const url = document.getElementById('videoURL').value.trim();
            addVideo(url);
        });

        // Handle Add Note form submission
        document.getElementById('addNoteForm').addEventListener('submit', function(e) {
            e.preventDefault();
            if (!currentDisplayedVideo) {
                alert('Please select a video first.');
                return;
            }
            const content = document.getElementById('noteContent').value.trim();
            const timestampInput = document.getElementById('noteTimestamp').value.trim();
            let timestamp = "";
            if (timestampInput !== "") {
                // Validate timestamp format
                if (!/^([0-1]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$/.test(timestampInput)) {
                    alert('Invalid timestamp format. Please use hh:mm:ss or mm:ss.');
                    return;
                }
                timestamp = timestampInput;
            }
            addNote(currentDisplayedVideo, content, timestamp);
        });

        // Initial render
        renderVideoList();

        // YouTube IFrame API for controlling video playback
        function loadYouTubeAPI() {
            const tag = document.createElement('script');
            tag.src = "https://www.youtube.com/iframe_api";
            const firstScriptTag = document.getElementsByTagName('script')[0];
            firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
        }

        loadYouTubeAPI();

        function onYouTubeIframeAPIReady() {
            player = new YT.Player('videoPlayer', {
                height: '300',
                width: '100%',
                videoId: '', // Start with no video
                events: {
                    'onReady': onPlayerReady
                }
            });
        }

        function onPlayerReady(event) {
            playerReady = true;
            // Dispatch a custom event to notify that the player is ready
            window.dispatchEvent(new Event('playerReady'));
        }

        // Convert hh:mm:ss or mm:ss to seconds
        function convertTimeToSeconds(time) {
            const parts = time.split(':').map(part => parseInt(part, 10));
            let seconds = 0;
            if (parts.length === 3) {
                seconds = parts[0] * 3600 + parts[1] * 60 + parts[2];
            } else if (parts.length === 2) {
                seconds = parts[0] * 60 + parts[1];
            } else if (parts.length === 1) {
                seconds = parts[0];
            }
            return seconds;
        }

        // Attach functions to window to make them accessible from inline onclick handlers
        window.editNote = editNote;
        window.deleteNote = deleteNote;
        window.seekVideo = seekVideo;
    </script>

</body>
</html>