Greasy Fork

Arcalive gallery view

arcalive 게시글의 이미지를 미리보여줍니다.

目前为 2025-01-21 提交的版本。查看 最新版本

// ==UserScript==
// @name         Arcalive gallery view
// @namespace    http://tampermonkey.net/
// @version      1.03
// @description  arcalive 게시글의 이미지를 미리보여줍니다.
// @author       You
// @include      /^https:\/\/arca\.live\/b\/([a-z]*)?([?&][a-z]=.*)*/
// @icon         https://www.google.com/s2/favicons?sz=64&domain=arca.live
// @grant        none
// @license      MIT
// ==/UserScript==
//'use strict';
//

/* 파라미터 */
const FETCH_DELAY = 60;
const IMAGE_ATTACH_POSITION = "날짜"; // 어디에다 이미지를 붙일지 선택 ! [제목, 날짜 중에서]
const WIDTH_THRESHOLD = 1800; // px단위. 이 px보다 커야 이미지미리보기가 발생한다
const SENSITIVE_WARN_IMG = false; // 민감성 포스팅 이미지 경고 표시유무

/* 사이트의 셀렉터 변경될 경우 수정하기 */
const TABLE_IMAGE_SELECTOR = ".article-content tbody img";
const VIDEO_SELECTOR = ".article-content video";
const IMAGE_SELECTOR = ".article-content img";
const ATTACH_TARGET_SELECTOR = ".vcol.col-title";

const ARTICLES_SELECTOR = ".vrow:not(.notice)";
const ARTICLES_WITHOUT_NOTICE_SELECTOR = ".article-list a.vrow.column";

/* 수정할 일 없음 */
const IMAGE_WIDTH_SMALL = 150;
const IMAGE_WIDTH_NORMAL = 200;
const IMAGE_WIDTH_LARGE = 300;
const IMAGE_WIDTH = IMAGE_WIDTH_LARGE;

function vrowToGallery($vrow){
    const $title = $vrow.querySelector('.vcol.col-title');
    console.log($title)
    $vrow.replaceChildren($title);
}

async function imageFetchAndAttach(vrow, delay) {
  // 이미지 페칭해서 붙임.
  await new Promise((r) => setTimeout(r, delay));

  const response = await fetch(vrow.href);
  const text = await response.text();
  const html = new DOMParser().parseFromString(text, "text/html");

  const tableImage = html.querySelector(TABLE_IMAGE_SELECTOR);
  const video = html.querySelector(VIDEO_SELECTOR);
  let image;

    if(tableImage) {
        image = tableImage;
    } else if (video && video.width >300) {
    image = new Image();
    image.src = video.poster;
  } else {
      const imageCandidates = html.querySelectorAll(IMAGE_SELECTOR);
      image = Array.from(imageCandidates).find(image=>SENSITIVE_WARN_IMG || !(image.width===1000 && image.height===667)) ?? new Image(300, 300);
  }

  fitImageSizeAndAlter(image);

    const target = vrow.querySelector(ATTACH_TARGET_SELECTOR);
    if (target) {
      target.style.width = `${IMAGE_WIDTH}px`;
      target.before(image);
    }

    vrow.style.display='inline-flex';
    vrow.style.flexDirection='column';
    vrow.style.width=`${IMAGE_WIDTH}px`
  console.log("fetched");
}

function fitImageSizeAndAlter(image) {
  const aspectRatio = image.height / image.width;
  image.style.display = 'block';
  image.style.width = `${IMAGE_WIDTH}px`;
  image.style.height = `${aspectRatio * IMAGE_WIDTH}px`;
}

function moveImageWithMark(vrow, image) {
  const brTag = document.createElement("span");

  let dest;
  switch (IMAGE_ATTACH_POSITION) {
    case "제목":
      dest = vrow.querySelector(".title");
      dest.append(brTag, image);
      dest.prepend(mark);
      break;
    case "날짜":
      dest = vrow.querySelector(".col-time");
      dest.prepend(image);
      image.append(brTag);
      break;
  }
}

let originalMediaWidth = getOriginalMediaWidth2();
const originalContentWrapper = getContentWrapperCloned();
let changedContentWrapper;

let timer = null;

function arcaliveDualMode() {
  if (window.innerWidth > 100) {
    removeRightSidebar();
    extendContentWrapper();
    moveHalfArticlesToRightPlane();
    restoreMediaSize2();
    changedContentWrapper = getContentWrapper();
    changedContentWrapper.after(originalContentWrapper);
    applyIfWidthSufficient();
    console.log("dualmode end");
  }
}

