Last active
August 11, 2024 11:42
-
-
Save antronic/f1dee102e69d8316bca6b654481d8713 to your computer and use it in GitHub Desktop.
Hareshi's Saved list
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Hareshi-My_List | |
// @match https://www.hareshi.net/browse/anime* | |
// @include https://www.hareshi.net/browse/anime* | |
// @description Hareshi's Saved list | |
// @namespace hareshi-my-list | |
// @version 2024-08-11 | |
// @author Jirachai Chansivanon | |
// @icon https://www.google.com/s2/favicons?sz=64&domain=hareshi.net | |
// @downloadURL https://raw.githubusercontent.com/antronic/hareshi-my-list/main/build/hareshi-my-list.tampermonkey.min.js | |
// @version 0.1 | |
// @grant none | |
// ==/UserScript== | |
"use strict";var __classPrivateFieldSet=(this&&this.__classPrivateFieldSet)||function(receiver,state,value,kind,f){if(kind==="m")throw new TypeError("Private method is not writable");if(kind==="a"&&!f)throw new TypeError("Private accessor was defined without a setter");if(typeof state==="function"?receiver!==state||!f:!state.has(receiver))throw new TypeError("Cannot write private member to an object whose class did not declare it");return(kind==="a"?f.call(receiver,value):f?f.value=value:state.set(receiver,value)),value;};var __classPrivateFieldGet=(this&&this.__classPrivateFieldGet)||function(receiver,state,kind,f){if(kind==="a"&&!f)throw new TypeError("Private accessor was defined without a getter");if(typeof state==="function"?receiver!==state||!f:!state.has(receiver))throw new TypeError("Cannot read private member from an object whose class did not declare it");return kind==="m"?f:kind==="a"?f.call(receiver):f?f.value:state.get(receiver);};var _Observable_value;class Observable extends EventTarget{constructor(initialData){super();_Observable_value.set(this,void 0);__classPrivateFieldSet(this,_Observable_value,initialData,"f");} | |
update(param){if(typeof param!=='function'){__classPrivateFieldSet(this,_Observable_value,param,"f");} | |
if(typeof param==='function'){const updater=param;__classPrivateFieldSet(this,_Observable_value,updater(__classPrivateFieldGet(this,_Observable_value,"f")),"f");} | |
this.dispatchEvent(new CustomEvent('dataChanged',{detail:__classPrivateFieldGet(this,_Observable_value,"f")}));} | |
onChange(callback){if(typeof callback==='function'){switch(callback.length){case 1:this.addEventListener('dataChanged',()=>callback(__classPrivateFieldGet(this,_Observable_value,"f")));break;case 2:this.addEventListener('dataChanged',(event)=>callback(event,__classPrivateFieldGet(this,_Observable_value,"f")));break;default:this.addEventListener('dataChanged',()=>callback());}}} | |
get(){return __classPrivateFieldGet(this,_Observable_value,"f");} | |
toString(){return JSON.stringify(__classPrivateFieldGet(this,_Observable_value,"f"));} | |
toJSON(){return __classPrivateFieldGet(this,_Observable_value,"f");}} | |
_Observable_value=new WeakMap();const loadMyList=()=>{let animeStorage=null;function validateStructure(storageStructure){if(storageStructure===undefined){return false;} | |
if(!Array.isArray(storageStructure.savedList)){return false;} | |
return true;} | |
function getStorage(){const DEFAULT_STRORAGE={savedList:[]};const storage=localStorage.getItem('hareshi_animate_storage');let parsedStorage=DEFAULT_STRORAGE;if(storage!==null){try{parsedStorage=Object.assign({},JSON.parse(storage));console.log('after parsedStorage',parsedStorage);if(!validateStructure(parsedStorage)){throw new Error('Invalid storage structure');}} | |
catch(e){console.log(e);parsedStorage=DEFAULT_STRORAGE;}} | |
console.log('parsedStorage',parsedStorage);const _savedList=new Observable(parsedStorage.savedList);animeStorage=Object.assign(Object.assign({},parsedStorage),{savedList:_savedList});} | |
function saveStorage(){localStorage.setItem('hareshi_animate_storage',JSON.stringify(animeStorage));} | |
function createAnimeData(){const coverImage=document.querySelector('.info .img-cover').src;const title=document.querySelector('.info #anipop.title').innerText;const animeId=window.location.pathname.split('/')[3];const host=window.location.hostname;const path=window.location.pathname;return{title,coverImage,animeId,host,path};} | |
function addToSavedList(anime){if(animeStorage.savedList.get().findIndex((i)=>i.animeId===anime.animeId)>-1){console.log('Already exists');return;} | |
animeStorage.savedList.update((saved)=>[...saved,anime]);saveStorage();} | |
function removeFromSaveList(storageIndex){const pageInfo=getPageInfo();const index=storageIndex===undefined?pageInfo.storageIndex:storageIndex;animeStorage.savedList.update((saved)=>[...saved.slice(0,index),...saved.slice(index+1),]);saveStorage();} | |
const toolbarHeader=document.createElement('div');function injectSaveButton(){const saveToggleButton=document.createElement('BUTTON');saveToggleButton.style.background='var(--primary)';saveToggleButton.style.color='#fff';saveToggleButton.style.borderRadius='.25rem';saveToggleButton.style.marginRight='4px';const pageInfo=getPageInfo();saveToggleButton.innerText=pageInfo.isSamePage?'✅ Saved':'➕ Save';animeStorage===null||animeStorage===void 0?void 0:animeStorage.savedList.onChange(()=>{const pageInfo=getPageInfo();saveToggleButton.innerText=pageInfo.isSamePage?'✅ Saved':'➕ Save';});saveToggleButton.addEventListener('click',()=>{const pageInfo=getPageInfo();if(pageInfo.isSamePage){removeFromSaveList();} | |
else{addToSavedList(createAnimeData());}});const underCoverMenu=document.createElement('DIV');underCoverMenu.appendChild(saveToggleButton);toolbarHeader.appendChild(saveToggleButton);} | |
function injectToolbar(){const toolbar=document.createElement('div');toolbar.style.position='fixed';toolbar.style.top='72px';toolbar.style.right='16px';toolbar.style.background='var(--primary)';toolbar.style.borderRadius='.25rem';const title=document.createElement('span');title.innerText='Saved list';toolbarHeader.appendChild(title);toolbarHeader.style.padding='0px 4px';toolbar.appendChild(toolbarHeader);const savedListContainer=document.createElement('DIV');savedListContainer.style.background='#fff';savedListContainer.style.padding='2px';function renderSavedList(){const list=animeStorage.savedList.get();savedListContainer.innerHTML='';list.forEach((item,index)=>{const title=document.createElement('a');title.innerText=item.title;title.href=`${item.path}`;title.style.marginBottom='4px';const delButton=document.createElement('button');delButton.innerText='🗑️';delButton.style.border='none';delButton.style.marginRight='2px';delButton.setAttribute('index',index.toString());delButton.addEventListener('click',()=>{removeFromSaveList(index);});const animeItem=document.createElement('DIV');animeItem.appendChild(delButton);animeItem.appendChild(title);savedListContainer.appendChild(animeItem);});} | |
renderSavedList();toolbar.appendChild(savedListContainer);animeStorage.savedList.onChange(()=>{renderSavedList();toolbar.appendChild(savedListContainer);});document.body.appendChild(toolbar);console.log(getPageInfo());} | |
function buildMenu(){} | |
let PAGE_TYPE;(function(PAGE_TYPE){PAGE_TYPE[PAGE_TYPE["ANIME_PAGE"]=0]="ANIME_PAGE";PAGE_TYPE[PAGE_TYPE["LIST_PAGE"]=1]="LIST_PAGE";PAGE_TYPE[PAGE_TYPE["INVALID"]=2]="INVALID";})(PAGE_TYPE||(PAGE_TYPE={}));function locationChanged(callback){window.addEventListener('locationchange',()=>callback());} | |
function checkWeb(){if(window.location.pathname.search(/\/browse\/anime\/\d/)===0){return PAGE_TYPE.ANIME_PAGE;} | |
if(window.location.pathname.search('/browse/anime')===0){return PAGE_TYPE.LIST_PAGE;} | |
return PAGE_TYPE.INVALID;} | |
function getPageInfo(){const pageType=checkWeb();const animeId=pageType===PAGE_TYPE.ANIME_PAGE&&window.location.pathname.split('/').length>=3?window.location.pathname.split('/')[3]:null;const storageIndex=pageType===PAGE_TYPE.ANIME_PAGE?animeStorage.savedList.get().findIndex((i)=>i.animeId===animeId):-1;return{type:pageType,path:window.location.pathname,animeId,isSamePage:storageIndex>-1,storageIndex,};} | |
function injectTools(){if(checkWeb()===PAGE_TYPE.ANIME_PAGE){injectSaveButton();} | |
injectToolbar();} | |
getStorage();injectTools();};loadMyList(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment