Blogger Feed Reader
ဒါကတော့ Blogger website တွေထဲကမှ မိမိကြိုက် နှစ်သက်တဲ့ blogger website ရဲ့ post များကို feed အဖြစ်ယူ၍ တနေရာထဲမှာကိုတစုတစည်းထဲပြသလို့ရ အောင် ပြုလုပ်ထားတဲ့ blog feed လေးပါ။ကြိုက် နှစ်သက်လို့ အသုံးပြုချင်တယ်ဆိုရင် အောက်မှာပြထားတဲ့အတိုင်းလုပ်ဆောင်၍ထည့်သွင်းအသုံးပြုနိုင်ပါသည်။
Online
Online အနေနဲ့အသုံးပြုချင်ရင်အောက်က code ကိုအသုံးပြုပါ
- မိမိ blog site ကို account အရင်ဝင်ပါ
- dashboard ထဲက Pages ကိုနှိပ်
- ➕ အိုင်ကွန်ကိုနှိပ်
- 🖍️ အိုင်ကွန်ကိုနှိပ်၍ < > HTML view ကိုရွေးချယ်၍နှိပ်ပါ
- အောက်က code ကို copy ယူပြီးကူးထည့်ပေးပါ
- save ကိုနှိပ်ပြီးပါပြီ
<label for="feedUrl">Enter Blogger Feed URL:</label>
<span class="feed-btn">
<input type="text" id="feedUrl" placeholder="https://yourblog.blogspot.com" />
<button id="loadFeedBtn">Load Feed</button>
</span>
<div id="feedBox"></div>
<div id="pagination"></div>
<div id="postModal" class="modal">
<div class="modal-box">
<div class="modal-header">
<span id="closeModal" class="closeBtn">×</span>
<h2 id="modalTitle"></h2>
</div>
<div id="modalBody" class="modal-content"></div>
</div>
</div>
<style>
body {font-family: Arial, sans-serif;padding:20px;background:#f6f7fb;margin:0;color:#333;}
h1 {text-align:center;color:#2196F3;}
.feed-btn{display:flex;gap:10px;width: 100%;flex-direction:row;}
.feed-btn input[type="text"], .feed-btn button {font-family:monospace;font-size:14px;margin-bottom:10px;padding:8px 10px;width:100%;border:none;border-radius: 8px;box-sizing:border-box;resize:vertical;}
.feed-btn button {background:#0066ff;color:#fff;cursor:pointer;}
#feedBox{display:grid;grid-template-columns:1fr;gap:5px;margin:10px auto;max-width:900px;padding:0 10px;}
.feed-item{margin-bottom:10px;padding:12px;background:white;border-radius:6px;box-shadow:0 2px 6px rgba(0,0,0,0.1);transition: box-shadow 0.3s ease;}
.feed-item:hover {box-shadow:0 4px 12px rgba(0,0,0,0.15);}
.feed-item a {font-weight:200;font-size:18px;color:#2196F3;text-decoration:none;}
.feed-item small {color:#888;font-size:13px;}
.feed-img{width:100%;height:auto;margin-bottom:8px;border-radius:4px;object-fit:cover;}
.modal {display:none;position:fixed;z-index:1000;inset:0;background:rgba(0,0,0,0.6);padding:0;overflow-y:auto;}
.modal-box {background:#fff;width:95%;max-width:680px;margin:40px auto;border-radius:12px;box-shadow:0 5px 15px rgba(0,0,0,0.3);max-height:90vh;display:flex;flex-direction:column;overflow:hidden;}
.modal-header {padding:15px;border-bottom:1px solid #eee;position:sticky;top:0;background:white;z-index:10;display:flex;align-items:center;}
.modal-header h2 {font-size:18px;margin:0;flex:1;}
.closeBtn {font-size:26px;cursor:pointer;padding:0 10px;color:#666;}
.closeBtn:hover {color:#000;}
.modal-content {padding:18px;overflow-y:auto;max-height:calc(90vh - 60px);-webkit-overflow-scrolling:touch;scroll-behavior:smooth;}
.modal-content img {max-width:100%;height:auto;border-radius:6px;margin-bottom:10px;}
.modal-content * {word-wrap:break-word;}
#pagination {margin:25px 0;text-align:center;}
#pagination button {padding:8px 15px;font-size:14px;margin:0 10px;background:#2196F3;color:white;border:none;border-radius:5px;cursor:pointer;box-shadow:0 2px 6px rgba(33,150,243,0.3);}
#pagination span {font-weight:bold;margin:0 10px;}
@media (min-width: 720px){
#feedBox {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 1024px){
#feedBox {
grid-template-columns: repeat(3, 1fr);
}
}
@media (min-width: 1280px){
#feedBox {
grid-template-columns: repeat(4, 1fr);
}
}
@media (min-width: 1536px){
#feedBox {
grid-template-columns: repeat(5, 1fr);
}
}
@media (max-width: 600px){
.feed-btn {
flex-direction:column;
}
}
</style>
<script>//<![CDATA[
const feedBox = document.getElementById('feedBox');
const feedUrlInput = document.getElementById('feedUrl');
const loadBtn = document.getElementById('loadFeedBtn');
const STORAGE_KEY = 'savedFeedUrl';
let currentPage = 1;
let perPage = 10;
// Pagination buttons
const paginationBox = document.getElementById("pagination");
async function fetchFeed(url, page = 1) {
try {
const startIndex = (page - 1) * perPage + 1;
const rss =
url.replace(/\/$/, '') +
`/feeds/posts/default?alt=rss&max-results=${perPage}&start-index=${startIndex}`;
const api = `https://api.rss2json.com/v1/api.json?rss_url=${encodeURIComponent(rss)}`;
const res = await fetch(api);
if (!res.ok) throw new Error('Network error');
return await res.json();
} catch (e) {
console.error(e);
return null;
}
}
function extractImage(desc) {
const match = desc.match(/<img[^>]+src="([^">]+)"/);
return match ? match[1] : "";
}
function renderFeed(items) {
if (!items || items.length === 0) {
feedBox.innerHTML = "<p>No posts found.</p>";
return;
}
feedBox.innerHTML = "";
items.forEach(item => {
const img = item.thumbnail || extractImage(item.description);
const div = document.createElement("div");
div.className = "feed-item";
div.innerHTML = `
${img ? `<img src="${img}" class="feed-img">` : ""}
<a href="#" data-content="${encodeURIComponent(item.description)}">${item.title}</a><br>
<small>${new Date(item.pubDate).toLocaleDateString()}</small>
`;
feedBox.appendChild(div);
});
document.querySelectorAll(".feed-item a").forEach(link => {
link.onclick = e => {
e.preventDefault();
openModal(decodeURIComponent(link.dataset.content));
};
});
}
function renderPagination() {
paginationBox.innerHTML = `
<button id="prevBtn">Previous</button>
<span>Page ${currentPage}</span>
<button id="nextBtn">Next</button>
`;
document.getElementById("prevBtn").onclick = () => {
if (currentPage > 1) {
currentPage--;
loadFeed(feedUrlInput.value, currentPage);
}
};
document.getElementById("nextBtn").onclick = () => {
currentPage++;
loadFeed(feedUrlInput.value, currentPage);
};
}
async function loadFeed(url, page = 1) {
feedBox.innerHTML = "<p>Loading...</p>";
const data = await fetchFeed(url, page);
if (data && data.items) {
renderFeed(data.items);
renderPagination();
} else {
feedBox.innerHTML = "<p>Failed to load feed.</p>";
}
}
loadBtn.onclick = () => {
const url = feedUrlInput.value.trim();
if (!url) {
alert("Please enter a Blogger URL");
return;
}
currentPage = 1;
saveFeedUrl(url);
loadFeed(url, 1);
};
function saveFeedUrl(url) {
localStorage.setItem(STORAGE_KEY, url);
}
function getSavedFeedUrl() {
return localStorage.getItem(STORAGE_KEY);
}
// Load saved
window.onload = () => {
const saved = getSavedFeedUrl();
if (saved) {
feedUrlInput.value = saved;
loadFeed(saved, 1);
}
};
// Modal
const modal = document.getElementById("postModal");
const modalBody = document.getElementById("modalBody");
document.getElementById("closeModal").onclick = () => (modal.style.display = "none");
window.onclick = e => { if (e.target === modal) modal.style.display = "none"; };
function openModal(content) {
modalBody.innerHTML = content;
modal.style.display = "block";
}
//]]></script>
Offline
Offline အနေနဲ့အသုံးပြုချင်ရင်အောက်က link ကိုနှိပ်ပါ
- https://kokhinmaungwin.github.io/Blogger-Feed-Reader-PWA
Install Appကိုနှိပ်- install ကိုနှိပ်
- offline app အဖြစ်အသုံးပြုလို့ရပါပြီ
Offline အနေနဲ့အသုံးပြုမည်ဆိုပါက အောက်ကအချက်အလက်အချို့သိထားရန်လိုအပ်ပါသည်။
Browser Cache ရှင်းရင် PWA Offline မအောင်မြင်နိုင်ခြင်း အကြောင်း သိထားစေလိုပါတယ်
Progressive Web App (PWA) တွေဟာ Service Worker နဲ့ browser cache ကိုအမြဲတမ်းအသုံးပြုပြီး Offline မှာပါ အဆင်ပြေစွာ အသုံးပြုနိုင်အောင် ဒီဇိုင်းလုပ်ထားတာပါ။ ဒါပေမယ့် အသုံးပြုသူတွေ Browser Cache ကိုရှင်းလိုက်ရင် Offline mode အတွက် အချို့ assets တွေ ပျောက်ကွယ်သွားပြီး အလုပ်မလုပ်နိုင်ခြင်း၊ Error တွေဖြစ်တတ်ပါတယ်။
ဘာကြောင့် Browser Cache ရှင်းရင် ပြဿနာဖြစ်သလဲ?
Browser Cache ဆိုတာ Browser က locally သိမ်းဆည်းထားတဲ့ JavaScript, CSS, HTML ဖိုင်တွေကို ဆိုလိုပါတယ်။ Service Worker က အခြား cache storage (Cache Storage API) ကိုအသုံးပြုပြီး ထပ်မံ သိမ်းဆည်းပေမယ့် Browser Cache မှာဖိုင်တွေမရှိတော့ရင် တချို့ assets ကို မရနိုင်တဲ့အခြေအနေဖြစ်တတ်ပါတယ်။
ဒီအတွက်အချက်တွေရှိပါတယ်
Browser Cache ရှင်းလိုက်ရင် အသုံးပြုတဲ့ assets တွေ ပျောက်ကွယ်သွားတတ်သည်
Service Worker cache က သာမက browser cache ကိုတစ်ခါတစ်ရံ အသုံးချတာကြောင့် Offline မှာ အသုံးပြုချိန်မှာ လိုအပ်တဲ့ assets မတွေ့လို့ error ဖြစ်တတ်တယ်
ဒီလိုဖြစ်ရင် App က ပြန်တက်ဖို့ (reload) နှင့် Internet ပြန်ဖွင့်ဖို့လိုတတ်တယ်
Browser Cache ကိုရှင်းခြင်းက PWA Offline Usage အတွက်အန္တရာယ်ရှိတတ်ပါသဖြင့် လိုအပ်မှသာလုပ်ပါ
Cache ရှင်းလိုက်ရင် app offline mode မှာ အဆင်မပြေဖြစ်နိုင်တာနဲ့တင်သိထားပြီးပြဿနာဖြစ်လာရင် Internet ဖွင့်ပြန်ပြီး reload လုပ်ပါ
အခုအချက်တွေကို နားလည်သိရှိထားပြီဆိုရင် PWA ကို ပိုမိုကောင်းမွန်စွာအသုံးပြုနိုင်ပါသည်