function applyIfWidthSufficient() {
  if (window.innerWidth > WIDTH_THRESHOLD) {
    originalContentWrapper.style.display = "none";
    originalContentWrapper.querySelector(".right-sidebar").style.display = "none";
    changedContentWrapper.style.display = "block";
    changedContentWrapper.querySelector(".right-sidebar").style.display = "none";
  } else {
    originalContentWrapper.style.display = "block";
    let originalSidebar = originalContentWrapper.querySelector(".right-sidebar");
    originalSidebar.style.display = "block";
    for (const el of originalSidebar.children) {
      el.style.display = "block";
    }
    // TODO: Display Sidebar As small size.
    changedContentWrapper.style.display = "none";
    changedContentWrapper.querySelector(".right-sidebar").style.display = "none";
  }
}

function getOriginalMediaWidth() {
  let image = document.querySelector(".fr-view.article-content img");
  let video = document.querySelector(".fr-view.article-content video");
  const width = image?.offsetWidth ?? video?.offsetWidth ?? null;

  return width;
}

function getOriginalMediaWidth2() {
  const images = document.querySelectorAll(".fr-view.article-content img");
  const videos = document.querySelectorAll(".fr-view.article-content video");
  const widths = { image: [], video: [] };

  images?.forEach((el) => widths.image.push(el.offsetWidth));
  videos?.forEach((el) => widths.video.push(el.offsetWidth));

  return widths;
}

function getContentWrapperCloned() {
  return getContentWrapper().cloneNode(true);
}
function getContentWrapper() {
  return document.querySelector(".content-wrapper.clearfix");
}

function removeRightSidebar() {
  document.querySelector(".right-sidebar").style.display = "none";
}

function extendContentWrapper() {
  const contentWrapper = document.querySelector(".content-wrapper.clearfix");
  contentWrapper.style = "margin:0 5rem 0;max-width:100%";
  const containerBoard = document.querySelector(".containe-fluid.board-article");
  containerBoard.style = "margin:0";
}

function moveHalfArticlesToRightPlane() {
  let articleListLeft;
  let articleListRight;
  let articleTableRight;
  cloneArticleListToRight();
  styleBothAriticleLists();
  moveHalfToRightPlane();

  function cloneArticleListToRight() {
    articleListLeft = document.querySelector(".article-list");
    articleListRight = articleListLeft.cloneNode(true);
    articleTableRight = articleListRight.querySelector(".list-table");

    const removeArticle = (el) => el.tagName == "A" && el.remove();
    articleTableRight.childNodes.forEach(removeArticle);
  }

  function styleBothAriticleLists() {
    articleListLeft.after(articleListRight);
    articleListLeft.style = "margin:5 0rem 0 0;float:left;width:49%;";
    articleListRight.style = "margin:5 0rem 0 0;float:right;width:49%;";
  }

  function moveHalfToRightPlane() {
    let articles = articleListLeft.querySelectorAll("a.vrow");

    const totalHeight = Array.from(articles).reduce((acc, el, i) => acc + el.offsetHeight, 0);
    console.log(`totalHeight : ${totalHeight}px`);
    let height = 0;
    for (const article of articles) {
      height += article.offsetHeight;
      if (height > (totalHeight + article.offsetHeight) / 2) articleTableRight.append(article);
    }
  }
}

function restoreMediaSize2() {
  let images = document.querySelectorAll(".fr-view.article-content img");
  let videos = document.querySelectorAll(".fr-view.article-content video");
  images.forEach(function (el, i) {
    el.style.width = `${originalMediaWidth.image[i]}px`;
  });
  videos.forEach(function (el, i) {
    el.style.width = `${originalMediaWidth.video[i]}px`;
  });
}

async function start() {
  const $table = document.querySelector("body > div.root-container > div.content-wrapper.clearfix > article > div > div.article-list > div.list-table.table");
    $table.style.display = 'flex';
    $table.style.flexWrap = 'wrap';
    $table.style.gap = '5px';
extendContentWrapper()
  const vrows = document.querySelectorAll(ARTICLES_SELECTOR);
  vrows.forEach(vrow=>vrowToGallery(vrow));

  const vrowsPromiseArray = Array.from(vrows).map((vrow, i) => imageFetchAndAttach(vrow, i *FETCH_DELAY));
  const articles = document.querySelectorAll(ARTICLES_WITHOUT_NOTICE_SELECTOR);
  articles.forEach((article) => {
    article.style = "height: auto !important";
  });

  Promise.all(vrowsPromiseArray);

}

addEventListener("load", setTimeout(start, 0));