redsave

adds feature in libreddit/redlib to save/unsave posts, which is saved in localStorage as post ids (won't work over incognito sessions)

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==UserScript==
// @name         redsave
// @namespace    http://tampermonkey.net/
// @version      1
// @description  adds feature in libreddit/redlib to save/unsave posts, which is saved in localStorage as post ids (won't work over incognito sessions)
// @author       @yokelman
// @match        https://libreddit.kavin.rocks/*
// @icon         https://libreddit.kavin.rocks/favicon.ico
// @grant        none
// @license      GNU AGPL-3.0
// ==/UserScript==

(function() {
    // !!!!!! THE SCRIPT CAN ACT WEIRDLY IF USING MULTIPLE TABS TO BROWSE THE SITE SINCE AFAIK LOCALSTORAGE ISN'T SYNCHRONIZED IN REAL TIME TO WORK ACROSS MULTIPLE TABS
    // !!!!!! EXAMPLE: IF YOU SAVE POST A AND B ON THE MAIN PAGE, THEN OPEN POST A ON A NEW TAB, THEN UNSAVE POST B ON THE MAIN PAGE TAB AND THEN UNSAVE POST A THROUGH THE NEWLY OPENED TAB (WHICH ONLY CONTAINS A)...
    // !!!!!! POST B (WHICH SHOULD HAVE BEEN UNSAVED THROUGH MAIN PAGE TAB) WILL STILL BE IN LOCALSTORAGE
    // !!!!!! MORAL: DON'T GO SAVING/UNSAVING ON MULTIPLE PAGES AS FAR AS POSSIBLE, AND AFTER SAVING/UNSAVING ON ONE TAB IDEALLY RELOAD ALL THE OTHER TABS

    // tested on v0.30.1, v0.31.0, v0.31.2, v0.34.0 on both libreddit and redlib which should be the majority of public instances

    'use strict';

    var domain = "https://libreddit.kavin.rocks/";

    // load savedPosts from localStorage and handle if empty
    var savedPosts = window.localStorage.getItem("savedPosts");
    if (!savedPosts) {
        savedPosts = [];
    }
    else {
        savedPosts = savedPosts.split(",");
        // if localStorage has savedPosts="", splitting gives you [""], don't want that empty string as an element
        if (!savedPosts[0]) {
            savedPosts.splice(0);
        }
    }

    // adds an option to view saved posts when user clicks on Feeds at top left corner (if saved posts exist)
    if (savedPosts.length) {
        var link = document.createElement("a");
        link.textContent = "Saved";
        link.onclick = showSaved;
        if (document.getElementById("feed_list").querySelectorAll("p").length == 2) {
            document.getElementById("feed_list").insertBefore(link, document.getElementById("feed_list").children[4]);
        }
        else {
            document.getElementById("feed_list").appendChild(link);
        }
    }

    // manage saving/unsaving when save/unsave button is clicked
    function manageSaved(id) {
        if (document.getElementsByClassName(id)[0].textContent == "save") {
            savedPosts.push(id);
            document.getElementsByClassName(id)[0].textContent = "unsave";
        }
        else {
            savedPosts.splice(savedPosts.indexOf(id), 1);
            document.getElementsByClassName(id)[0].textContent = "save";
        }
        window.localStorage.setItem("savedPosts", savedPosts);
    }

    var post_footer = document.getElementsByClassName("post_footer");

    // go post by post and add the save/unsave element
    for (var i = 0; i < post_footer.length; i++) {
        var save = document.createElement("a");
        // the below is basically a somehow-works hack to get the post id (because the page could either have a collection of posts, or just a single post and i don't want to code for different cases) - can definitely lead to errors if site layout changes
        var postId = post_footer[i].querySelector("a").href.split("/")[6];
        if ((savedPosts.includes(postId))) {
            save.textContent = "unsave";
        }
        else {
            save.textContent = "save";
        }
        save.style = "font-weight: bold;";
        save.className = post_footer[i].querySelector("a").href.split("/")[6];
        (function(localPostId) {save.onclick = function() {manageSaved(localPostId);};})(postId);
        // if url includes comments, it means you're viewing an individual post (hopefully there's no loophole in this)
        if (!window.location.href.includes("comments")) {
            post_footer[i].appendChild(save);
        }
        else {
            document.getElementById("post_links").appendChild(save);
        }
    }

    // function to make a div (manipulate the existing div tbh) to show all the saved posts
    // function is async so posts will show in chronological order but it's a compromise for speed as posts load one by one (speed depends on your network and libreddit/redlib server chosen)
    async function showSaved() {
        if (window.location.href != domain) {
            alert("You can only see Saved posts from home page. Try from there.");
        }
        else {
            if (!savedPosts.length) {
                alert("No saved posts yet. Go ahead and save some!");
            }
            else {
                // no pagination for now
                if (document.querySelectorAll("footer").length == 2) {
                    document.querySelector("footer").remove();
                }
                if (document.querySelectorAll("form").length == 2) {
                    document.querySelectorAll("form")[1].remove();
                }
                document.title = "loading saved...";
                var postPage;
                var hr = document.createElement("hr");
                hr.className = "sep";
                document.getElementById("posts").innerHTML = "";

                for (var j = savedPosts.length - 1; j > -1; j--) {
                    document.getElementById("posts").appendChild(hr);
                    await fetch(domain + "comments/" + savedPosts[j])
                        .then(response => {return response.text();})
                        .then(html => {postPage = new DOMParser().parseFromString(html, "text/html");
                                       document.getElementById("posts").appendChild(postPage.getElementsByClassName("post")[0]);
                                       console.log(j);
                                       document.getElementsByClassName("post")[document.getElementsByClassName("post").length - 1].id = savedPosts[j];})
                        .catch(err => console.error("Error occurred: " + err));
                }
                for (var k = 0; k < savedPosts.length; k++) {
                    var save = document.createElement("a");
                    save.style = "font-weight: bold;";
                    save.className = savedPosts[k];
                    save.textContent = "unsave";
                    (function(index) {save.onclick = function() {manageSaved(savedPosts[index]);};})(k);
                    document.getElementById(savedPosts[k]).querySelector(".post_footer").children[0].appendChild(save);
                }
                document.title = "saved";
            }
        }
    }
})();