init
commit
bf7b6b7993
|
@ -0,0 +1,17 @@
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
.idea
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
build
|
||||||
|
build/**
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
node_modules/**
|
||||||
|
|
||||||
|
package-lock.json
|
|
@ -0,0 +1,53 @@
|
||||||
|
/* app */
|
||||||
|
const { app, session, Menu, ipcMain } = require('electron')
|
||||||
|
const { join } = require('path')
|
||||||
|
const fs = require('fs')
|
||||||
|
|
||||||
|
// const createTray = require('./tools/tray')
|
||||||
|
const { createMainWindow } = require('./tools/windows')
|
||||||
|
|
||||||
|
const ROOT = __dirname
|
||||||
|
const APP_DIR = join(app.getPath('appData'), './clash')
|
||||||
|
const CONFIG_FILE = join(APP_DIR, './config.json')
|
||||||
|
|
||||||
|
/* ----------------------------------------------------- */
|
||||||
|
|
||||||
|
app.commandLine.appendSwitch('lang', 'zh-CN')
|
||||||
|
app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required')
|
||||||
|
|
||||||
|
Menu.setApplicationMenu(null)
|
||||||
|
|
||||||
|
/* ----------------------------------------------------- */
|
||||||
|
|
||||||
|
// 初始化应用
|
||||||
|
app.once('ready', () => {
|
||||||
|
let win = createMainWindow(join(ROOT, './images/app.png'))
|
||||||
|
|
||||||
|
// app.toggleTray = createTray(win)
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.on('app', (ev, conn) => {
|
||||||
|
switch (conn.type) {
|
||||||
|
case 'saveToken':
|
||||||
|
fs.writeFile(CONFIG_FILE, conn.data, function (err) {})
|
||||||
|
ev.returnValue = true
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'readToken':
|
||||||
|
{
|
||||||
|
let cache = ''
|
||||||
|
try {
|
||||||
|
cache = fs.readFileSync(CONFIG_FILE).toString()
|
||||||
|
} catch (err) {}
|
||||||
|
ev.returnValue = cache
|
||||||
|
}
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'toggleTray':
|
||||||
|
{
|
||||||
|
app.toggleTray(conn.data)
|
||||||
|
ev.returnValue = true
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"name": "clash-manager",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "clash管理面板",
|
||||||
|
"main": "src/main.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "electron ."
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"name": "yutent",
|
||||||
|
"email": "yutent.io@gmail.com"
|
||||||
|
},
|
||||||
|
"devDependencies": {},
|
||||||
|
"dependencies": {}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
html{width:840px;height:540px}body{width:100%;height:100%;font-size:14px;color:var(--color-dark-1)}.app{display:flex;width:100%;height:100%;background:#f7f8fb}.holder{flex:1}.aside{flex-shrink:0;display:flex;flex-direction:column;width:128px;box-shadow:4px 0 12px rgba(0,0,0,.03)}.aside .logo{width:64px;height:64px;margin:16px auto;background:url(../icons/128x128.png) no-repeat;background-size:100%}.aside .nav-list{display:flex;flex-direction:column;width:100%;padding:0 16px}.aside .nav-list .item{width:100%;height:32px;margin-top:16px;line-height:32px;border-radius:16px;text-align:center;cursor:pointer;transition:color .2s linear,background .2s linear}.aside .nav-list .item:hover{color:var(--color-blue-1)}.aside .nav-list .item.active{color:#fff;background:var(--color-blue-1)}.aside .version{line-height:36px;text-align:center}.tab-content{flex:1;flex-shrink:0;display:flex;flex-direction:column;height:540px;padding:16px}.tab-content .field{display:flex;align-items:center;width:100%;height:36px;margin-top:12px}.tab-content .field .label{width:128px;font-weight:bold;color:var(--color-grey-3)}.tab-content .field .full{flex:1}.tab-content.configs{width:49%;margin-left:1%}.tab-content.remote wc-button,.tab-content.rules wc-button{width:64px;min-width:64px;margin-left:16px}.tab-content.remote .scroll,.tab-content.rules .scroll{overflow:hidden;flex:1;margin-top:24px}.tab-content.remote .card,.tab-content.rules .card{margin:0 auto}.tab-content.remote .list,.tab-content.rules .list{word-break:break-all}.tab-content.remote .list .item,.tab-content.rules .list .item{display:flex;align-items:center;justify-content:space-between;height:36px;padding:0 16px;border-bottom:1px solid var(--color-plain-1);font-family:Menlo,"Courier New",Courier,monospace;transition:background .2s linear}.tab-content.remote .list .item:hover,.tab-content.rules .list .item:hover{background-color:var(--color-plain-1)}.tab-content.remote .list span.type,.tab-content.rules .list span.type{padding:2px 3px;border-radius:2px;background-color:var(--color-blue-1);color:#fff}.card{flex:1;flex-shrink:0;display:flex;flex-direction:column;flex-wrap:wrap;width:100%;max-height:100%;padding:12px;margin:0 auto 24px;border:0;border-radius:4px;background-color:#fff;box-shadow:0 0 8px rgba(0,0,0,.075)}.card legend{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;color:var(--color-blue-1);font-weight:bold}
|
|
@ -0,0 +1,170 @@
|
||||||
|
html {
|
||||||
|
width: 840px;
|
||||||
|
height: 540px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--color-dark-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.app {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: #f7f8fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.holder {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aside {
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 128px;
|
||||||
|
box-shadow: 4px 0 12px rgba(0, 0, 0, 0.03);
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
margin: 16px auto;
|
||||||
|
background: url(../icons/128x128.png) no-repeat;
|
||||||
|
background-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 16px;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
width: 100%;
|
||||||
|
height: 32px;
|
||||||
|
margin-top: 16px;
|
||||||
|
line-height: 32px;
|
||||||
|
border-radius: 16px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color 0.2s linear, background 0.2s linear;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--color-blue-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: #fff;
|
||||||
|
background: var(--color-blue-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.version {
|
||||||
|
line-height: 36px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
flex: 1;
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 540px;
|
||||||
|
padding: 16px;
|
||||||
|
|
||||||
|
.field {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 36px;
|
||||||
|
margin-top: 12px;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
width: 128px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--color-grey-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.full {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.configs {
|
||||||
|
width: 49%;
|
||||||
|
margin-left: 1%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.remote,
|
||||||
|
&.rules {
|
||||||
|
wc-button {
|
||||||
|
width: 64px;
|
||||||
|
min-width: 64px;
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll {
|
||||||
|
overflow: hidden;
|
||||||
|
flex: 1;
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list {
|
||||||
|
word-break: break-all;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 36px;
|
||||||
|
padding: 0 16px;
|
||||||
|
border-bottom: 1px solid var(--color-plain-1);
|
||||||
|
font-family: Menlo, 'Courier New', Courier, monospace;
|
||||||
|
transition: background 0.2s linear;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--color-plain-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span.type {
|
||||||
|
padding: 2px 3px;
|
||||||
|
border-radius: 2px;
|
||||||
|
background-color: var(--color-blue-1);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
flex: 1;
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
padding: 12px;
|
||||||
|
margin: 0 auto 24px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 0 0 8px rgba(0, 0, 0, 0.075);
|
||||||
|
|
||||||
|
legend {
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
user-select: none;
|
||||||
|
color: var(--color-blue-1);
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
Binary file not shown.
After Width: | Height: | Size: 116 KiB |
|
@ -0,0 +1,126 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
|
||||||
|
<title>Clash Web Panel</title>
|
||||||
|
<link rel="favicon" href="favicon.ico">
|
||||||
|
<link rel="icon" type="image/x-icon" href="icons/192x192.png">
|
||||||
|
<link href="//unpkg.yutent.top/@bytedo/wcui/dist/css/reset-basic.css" rel="stylesheet">
|
||||||
|
<link href="css/app.css" rel="stylesheet">
|
||||||
|
<script src="js/app.js" type="module"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="app noselect" anot="app">
|
||||||
|
<aside class="aside">
|
||||||
|
<a class="logo"></a>
|
||||||
|
|
||||||
|
<nav class="nav-list">
|
||||||
|
<a
|
||||||
|
class="item"
|
||||||
|
:for="i it in navs"
|
||||||
|
:class="{active: i === tab}"
|
||||||
|
@click="changeTab(i)"
|
||||||
|
:text="it">
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<span class="holder"></span>
|
||||||
|
<span class="version">{{version}}</span>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<main class="tab-content" :if="tab === 0"></main>
|
||||||
|
|
||||||
|
<main class="tab-content rules" :if="tab === 1">
|
||||||
|
<fieldset class="card">
|
||||||
|
<legend>规则列表</legend>
|
||||||
|
|
||||||
|
<wc-scroll class="scroll">
|
||||||
|
<ul class="list">
|
||||||
|
<li class="item" :for="i it in rules">
|
||||||
|
<span>{{it.type}}</span>
|
||||||
|
<span>{{it.payload}}</span>
|
||||||
|
<span class="type">{{it.proxy}}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</wc-scroll>
|
||||||
|
</fieldset>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<main class="tab-content" :if="tab === 2"></main>
|
||||||
|
|
||||||
|
<main class="tab-content remote" :if="tab === 3">
|
||||||
|
<fieldset class="card">
|
||||||
|
<legend>订阅配置</legend>
|
||||||
|
|
||||||
|
<section class="field">
|
||||||
|
<span class="label">订阅地址</span>
|
||||||
|
<wc-input class="full" :duplex="remote.link"></wc-input>
|
||||||
|
<wc-button type="info" :disabled="!remote.link" @click="updateRemote">更新</wc-button>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<wc-scroll class="scroll">
|
||||||
|
<ul class="list">
|
||||||
|
<li class="item" :for="i it in remote.list">
|
||||||
|
{{i + 1}}.
|
||||||
|
<span>{{it[0]}}</span>
|
||||||
|
<span class="type">{{it[1]}}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</wc-scroll>
|
||||||
|
</fieldset>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<main class="tab-content configs" :if="tab === 4">
|
||||||
|
<fieldset class="card">
|
||||||
|
<legend>系统设置</legend>
|
||||||
|
|
||||||
|
<section class="field">
|
||||||
|
<span class="label">开机启动Clash</span>
|
||||||
|
<wc-switch disabled></wc-switch>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="field">
|
||||||
|
<span class="label">设置为系统代理</span>
|
||||||
|
<wc-switch disabled></wc-switch>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="field">
|
||||||
|
<span class="label">允许局域网的连接</span>
|
||||||
|
<wc-switch :duplex="configs.allowLan"></wc-switch>
|
||||||
|
</section>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset class="card">
|
||||||
|
<legend>Clash设置</legend>
|
||||||
|
|
||||||
|
<section class="field">
|
||||||
|
<span class="label">代理模式</span>
|
||||||
|
<wc-radio-group :duplex="configs.proxy">
|
||||||
|
<wc-radio value="global">全局</wc-radio>
|
||||||
|
<wc-radio value="rule">规则</wc-radio>
|
||||||
|
<wc-radio value="direct">直连</wc-radio>
|
||||||
|
</wc-radio-group>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="field">
|
||||||
|
<span class="label">Socks5 代理端口</span>
|
||||||
|
<wc-input size="small" :duplex="configs.socks5"></wc-input>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="field">
|
||||||
|
<span class="label">HTTP 代理端口</span>
|
||||||
|
<wc-input size="small" :duplex="configs.http"></wc-input>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="field">
|
||||||
|
<span class="label">混合代理端口</span>
|
||||||
|
<wc-input size="small" :duplex="configs.mixed"></wc-input>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</fieldset>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,172 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author yutent<yutent.io@gmail.com>
|
||||||
|
* @date 2022/05/16 00:38:48
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Anot from '//unpkg.yutent.top/anot/dist/anot.js'
|
||||||
|
import fetch from '//unpkg.yutent.top/@bytedo/fetch/dist/index.js'
|
||||||
|
import '//unpkg.yutent.top/@bytedo/wcui/dist/layer/index.js'
|
||||||
|
import '//unpkg.yutent.top/@bytedo/wcui/dist/form/switch.js'
|
||||||
|
import '//unpkg.yutent.top/@bytedo/wcui/dist/form/radio.js'
|
||||||
|
import '//unpkg.yutent.top/@bytedo/wcui/dist/form/button.js'
|
||||||
|
|
||||||
|
fetch.inject.response(r => r.json())
|
||||||
|
|
||||||
|
Anot({
|
||||||
|
$id: 'app',
|
||||||
|
|
||||||
|
state: {
|
||||||
|
version: '1.10.0',
|
||||||
|
navs: ['代理', '规则', '连接', '订阅', '设置'],
|
||||||
|
tab: +Anot.ls('tab') || 0,
|
||||||
|
contrl: {
|
||||||
|
host: '//127.0.0.1:',
|
||||||
|
port: 6767,
|
||||||
|
key: ''
|
||||||
|
},
|
||||||
|
rules: [],
|
||||||
|
remote: {
|
||||||
|
link: Anot.ls('remote_link') || '',
|
||||||
|
list: []
|
||||||
|
},
|
||||||
|
configs: {
|
||||||
|
proxy: 'rule',
|
||||||
|
http: 0,
|
||||||
|
socks5: 0,
|
||||||
|
mixed: 7890,
|
||||||
|
allowLan: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
if (this.contrl.port) {
|
||||||
|
fetch.BASE_URL = this.contrl.host + this.contrl.port
|
||||||
|
} else {
|
||||||
|
return layer
|
||||||
|
.prompt('请输入Clash本地管理端口', (v, done) => {
|
||||||
|
let n = +v.trim()
|
||||||
|
if (n === n) {
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(v => {
|
||||||
|
Anot.ls('web_port', v)
|
||||||
|
location.reload()
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
location.reload()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.getVersion()
|
||||||
|
this.getConfig()
|
||||||
|
this.getRule()
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
changeTab(idx) {
|
||||||
|
this.tab = idx
|
||||||
|
Anot.ls('tab', idx)
|
||||||
|
},
|
||||||
|
getVersion() {
|
||||||
|
fetch('/version').then(r => {
|
||||||
|
this.version = r.version
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
getConfig() {
|
||||||
|
fetch('/configs').then(r => {
|
||||||
|
console.log(r)
|
||||||
|
Object.assign(this.configs, {
|
||||||
|
proxy: r.mode,
|
||||||
|
http: r.port,
|
||||||
|
socks5: r['socks-port'],
|
||||||
|
mixed: r['mixed-port'],
|
||||||
|
allowLan: r['allow-lan']
|
||||||
|
})
|
||||||
|
// this.version = r.version
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
getRule() {
|
||||||
|
fetch('/rules').then(r => {
|
||||||
|
console.log(r)
|
||||||
|
this.rules = r.rules
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
updateRemote() {
|
||||||
|
if (this.remote.link) {
|
||||||
|
if (!/^(https?:)?\/\//.test(this.remote.link)) {
|
||||||
|
return layer.toast('订阅地址格式不正确', 'error')
|
||||||
|
}
|
||||||
|
Anot.ls('remote_link', this.remote.link)
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let txt = ''
|
||||||
|
let names = ['DIRECT']
|
||||||
|
let r = (Anot.ss('temp') || '').trim()
|
||||||
|
|
||||||
|
this.remote.list = r.split('\n').map(it => {
|
||||||
|
let tmp = decodeURIComponent(it).split('#')
|
||||||
|
let tmp2 = new URL(tmp[0])
|
||||||
|
let protocol = tmp2.protocol.slice(0, -1)
|
||||||
|
let path = tmp2.pathname.slice(2)
|
||||||
|
let info = { name: tmp.pop(), type: protocol, udp: true }
|
||||||
|
|
||||||
|
path = path.split(':')
|
||||||
|
|
||||||
|
info.port = path.pop()
|
||||||
|
|
||||||
|
path = path[0].split('@')
|
||||||
|
info.server = path.pop()
|
||||||
|
|
||||||
|
switch (protocol) {
|
||||||
|
case 'ss':
|
||||||
|
path = atob(path[0]).split(':')
|
||||||
|
console.log(path)
|
||||||
|
Object.assign(info, {
|
||||||
|
cipher: path[0],
|
||||||
|
password: path[1]
|
||||||
|
})
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'trojan':
|
||||||
|
Object.assign(info, {
|
||||||
|
password: path[0],
|
||||||
|
sni: tmp2.searchParams.get('sni'),
|
||||||
|
'skip-cert-verify': true
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
names.push(info.name)
|
||||||
|
txt += ` - { name: ${info.name}, type: ${info.type}, server: ${info.server}, port: ${
|
||||||
|
info.port
|
||||||
|
}, password: ${info.password}, udp: true, ${info.type === 'ss' ? 'cipher' : 'sni'}: ${
|
||||||
|
info.type === 'ss' ? info.cipher : info.sni
|
||||||
|
}}\n`
|
||||||
|
return [info.name, info.type]
|
||||||
|
})
|
||||||
|
|
||||||
|
// window.foo = txt
|
||||||
|
// window.bar = names.join(', ')
|
||||||
|
// // console.log(txt)
|
||||||
|
|
||||||
|
return
|
||||||
|
window
|
||||||
|
.fetch(this.remote.link, { cors: true })
|
||||||
|
.then(r => r.text())
|
||||||
|
.then(r => {
|
||||||
|
r = atob(r).trim()
|
||||||
|
Anot.ss('temp', r)
|
||||||
|
layer.toast('订阅更新成功', 'success')
|
||||||
|
this.remote.list = r.split('\n').map(it => {
|
||||||
|
let tmp = decodeURIComponent(it).split('#')
|
||||||
|
return [tmp.pop(), tmp[0]?.split('://').shift()]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
Loading…
Reference in New Issue