Skip to content

Commit

Permalink
Update manifest.json and scripts.js, and add opmlhelper.js and settin…
Browse files Browse the repository at this point in the history
…gs.html files
  • Loading branch information
BumpyClock committed Apr 11, 2024
1 parent 9a01834 commit 8071152
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 54 deletions.
2 changes: 1 addition & 1 deletion src/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["./scripts/utils/readability.js","./scripts/utils/masonry.pkgd.js","./scripts/utils/lazysizes.min.js","./scripts/utils/purify.min.js","./scripts/utils/imagesloaded.pkgd.min.js"],
"js": ["./scripts/utils/readability.js","./scripts/utils/masonry.pkgd.js","./scripts/utils/lazysizes.min.js","./scripts/utils/purify.min.js","./scripts/utils/imagesloaded.pkgd.min.js","./scripts/utils/opmlhelper.js"],
"all_frames": true
}],

Expand Down
8 changes: 5 additions & 3 deletions src/scripts.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,10 @@ function initializeMasonry() {
itemSelector: ".card",
columnWidth: ".card",
gutter: 24,
transitionDuration: '0.2s', // set the transition duration
stagger: 10 // set the stagger delay
transitionDuration: '0.12s', // set the transition duration
stagger: 5, // set the stagger delay
fitwidth: true,
isFitWidth: true,
});
document.querySelectorAll(".masonry-item").forEach(item => {
item.addEventListener("load", () => {
Expand All @@ -255,7 +257,7 @@ function initializeMasonry() {
});
const debouncedLayout = debounce(() => {
msnry.layout();
}, 100);
}, 300);
window.addEventListener("resize", debouncedLayout);
}

Expand Down
136 changes: 94 additions & 42 deletions src/scripts/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,46 @@ function setupEventListener(id, eventType, eventHandler) {
element.addEventListener(eventType, eventHandler);
}

async function updateSubscribedFeeds(feedURLs) {
// If feedURLs is not an array, convert it into an array with a single element
if (!Array.isArray(feedURLs)) {
feedURLs = [feedURLs];
}

const feeds = getSubscribedFeeds();

for (let feedURL of feedURLs) {
// Check if the feed URL already exists in the subscribedFeeds array
if (!feeds.subscribedFeeds.includes(feedURL)) {
feeds.subscribedFeeds.push(feedURL);
} else {
console.log(`Feed ${feedURL} is already subscribed.`);
}
}

setSubscribedFeeds(feeds.subscribedFeeds);
await clearCache();
refreshFeeds();
await displaySubscribedFeeds();
}

