From ebaf73ec336929e72ee5c7f4fc4849ffe7686b9b Mon Sep 17 00:00:00 2001 From: Mostafa Osama Date: Mon, 1 Dec 2025 22:44:11 +0200 Subject: [PATCH 1/2] feature: Add favorites functionality and UI updates for Quran MP3 player - Initialize favorites file and handle favorite toggling in quran_mp3.js - Update quran_mp3.html to include favorite filter button and search functionality - Create favorites.json to store user favorites - Enhance CSS for better layout and styling of favorite icons and search bar - Add heart icons for favorite representation --- src/data/favorites.json | 1 + src/pages/quran_mp3.html | 76 ++-- src/preload/preload_modules/quran_mp3.js | 431 +++++++++++++++-------- src/public/css/quran_mp3.css | 344 +++++++++++------- src/public/icon/dark/heart-solid.svg | 5 + src/public/icon/dark/heart.svg | 3 + src/public/icon/heart-solid.svg | 3 + src/public/icon/heart.svg | 1 + 8 files changed, 548 insertions(+), 316 deletions(-) create mode 100644 src/data/favorites.json create mode 100644 src/public/icon/dark/heart-solid.svg create mode 100644 src/public/icon/dark/heart.svg create mode 100644 src/public/icon/heart-solid.svg create mode 100644 src/public/icon/heart.svg diff --git a/src/data/favorites.json b/src/data/favorites.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/src/data/favorites.json @@ -0,0 +1 @@ +{} diff --git a/src/pages/quran_mp3.html b/src/pages/quran_mp3.html index 337120a..5ce9c72 100644 --- a/src/pages/quran_mp3.html +++ b/src/pages/quran_mp3.html @@ -1,19 +1,17 @@ - - - - - - - - - - - - - - + + + + + + + + + + + +
@@ -21,35 +19,41 @@
+ - - - + - + - -
+
+ - +
    -
      - -

      - -
        -
      - -
      +

      +
        +
        - - - \ No newline at end of file + + diff --git a/src/preload/preload_modules/quran_mp3.js b/src/preload/preload_modules/quran_mp3.js index c4ea5a4..04cd47b 100644 --- a/src/preload/preload_modules/quran_mp3.js +++ b/src/preload/preload_modules/quran_mp3.js @@ -1,167 +1,294 @@ module.exports = function quran_mp3(fs, path, App_Path, settings) { + let Quran_json = fs.readJsonSync( + path.join(__dirname, "../../data/Quran.json") + ); + let mp3quran_json = fs.readJsonSync( + path.join(__dirname, "../../data/mp3quran.json") + ); + let volume = settings?.volume; + let dark_mode = settings?.dark_mode; + let ul_group = document.getElementById("ul_group"); + let Sheikh = document.getElementById("Sheikh"); + let li_Sheikh_number = 1; + + // Initialize favorites file if it doesn't exist + let favoritesPath = path.join(App_Path, "./data/favorites.json"); + let favorites = {}; + try { + if (fs.existsSync(favoritesPath)) { + favorites = fs.readJsonSync(favoritesPath); + } else { + fs.writeJsonSync(favoritesPath, {}); + } + } catch (error) { + favorites = {}; + fs.writeJsonSync(favoritesPath, {}); + } + + let showOnlyFavorites = false; + + ul_group.style = "display: none;"; + Sheikh.style = "display: flex;"; + + for (let item of mp3quran_json) { + let li_Sheikh = document.createElement("li"); + let reader_name = document.createElement("p"); + let reader = document.createElement("div"); + let reader_info = document.createElement("div"); + let Sheikh_name = document.createElement("p"); + let Sheikh_rewaya = document.createElement("p"); + let favorite_icon = document.createElement("img"); + let li_Sheikh_id = `li_Sheikh_${li_Sheikh_number++}`; + + Sheikh.appendChild(li_Sheikh); + li_Sheikh.id = li_Sheikh_id; + li_Sheikh.className = "li_Sheikh"; + li_Sheikh.setAttribute("data-sheikh-id", item?.id); + li_Sheikh.appendChild(reader_name); + reader_name.id = "reader_name"; + li_Sheikh.appendChild(reader); + reader.id = "reader"; + + // First column: "القارئ" label + let reader_label = document.createElement("p"); + reader_label.className = "reader-label"; + reader_label.innerText = "القارئ"; + reader.appendChild(reader_label); + + // Second column: Sheikh info + reader.appendChild(reader_info); + reader_info.className = "reader-info"; + reader_info.appendChild(Sheikh_name); + Sheikh_name.id = "Sheikh_name"; + Sheikh_name.innerText = item?.name; + reader_info.appendChild(Sheikh_rewaya); + Sheikh_rewaya.id = "Sheikh_rewaya"; + Sheikh_rewaya.innerText = item?.rewaya; + + // Third column: favorite icon + reader.appendChild(favorite_icon); + favorite_icon.className = "favorite-icon"; + favorite_icon.id = `favorite_icon_${item?.id}`; + favorite_icon.src = favorites[item?.id] + ? dark_mode + ? "../public/icon/dark/heart-solid.svg" + : "../public/icon/heart-solid.svg" + : dark_mode + ? "../public/icon/dark/heart.svg" + : "../public/icon/heart.svg"; + favorite_icon.title = favorites[item?.id] + ? "إزالة من المفضلة" + : "إضافة إلى المفضلة"; + } + + let li_Sheikh = document.getElementsByClassName("li_Sheikh"); + let item_li_Sheikh = Array.from(li_Sheikh); + + // Function to toggle favorite + function toggleFavorite(sheikhId, event) { + event.stopPropagation(); // Prevent li click event + let favoritesPath = path.join(App_Path, "./data/favorites.json"); + let currentFavorites = fs.readJsonSync(favoritesPath); + let favoriteIcon = document.getElementById(`favorite_icon_${sheikhId}`); + + if (currentFavorites[sheikhId]) { + delete currentFavorites[sheikhId]; + favoriteIcon.src = dark_mode + ? "../public/icon/dark/heart.svg" + : "../public/icon/heart.svg"; + favoriteIcon.title = "إضافة إلى المفضلة"; + } else { + currentFavorites[sheikhId] = true; + favoriteIcon.src = dark_mode + ? "../public/icon/dark/heart-solid.svg" + : "../public/icon/heart-solid.svg"; + favoriteIcon.title = "إزالة من المفضلة"; + } - let Quran_json = fs.readJsonSync(path.join(__dirname, '../../data/Quran.json')); - let mp3quran_json = fs.readJsonSync(path.join(__dirname, '../../data/mp3quran.json')); - let volume = settings?.volume; - let dark_mode = settings?.dark_mode; - let ul_group = document.getElementById('ul_group'); - let Sheikh = document.getElementById('Sheikh'); - let li_Sheikh_number = 1 - - ul_group.style = 'display: none;' - Sheikh.style = 'display: flex;' - - for (let item of mp3quran_json) { - - let li_Sheikh = document.createElement("li"); - let reader_name = document.createElement('p'); - let reader = document.createElement('div'); - let Sheikh_name = document.createElement('p'); - let Sheikh_rewaya = document.createElement('p'); - let li_Sheikh_id = `li_Sheikh_${li_Sheikh_number++}` - - Sheikh.appendChild(li_Sheikh); - li_Sheikh.id = li_Sheikh_id; - li_Sheikh.className = 'li_Sheikh' - li_Sheikh.appendChild(reader_name); - reader_name.id = 'reader_name'; - reader_name.innerText = 'القارئ'; - li_Sheikh.appendChild(reader); - reader.id = 'reader'; - reader.appendChild(Sheikh_name); - Sheikh_name.id = 'Sheikh_name'; - Sheikh_name.innerText = item?.name; - reader.appendChild(Sheikh_rewaya); - Sheikh_rewaya.id = 'Sheikh_rewaya'; - Sheikh_rewaya.innerText = item?.rewaya; + fs.writeJsonSync(favoritesPath, currentFavorites); + favorites = currentFavorites; + // If showing only favorites, reapply filter + if (showOnlyFavorites) { + filterFavorites(); } - - let li_Sheikh = document.getElementsByClassName('li_Sheikh'); - let item_li_Sheikh = Array.from(li_Sheikh); - item_li_Sheikh.forEach((event, item) => { - - document.getElementById(event.id).addEventListener('click', e => { - - window.scrollTo(0, 0); - let Sheikh_true = event.id.split('li_Sheikh_')[1] - let ArrayMp3 = mp3quran_json.find(e => e?.id.toString() === Sheikh_true); - let quran_mp3_name_Sheikh = document.getElementById('quran_mp3_name_Sheikh') - let quran_mp3_back = document.getElementById('quran_mp3_back') - quran_mp3_name_Sheikh.innerText = ArrayMp3?.name - quran_mp3_name_Sheikh.style.display = "block" - quran_mp3_back.style.display = "block" - quran_mp3_back.addEventListener("click", e => { - window.location.href = './quran_mp3.html' + } + + // Add favorite icon click handlers + mp3quran_json.forEach((item) => { + let favoriteIcon = document.getElementById(`favorite_icon_${item?.id}`); + if (favoriteIcon) { + favoriteIcon.addEventListener("click", (e) => + toggleFavorite(item?.id, e) + ); + } + }); + + item_li_Sheikh.forEach((event, item) => { + document.getElementById(event.id).addEventListener("click", (e) => { + window.scrollTo(0, 0); + let Sheikh_true = event.id.split("li_Sheikh_")[1]; + let ArrayMp3 = mp3quran_json.find( + (e) => e?.id.toString() === Sheikh_true + ); + let quran_mp3_name_Sheikh = document.getElementById( + "quran_mp3_name_Sheikh" + ); + let quran_mp3_back = document.getElementById("quran_mp3_back"); + quran_mp3_name_Sheikh.innerText = ArrayMp3?.name; + quran_mp3_name_Sheikh.style.display = "block"; + quran_mp3_back.style.display = "block"; + quran_mp3_back.addEventListener("click", (e) => { + window.location.href = "./quran_mp3.html"; + }); + ul_group.style = "display: flex;"; + Sheikh.style = "display: none;"; + let num = 1; + + for (let item of Quran_json) { + let numberx = num++; + let url = `${ArrayMp3?.Server}/${String(numberx).padStart(3, 0)}.mp3`; + let li_group = document.createElement("li"); + let grid_mp3 = document.createElement("div"); + let number = document.createElement("p"); + let name = document.createElement("p"); + let download = document.createElement("div"); + let audio = document.createElement("audio"); + let icon_mp3 = document.createElement("img"); + let icon_mp3_ddownload = document.createElement("img"); + let a_download = document.createElement("a"); + + ul_group.appendChild(li_group); + li_group.className = "li_group"; + li_group.appendChild(grid_mp3); + grid_mp3.id = "grid_mp3"; + grid_mp3.appendChild(number); + number.className = "number"; + number.innerText = item?.Number; + grid_mp3.appendChild(name); + name.className = "name"; + name.innerText = item?.Name; + grid_mp3.appendChild(download); + download.id = "download"; + download.appendChild(icon_mp3); + icon_mp3.className = "icon_mp3"; + icon_mp3.id = `icon_mp3_${item?.Number}`; + icon_mp3.src = dark_mode + ? "../public/icon/play.png" + : "../public/icon/dark/play.png"; + download.appendChild(a_download); + a_download.id = `a_download_${item?.Number}`; + a_download.href = url; + a_download.download = `${item?.Name}_${ArrayMp3?.name}.mp3`; + a_download.appendChild(icon_mp3_ddownload); + icon_mp3_ddownload.className = "icon_mp3_ddownload"; + icon_mp3_ddownload.id = `icon_mp3_ddownload_${item?.Number}`; + icon_mp3_ddownload.src = dark_mode + ? "../public/icon/download.png" + : "../public/icon/dark/download.png"; + download.appendChild(audio); + audio.id = `start_mp3_${numberx}`; + audio.src = url; + audio.preload = "none"; + audio.autoplay = false; + audio.volume = volume ? volume : 1; + } + + let icon_mp3 = document.getElementsByClassName("icon_mp3"); + let item_icon_mp3 = Array.from(icon_mp3); + let number = 1; + + item_icon_mp3.forEach((event) => { + let id_mp3 = event.id; + let item = number++; + let icon_mp3 = document.getElementById(`icon_mp3_${item}`); + icon_mp3.addEventListener("click", async (event) => { + let sound_json = fs.readJsonSync( + path.join(App_Path, "./data/sound.json") + ); + let ArrayMp3 = mp3quran_json.find( + (e) => e?.id.toString() === Sheikh_true + ); + let url = `${ArrayMp3?.Server}/${String(item).padStart(3, 0)}.mp3`; + let id = id_mp3.split("icon_mp3_")[1]; + let sound = document.getElementById(`start_mp3_${id}`); + + if (sound_json?.sound) { + icon_mp3.src = dark_mode + ? "../public/icon/pause.png" + : "../public/icon/dark/pause.png"; + sound.play(); + fs.writeJsonSync(path.join(App_Path, "./data/sound.json"), { + sound: false, }); - ul_group.style = 'display: flex;' - Sheikh.style = 'display: none;' - let num = 1 - - for (let item of Quran_json) { - - let numberx = num++ - let url = `${ArrayMp3?.Server}/${String(numberx).padStart(3, 0)}.mp3` - let li_group = document.createElement("li"); - let grid_mp3 = document.createElement('div'); - let number = document.createElement('p'); - let name = document.createElement('p'); - let download = document.createElement('div'); - let audio = document.createElement('audio'); - let icon_mp3 = document.createElement('img'); - let icon_mp3_ddownload = document.createElement('img'); - let a_download = document.createElement('a'); - - ul_group.appendChild(li_group); - li_group.className = 'li_group'; - li_group.appendChild(grid_mp3); - grid_mp3.id = 'grid_mp3'; - grid_mp3.appendChild(number); - number.className = 'number'; - number.innerText = item?.Number; - grid_mp3.appendChild(name); - name.className = 'name'; - name.innerText = item?.Name; - grid_mp3.appendChild(download); - download.id = 'download'; - download.appendChild(icon_mp3); - icon_mp3.className = 'icon_mp3'; - icon_mp3.id = `icon_mp3_${item?.Number}` - icon_mp3.src = dark_mode ? '../public/icon/play.png' : '../public/icon/dark/play.png'; - download.appendChild(a_download); - a_download.id = `a_download_${item?.Number}` - a_download.href = url - a_download.download = `${item?.Name}_${ArrayMp3?.name}.mp3` - a_download.appendChild(icon_mp3_ddownload); - icon_mp3_ddownload.className = 'icon_mp3_ddownload'; - icon_mp3_ddownload.id = `icon_mp3_ddownload_${item?.Number}` - icon_mp3_ddownload.src = dark_mode ? '../public/icon/download.png' : '../public/icon/dark/download.png'; - download.appendChild(audio); - audio.id = `start_mp3_${numberx}` - audio.src = url - audio.preload = 'none' - audio.autoplay = false - audio.volume = volume ? volume : 1 - } - - let icon_mp3 = document.getElementsByClassName('icon_mp3'); - let item_icon_mp3 = Array.from(icon_mp3); - let number = 1 - - item_icon_mp3.forEach(event => { - - let id_mp3 = event.id - let item = number++; - let icon_mp3 = document.getElementById(`icon_mp3_${item}`); - icon_mp3.addEventListener('click', async event => { - - - let sound_json = fs.readJsonSync(path.join(App_Path, './data/sound.json')); - let ArrayMp3 = mp3quran_json.find(e => e?.id.toString() === Sheikh_true); - let url = `${ArrayMp3?.Server}/${String(item).padStart(3, 0)}.mp3` - let id = id_mp3.split('icon_mp3_')[1]; - let sound = document.getElementById(`start_mp3_${id}`); - - if (sound_json?.sound) { - - icon_mp3.src = dark_mode ? '../public/icon/pause.png' : '../public/icon/dark/pause.png'; - sound.play() - fs.writeJsonSync(path.join(App_Path, './data/sound.json'), { sound: false }); - } - - - - else { - icon_mp3.src = dark_mode ? '../public/icon/play.png' : '../public/icon/dark/play.png'; - sound.pause() - fs.writeJsonSync(path.join(App_Path, './data/sound.json'), { sound: true }); - } - - }); - + } else { + icon_mp3.src = dark_mode + ? "../public/icon/play.png" + : "../public/icon/dark/play.png"; + sound.pause(); + fs.writeJsonSync(path.join(App_Path, "./data/sound.json"), { + sound: true, }); - + } }); - + }); + }); + }); + // Search bar logic + let searchInput = document.getElementById("search-input"); + + searchInput.addEventListener("input", function () { + let searchValue = searchInput.value.toLowerCase(); + let sheikhs = Array.from(document.getElementById("Sheikh").children); + + sheikhs.forEach(function (li) { + let sheikhName = li.querySelector("#Sheikh_name").innerText.toLowerCase(); + let sheikhId = li.getAttribute("data-sheikh-id"); + + let matchesSearch = sheikhName.includes(searchValue); + let matchesFavorite = !showOnlyFavorites || favorites[sheikhId]; + + if (matchesSearch && matchesFavorite) { + li.style.display = "flex"; + } else { + li.style.display = "none"; + } }); - // Search bar logic - let searchInput = document.getElementById('search-input'); + }); - searchInput.addEventListener('input', function () { - let searchValue = searchInput.value.toLowerCase(); - let sheikhs = Array.from(document.getElementById('Sheikh').children); + // Favorite filter button logic + let favoriteFilterBtn = document.getElementById("favorite-filter-btn"); - sheikhs.forEach(function (li) { - let sheikhName = li.querySelector('#Sheikh_name').innerText.toLowerCase(); + function filterFavorites() { + let sheikhs = Array.from(document.getElementById("Sheikh").children); + let searchValue = searchInput.value.toLowerCase(); - if (sheikhName.includes(searchValue)) { - li.style.display = 'flex'; - } else { - li.style.display = 'none'; - } - }); + sheikhs.forEach(function (li) { + let sheikhId = li.getAttribute("data-sheikh-id"); + let sheikhName = li.querySelector("#Sheikh_name").innerText.toLowerCase(); + + let matchesSearch = sheikhName.includes(searchValue); + let matchesFavorite = !showOnlyFavorites || favorites[sheikhId]; + + if (matchesSearch && matchesFavorite) { + li.style.display = "flex"; + } else { + li.style.display = "none"; + } }); + } + favoriteFilterBtn.addEventListener("click", function () { + showOnlyFavorites = !showOnlyFavorites; + if (showOnlyFavorites) { + favoriteFilterBtn.classList.add("active"); + favoriteFilterBtn.title = "عرض الكل"; + } else { + favoriteFilterBtn.classList.remove("active"); + favoriteFilterBtn.title = "عرض المفضلة"; + } -} \ No newline at end of file + filterFavorites(); + }); +}; diff --git a/src/public/css/quran_mp3.css b/src/public/css/quran_mp3.css index 9f2f912..673debe 100644 --- a/src/public/css/quran_mp3.css +++ b/src/public/css/quran_mp3.css @@ -1,190 +1,278 @@ #icon_menu_mp3 { - background-color: var(--background_div_hover); + background-color: var(--background_div_hover); } #quran_mp3 { - padding-top: 30px; - padding-right: 20px; - margin-top: 10px; - width: 100%; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -o-user-select: none; - user-select: none; + padding-top: 30px; + padding-right: 20px; + margin-top: 10px; + width: 100%; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; } #ul_group { - display: flex; - flex-direction: row; - flex-wrap: wrap; - justify-content: center; - direction: rtl; + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: center; + direction: rtl; } .li_group { - list-style: none; - text-align: center; - margin: 10px 10px 10px 10px; - background-color: var(--background_div); - width: 350px; - height: 30px; - border-radius: 8px; - align-items: center; - padding: 10px; - box-shadow: 0px 0px 10px 0px #00000010; + list-style: none; + text-align: center; + margin: 10px 10px 10px 10px; + background-color: var(--background_div); + width: 350px; + height: 30px; + border-radius: 8px; + align-items: center; + padding: 10px; + box-shadow: 0px 0px 10px 0px #00000010; } .li_group:hover { - background-color: var(--background_div_hover); + background-color: var(--background_div_hover); } #grid_mp3 { - display: grid; - grid-template-columns: 1fr 1fr 1fr; - direction: rtl; - align-items: center; - justify-items: center; - text-align: center; + display: grid; + grid-template-columns: 1fr 1fr 1fr; + direction: rtl; + align-items: center; + justify-items: center; + text-align: center; } .name { - color: var(--white-div); - font-size: 18px; - margin-top: 5px; + color: var(--white-div); + font-size: 18px; + margin-top: 5px; } .number { - margin-top: 0px; - color: var(--color_font_grey); + margin-top: 0px; + color: var(--color_font_grey); } .icon_mp3, .icon_mp3_ddownload { - width: 15%; - margin-left: 3px; - margin-right: 3px; - margin-bottom: 10px; - cursor: pointer; + width: 15%; + margin-left: 3px; + margin-right: 3px; + margin-bottom: 10px; + cursor: pointer; } #Sheikh { - display: flex; - flex-direction: row; - flex-wrap: wrap; - justify-content: center; - direction: rtl; + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: center; + direction: rtl; } #Sheikh_name { - color: var(--white-div); - font-size: 19px; - margin: 0 0 0 0; - + color: var(--white-div); + font-size: 19px; + margin: 0 0 0 0; + text-align: center; } #Sheikh_rewaya { - color: var(--color_font_grey); - font-size: 12px; - margin: 0 0 0 0; - direction: rtl; - + color: var(--color_font_grey); + font-size: 12px; + margin: 0 0 0 0; + direction: rtl; + text-align: center; } #Sheikh li { - /* width: max-content; */ - list-style: none; - margin: 10px 10px 10px 10px; - background-color: var(--background_div); - box-shadow: 0px 0px 10px 0px #00000010; - width: 350px; - height: auto; - border-radius: 8px; - padding: 5px; - justify-content: center; - cursor: pointer; + /* width: max-content; */ + list-style: none; + margin: 10px 10px 10px 10px; + background-color: var(--background_div); + box-shadow: 0px 0px 10px 0px #00000010; + width: 350px; + height: auto; + border-radius: 8px; + padding: 5px; + justify-content: center; + cursor: pointer; } #Sheikh li:hover { - background-color: var(--background_div_hover); + background-color: var(--background_div_hover); } #reader { - /* width: max-content; */ - width: 100%; - display: inline-flex; - justify-content: space-evenly; - align-items: center; - padding: 0; - margin-top: 0px; - margin-bottom: 15px; + /* width: max-content; */ + width: 100%; + display: grid; + grid-template-columns: auto 1fr auto; + gap: 15px; + align-items: center; + padding: 0 10px; + margin-top: 0px; + margin-bottom: 15px; +} + +.reader-info { + display: flex; + flex-direction: column; + align-items: center; + flex-grow: 1; +} + +.favorite-icon { + width: 25px; + height: 25px; + cursor: pointer; + transition: transform 0.2s ease; + flex-shrink: 0; +} + +.favorite-icon:hover { + transform: scale(1.2); } #reader_name { - text-align: center; - margin-top: 0px; - margin-bottom: 10px; - font-family: 'Quran'; - color: var(--color_font_grey); - font-size: 18px; + text-align: center; + margin-top: 0px; + margin-bottom: 10px; + font-family: "Quran"; + color: var(--color_font_grey); + font-size: 18px; +} + +.reader-label { + text-align: center; + margin: 0; + font-family: "Quran"; + color: var(--color_font_grey); + font-size: 18px; + white-space: nowrap; } #quran_mp3_back { - display: none; - margin-top: 20px; - width: 30px; - cursor: pointer; - right: 100px; - position: absolute; + display: none; + margin-top: 20px; + width: 30px; + cursor: pointer; + right: 100px; + position: absolute; } #quran_mp3_name_Sheikh { - display: none; - width: 60%; - text-align: center; - margin-left: auto; - margin-right: auto; - margin-bottom: 20px; - color: var(--white-div); - padding: 10px; - background-color: var(--background_div); - border-radius: 10px; - box-shadow: 0px 0px 10px 0px #00000010; + display: none; + width: 60%; + text-align: center; + margin-left: auto; + margin-right: auto; + margin-bottom: 20px; + color: var(--white-div); + padding: 10px; + background-color: var(--background_div); + border-radius: 10px; + box-shadow: 0px 0px 10px 0px #00000010; } - #search-bar { - display: flex; - justify-content: center; - align-items: center; - margin-top: 20px; - margin-right: 80px; - position: fixed; - top: 0; - left: 0; - right: 0; - padding: 10px; - z-index: 9999; + display: flex; + justify-content: center; + align-items: center; + gap: 10px; + margin-top: 20px; + margin-right: 80px; + position: fixed; + top: 0; + left: 0; + right: 0; + padding: 10px; + z-index: 9999; } #search-bar input[type="text"] { - direction: rtl; - text-align: center; - width: 300px; - height: 30px; - padding: 5px; - border-radius: 5px; - border: 1px solid #ccc; - font-size: 14px; + direction: rtl; + text-align: center; + width: 300px; + height: 30px; + padding: 5px; + border-radius: 5px; + border: 1px solid #ccc; + font-size: 14px; } #search-bar input[type="text"]:focus { - outline: none; - border-width: 2px; - /* Remove the default focus outline */ - border-color:var(--background_div_hover);; - /* Change the border color when selected */ - box-shadow: 0 0 5px var(--background_div_hover); - /* Add a box shadow when selected */ -} \ No newline at end of file + outline: none; + border-width: 2px; + /* Remove the default focus outline */ + border-color: var(--background_div_hover); + /* Change the border color when selected */ + box-shadow: 0 0 5px var(--background_div_hover); + /* Add a box shadow when selected */ +} + +#favorite-filter-btn { + width: 40px; + height: 40px; + border-radius: 5px; + border: 1px solid #ccc; + background-color: var(--background_div); + cursor: pointer; + display: flex; + justify-content: center; + align-items: center; + transition: all 0.3s ease; +} + +#favorite-filter-btn:hover { + background-color: var(--background_div_hover); + box-shadow: 0 0 5px var(--background_div_hover); +} + +#favorite-filter-btn.active { + background-color: var(--background_div_hover); + border-color: var(--background_div_hover); + box-shadow: 0 0 10px var(--background_div_hover); +} + +#favorite-filter-icon { + width: 20px; + height: 20px; +} + +.favorite-icon { + width: 25px; + height: 25px; + cursor: pointer; + margin-right: 10px; + transition: transform 0.2s ease; +} + +.favorite-icon:hover { + transform: scale(1.2); +} + +#reader { + /* width: max-content; */ + width: 100%; + display: inline-flex; + justify-content: space-between; + align-items: center; + padding: 0 10px; + margin-top: 0px; + margin-bottom: 15px; +} + +.reader-info { + display: flex; + flex-direction: column; + align-items: center; + flex-grow: 1; +} diff --git a/src/public/icon/dark/heart-solid.svg b/src/public/icon/dark/heart-solid.svg new file mode 100644 index 0000000..bacc178 --- /dev/null +++ b/src/public/icon/dark/heart-solid.svg @@ -0,0 +1,5 @@ + + + diff --git a/src/public/icon/dark/heart.svg b/src/public/icon/dark/heart.svg new file mode 100644 index 0000000..d77fdc6 --- /dev/null +++ b/src/public/icon/dark/heart.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/public/icon/heart-solid.svg b/src/public/icon/heart-solid.svg new file mode 100644 index 0000000..1401887 --- /dev/null +++ b/src/public/icon/heart-solid.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/public/icon/heart.svg b/src/public/icon/heart.svg new file mode 100644 index 0000000..7d47267 --- /dev/null +++ b/src/public/icon/heart.svg @@ -0,0 +1 @@ + \ No newline at end of file From 52c761def61c0e918c42c6b8f78b0f1aab80a95d Mon Sep 17 00:00:00 2001 From: Mostafa Osama Date: Tue, 2 Dec 2025 16:00:11 +0200 Subject: [PATCH 2/2] refactor: Update favorite button and improve layout for Quran MP3 player --- src/pages/quran_mp3.html | 4 +-- src/preload/preload_modules/quran_mp3.js | 7 ++-- src/public/css/quran_mp3.css | 45 ++++-------------------- 3 files changed, 11 insertions(+), 45 deletions(-) diff --git a/src/pages/quran_mp3.html b/src/pages/quran_mp3.html index 5ce9c72..39ed62f 100644 --- a/src/pages/quran_mp3.html +++ b/src/pages/quran_mp3.html @@ -50,9 +50,9 @@

        placeholder="إبحث عن قارئ" /> - diff --git a/src/preload/preload_modules/quran_mp3.js b/src/preload/preload_modules/quran_mp3.js index 04cd47b..69abe99 100644 --- a/src/preload/preload_modules/quran_mp3.js +++ b/src/preload/preload_modules/quran_mp3.js @@ -32,7 +32,6 @@ module.exports = function quran_mp3(fs, path, App_Path, settings) { for (let item of mp3quran_json) { let li_Sheikh = document.createElement("li"); - let reader_name = document.createElement("p"); let reader = document.createElement("div"); let reader_info = document.createElement("div"); let Sheikh_name = document.createElement("p"); @@ -44,8 +43,6 @@ module.exports = function quran_mp3(fs, path, App_Path, settings) { li_Sheikh.id = li_Sheikh_id; li_Sheikh.className = "li_Sheikh"; li_Sheikh.setAttribute("data-sheikh-id", item?.id); - li_Sheikh.appendChild(reader_name); - reader_name.id = "reader_name"; li_Sheikh.appendChild(reader); reader.id = "reader"; @@ -249,7 +246,7 @@ module.exports = function quran_mp3(fs, path, App_Path, settings) { let matchesFavorite = !showOnlyFavorites || favorites[sheikhId]; if (matchesSearch && matchesFavorite) { - li.style.display = "flex"; + li.style.display = ""; } else { li.style.display = "none"; } @@ -271,7 +268,7 @@ module.exports = function quran_mp3(fs, path, App_Path, settings) { let matchesFavorite = !showOnlyFavorites || favorites[sheikhId]; if (matchesSearch && matchesFavorite) { - li.style.display = "flex"; + li.style.display = ""; } else { li.style.display = "none"; } diff --git a/src/public/css/quran_mp3.css b/src/public/css/quran_mp3.css index 673debe..d7994ed 100644 --- a/src/public/css/quran_mp3.css +++ b/src/public/css/quran_mp3.css @@ -93,7 +93,7 @@ } #Sheikh li { - /* width: max-content; */ + width: max-content; list-style: none; margin: 10px 10px 10px 10px; background-color: var(--background_div); @@ -111,15 +111,13 @@ } #reader { - /* width: max-content; */ + width: max-content; width: 100%; display: grid; - grid-template-columns: auto 1fr auto; - gap: 15px; + grid-template-columns: 1fr 2fr 1fr; + gap: 5px; align-items: center; - padding: 0 10px; - margin-top: 0px; - margin-bottom: 15px; + padding: 10px; } .reader-info { @@ -135,6 +133,7 @@ cursor: pointer; transition: transform 0.2s ease; flex-shrink: 0; + justify-self: center; } .favorite-icon:hover { @@ -219,13 +218,13 @@ } #favorite-filter-btn { - width: 40px; height: 40px; border-radius: 5px; border: 1px solid #ccc; background-color: var(--background_div); cursor: pointer; display: flex; + gap: 5px; justify-content: center; align-items: center; transition: all 0.3s ease; @@ -246,33 +245,3 @@ width: 20px; height: 20px; } - -.favorite-icon { - width: 25px; - height: 25px; - cursor: pointer; - margin-right: 10px; - transition: transform 0.2s ease; -} - -.favorite-icon:hover { - transform: scale(1.2); -} - -#reader { - /* width: max-content; */ - width: 100%; - display: inline-flex; - justify-content: space-between; - align-items: center; - padding: 0 10px; - margin-top: 0px; - margin-bottom: 15px; -} - -.reader-info { - display: flex; - flex-direction: column; - align-items: center; - flex-grow: 1; -}