redsave

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

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==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";
            }
        }
    }
})();