async function setupSubscriptionForm() {
setupEventListener("subscription-form", "submit", async event => {
setupEventListener("subscription-form", "submit", async (event) => {
event.preventDefault();
const form = event.target;
const feedURL = form.elements["feed-url"].value;
const feeds = getSubscribedFeeds();
feeds.subscribedFeeds.push(feedURL);
setSubscribedFeeds(feeds.subscribedFeeds);
await updateSubscribedFeeds(feedURL);
form.reset();
await clearCache();
refreshFeeds();
await displaySubscribedFeeds();
});
}

document.getElementById("upload-button").addEventListener("click", function () {
console.log("upload button clicked");
var fileInput = document.getElementById("opml-upload");
var file = fileInput.files[0];
handleFileUpload(file);
});

function setupUnsubscribeButton(elem, feedUrl) {
elem.addEventListener("click", async () => {
removeFeed(feedUrl);
Expand All @@ -43,8 +68,8 @@ async function displaySubscribedFeeds() {
const listfragment = document.createDocumentFragment();

const feedPromises = feedDetails.map(async (detail, index) => {
if ( feedDetails[index].feedUrl != null) {
const listItem = await createListItem(detail, feedDetails[index].feedUrl);
if (feedDetails[index].feedUrl != null) {
const listItem = await createListItem(detail, feedDetails[index].feedUrl);
listfragment.appendChild(listItem);
}
});
Expand All @@ -56,45 +81,68 @@ async function displaySubscribedFeeds() {
});
}
async function createListItem(detail, feedURL) {
const listItem = createElement("div", "list-item");
const bgImageContainer = createElement("div", "bg");
const faviconSrc = detail.favicon || await getSiteFavicon(new URL(feedURL).hostname);
const bgImage = createElement("img", "bg lazyload", {"data-src": faviconSrc});
const noiseLayer = createElement("div", "noise");
const websiteInfo = createElement("div", "website-info");
const favicon = createElement("img", "site-favicon", {src: faviconSrc, alt: `${detail.siteTitle} Favicon`});
const websiteName = createElement("h3", "", {}, detail.siteTitle || detail.feedTitle);
const feedTitle = createElement("p", "feed-title", {}, detail.feedTitle || detail.siteTitle);
const feedUrl = createElement("p", "feed-url", {}, feedURL);
const removeButton = createElement("button", "remove-feed-button");
const removeButtonText = createElement("p", "unsubscribe-button", {}, "Unsubscribe");

bgImageContainer.append(bgImage, noiseLayer);
websiteInfo.append(favicon, websiteName, feedTitle, feedUrl);
removeButton.appendChild(removeButtonText);
listItem.append(websiteInfo, removeButton, bgImageContainer);

setupEventListener(removeButton, "click", async () => {
removeFeed(feedURL);
await clearCache();
displaySubscribedFeeds();
});

return listItem;
}
const listItem = createElement("div", "list-item");
const bgImageContainer = createElement("div", "bg");
const faviconSrc =
detail.favicon || (await getSiteFavicon(new URL(feedURL).hostname));
const bgImage = createElement("img", "bg lazyload", {
"data-src": faviconSrc
});
const noiseLayer = createElement("div", "noise");
const websiteInfo = createElement("div", "website-info");
const favicon = createElement("img", "site-favicon", {
src: faviconSrc,
alt: `${detail.siteTitle} Favicon`
});
const websiteName = createElement(
"h3",
"",
{},
detail.siteTitle || detail.feedTitle
);
const feedTitle = createElement(
"p",
"feed-title",
{},
detail.feedTitle || detail.siteTitle
);
const feedUrl = createElement("p", "feed-url", {}, feedURL);
const removeButton = createElement("button", "remove-feed-button");
const removeButtonText = createElement(
"p",
"unsubscribe-button",
{},
"Unsubscribe"
);

bgImageContainer.append(bgImage, noiseLayer);
websiteInfo.append(favicon, websiteName, feedTitle, feedUrl);
removeButton.appendChild(removeButtonText);
listItem.append(websiteInfo, removeButton, bgImageContainer);

setupEventListener(removeButton, "click", async () => {
removeFeed(feedURL);
await clearCache();
displaySubscribedFeeds();
});

function createElement(tag, className, attributes = {}, textContent = '') {
return listItem;
}

function createElement(tag, className, attributes = {}, textContent = "") {
const element = document.createElement(tag);
element.className = className;
if (typeof attributes === 'object' && attributes !== null) {
Object.keys(attributes).forEach(key => element.setAttribute(key, attributes[key]));
if (typeof attributes === "object" && attributes !== null) {
Object.keys(attributes).forEach((key) =>
element.setAttribute(key, attributes[key])
);
}
element.textContent = textContent;
return element;
}

function setupEventListener(element, eventType, eventHandler) {
if (typeof element === 'string') {
if (typeof element === "string") {
element = document.getElementById(element);
}
element.addEventListener(eventType, eventHandler);
Expand All @@ -113,7 +161,11 @@ function setupFeedDiscoveryToggle() {
}

function setupSearchPreferenceToggle() {
setupToggle("search-preference-toggle", getSearchPreference, setSearchPreference);
setupToggle(
"search-preference-toggle",
getSearchPreference,
setSearchPreference
);
}

async function setupApiUrlFormEventHandler() {
Expand All @@ -122,12 +174,12 @@ async function setupApiUrlFormEventHandler() {
apiUrlInput.value = await getApiUrl();
const apiUrlSubmitButton = document.getElementById("apiUrl-submit-button");

apiUrlForm.addEventListener("submit", event => {
apiUrlForm.addEventListener("submit", (event) => {
event.preventDefault();
setApiUrl(apiUrlInput.value);
});

apiUrlSubmitButton.addEventListener("click", () => {
setApiUrl(apiUrlInput.value);
});
}
}
31 changes: 31 additions & 0 deletions src/scripts/utils/opmlhelper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

// Function to handle file upload
function handleFileUpload(file) {

console.log("🚀 ~ handleFileUpload ~ file", file);
// Check if the file is an OPML file
if (file) {
const reader = new FileReader();
reader.onload = (e) => {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(e.target.result, "text/xml");

let urls = [];
const outlines = xmlDoc.getElementsByTagName("outline");
for (let i = 0; i < outlines.length; i++) {
const outline = outlines[i];
if (outline.getAttribute("type") === "rss") {
const xmlUrl = outline.getAttribute("xmlUrl");
if (xmlUrl) {
urls.push(xmlUrl);
}
}
}
console.log("Imported URLs:", urls);

updateSubscribedFeeds(urls); };
reader.readAsText(file);
}
// Return an empty array if the file is not an OPML file
return [];
}
18 changes: 17 additions & 1 deletion src/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,27 @@
<h1>Settings</h1>
<h2>Subscribed Feeds</h2>
<div id="subscribed-feeds-list" class="subscribed-feeds-list"></div>

<h2>Add a new feed</h2>
<div id="add-a-url-container" class="settings-section">


<form id="subscription-form" class="subscription-form">
<input type="url" id="feed-url" placeholder="Enter feed URL" required>
<button type="submit">Subscribe</button>
</form>

</div>

<div id="opml-import-container" class="settings-section">
<div class="infoContainer">
<h3>OPML Import</h3>
<p>Import an OPML file to subscribe to multiple feeds at once</p>
</div>
<form id="opml-import-form" class="opml-import-form">
<input type="file" id="opml-file" accept=".opml" required>
<button type="submit">Import</button>
</form>
</div>
<!-- ... -->
<div id="display-preferences-container" class="display-preferences-container">
<h2>Display Preferences</h2>
Expand Down Expand Up @@ -85,6 +100,7 @@ <h4>rss-to-json</h4>
<script src="./scripts/utils/lazysizes.min.js" defer></script>
<script src="./scripts/utils/purify.min.js" defer></script>
<script src="./scripts/settings.js" defer></script>
<script src="./scripts/utils/opmlhelper.js" defer></script>
<script src="scripts.js" defer></script>


Expand Down
16 changes: 9 additions & 7 deletions src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ body > :not(.background-image-container)::selection {
break-inside: avoid;
-webkit-backdrop-filter: var(--blur);
backdrop-filter: var(--blur);
transition: var(--transition-standard)
transition: var(--transition-standard);
}


Expand Down Expand Up @@ -605,23 +605,22 @@ body {
@media screen and (min-width:720px) {
.grid-sizer {
width: 20%;
max-width: 45%
max-width: 400px;
}
.card {
max-width: 45%;
max-width: 400px;
min-width: 320px
}
.gutter {
width: 2%
}
}
@media screen and (min-width:900px) {
@media screen and ((max-width:720px) and (min-width:900px)) {
.grid-sizer {
width: 20%;
max-width: 35%
}
.card {
max-width: 30%;
min-width: 280px
}
}
Expand All @@ -631,15 +630,18 @@ body {
max-width: 20%
}
.card {
max-width: 15%;
min-width: 340px

}
}



#feed-container {
opacity: 0;
margin: 0 auto;
border-radius: 24px;
max-width: 2200px;
/* max-width: 1200px; */
z-index: 4
}
#feed-container::after {
Expand Down

0 comments on commit 8071152

Please sign in to comment.