Greasy Fork is available in English.

Komica thread collapse

Let you collapse/expand threads on Komica

// ==UserScript==
// @name          Komica thread collapse
// @version       1.0.2
// @description   Let you collapse/expand threads on Komica
// @author        peng-devs
// @match         https://*.komica.org/*
// @match         https://*.komica1.org/*
// @match         https://*.komica2.net/*
// @exclude-match https://2cat.komica.org/*
// @icon          https://www.google.com/s2/favicons?domain=komica.org
// @grant         none
// @allFrames     true
// @license MIT
// @namespace https://greasyfork.org/users/57176
// ==/UserScript==

(function() {
  'use strict';

  const get_storage = () => window.localStorage.getItem('collapsed_threads') || '';

  const save_to_storage = data_no => {
    let storage = get_storage();

    if ((storage.match(/,/g) || []).length > 100) {
      storage = storage.slice(storage.indexOf(',') + 1);
    }

    window.localStorage.setItem('collapsed_threads', `${storage}${data_no},`);
  };

  const remove_from_storage = data_no => {
    const storage = get_storage();
    window.localStorage.setItem('collapsed_threads', storage.replaceAll(`${data_no},`, ''));
  };


  const get_thread = (data_no, collapsed = false) =>
    document.querySelector(`div.${collapsed ? 'collapsed_thread' : 'thread'}[data-no="${data_no}"`);

  const create_collapsed_thread = thread => {
    const data_no = thread.getAttribute('data-no');
    const thread_collapse_button = create_thread_collapse_button(data_no, true);
    const head = thread.querySelector('div.post-head').cloneNode(true);
    const hr = document.createElement('hr');

    const collapsed_thread = document.createElement('div');
    collapsed_thread.className = 'collapsed_thread';
    collapsed_thread.setAttribute('data-no', data_no);
    collapsed_thread.appendChild(thread_collapse_button);
    collapsed_thread.appendChild(head);
    collapsed_thread.appendChild(hr);

    return collapsed_thread;
  };

  const thread_collapse = data_no => _ => {
    const thread = get_thread(data_no);

    const collapsed_thread = create_collapsed_thread(thread);
    thread.before(collapsed_thread);
    thread.style.display = 'none';

    save_to_storage(data_no);
    console.log(`thread ${data_no} collapsed`);
  };

  const thread_expand = data_no => _ => {
    const thread = get_thread(data_no);
    const collapsed_thread = get_thread(data_no, true);

    thread.style.display = 'inherit';
    collapsed_thread.remove();

    remove_from_storage(data_no);
    console.log(`thread ${data_no} expanded`);
  };

  const create_thread_collapse_button = (data_no, collapsed = false) => {
    const thread_collapse_button = document.createElement('a');
    thread_collapse_button.className = 'thread-collapse-button';
    thread_collapse_button.style = 'float: left; margin-right: 5px;';
    thread_collapse_button.setAttribute('data-no', data_no);
    thread_collapse_button.innerText = `[${collapsed ? '+' : '–'}]`;
    thread_collapse_button.addEventListener('click', collapsed ? thread_expand(data_no) : thread_collapse(data_no));

    return thread_collapse_button;
  };


  const collapsed_threads = get_storage();
  const threads = document.querySelectorAll('div.thread');
  [...threads].forEach(thread => {
    const data_no = thread.getAttribute('data-no');

    if (collapsed_threads.includes(data_no)) {
      thread_collapse(data_no)();
    }

    const thread_collapse_button = create_thread_collapse_button(data_no);
    thread.prepend(thread_collapse_button);
  });

})();