├── .env.production ├── .env.development ├── .vscode └── extensions.json ├── src ├── vite-env.d.ts ├── lib │ └── Counter.svelte ├── app.css ├── main.js ├── sites │ ├── index.js │ ├── mteam.js │ ├── kamept.js │ ├── _index.svelte │ ├── kamept.svelte │ └── mteam.svelte ├── assets │ ├── vite.svg │ └── svelte.svg ├── component │ ├── btnTurnPage.svelte │ ├── switch.svelte │ └── toggle.svelte ├── default.config.js ├── stores │ └── index.js ├── main.svelte ├── utils │ ├── index.js │ └── masonry.pkgd.min.js └── sidepanel.svelte ├── .gitignore ├── package.json ├── vite.config.js ├── userscript.config.js ├── jsconfig.json ├── README.md └── pnpm-lock.yaml /.env.production: -------------------------------------------------------------------------------- 1 | VITE_APP_ENV = 'production' -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | VITE_APP_ENV = 'development' -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["svelte.svelte-vscode"] 3 | } 4 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | //// 5 | -------------------------------------------------------------------------------- /src/lib/Counter.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sveltegreasytest", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "sh ./build.sh", 9 | "build:normal": "vite build --minify false", 10 | "build:minify": "vite build", 11 | "preview": "vite preview" 12 | }, 13 | "devDependencies": { 14 | "@sveltejs/vite-plugin-svelte": "2.2.0", 15 | "svelte": "^3.59.0", 16 | "vite": "^4.3.5", 17 | "vite-plugin-monkey": "^3.2.0" 18 | } 19 | } -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import { svelte } from '@sveltejs/vite-plugin-svelte'; 3 | import monkey from 'vite-plugin-monkey'; 4 | // -------------------- 5 | import { config } from './userscript.config.js' 6 | 7 | // https://vitejs.dev/config/ 8 | export default defineConfig({ 9 | build: { 10 | minify: true, 11 | }, 12 | plugins: [ 13 | svelte(), 14 | monkey({ 15 | entry: 'src/main.js', 16 | 17 | // NOTE: 详细油猴文件头配置见 ./userscript.config.js 18 | userscript: config 19 | }), 20 | ], 21 | }); 22 | -------------------------------------------------------------------------------- /userscript.config.js: -------------------------------------------------------------------------------- 1 | export const config = { 2 | name: { 3 | "": "PT种子列表瀑布流视图(Svelte重构)", 4 | en: "PT_Masonry_View_Svelte", 5 | }, 6 | icon: "https://avatars.githubusercontent.com/u/23617963", 7 | namespace: "https://github.com/KesaubeEire/PT_Masonry_View_Svelte", 8 | description: { 9 | "": "PT种子列表无限下拉瀑布流视图(Svelte重构)", 10 | en: "PT Masonry View by Svelte.", 11 | }, 12 | author: "Kesa", 13 | match: [ 14 | "https://kamept.com/*", 15 | "https://kp.m-team.cc/*", 16 | "https://pterclub.com/*", 17 | ], 18 | exclude: [ 19 | "*/offers.php*", 20 | "*/index.php*", 21 | "*/forums.php*", 22 | "*/viewrequests.php*", 23 | "*/seek.php*", 24 | ], 25 | grant: "none", 26 | license: "MIT", 27 | 28 | // NOTE: 经常修改这里就行了 29 | version: "1.1.0", 30 | } -------------------------------------------------------------------------------- /src/app.css: -------------------------------------------------------------------------------- 1 | /* 瀑布流主容器 */ 2 | div.waterfall { 3 | width: 100%; 4 | padding-top: 20px; 5 | padding-bottom: 60px; 6 | border-radius: 20px; 7 | height: 100%; 8 | 9 | /* margin: 0 auto; */ 10 | margin: 20px auto; 11 | 12 | transition: height 0.3s; 13 | } 14 | 15 | /* 调试按键统一样式 */ 16 | button.debug { 17 | position: fixed; 18 | top: 10px; 19 | right: 10px; 20 | padding: 4px; 21 | background-color: #333; 22 | color: #fff; 23 | border: none; 24 | border-radius: 5px; 25 | cursor: pointer; 26 | } 27 | 28 | /* 调试按键1: 显示隐藏原种子列表 */ 29 | button#toggle_oldTable { 30 | top: 10px; 31 | } 32 | 33 | /* 调试按键2: Masonry 切换卡片宽度 */ 34 | button#btnReLayout { 35 | top: 40px; 36 | } 37 | 38 | /* 调试按键3: 切换下一页加载方式 */ 39 | button#btnSwitchMode { 40 | top: 70px; 41 | } 42 | 43 | /* 调试按键4: Masonry 重新排列 */ 44 | button#sort_masonry { 45 | top: 100px; 46 | } 47 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import App from './main.svelte'; 2 | import { GET_TORRENT_LIST_SELECTOR } from './sites/index.js'; 3 | // ------------------------------------------------------------- 4 | 5 | export { _ORIGIN_TL_Node }; 6 | 7 | // ------------------------------------------------------------- 8 | 9 | console.log("________PT-TorrentList-Masonry________"); 10 | 11 | // ------------------------------------------------------------- 12 | /** 相应站点的种子列表 selector */ 13 | const list_selector = GET_TORRENT_LIST_SELECTOR(); 14 | /**原种子列表DOM */ 15 | const _ORIGIN_TL_Node = document.querySelector(list_selector); 16 | 17 | // 没有相应站点的种子列表 selector 或 种子列表 dom 不存在 就不进行整个程序 18 | if (list_selector && !!_ORIGIN_TL_Node) { 19 | const app = new App({ 20 | target: (() => { 21 | const app = document.createElement('div'); 22 | document.body.append(app); 23 | return app; 24 | })(), 25 | }); 26 | } 27 | else { console.log('未识别到种子列表捏~') } 28 | -------------------------------------------------------------------------------- /src/sites/index.js: -------------------------------------------------------------------------------- 1 | import { config as config_Kame } from "./kamept"; 2 | import { config as config_Mteam } from "./mteam"; 3 | 4 | /** 站点参数相关参数顶层对象 */ 5 | const SITE = { 6 | "kamept.com": config_Kame, 7 | "kp.m-team.cc": config_Mteam, 8 | }; 9 | 10 | /** 获得当前PT站的名字 @returns 当前PT站名 */ 11 | function GET_CURRENT_PT_DOMAIN() { 12 | const domain = window.location.hostname; 13 | // 输出当前链接的域名 14 | // console.log("当前站点: ", domain); 15 | return domain; 16 | } 17 | 18 | /** 判断该页面是否存在种子列表 19 | * @returns selector 20 | */ 21 | function GET_TORRENT_LIST_SELECTOR() { 22 | const domain = GET_CURRENT_PT_DOMAIN(); 23 | console.log("|-> 当前站点: ", domain); 24 | console.log('|-> 当前页面: ', window.location.pathname); 25 | 26 | const res = SITE[domain]?.torrentListTable ?? null; 27 | console.log('|-> 站点selector:', res); 28 | return res 29 | } 30 | 31 | export { 32 | GET_CURRENT_PT_DOMAIN, 33 | SITE as GLOBAL_SITE, 34 | GET_TORRENT_LIST_SELECTOR, 35 | } -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "Node", 4 | "target": "ESNext", 5 | "module": "ESNext", 6 | /** 7 | * svelte-preprocess cannot figure out whether you have 8 | * a value or a type, so tell TypeScript to enforce using 9 | * `import type` instead of `import` for Types. 10 | */ 11 | "importsNotUsedAsValues": "error", 12 | "isolatedModules": true, 13 | "resolveJsonModule": true, 14 | /** 15 | * To have warnings / errors of the Svelte compiler at the 16 | * correct position, enable source maps by default. 17 | */ 18 | "sourceMap": true, 19 | "esModuleInterop": true, 20 | "skipLibCheck": true, 21 | "forceConsistentCasingInFileNames": true, 22 | "baseUrl": ".", 23 | /** 24 | * Typecheck JS in `.svelte` and `.js` files by default. 25 | * Disable this if you'd like to use dynamic types. 26 | */ 27 | "checkJs": true 28 | }, 29 | /** 30 | * Use global.d.ts instead of compilerOptions.types 31 | * to avoid limiting type declarations. 32 | */ 33 | "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"] 34 | } 35 | -------------------------------------------------------------------------------- /src/assets/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/component/btnTurnPage.svelte: -------------------------------------------------------------------------------- 1 | 34 | 35 | 36 |
37 | 50 |
51 | 52 | 68 | -------------------------------------------------------------------------------- /src/assets/svelte.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/default.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 各种默认参数 3 | */ 4 | 5 | import { get } from 'svelte/store'; 6 | import { _card_width } from './stores'; 7 | 8 | /** 瀑布流卡片相关参数顶层对象 */ 9 | const CARD = { 10 | /** 瀑布流卡片宽度 */ 11 | CARD_WIDTH: get(_card_width), 12 | 13 | /** NOTE: 瀑布流卡片边框宽度 -> 这个2是真值, 但是边框好像是会随着分辨率和缩放变化, 给高有利大分辨率, 给低有利于小分辨率 */ 14 | CARD_BORDER: 0, 15 | 16 | /** 瀑布流卡片索引 */ 17 | CARD_INDEX: 0, 18 | 19 | /** 图片悬浮预览方式 20 | * 0: 一律放大到全视窗[默认] 21 | * 1: 最小为原图 22 | */ 23 | PIC_HOVER_STYLE: 0, 24 | }; 25 | 26 | /** 翻页相关参数顶层对象 */ 27 | // @ts-ignore 28 | const PAGE = { 29 | /** 翻页: 底部检测时间间隔 */ 30 | GAP: 3000, 31 | 32 | /** 翻页: 底部检测视点与底部距离 */ 33 | DISTANCE: 300, 34 | 35 | /** 翻页: 是否为初始跳转页面 */ 36 | IS_ORIGIN: true, 37 | 38 | /** 翻页: 初始页面 */ 39 | PAGE_ORIGIN: 0, 40 | 41 | /** 翻页: 当前页数 */ 42 | PAGE_CURRENT: 0, 43 | 44 | /** 翻页: 下一页数 */ 45 | PAGE_NEXT: 0, 46 | 47 | /** 翻页: 下一页的链接 */ 48 | NEXT_URL: "", 49 | 50 | /** 翻页: 下一页的加载方式: Button | Slip */ 51 | SWITCH_MODE: "Button", 52 | }; 53 | 54 | /** 网站图标链接 */ 55 | // @ts-ignore 56 | const ICON = { 57 | /** 大小图标 */ 58 | SIZE: 'size', 59 | /** 评论图标 */ 60 | COMMENT: 61 | 'comments', 62 | /** 上传人数图标 */ 63 | SEEDERS: 64 | 'seeders', 65 | /** 下载人数图标 */ 66 | LEECHERS: 67 | 'leechers', 68 | /** 已完成人数图标 */ 69 | SNATCHED: 70 | 'snatched', 71 | /** 下载图标 */ 72 | DOWNLOAD: 73 | 'download', 74 | /** 未收藏图标 */ 75 | COLLET: 76 | 'Unbookmarked', 77 | /** 已收藏图标 */ 78 | COLLETED: 'Bookmarked', 79 | }; 80 | 81 | export { CARD, PAGE, ICON } -------------------------------------------------------------------------------- /src/stores/index.js: -------------------------------------------------------------------------------- 1 | import { writable } from 'svelte/store'; 2 | import { sortMasonry } from "../utils"; 3 | 4 | // ---------------------------------------------------------------- 5 | 6 | /** 持久化 Stores -> 配置联动 localstorage*/ 7 | function persistStore(key, startValue) { 8 | const savedValue = localStorage.getItem(key); 9 | const initialValue = savedValue ? JSON.parse(savedValue) : startValue; 10 | const store = writable(initialValue); 11 | 12 | store.subscribe(value => { 13 | localStorage.setItem(key, JSON.stringify(value)); 14 | }); 15 | 16 | return store; 17 | } 18 | 19 | // ---------------------------------------------------------------- 20 | 21 | // 全局类变量 ------------------------------------- 22 | /** 全局Masonry */ 23 | export const _Global_Masonry = writable({}); 24 | 25 | /** 显示模式: 表格(0) or 瀑布流(1) */ 26 | export const _show_mode = persistStore('_showMode', 1); 27 | 28 | // iframe变量 ------------------------------------- 29 | /** iframe 开关 */ 30 | export const _iframe_switch = writable(0) 31 | /** iframe 网址 */ 32 | export const _iframe_url = writable('https://kamept.com/index.php') 33 | 34 | // 站点类变量 ------------------------------------- 35 | /** 当前所在站点域名 */ 36 | // export const _current_domain = writable("") 37 | export const _current_domain = persistStore('_domain', ""); 38 | 39 | /** 当前所在站点背景颜色 */ 40 | export const _current_bgColor = persistStore('_bgColor', ""); 41 | 42 | // 配置类变量 ------------------------------------- 43 | /** 是否显示原始种子列表 */ 44 | export const _show_originTable = writable(0) 45 | // export const _show_originTable = persistStore('_show_ori_table', 0); 46 | 47 | /** 是否显示侧边栏 */ 48 | export const _show_configPanel = writable(false) 49 | 50 | /** 侧边栏位置: x->left y->top */ 51 | export const _panelPos = persistStore('_panelPos', { x: 0, y: 0 }) 52 | 53 | /** 加载下一页方式: 点击false(0) 滚动true(1) */ 54 | export const _turnPage = persistStore('_turnPage', false); 55 | 56 | /** 是否显示侧边栏 debug 按钮 */ 57 | export const _show_debug_btn = persistStore('_show_debug_btn', 0); 58 | 59 | /** 是否显示鼠标悬浮预览大图 */ 60 | export const _show_nexus_pic = persistStore('_show_nexus_pic', 1); 61 | 62 | /** 是否延迟显示悬浮预览大图 */ 63 | export const _delay_nexus_pic = persistStore('_delay_nexus_pic', 600); 64 | 65 | // 卡片类变量 ------------------------------------- 66 | /** 卡片宽度 */ 67 | // export const _card_width = writable(200); 68 | export const _card_width = persistStore('_card_width', 200); 69 | 70 | /** 卡片设置: 全站点配置 & 各个站点配置 */ 71 | const site_setting = { 72 | mt: { 73 | // 隐藏gay卡片: 默认为true 74 | hide_gay: true 75 | } 76 | } 77 | export const _SITE_SETTING = persistStore('_SITE_SETTING', site_setting); 78 | let mark1 = false 79 | _SITE_SETTING.subscribe(value => { 80 | // 初始化时不寻找 masonry 81 | if (!mark1) { 82 | mark1 = true; 83 | } 84 | else { 85 | sortMasonry('fast'); 86 | sortMasonry('fast'); 87 | sortMasonry(); 88 | sortMasonry(); 89 | } 90 | }) 91 | 92 | /** 卡片显示_总开关 */ 93 | const show_switch = { 94 | // 全局总开关 95 | all: false, 96 | 97 | // 显示标题 98 | title: true, 99 | // 显示置顶和免费 100 | free: false, 101 | // 显示副标题 102 | sub_title: false, 103 | // 显示标签 104 | tags: false, 105 | // 显示大小&下载&收藏 106 | size_download_collect: false, 107 | // 显示上传时间 108 | upload_time: false, 109 | // 显示评论/上传/下载/完成 110 | statistics: false, 111 | } 112 | // export const _CARD_SHOW = writable(show_switch); 113 | export const _CARD_SHOW = persistStore('_card_show', show_switch); 114 | let mark = false; 115 | _CARD_SHOW.subscribe(value => { 116 | // console.log(get(_CARD_SHOW)); 117 | 118 | // 初始化时不寻找 masonry 119 | if (!mark) { 120 | mark = true; 121 | } 122 | else { 123 | sortMasonry('fast'); 124 | sortMasonry('fast'); 125 | sortMasonry(); 126 | sortMasonry(); 127 | } 128 | }); 129 | 130 | 131 | -------------------------------------------------------------------------------- /src/main.svelte: -------------------------------------------------------------------------------- 1 | 106 | 107 | 108 | {#if $_iframe_switch} 109 | 110 |
111 |