OXIESEC PANEL
- Current Dir:
/
/
var
/
www
/
cream
/
new_cream
Server IP: 139.59.38.164
Upload:
Create Dir:
Name
Size
Modified
Perms
📁
..
-
06/17/2025 10:17:24 AM
rwxrwxr-x
📄
A_index.php
65.56 KB
05/19/2025 10:07:21 AM
rw-r--r--
📁
arvind-assets
-
05/12/2025 10:35:45 AM
rwxr-xr-x
📄
new_social.php
73.82 KB
05/19/2025 10:07:21 AM
rw-r--r--
Editing: new_social.php
Close
<?php require_once './assets/php/db_connect.php'; require_once './assets/php/config.php'; require_once './assets/php/db_config.php'; require_once './assets/php/validate.logged.php'; require_once './assets/php/function.php'; // Handle the AJAX request for data if (isset($_GET['page'])) { $page = (int)$_GET['page']; // Get page number $size = (int)$_GET['size']; // Get number of items per page $offset = ($page - 1) * $size; // Query to get the latest records, ordered by postedOn or ID in descending order // $sql = "SELECT * FROM reader_stream WHERE deleteFlag = 0 AND referenceId IS NULL ORDER BY postedOn DESC LIMIT $size OFFSET $offset"; $sql = " SELECT rs.* FROM reader.reader_stream rs WHERE (rs.visibility = 'public' OR rs.userId IN ( SELECT following_id FROM reader_stream_follow WHERE follower_id = $gUserId UNION SELECT $gUserId ) ) AND rs.deleteFlag = 0 AND rs.referenceId IS NULL AND rs.id NOT IN (SELECT streamId FROM report_stream WHERE userId = $gUserId) AND rs.userId NOT IN (SELECT blockedUserId FROM cream.block_acc WHERE userId = $gUserId) AND rs.userId NOT IN (SELECT userId FROM cream.block_acc WHERE blockedUserId = $gUserId) ORDER BY rs.postedOn DESC LIMIT $size OFFSET $offset"; $result = $readerdb->query($sql); // Initialize the data container $htmlOutput = ''; if ($result->num_rows > 0) { while ($row = $result->fetch_assoc()) { $htmlOutput .= captureStream($row['id'], $row['userId'], $row['chat'], $row['postedOn'], $row['editedOn'], $row['mediaPath'], $row['metadata']); } } // Check if the current batch is the last one (i.e., less than the requested size) $last = (count(explode('</div>', $htmlOutput)) - 1 < $size) ? true : false; // Return the HTML and the last page status as JSON response echo json_encode(['html' => $htmlOutput, 'last' => $last]); // Close connection $readerdb->close(); exit; } function get_ip_loc() { $ip = getenv('HTTP_CLIENT_IP') ?: getenv('HTTP_X_FORWARDED_FOR') ?: getenv('HTTP_X_FORWARDED') ?: getenv('HTTP_FORWARDED_FOR') ?: getenv('HTTP_FORWARDED') ?: getenv('REMOTE_ADDR'); $response = unserialize(file_get_contents('http://www.geoplugin.net/php.gp?ip=' . $ip)); if ($response === false) { $visitCity = ''; $visitCountry = ''; } else { $visitCity = $response['geoplugin_city']; $visitCountry = $response['geoplugin_countryName']; } return array( "ip" => $ip, "city" => $visitCity, "country" => $visitCountry ); } if (isset($_POST['streamId'])) { $iploc = get_ip_loc(); // SQL query using INSERT WHERE NOT EXISTS to prevent duplicate insertion $sql = "INSERT INTO stream_analytics (streamId, userId, ip, city, country) SELECT ?, ?, ?, ?, ? FROM DUAL WHERE NOT EXISTS ( SELECT 1 FROM stream_analytics WHERE streamId = ? AND userId = ? )"; // Prepare the statement $stmt = $readerdb->prepare($sql); // Bind the parameters $stmt->bind_param("iisssii", $_POST['streamId'], $gUserId, $iploc['ip'], $iploc['city'], $iploc['country'], $_POST['streamId'], $gUserId); // Execute the query $result = $stmt->execute(); if ($result) { // Check if the insertion was successful if ($stmt->affected_rows > 0) { echo json_encode(['status' => "success", "message" => "Data inserted successfully"]); } else { echo json_encode(['status' => "success", "message" => "Combination of streamId and userId already exists."]); } } else { echo json_encode(['status' => "error", "message" => $stmt->error]); } exit; } function check_cream_subscription($userId) { global $creamdb; $sql = "SELECT plan, plan_type FROM cream_subscription WHERE userId = ? AND NOW() BETWEEN start_date AND end_date"; if ($stmt = $creamdb->prepare($sql)) { $stmt->bind_param("i", $userId); if ($stmt->execute()) { $result = $stmt->get_result(); if ($result->num_rows > 0) { $row = $result->fetch_assoc(); if ($row['plan'] = ! 'Pro') { echo "<script type='text/javascript'> alert('Your plan has ended, Please login!') window.location.href = 'logout.php'; </script>"; } } else { echo "<script type='text/javascript'> alert('Your plan has ended, Please login!') window.location.href = 'logout.php'; </script>"; } } } } // Function to check if the user exists in the session_log and add session if it doesn't exist function checkAndAddUserSession($userId, $creamdb) { $sessionId = session_id(); // SQL query to check if the user has an active session in the session_log table $session_sql = "SELECT COUNT(*) AS session_count FROM session_log WHERE userId = ? AND sessionId = ? AND endTime IS NULL AND startTime >= CURDATE() - INTERVAL 30 DAY"; try { // Prepare the query $stmt = $creamdb->prepare($session_sql); $stmt->bind_param('is', $userId, $sessionId); // Bind the userId parameter to the query $stmt->execute(); // Get the result $result = $stmt->get_result(); $row = $result->fetch_assoc(); // If session_count is 0, the user does not have an active session if ($row['session_count'] == 0) { // Insert a new session entry if the session does not exist createNewSession($userId, $creamdb); } } catch (mysqli_sql_exception $e) { echo "Error checking session: " . $e->getMessage(); } } // Function to create a new session log for the user function createNewSession($userId, $creamdb) { // Get the current session ID $sessionId = session_id(); // Assuming the session ID is already started (session_start() is called earlier) // Insert the new session into the session_log table $insert_sql = "INSERT INTO session_log (userId, sessionId, startTime) VALUES (?, ?, NOW())"; try { // Prepare the query $stmt = $creamdb->prepare($insert_sql); $stmt->bind_param('is', $userId, $sessionId); // Bind userId and sessionId $stmt->execute(); } catch (mysqli_sql_exception $e) { echo "Error inserting new session: " . $e->getMessage(); } } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Knobly Social</title> <link rel="stylesheet" href="assets/css/social.css"> <link rel="sheet" href="style.css"> <script src="assets/js/new_social_script.js"></script> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <!-- Make sure you have this or similar in your <head> --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"> <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.10.0/font/bootstrap-icons.min.css" rel="stylesheet"> <script> const userId = <?= $gUserId ?>; let tempUrl = ''; let letUrl = true; let dotInterval; var myModal; let page = 1; // Start with the first page const pageSize = 20; // Number of items per page let isLoading = false; // Flag to prevent multiple AJAX calls at once let isLastPage = false; // Flag to check if the last page is reached function shareNow(postId) { // console.log(postId); var link = "https://knoblycream.com/streamPush.php?id=" + postId; copyToClipboard(link); } function copyToClipboard(note) { // Text to copy var textToCopy = note; // Try using the Clipboard API first if (navigator.clipboard) { navigator.clipboard.writeText(textToCopy).then(function() { showToast('Link copied to clipboard'); }).catch(function(error) { console.error('Clipboard API error: ', error); fallbackCopy(textToCopy); }); } else { console.error('Clipboard API is not available'); fallbackCopy(textToCopy); } // Fallback method using a temporary textarea element function fallbackCopy(textToCopy) { var $tempTextArea = $('<textarea>'); $tempTextArea.val(textToCopy).appendTo('body'); $tempTextArea.focus().select(); $tempTextArea[0].setSelectionRange(0, textToCopy.length); try { var successful = document.execCommand('copy'); if (successful) { showToast('Link copied to clipboard'); } else { showToast('Failed to copy link'); } } catch (err) { console.error('Error copying text: ', err); showToast('Failed to copy link'); } finally { $tempTextArea.remove(); } } } function showToast(message) { // Remove any existing toast $('.toast-notification').remove(); // Create a new toast element var toast = $('<div class="toast-notification">' + message + '</div>'); // Append to body $('body').append(toast); // Show the toast with animation setTimeout(function() { toast.addClass('show'); // Hide and remove the toast after 2 seconds setTimeout(function() { toast.removeClass('show'); setTimeout(function() { toast.remove(); }, 300); }, 2000); }, 10); } $(document).on('click', '.shareNow', function() { shareNow($(this).data('id')); }); function removeMeta() { $('#linkPreview').hide(); $('#hiddenTitle').val(''); $('#hiddenDesc').val(''); $('#hiddenUrl').val(''); $('#hiddenDomain').val(''); $('#hiddenImage').val(''); } function removeYT() { $('ytPreview').html(''); $('#ytPreview').hide(); } function openModal(type, path, count) { let str = path; let mediaPaths = str.split(","); event.stopPropagation(); // Prevent event propagation if (type === 'image') { // Convert the array of image paths to a string and encode it const imagePaths = encodeURIComponent(mediaPaths.join(",")); const selectedImage = mediaPaths[count]; // Redirect to a new page with all images and the selected image index window.location.href = 'new-page-copy.php?imagePaths=' + imagePaths + '&selectedImage=' + encodeURIComponent(selectedImage); } if (type === 'video') { const videoSrc = mediaPaths[count]; // Redirect to a new page with the selected video window.location.href = 'new-page-copy.php?videoPath=' + encodeURIComponent(videoSrc); } } function generateVideoThumbnail($ele) { try { // Fetch the video URL from the source element inside the .post div var videoUrl = $ele.find('video source').attr('src'); if (!videoUrl) { return false; // If no video URL, return false early } var $video = $('<video>').attr('controls', true).css({ maxWidth: '100%', maxHeight: '70vh' // Set max height for the preview }); // Create a hidden video element to extract the first frame var videoElement = document.createElement('video'); videoElement.src = videoUrl; // Create a canvas to draw the first frame var $thumbnailCanvas = $('<canvas>')[0]; var thumbnailContext = $thumbnailCanvas.getContext('2d'); // Wait for the video to load and then set it to the first frame $(videoElement).on('loadeddata', function() { videoElement.currentTime = 0; // Set video to the first frame }); // Once the video seeks to the first frame, capture the thumbnail $(videoElement).on('seeked', function() { // Set canvas size to match video dimensions $thumbnailCanvas.width = videoElement.videoWidth; $thumbnailCanvas.height = videoElement.videoHeight; // Draw the current frame (first frame) onto the canvas thumbnailContext.drawImage(videoElement, 0, 0, videoElement.videoWidth, videoElement.videoHeight); // Convert the canvas to a data URL and set it as the video poster var dataUrl = $thumbnailCanvas.toDataURL(); $video.attr('poster', dataUrl); // Set the first frame as the thumbnail }); // Keep the existing content of the div intact var existingVideo = $ele.find('video'); // Replace the video inside the .post div with the new one that has a thumbnail existingVideo.replaceWith($video); // Set the video source and load it $video.attr('src', videoUrl); $video[0].load(); // $video[0].play(); // Optionally, you can play the video if needed return true; // Return true if the function completes successfully } catch (error) { console.error("Error generating video thumbnail:", error); return false; // Return false if an error occurs } } function handleLazyLoad() { $('.post-content').each(function() { if ($(this).data('thumbnail') === false && $(this).find('video').length > 0) { generateVideoThumbnail($(this)); $(this).data('thumbnail', true); } }); } function isElementInView($el) { var windowTop = $(window).scrollTop(); var windowBottom = windowTop + $(window).height(); var elementTop = $el.offset().top; var elementBottom = elementTop + $el.height(); // Check if element is in the viewport return elementBottom >= windowTop && elementTop <= windowBottom; } function storeAnalytics($streamId) { $.ajax({ url: '', // The same file since we handle both front-end and back-end here type: 'POST', data: { streamId: $streamId }, success: function(response) { const data = JSON.parse(response); if (data.status == "error") { alert('Please Check the Internet Connection.'); } }, error: function() { alert('Please Check the Internet Connection.'); } }); } function streamAnalytics() { $('.post').each(function() { var $ele = $(this); // Current .post element if (isElementInView($ele) && !$ele.hasClass('logged')) { storeAnalytics($ele.attr('data-id')); $ele.addClass('logged'); // Mark it as logged } }); } // Function to play or pause the video based on its visibility function handleVideoVisibility(videoElement, $postElement) { if (isElementInView($postElement)) { // Video is in the viewport, play it if it's not already playing // if (videoElement.paused) { // videoElement.play().catch(function(error) {}); // } } else { // Video is out of the viewport, pause it if it's playing if (!videoElement.paused) { videoElement.pause(); } } } // Function to check all videos within .post elements function checkVideoVisibility() { $('.post').each(function() { var video = $(this).find('video')[0]; // Get the video element if (video) { handleVideoVisibility(video, $(this)); // Call the function to handle play/pause } }); } // Function to load data from the server function loadData() { if (isLoading || isLastPage) return; // If data is already being loaded or the last page is reached, return early isLoading = true; // Set flag to true to prevent further calls $('.loading-spinner').show(); // Show the loading indicator $.ajax({ url: '', // The same file since we handle both front-end and back-end here type: 'GET', data: { page: page, size: pageSize }, success: function(response) { const data = JSON.parse(response); const html = data.html; if (html.length > 0) { // Append the HTML content directly to the container (this loads latest data below) // $('#data-container').append(html); $('.first_right_container').append(html); // Check if the last page is reached isLastPage = data.last; page++; // Increment the page number for the next request } $('.loading-spinner').hide(); // Hide the loading indicator isLoading = false; // Reset the flag after data is loaded }, error: function() { $('.loading-spinner').hide(); isLoading = false; // Reset the flag in case of error alert('Error loading data'); } }); } function blockAccount(userId) { // Ask the user for confirmation before proceeding if (confirm("Are you sure you want to block this account?")) { $.ajax({ url: 'assets/php/blockAccount.php', // The PHP script to handle the blocking method: 'POST', data: { act: 'block', userId: userId }, success: function(response) { // Check if the block operation was successful if (response.status === 'success') { alert("Blocked the account"); window.location.reload(); // Reload the page to reflect the changes } else { alert(response.message); // Show error message if blocking fails } }, error: function() { alert('There was an error while blocking the account.'); } }); } } // Function to handle the report submission with AJAX function report_stream(userId, streamId, reason) { // Prepare the data for the server using FormData const formData = new FormData(); formData.append('userId', userId); formData.append('streamId', streamId); formData.append('reason', reason); // Perform the AJAX request with jQuery $.ajax({ url: '/assets/php/report_stream.php', type: 'POST', data: formData, dataType: 'json', processData: false, contentType: false, success: function(data) { console.log(data); if (data.status === 'success') { alert(data.message); window.location.reload(); // Reload the page after successful submission } else { alert('Error: ' + data.message); } }, error: function(xhr, status, error) { console.error('Error:', error); alert('An error occurred while trying to report the post. Please try again later.'); } }); } $(function() { // Initialize the modal when the document is ready reportModal = new bootstrap.Modal($("#reportModal")[0]); // Initialize the modal when the document is ready myModal = new bootstrap.Modal($("#uploadModal")[0]); // Event listener for showing the modal (for example, when the plus button is clicked) $("#plusButton").on("click", function() { myModal.show(); // Show the modal }); }); $(document).ready(function() { // Initialize the height on page load var $textarea = $('#contentTextarea'); if ($textarea.length) { adjustTextareaHeight($textarea[0]); } $(document).on('click', '.follow-button', function() { const targetUserId = $(this).data('id'); // ID of the user to follow/unfollow toggleFollow(this, userId, targetUserId); // Pass `this` (the button element) as the first parameter }); $('#saveModalEditButton').on('click', function() { saveEditedContent(); }); $(document).on('click', '.saveButton', function(e) { var id = $(this).data('id'); toggleSave(this, id); }); // likedUsers $(document).on('click', '.likedUsers', function() { const postId = $(this).data('id'); // Get post ID from the button's data attribute $.ajax({ url: 'fetch_liked_users.php', type: 'POST', data: { postId: postId }, success: function(response) { const users = JSON.parse(response); if (users.error) { alert(users.error); } else if (users.message) { $('#likedUsersList').html('<li class="list-group-item text-center">' + users.message + '</li>'); } else { const userList = users.map(user => `<li class="list-group-item">${user}</li>`).join(''); $('#likedUsersList').html(userList); } const likedUsersModal = new bootstrap.Modal(document.getElementById('likedUsersModal')); likedUsersModal.show(); }, error: function() { alert('Error fetching likes.'); } }); }); // Handle like button clicks $(document).on('click', '.likeButton', function(e) { event.stopPropagation(); // If the clicked element has the `likedUsers` class, do not toggle like/unlike if ($(e.target).hasClass('likedUsers')) { return; // Prevent triggering the like toggle } // Proceed with like toggle functionality var feedId = $(this).data('id'); toggleLike(this, feedId, userId); }); $('#contentTextarea').on('input', function() { var content = $('#contentTextarea').val().trim(); // Updated regular expression to match full URLs, including subdomains and paths // var url_pattern = /(?:https?|ftp):\/\/(?:[a-zA-Z0-9-]+\.)?(?:[a-zA-Z0-9-]+\.[a-zA-Z]{2,})(?:\/[^\s]*)?/g; var url_pattern = /(?:https?|ftp):\/\/(?:[a-zA-Z0-9-]+\.)?(?:[a-zA-Z0-9-]+\.[a-zA-Z]{2,})(?:\/[^\s\)]*)?/g; var youtube_pattern = /(?:v=|youtu\.be\/|embed\/)([a-zA-Z0-9_-]+)/; // Attempt to match all URLs within the content var matchedUrls = content.match(url_pattern); var youtubeUrl = content.match(youtube_pattern); if (youtubeUrl) { youtubeUrl.forEach(function(url) { // console.log('Matched URL:', url); // Log each matched URL }); if (tempUrl != youtubeUrl[0]) { letUrl = true; tempUrl = youtubeUrl[0]; removeMeta(); // Show the loading animation $('#loadingIcon').show(); // $('#postedContent').html(''); // Clear any previous metadata // Send the first matched URL to the server for metadata fetching $.ajax({ url: 'link.php', // Submit to the same page type: 'POST', data: { ytUrl: youtubeUrl[0] }, // Send the first matched URL success: function(response) { // Hide the loading animation $('#loadingIcon').hide(); if (response.iframe) { $('#ytPreview').html(response.iframe); $('#hiddenYTLink').val(response.iframe || ''); $('#hiddenTitle').val(response.title || ''); $('#ytPreview').show(); } else { return; } }, error: function() { // Hide the loading animation on error $('#loadingIcon').hide(); // console.log("Error fetching Youtube Link"); } }); } } else if (matchedUrls) { // Log all matched URLs to the console (for testing purposes) matchedUrls.forEach(function(url) { // console.log('Matched URL:', url); // Log each matched URL }); if (tempUrl != matchedUrls[0]) { letUrl = true; tempUrl = matchedUrls[0]; removeYT(); // Show the loading animation $('#loadingIcon').show(); // $('#postedContent').html(''); // Clear any previous metadata // Send the first matched URL to the server for metadata fetching $.ajax({ url: 'link.php', // Submit to the same page type: 'POST', data: { url: matchedUrls[0] }, // Send the first matched URL success: function(response) { // Hide the loading animation $('#loadingIcon').hide(); $('#linkPreview').show(); if (response.url) { $('#linkPreview #linkHeading').html(response.title || ''); // Set heading text $('#linkPreview #linkDesc').html(response.description || ''); // Set description text $('#linkPreview #linkUrl').attr('href', response.url || ''); // Set link URL $('#linkPreview #linkUrl').html(response.domain || ''); $('#hiddenTitle').val(response.title || ''); $('#hiddenDesc').val(response.description || ''); $('#hiddenUrl').val(response.url || ''); $('#hiddenDomain').val(response.domain || ''); if (response.image) { $('#linkPreview img').attr('src', response.image); // Set image source $('#hiddenImage').val(response.image); } } else { return; } }, error: function() { // Hide the loading animation on error $('#loadingIcon').hide(); // console.log("Error fetching the metadata"); } }); } } else { // Clear content and hide the loading animation if no valid URL is found $('#loadingIcon').hide(); } if (tempUrl != youtubeUrl[0]) { removeYT(); } if (tempUrl != matchedUrls[0]) { removeMeta() } if (youtubeUrl[0] == '') { removeYT(); } if (matchedUrls[0] == '') { removeMeta(); } }); // $(window).on('scroll', checkVideoVisibility); $(window).on('scroll', function() { streamAnalytics(); checkVideoVisibility(); // Check if the user has scrolled near the bottom of the page if ($(window).scrollTop() + $(window).height() >= $(document).height() - 100) { loadData(); // Load more data when scrolled near the bottom } }); $('.post-content').attr('tabindex', '0'); $(document).on('mouseenter', '.post-content', function() { if ($(this).data('thumbnail') === false && $(this).find('video').length > 0) { generateVideoThumbnail($(this)); $(this).data('thumbnail', true); } }); $(document).on('ajaxComplete', function() { handleLazyLoad(); // Also check on page load in case elements are already in view $(window).trigger('scroll'); }); $("#reportReasonSelect").on("change", function() { const otherReasonContainer = $("#otherReasonContainer"); if ($(this).val() === "Others") { otherReasonContainer.show(); } else { otherReasonContainer.hide(); } }); // Initial data load loadData(); }); // Close the dropdown menu if the user clicks anywhere outside the menu or the icon $(document).click(function(event) { var $isClickInsideMenu = $(event.target).closest('.dropcardMenu'); var $isClickInsideIcon = $(event.target).closest('.menu-container'); // Close the dropdown if the click is outside the menu and icon if ($isClickInsideMenu.length === 0 && $isClickInsideIcon.length === 0) { closeAllDropcardMenus(); } }); // Add event listeners to Edit and Delete buttons to close the dropdown when clicked $('.editBtn').click(function() { closeAllDropcardMenus(); }); $('.dropcardMenu a button').click(function() { closeAllDropcardMenus(); }); $(document).on('click', '.reportThisPost', function() { var reportId = $(this).data('id'); reportModal.show(); $('#reportStreamId').val(reportId); }); $(document).on('click', '.blockThisPost', function() { var blockId = $(this).data('userid'); // reportModal.show(); // $('#reportStreamId').val(reportId); blockAccount(blockId); }); // jQuery code to handle the 'Submit' button click $(document).on('click', '#submitReportButton', function() { // Get the selected reason from the dropdown const reason = $('#reportReasonSelect').val(); const streamId = $('#reportStreamId').val(); const otherReason = $('#otherReasonTextarea').val().trim(); // Get the value from the textarea // console.log(reason); // console.log(streamId); // console.log(otherReason); // Ensure a reason is selected if (!reason) { alert('Please select a reason.'); return; } // If "Others" is selected, ensure the textarea is filled let finalReason = reason; if (reason === 'Others') { if (!otherReason) { alert('Please provide a reason.'); return; } finalReason = otherReason; // Use the value from the textarea as the reason } // Call the report_stream function with the selected data report_stream(userId, streamId, finalReason); }); // Attach the `oninput` event for dynamic resizing $(document).on('input', '#contentTextarea', function() { adjustTextareaHeight(this); }); // function fetchChannelData(id) { // const userId = <?= $gUserId ?>; // const postId = id; // const channelList = $("#channelList_" + postId); // // Close other dropdowns before showing this one // $(".channels_list").hide(); // // Clear previous entries before making the request // channelList.empty(); // // Perform AJAX request // $.ajax({ // url: "handle_channel.php", // type: "GET", // data: { // user_id: userId, // post_id: postId // }, // dataType: "json", // success: function(data) { // if (data.success) { // if (data.channels.length === 0) { // channelList.append("<p class='dropdown-item'>No channels available</p>"); // } else { // $.each(data.channels, function(index, channel) { // let listItem = $("<button>") // .addClass("channel-item dropdown-item") // .attr("data-id", channel.id) // .text(channel.name) // .on("click", function() { // addToChannel(postId, channel.id); // }); // channelList.append(listItem); // }); // } // // Add "Add Channels" button below the channel list // let addButton = $("<button>") // .addClass("add-channels-btn dropdown-item") // .text("Add Channels") // .on("click", function() { // // Redirect to add_channel.php // window.location.href = "add_channel.php"; // Redirect to the page // }); // channelList.append(addButton); // // Show the dropdown only after data is fetched // channelList.show(); // } else { // alert("Error: " + data.message); // } // }, // error: function(xhr, status, error) { // console.error("AJAX Error:", error); // } // }); // } // Updated fetchChannelData function function fetchChannelData(id) { const userId = <?= $gUserId ?>; const postId = id; // Show the modal and overlay const overlay = document.getElementById(`channelOverlay_${id}`); const wrapper = document.getElementById(`channelCardsWrapper_${id}`); const cardsContent = document.getElementById(`channelCardsContent_${id}`); // Show loading state overlay.style.display = 'block'; wrapper.classList.add('active'); cardsContent.innerHTML = '<div class="loading-indicator">Loading channels...</div>'; // Perform AJAX request $.ajax({ url: "handle_channel.php", type: "GET", data: { user_id: userId, post_id: postId }, dataType: "json", success: function(data) { // Clear the container cardsContent.innerHTML = ''; if (data.success) { if (data.channels.length === 0) { cardsContent.innerHTML = '<div class="no-channels-message">No channels available</div>'; } else { // Create channel cards $.each(data.channels, function(index, channel) { let card = $("<div>") .addClass("channel-card") .append( $("<div>") .addClass("channel-name") .text(channel.name) ) .append( $("<button>") .addClass("add-to-channel-btn") .text("Add") .on("click", function() { addToChannel(postId, channel.id); }) ); $(cardsContent).append(card); }); } // Add "Add Channels" button as a card let addCard = $("<div>") .addClass("add-channel-card") .append( $("<a>") .addClass("add-channel-btn") .attr("href", "add_channel.php") .text("+ Add New Channel") ); $(cardsContent).append(addCard); } else { cardsContent.innerHTML = '<div class="error-message">Error: ' + data.message + '</div>'; } }, error: function(xhr, status, error) { cardsContent.innerHTML = '<div class="error-message">Failed to load channels. Please try again.</div>'; console.error("AJAX Error:", error); } }); // Add a document click handler to close the modal when clicking outside setTimeout(function() { $(document).one("click", function(e) { if (!$(e.target).closest('.channel-cards-wrapper, .action-button').length) { hideChannelCards(id); } }); }, 100); } function hideChannelCards(id) { const overlay = document.getElementById(`channelOverlay_${id}`); const wrapper = document.getElementById(`channelCardsWrapper_${id}`); overlay.style.display = 'none'; wrapper.classList.remove('active'); } function addToChannel(postId, channelId) { // Your existing addToChannel logic here console.log(`Adding post ${postId} to channel ${channelId}`); // You might want to make an AJAX call to save the selection $.ajax({ url: "add_to_channel.php", type: "POST", data: { post_id: postId, channel_id: channelId }, dataType: "json", success: function(response) { if (response.success) { // Show success message alert("Added to channel successfully!"); hideChannelCards(postId); } else { // Show error message alert("Error: " + response.message); } }, error: function(xhr, status, error) { alert("Failed to add to channel. Please try again."); console.error("AJAX Error:", error); } }); } // Hide dropdown when clicking outside $(document).on("click", function(event) { if (!$(event.target).closest(".channels_list").length) { $(".channels_list").hide(); } }); function addToChannel(postId, channelId) { $.ajax({ url: 'add_to_channel.php', type: 'POST', data: { postId: postId, channelId: channelId }, success: function(response) { const result = JSON.parse(response); // Parse the JSON response if (result.success) { alert('Post added to channel'); } else { alert('Failed to add to channel: ' + result.message); } }, error: function(xhr, status, error) { alert('Error: ' + error); } }); } // Select the bookmark icon and notification elements $(document).ready(function() { const notification = document.querySelector('.bookmarkNotification'); // Target elements that have both fa-regular AND fa-thumbs-up classes $('body').on('click', '.fa-regular.fa-bookmark', function(e) { $('.bookmarkNotification').text('Bookmark Added'); notification.classList.add('show'); // Hide it after 2 seconds (2000 milliseconds) setTimeout(() => { notification.classList.remove('show'); }, 1000); }) $('body').on('click', '.fa-solid.fa-bookmark', function(e) { $('.bookmarkNotification').text('Bookmark Removed'); notification.classList.add('show'); // Hide it after 2 seconds (2000 milliseconds) setTimeout(() => { notification.classList.remove('show'); }, 1000); }) }); </script> <script> $(document).ready(function() { // Target elements that have both fa-regular AND fa-thumbs-up classes $('body').on('click', '.fa-regular.fa-thumbs-up', function(e) { // List of emojis to use - only thumbs up const emojis = ['👍']; // const emojis = ['👍', '❤️', '😊', '🎉', '⭐', '🚀', '💯', '🔥']; // Always create exactly 4 emoji elements const emojiCount = 1; for (let i = 0; i < emojiCount; i++) { // Create an emoji span const emoji = $('<span></span>'); // Use thumbs up emoji emoji.html(emojis[0]); emoji.addClass('flowing-emoji'); // Get button position const buttonOffset = $(this).offset(); const startX = buttonOffset.left + $(this).width() / 2; const startY = buttonOffset.top; // Add some randomness to starting position const randomOffsetX = (Math.random() - 0.5) * 20; // Set emoji styles emoji.css({ 'position': 'absolute', 'left': `${startX + randomOffsetX}px`, 'top': `${startY}px`, 'font-size': `${1.2 + Math.random() * 0.4}rem`, 'z-index': '999999', 'pointer-events': 'none', 'opacity': '1', 'transform': `translate(-50%, 0%) rotate(${(Math.random() - 0.5) * 20}deg)` }); // Append to body $('body').append(emoji); // Calculate random path parameters const endX = startX + (Math.random() - 0.5) * 60; const endY = startY - (120 + Math.random() * 60); const delay = Math.random() * 200; const duration = 1000 + Math.random() * 500; // Animate with a smooth path setTimeout(function() { emoji.animate({ top: `${endY}px`, left: `${endX}px`, opacity: 0 }, { duration: duration, easing: 'easeOutQuad', step: function(now, fx) { if (fx.prop === "top") { const wiggle = Math.sin(now * 0.03) * 3; $(this).css('margin-left', wiggle + 'px'); } }, complete: function() { $(this).remove(); } }); }, delay); } }); // Add CSS styles dynamically if not already there if ($('#emoji-flow-styles').length === 0) { $('head').append(` <style id="emoji-flow-styles"> .flowing-emoji { position: absolute; pointer-events: none; user-select: none; z-index: 9999; transition: transform 0.2s ease-out; } </style> `); } // Make sure jQuery easing is available if (typeof $.easing.easeOutQuad === 'undefined') { $.easing.easeOutQuad = function(x, t, b, c, d) { return -c * (t /= d) * (t - 2) + b; }; } }); </script> </head> <body> <div class="media-share-modal" id="post-modal"> <div class="media-modal-content"> <div class="media-modal-header"> <h5 class="media-modal-title">Share</h5> <button type="button" class="media-close-modal" data-bs-dismiss="modal" aria-label="Close"> <i class="fas fa-times"></i> </button> </div> <div class="media-upload-section"> <!-- Upload form section --> <div class="media-upload-container"> <div class="media-upload-wrapper"> <div id="loadingIndicator" class="media-loading-indicator">Generating<span id="dots">...</span></div> <div class="media-textarea-container"> <textarea id="contentTextarea" class="media-content-textarea" placeholder="What would you like to share?" oninput="adjustTextareaHeight(this)"></textarea> </div> <!-- Media preview area --> <div id="mediaSlider" class="media-slider-container"> <div id="mediaSlides" class="media-slider-slides"> <!-- Dynamic media elements will be appended here --> </div> <button class="media-prev media-slideBtn" onclick="moveSlide(-1)"> <i class="fas fa-chevron-left"></i> </button> <button class="media-next media-slideBtn" onclick="moveSlide(1)"> <i class="fas fa-chevron-right"></i> </button> </div> <!-- Link preview area --> <div id="linkPreview" class="media-link-preview"> <div class="media-hyperlink-container"> <img class="media-link-image" src="" alt="Link preview"> <div class="media-link-content"> <h3 id="linkHeading" class="media-link-title"></h3> <p id="linkDesc" class="media-link-description"></p> <a id="linkUrl" class="media-link-url" href=""></a> </div> </div> </div> <!-- YouTube preview area --> <div id="ytPreview" class="media-youtube-preview"></div> <!-- Loading indicator --> <div id="loadingIcon" class="media-loading-spinner"> <div class="media-spinner"></div> </div> <!-- Hidden fields for data storage --> <div class="media-hidden-fields"> <input type="hidden" id="hiddenTitle"> <input type="hidden" id="hiddenDesc"> <input type="hidden" id="hiddenUrl"> <input type="hidden" id="hiddenImage"> <input type="hidden" id="hiddenDomain"> <input type="hidden" id="hiddenYTLink"> </div> </div> </div> </div> <div class="media-share-footer"> <div class="media-privacy-selector"> <span class="media-privacy-label">Who can see this post?</span> <div class="media-dropdown-container"> <button class="media-dropdown-button" id="privacy-dropdown-btn" style="gap:4px;"> <i class="fas fa-globe"></i> <span>Public</span> <i class="fas fa-caret-down"></i> </button> <div class="media-dropdown-content" id="privacy-dropdown-content"> <div class="media-dropdown-item active" style="gap:4px;"> <i class="fas fa-globe"></i> <span>Public</span> </div> <div class="media-dropdown-item" style="gap:4px;"> <i class="fas fa-user-friends"></i> <span>People I follow</span> </div> </div> </div> </div> <div class="media-share-actions"> <!-- File upload button --> <button class="media-action-icon-btn" id="media-upload-btn"> <i class="fas fa-image"></i> </button> <input type="file" id="fileInput" class="media-file-input" accept="image/*,video/*" onchange="previewMedia();" multiple> <!-- AI content generation button --> <button class="media-action-icon-btn" id="ai-generate-btn" onclick="fetchGenAIContent()"> <i class="fas fa-magic"></i> </button> <!-- Post submission button --> <button class="media-post-button" id="submit-post" onclick="uploadPost()"> <i class="fas fa-paper-plane"></i> </button> </div> </div> </div> </div> <!-- Edit Post Modal --> <div class="edit-post-modal" id="editPostModal"> <div class="edit-post-modal-content"> <div class="edit-post-modal-header"> <h3>Edit Post</h3> <button type="button" class="close-edit-modal" data-bs-dismiss="modal"> <i class="fas fa-times"></i> </button> </div> <div class="edit-post-input-container"> <textarea id="modalContentTextarea" class="form-control"></textarea> </div> <div class="edit-post-footer"> <button type="button" class="cancel-edit-btn" data-bs-dismiss="modal">Cancel</button> <button type="button" class="save-edit-btn" id="saveModalEditButton">Save Changes</button> </div> </div> </div> <!-- Main container --> <div class="container"> <!-- Navbar --> <?php include 'assets/php/new_social_navbar.php' ?> <!-- Sidebar --> <?php include 'assets/php/new_social_sidebar.php' ?> <!-- Main content area --> <div class="main-content"> <!-- Posts feed --> <div class="posts-feed"> <!-- Floating Action Button --> <div class="first_right_container"> </div> <div class="loading-spinner"></div> </div> <div class="fab-container"> <button class="fab-button" id="create-post-fab"> <i class="fas fa-plus"></i> </button> </div> <!-- Right sidebar --> <div class="right-sidebar"> <div class="sidebar-card news-card"> <div class="sidebar-title">Latest News</div> <div class="news-container"> <div class="news-item"> <img src="assets/img/bus.jpg" alt="News thumbnail" class="news-thumbnail"> <div class="news-content"> <div class="news-headline">New Design Trends for 2025 Revealed at Global UX Conference</div> <div class="news-source">Design Weekly • 2h ago</div> </div> </div> <div class="news-item"> <img src="assets/img/home_screen4.jpg" alt="News thumbnail" class="news-thumbnail"> <div class="news-content"> <div class="news-headline">Tech Giants Announce Collaboration on Open-Source Design System</div> <div class="news-source">Tech Today • 5h ago</div> </div> </div> <div class="news-item"> <img src="assets/img/education_and_learning.jpg" alt="News thumbnail" class="news-thumbnail"> <div class="news-content"> <div class="news-headline">Study Shows Increase in Demand for UI/UX Designers in 2025</div> <div class="news-source">Career Insights • 8h ago</div> </div> </div> <div class="news-item"> <img src="assets/img/read_mode.png" alt="News thumbnail" class="news-thumbnail"> <div class="news-content"> <div class="news-headline">The Rise of Immersive Web Experiences: What Designers Need to Know</div> <div class="news-source">Web Design Mag • 12h ago</div> </div> </div> <div class="news-item"> <img src="assets/img/real_time_tracking.jpg" alt="News thumbnail" class="news-thumbnail"> <div class="news-content"> <div class="news-headline">Color Psychology in UI: Latest Research and Applications</div> <div class="news-source">Design Psychology • 1d ago</div> </div> </div> <div class="news-item"> <img src="assets/img/home_screen4.jpg" alt="News thumbnail" class="news-thumbnail"> <div class="news-content"> <div class="news-headline">Accessibility First: The New Standard in Web Development</div> <div class="news-source">Inclusive Design • 1d ago</div> </div> </div> </div> <div class="news-footer">See all news</div> </div> <div class="sidebar-card"> <div class="sidebar-title">Who to follow</div> <div class="friend-item"> <div class="user-avatar">D</div> <div class="friend-info"> <div class="friend-name">David Chen</div> <!-- <div class="post-meta">@designdavid</div> --> </div> </div> <div class="friend-item"> <div class="user-avatar">L</div> <div class="friend-info"> <div class="friend-name">Lisa Morgan</div> <!-- <div class="post-meta">@lisacreates</div> --> </div> </div> <div class="friend-item"> <div class="user-avatar">K</div> <div class="friend-info"> <div class="friend-name">Kevin Patel</div> <!-- <div class="post-meta">@kevindev</div> --> </div> </div> </div> </div> </div> <div class="sidebar-overlay" id="sidebar-overlay"></div> <div class="mobile-footer"> <div class="footer-item active"> <i class="fas fa-home"></i> </div> <div class="footer-item"> <i class="fas fa-search"></i> </div> <div class="footer-item"> <i class="fas fa-book-reader"></i> </div> <div class="footer-item"> <i class="fas fa-layer-group"></i> </div> <div class="footer-item"> <i class="fas fa-user"></i> </div> </div> </div> <!-- Font Awesome for icons --> <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/js/all.min.js"></script> <script> // Mobile sidebar toggle const sidebarToggle = document.getElementById('sidebar-toggle'); const sidebar = document.querySelector('.sidebar'); const sidebarOverlay = document.getElementById('sidebar-overlay'); sidebarToggle.addEventListener('click', function() { sidebar.classList.toggle('active'); sidebarOverlay.classList.toggle('active'); }); sidebarOverlay.addEventListener('click', function() { sidebar.classList.remove('active'); sidebarOverlay.classList.remove('active'); }); </script> <script> // Toggle the modal visibility function toggleModal() { const modal = document.getElementById('post-modal'); modal.classList.toggle('active'); // Reset form when opening if (modal.classList.contains('active')) { resetForm(); } } // Reset the form fields function resetForm() { document.getElementById('contentTextarea').value = ''; document.getElementById('mediaSlider').style.display = 'none'; document.getElementById('mediaSlides').innerHTML = ''; document.getElementById('linkPreview').style.display = 'none'; document.getElementById('ytPreview').style.display = 'none'; document.getElementById('loadingIndicator').style.display = 'none'; document.getElementById('loadingIcon').style.display = 'none'; // Reset hidden fields document.getElementById('hiddenTitle').value = ''; document.getElementById('hiddenDesc').value = ''; document.getElementById('hiddenUrl').value = ''; document.getElementById('hiddenImage').value = ''; document.getElementById('hiddenDomain').value = ''; document.getElementById('hiddenYTLink').value = ''; } // Adjust textarea height based on content function adjustTextareaHeight(textarea) { textarea.style.height = 'auto'; textarea.style.height = textarea.scrollHeight + 'px'; } // Toggle dropdown visibility function toggleDropdown() { const dropdown = document.getElementById('privacy-dropdown-content'); dropdown.classList.toggle('active'); } // Handle dropdown item selection function selectPrivacyOption(option) { const dropdown = document.getElementById('privacy-dropdown-content'); const dropdownBtn = document.getElementById('privacy-dropdown-btn'); // Update dropdown button text and icon const icon = option === 'public' ? 'fa-globe' : 'fa-user-friends'; const text = option === 'public' ? 'Public' : 'People I follow'; dropdownBtn.innerHTML = ` <i class="fas ${icon}"></i> <span>${text}</span> <i class="fas fa-caret-down"></i> `; // Update active class const items = dropdown.querySelectorAll('.media-dropdown-item'); items.forEach(item => { item.classList.remove('active'); if (item.querySelector('span').textContent === text) { item.classList.add('active'); } }); // Close dropdown dropdown.classList.remove('active'); } // Handle media file preview function previewMedia() { const fileInput = document.getElementById('fileInput'); const mediaSlider = document.getElementById('mediaSlider'); const mediaSlides = document.getElementById('mediaSlides'); if (fileInput.files.length > 0) { mediaSlider.style.display = 'block'; mediaSlides.innerHTML = ''; Array.from(fileInput.files).forEach(file => { const reader = new FileReader(); reader.onload = function(e) { const slideDiv = document.createElement('div'); slideDiv.className = 'slide'; if (file.type.startsWith('image/')) { const img = document.createElement('img'); img.src = e.target.result; img.alt = 'Uploaded image'; slideDiv.appendChild(img); } else if (file.type.startsWith('video/')) { const video = document.createElement('video'); video.src = e.target.result; video.controls = true; slideDiv.appendChild(video); } mediaSlides.appendChild(slideDiv); }; reader.readAsDataURL(file); }); } else { mediaSlider.style.display = 'none'; } } // Handle slider navigation let slideIndex = 0; function moveSlide(direction) { const slides = document.querySelectorAll('.slide'); if (slides.length === 0) return; slideIndex += direction; if (slideIndex >= slides.length) { slideIndex = 0; } else if (slideIndex < 0) { slideIndex = slides.length - 1; } const translateValue = -slideIndex * 100; document.getElementById('mediaSlides').style.transform = `translateX(${translateValue}%)`; } // Handle AI content generation // function fetchGenAIContent() { // const loadingIndicator = document.getElementById('loadingIndicator'); // const textarea = document.getElementById('contentTextarea'); // loadingIndicator.style.display = 'block'; // // Simulate AI content generation (you would replace this with actual API call) // setTimeout(() => { // loadingIndicator.style.display = 'none'; // textarea.value = "This is AI-generated content that would normally come from your API."; // adjustTextareaHeight(textarea); // }, 1500); // // Animate loading dots // animateLoadingDots(); // } function fetchGenAIContent() { const loadingIndicator = document.getElementById('loadingIndicator'); const textarea = document.getElementById('contentTextarea'); // Check if textarea exists if (!textarea) { console.error("Textarea with id 'contentTextarea' not found."); return; } const textareaValue = textarea.value.trim(); // Check if the textarea is empty if (!textareaValue) { alert("Please enter something in the textarea."); console.warn("Textarea is empty. AJAX request not sent."); return; } // Show loading indicator loadingIndicator.style.display = 'block'; animateLoadingDots(); // Your existing animation function // Make the AJAX request using fetch API (modern replacement for $.ajax) fetch("genai/process_genai.php", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", }, body: new URLSearchParams({ working_headline: textareaValue, avatar: "#post" }) }) .then(response => { if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } return response.text(); }) .then(data => { // Populate the textarea with the response textarea.value = data; adjustTextareaHeight(textarea); // Adjust height after setting the response }) .catch(error => { console.error(`Error fetching GenAI content: ${error}`); }) .finally(() => { // Hide the loading indicator when complete loadingIndicator.style.display = 'none'; // Assuming you have a function to stop the animation stopAnimatingLoadingDots(); }); } // Animate loading dots for AI generation function animateLoadingDots() { const dots = document.getElementById('dots'); let dotCount = 0; const interval = setInterval(() => { dotCount = (dotCount + 1) % 4; dots.textContent = '.'.repeat(dotCount); if (document.getElementById('loadingIndicator').style.display === 'none') { clearInterval(interval); } }, 300); } // Get media files from input function getMediaFiles() { const fileInput = document.getElementById('fileInput'); return Array.from(fileInput.files); } // Show toast notification function showToast(message) { // Create toast notification if it doesn't exist let toast = document.querySelector('.toast-notification'); if (!toast) { toast = document.createElement('div'); toast.className = 'toast-notification'; document.body.appendChild(toast); } toast.textContent = message; toast.classList.add('show'); // Hide toast after 3 seconds setTimeout(() => { toast.classList.remove('show'); }, 3000); } // Initialize event listeners document.addEventListener('DOMContentLoaded', function() { // Open modal document.querySelector('.fab-button')?.addEventListener('click', toggleModal); // Close modal document.querySelector('.media-close-modal').addEventListener('click', toggleModal); // Toggle privacy dropdown document.getElementById('privacy-dropdown-btn').addEventListener('click', toggleDropdown); // Handle privacy option selection document.querySelectorAll('.media-dropdown-item').forEach(item => { item.addEventListener('click', function() { const option = this.querySelector('span').textContent === 'Public' ? 'public' : 'private'; selectPrivacyOption(option); }); }); // Handle media upload button click document.getElementById('media-upload-btn').addEventListener('click', function() { document.getElementById('fileInput').click(); }); // Close modal when clicking outside window.addEventListener('click', function(event) { const modal = document.getElementById('post-modal'); if (event.target === modal) { toggleModal(); } }); // Close dropdown when clicking outside window.addEventListener('click', function(event) { const dropdown = document.getElementById('privacy-dropdown-content'); const dropdownBtn = document.getElementById('privacy-dropdown-btn'); if (event.target !== dropdownBtn && !dropdownBtn.contains(event.target)) { dropdown.classList.remove('active'); } }); }); </script> </body> </html>