├── .github └── workflows │ └── build.yml ├── LICENSE ├── Makefile ├── Meta.png ├── README.md ├── rootfs ├── etc │ └── init.d │ │ └── clash ├── opt │ └── clash │ │ ├── bin │ │ └── clash-rules │ │ ├── config.yaml │ │ ├── nft.conf │ │ └── ui │ │ ├── Twemoji_Mozilla.ttf │ │ ├── _headers │ │ ├── apple-touch-icon-precomposed.png │ │ ├── assets │ │ ├── BaseModal-0f630377.js │ │ ├── BaseModal-e9f180d4.css │ │ ├── Config-3d242ed2.js │ │ ├── Config-7eb3f1bb.css │ │ ├── Connections-2720e021.js │ │ ├── Connections-2b49f1fb.css │ │ ├── Fab-48def6bf.css │ │ ├── Fab-e6dedc20.js │ │ ├── Input-eec9e65c.js │ │ ├── Logs-4c263fad.css │ │ ├── Logs-8ed10c2c.js │ │ ├── Proxies-06b60f95.css │ │ ├── Proxies-ce7620dc.js │ │ ├── Rules-162ef666.css │ │ ├── Rules-2c94a03b.js │ │ ├── Select-07e025ab.css │ │ ├── Select-3321dc18.js │ │ ├── TextFitler-2e63abd5.js │ │ ├── TextFitler-a112af1a.css │ │ ├── Twemoji_Mozilla-6d90152e.ttf │ │ ├── chart-lib-6081a478.js │ │ ├── debounce-c1ba2006.js │ │ ├── en-1067a8eb.js │ │ ├── index-64292e67.css │ │ ├── index-7c6466d3.js │ │ ├── index-84fa0cb3.js │ │ ├── index-e51a0671.js │ │ ├── inter-latin-400-normal-0364d368.woff2 │ │ ├── inter-latin-400-normal-3ea830d4.woff │ │ ├── inter-latin-800-normal-a51ac27d.woff2 │ │ ├── inter-latin-800-normal-d08d7178.woff │ │ ├── logs-8ad08aa6.js │ │ ├── objectWithoutPropertiesLoose-4f48578a.js │ │ ├── play-4baa6dad.js │ │ ├── roboto-mono-latin-400-normal-7295944e.woff2 │ │ ├── roboto-mono-latin-400-normal-dffdffa7.woff │ │ ├── rotate-cw-76728396.js │ │ ├── useRemainingViewPortHeight-aa016eed.js │ │ ├── vi-75c7db25.js │ │ ├── zh-cn-ace621d4.js │ │ └── zh-tw-47d3ce5e.js │ │ ├── index.html │ │ ├── logo.png │ │ ├── manifest.webmanifest │ │ ├── registerSW.js │ │ ├── sw.js │ │ ├── yacd.ico │ │ └── yacd.png ├── usr │ └── share │ │ ├── luci │ │ └── menu.d │ │ │ └── luci-app-ssclash.json │ │ └── rpcd │ │ └── acl.d │ │ └── luci-app-ssclash.json └── www │ └── luci-static │ └── resources │ └── view │ └── ssclash │ ├── ace │ ├── ace.js │ ├── mode-text.js │ ├── mode-yaml.js │ └── theme-tomorrow_night_bright.js │ ├── config.js │ └── log.js ├── scr-00.png ├── scr-01.png └── update_all_rule_providers.sh /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | workflow_dispatch: 9 | inputs: 10 | release-tag: 11 | description: 'Release Tag (v1.x.x)' 12 | required: true 13 | 14 | jobs: 15 | release: 16 | name: Build and Release 17 | runs-on: ubuntu-20.04 18 | env: 19 | PACKAGE_NAME: luci-app-ssclash 20 | SDK_URL_PATH: https://downloads.openwrt.org/releases/23.05.5/targets/x86/64/ 21 | SDK_NAME: -sdk- 22 | steps: 23 | - uses: actions/checkout@v2 24 | - name: Install Dependencies 25 | run: | 26 | sudo apt-get update 27 | sudo apt-get install -yq gettext libncurses5-dev rsync xsltproc 28 | - name: Create Directories 29 | run: | 30 | echo "SDK_DL_DIR=$(mktemp -d)" >> $GITHUB_ENV 31 | echo "SDK_HOME=$(mktemp -d)" >> $GITHUB_ENV 32 | - name: Prepare Build Environment 33 | run: | 34 | cd "$SDK_DL_DIR" 35 | if ! ( wget -q -O - "$SDK_URL_PATH/sha256sums" | grep -- "$SDK_NAME" > sha256sums.small 2>/dev/null ) ; then 36 | echo "Can not find ${SDK_NAME} file in sha256sums." 37 | exit 1 38 | fi 39 | SDK_FILE="$(cat sha256sums.small | cut -d' ' -f2 | sed 's/*//g')" 40 | wget -q -O "$SDK_FILE" "$SDK_URL_PATH/$SDK_FILE" 41 | if ! sha256sum -c ./sha256sums.small >/dev/null 2>&1 ; then 42 | echo "SDK can not be verified!" 43 | exit 1 44 | fi 45 | tar -Jxf "$SDK_DL_DIR/$SDK_FILE" -C "$SDK_HOME" --strip=1 46 | - name: Build Packages 47 | run: | 48 | cd "$SDK_HOME" 49 | ./scripts/feeds update luci > /dev/null 2>&1 50 | ln -s "${{ github.workspace }}" "package/$PACKAGE_NAME" 51 | make defconfig > /dev/null 2>&1 52 | make package/${PACKAGE_NAME}/compile V=s > /dev/null 53 | find "$SDK_HOME/bin" -type f -name "${PACKAGE_NAME}_*.ipk" \ 54 | -exec cp -f {} "${{ github.workspace }}" \; 55 | 56 | - name: Release and Upload Assets 57 | uses: softprops/action-gh-release@v1 58 | with: 59 | files: "*.ipk" 60 | tag_name: ${{ inputs.release-tag }} 61 | env: 62 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 63 | 64 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2024-2025 ZeroChaos (https://github.com/zerolabnet/ssclash) 2 | # This is free software, licensed under the GNU General Public License v2. 3 | 4 | include $(TOPDIR)/rules.mk 5 | 6 | PKG_NAME:=luci-app-ssclash 7 | PKG_VERSION:=1.8.2 8 | PKG_RELEASE:=1 9 | PKG_MAINTAINER:=ZeroChaos 10 | 11 | LUCI_TITLE:=LuCI Support for SSClash 12 | LUCI_DEPENDS:=+luci-base 13 | LUCI_PKGARCH:=all 14 | 15 | include $(INCLUDE_DIR)/package.mk 16 | 17 | define Package/$(PKG_NAME) 18 | SECTION:=luci 19 | CATEGORY:=LuCI 20 | SUBMENU:=3. Applications 21 | TITLE:=$(LUCI_TITLE) 22 | DEPENDS:=$(LUCI_DEPENDS) 23 | PKGARCH:=$(LUCI_PKGARCH) 24 | endef 25 | 26 | define Package/$(PKG_NAME)/description 27 | LuCI interface for SSClash, a tool for managing and configuring Clash. 28 | endef 29 | 30 | define Build/Prepare 31 | # No preparation steps required 32 | endef 33 | 34 | define Build/Compile 35 | # No compilation steps required 36 | endef 37 | 38 | define Package/$(PKG_NAME)/conffiles 39 | /opt/clash/config.yaml 40 | endef 41 | 42 | define Package/$(PKG_NAME)/install 43 | $(INSTALL_DIR) $(1)/etc/init.d 44 | $(INSTALL_BIN) ./rootfs/etc/init.d/clash $(1)/etc/init.d/ 45 | 46 | $(INSTALL_DIR) $(1)/opt/clash/bin 47 | $(INSTALL_BIN) ./rootfs/opt/clash/bin/clash-rules $(1)/opt/clash/bin/ 48 | 49 | $(INSTALL_DIR) $(1)/opt/clash 50 | $(INSTALL_DATA) ./rootfs/opt/clash/config.yaml $(1)/opt/clash/ 51 | $(INSTALL_BIN) ./rootfs/opt/clash/nft.conf $(1)/opt/clash/ 52 | 53 | $(INSTALL_DIR) $(1)/opt/clash/ui 54 | $(CP) ./rootfs/opt/clash/ui/* $(1)/opt/clash/ui/ 55 | 56 | $(INSTALL_DIR) $(1)/usr/share/luci/menu.d 57 | $(INSTALL_DATA) ./rootfs/usr/share/luci/menu.d/luci-app-ssclash.json $(1)/usr/share/luci/menu.d/ 58 | 59 | $(INSTALL_DIR) $(1)/usr/share/rpcd/acl.d 60 | $(INSTALL_DATA) ./rootfs/usr/share/rpcd/acl.d/luci-app-ssclash.json $(1)/usr/share/rpcd/acl.d/ 61 | 62 | $(INSTALL_DIR) $(1)/www/luci-static/resources/view/ssclash 63 | $(CP) ./rootfs/www/luci-static/resources/view/ssclash/* $(1)/www/luci-static/resources/view/ssclash/ 64 | endef 65 | 66 | define Package/$(PKG_NAME)/postrm 67 | #!/bin/sh 68 | [ -n "$$IPKG_INSTROOT" ] || { 69 | rm -rf /opt/clash/ui 70 | rm -f /opt/clash/ruleset 71 | rm -rf /tmp/clash 72 | rm -rf /www/luci-static/resources/view/ssclash 73 | } 74 | endef 75 | 76 | $(eval $(call BuildPackage,$(PKG_NAME))) 77 | -------------------------------------------------------------------------------- /Meta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zerolabnet/SSClash/5cafaf7358abc10515723fa3d6eba783f11be3e4/Meta.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Meta Kernel 3 |
Meta Kernel
4 |

5 | 6 |

Here's the step-by-step process for installing and configuring SSClash on your OpenWrt router

7 | 8 | # Setup Guide 9 | 10 | ## Step 1: Update Package List 11 | Update the package list to ensure you have the latest available versions. 12 | 13 | ```bash 14 | opkg update 15 | ``` 16 | 17 | ## Step 2: Install Required Packages 18 | Install the necessary kernel module for nftables. 19 | 20 | ```bash 21 | opkg install kmod-nft-tproxy 22 | ``` 23 | 24 | For iptables (if you have OpenWrt version < 22.03.x) – `iptables-mod-tproxy`. 25 | 26 | ## Step 3: Download and Install `luci-app-ssclash` Package 27 | Download the SSClash package and install it. 28 | 29 | ```bash 30 | curl -L https://github.com/zerolabnet/ssclash/releases/download/v1.8.2/luci-app-ssclash_1.8.2-1_all.ipk -o /tmp/luci-app-ssclash_1.8.2-1_all.ipk 31 | opkg install /tmp/luci-app-ssclash_1.8.2-1_all.ipk 32 | rm /tmp/*.ipk 33 | ``` 34 | 35 | ## Step 4: Download Clash.Meta Kernel 36 | Navigate to the `bin` directory and download the Clash.Meta Kernel. Choose the appropriate architecture. 37 | 38 | ```bash 39 | cd /opt/clash/bin 40 | ``` 41 | 42 | For **amd64** architecture: 43 | 44 | ```bash 45 | curl -L https://github.com/MetaCubeX/mihomo/releases/download/v1.19.2/mihomo-linux-amd64-compatible-v1.19.2.gz -o clash.gz 46 | ``` 47 | 48 | For **arm64** architecture: 49 | 50 | ```bash 51 | curl -L https://github.com/MetaCubeX/mihomo/releases/download/v1.19.2/mihomo-linux-arm64-v1.19.2.gz -o clash.gz 52 | ``` 53 | 54 | For **mipsel_24kc** architecture: 55 | 56 | ```bash 57 | curl -L https://github.com/MetaCubeX/mihomo/releases/download/v1.19.2/mihomo-linux-mipsle-softfloat-v1.19.2.gz -o clash.gz 58 | ``` 59 | 60 | Need a different architecture? Visit the [MetaCubeX Release Page](https://github.com/MetaCubeX/mihomo/releases) and choose the one that matches your device. 61 | 62 | ## Step 5: Prepare the Clash Binary 63 | Decompress the downloaded file and make it executable. 64 | 65 | ```bash 66 | gunzip clash.gz 67 | chmod +x clash 68 | ``` 69 | 70 | ## Step 6: Managing Clash from LuCI interface 71 | I've written a simple interface for managing Clash from LuCI interface `luci-app-ssclash`. Edit Clash config and Apply. 72 | 73 |

74 | 75 |

76 | 77 | ## Step 7: You can access to Dashboard from LuCI interface or manual 78 | You can access the Dashboard at: 79 | 80 | ``` 81 | http://ROUTER_IP:9090/ui/ 82 | ``` 83 | 84 |

85 | 86 |

87 | 88 | # Remove Clash 89 | To remove Clash, delete the related files, `luci-app-ssclash` package and kernel module `kmod-nft-tproxy` or `iptables-mod-tproxy`. 90 | 91 | ```bash 92 | opkg remove luci-app-ssclash kmod-nft-tproxy 93 | rm -rf /opt/clash 94 | ``` 95 | 96 | --- 97 | 98 | # Extra info (optional): Automating Clash Rules Update in OpenWrt whenever the Internet interface is brought up 99 | 100 | To automatically update the rules for Clash whenever the Internet interface is brought up in OpenWrt, follow these step: 101 | 102 | ## Create the Shell Script 103 | 104 | 1. Open a terminal and create a new shell script named `40-clash_rules` in the `/etc/hotplug.d/iface/` directory: 105 | 106 | ```bash 107 | vi /etc/hotplug.d/iface/40-clash_rules 108 | ``` 109 | 110 | 2. [Insert the following script content](https://raw.githubusercontent.com/zerolabnet/ssclash/main/update_all_rule_providers.sh) (change `api_base_url` if needed): 111 | 112 | ```sh 113 | #!/bin/sh 114 | 115 | # Add delay 116 | sleep 10 117 | 118 | # API IP address and port 119 | api_base_url="http://192.168.1.1:9090" 120 | 121 | # API URL 122 | base_url="$api_base_url/providers/rules" 123 | 124 | # Get JSON response with provider names 125 | response=$(curl -s "$base_url") 126 | 127 | # Extract provider names using standard utilities 128 | providers=$(echo "$response" | grep -o '"name":"[^"]*"' | sed 's/"name":"\([^"]*\)"/\1/') 129 | 130 | # Check if data retrieval was successful 131 | if [ -z "$providers" ]; then 132 | echo "Failed to retrieve providers or no providers found." 133 | exit 1 134 | fi 135 | 136 | # Loop through each provider name and send PUT request to update 137 | for provider in $providers; do 138 | echo "Updating provider: $provider" 139 | curl -X PUT "$base_url/$provider" 140 | 141 | # Check success and output the result 142 | if [ $? -eq 0 ]; then 143 | echo "Successfully updated $provider" 144 | else 145 | echo "Failed to update $provider" 146 | fi 147 | done 148 | 149 | # Service restart 150 | /etc/init.d/clash reload 151 | ``` 152 | 153 | 3. Save and exit the editor. 154 | 155 | The script will now automatically run whenever the Internet interface is brought up. This ensures that the rules for Clash are updated as soon as the router is rebooted and connected to the Internet. 156 | -------------------------------------------------------------------------------- /rootfs/etc/init.d/clash: -------------------------------------------------------------------------------- 1 | #!/bin/sh /etc/rc.common 2 | 3 | START=21 4 | STOP=89 5 | 6 | USE_PROCD=1 7 | 8 | FLAG_FILE="/tmp/dnsmasq_once" 9 | 10 | msg() { 11 | logger -p daemon.info -st "clash[$$]" "$*" 12 | } 13 | 14 | start_service() { 15 | # The ruleset folder is used from tmpfs 16 | if [ ! -d /tmp/clash/ruleset ]; then 17 | mkdir -p /tmp/clash/ruleset 18 | msg "The folder '/tmp/clash/ruleset' was created" 19 | fi 20 | if [ ! -L /opt/clash/ruleset ] || [ "$(readlink /opt/clash/ruleset)" != "/tmp/clash/ruleset" ]; then 21 | rm -rf /opt/clash/ruleset 22 | ln -s /tmp/clash/ruleset /opt/clash/ruleset 23 | msg "Created a symlink from '/tmp/clash/ruleset' to '/opt/clash/ruleset'" 24 | fi 25 | 26 | /opt/clash/bin/clash -d /opt/clash -t 27 | if [ $? -ne 0 ]; then 28 | msg "Clash instance is not started" 29 | return 30 | fi 31 | 32 | procd_open_instance 33 | procd_set_param command /opt/clash/bin/clash -d /opt/clash 34 | procd_set_param stdout 1 35 | procd_set_param stderr 1 36 | procd_set_param respawn 37 | procd_close_instance 38 | msg "Clash instance is started" 39 | 40 | uci add_list dhcp.@dnsmasq[0].server='127.0.0.1#7874' 41 | uci set dhcp.@dnsmasq[0].cachesize='0' 42 | uci set dhcp.@dnsmasq[0].noresolv='1' 43 | uci commit dhcp 44 | msg "DNS settings have been changed" 45 | 46 | /opt/clash/bin/clash-rules start 47 | msg "Firewall rules applied" 48 | 49 | /etc/init.d/dnsmasq restart > /dev/null 2>&1 50 | msg "dnsmasq restarted" 51 | } 52 | 53 | stop_service() { 54 | msg "Clash instance has been stopped" 55 | uci del dhcp.@dnsmasq[0].server 56 | uci del dhcp.@dnsmasq[0].cachesize 57 | uci del dhcp.@dnsmasq[0].noresolv 58 | uci commit dhcp 59 | msg "DNS settings have been restored" 60 | 61 | /opt/clash/bin/clash-rules stop 62 | msg "Firewall rules have been restored" 63 | 64 | if [ ! -f "$FLAG_FILE" ]; then 65 | /etc/init.d/dnsmasq restart > /dev/null 2>&1 66 | msg "dnsmasq restarted" 67 | fi 68 | 69 | rm -f "$FLAG_FILE" 70 | } 71 | 72 | reload_service() { 73 | touch "$FLAG_FILE" 74 | stop 75 | start 76 | } 77 | 78 | boot() { 79 | sleep 10 80 | start 81 | } 82 | -------------------------------------------------------------------------------- /rootfs/opt/clash/bin/clash-rules: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | start() { 4 | if hash nft 2>/dev/null; then 5 | nft -f /opt/clash/nft.conf 6 | ip route add local default dev lo table 100 7 | ip rule add fwmark 1 table 100 8 | elif hash iptables 2>/dev/null; then 9 | # Block QUIC first (for YouTube) 10 | iptables -t filter -I INPUT -p udp --dport 443 -j REJECT 11 | iptables -t filter -I FORWARD -p udp --dport 443 -j REJECT 12 | 13 | iptables -t mangle -N CLASH 14 | iptables -t mangle -N CLASH_LOCAL 15 | 16 | # Exclude local networks in CLASH 17 | for addr in 0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 127.0.0.0/8 169.254.0.0/16 172.16.0.0/12 192.168.0.0/16 224.0.0.0/4 240.0.0.0/4; do 18 | iptables -t mangle -A CLASH -d $addr -j RETURN 19 | done 20 | 21 | # Exclude interfaces in CLASH 22 | for intf in wan+ ppp+ tun+ tap+ wg+ lxc+ veth+ vnet+ docker+ dummy+; do 23 | iptables -t mangle -A CLASH -i $intf -j RETURN 24 | iptables -t mangle -A CLASH -o $intf -j RETURN 25 | done 26 | 27 | # TPROXY rules 28 | iptables -t mangle -A CLASH -p tcp -j TPROXY --on-ip 127.0.0.1 --on-port 7894 --tproxy-mark 1 29 | iptables -t mangle -A CLASH -p udp -j TPROXY --on-ip 127.0.0.1 --on-port 7894 --tproxy-mark 1 30 | 31 | iptables -t mangle -A PREROUTING -j CLASH 32 | 33 | # Exclude local networks in CLASH_LOCAL 34 | for addr in 0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 127.0.0.0/8 169.254.0.0/16 172.16.0.0/12 192.168.0.0/16 224.0.0.0/4 240.0.0.0/4; do 35 | iptables -t mangle -A CLASH_LOCAL -d $addr -j RETURN 36 | done 37 | 38 | # Exclude interfaces in CLASH_LOCAL 39 | for intf in wan+ ppp+ tun+ tap+ wg+ lxc+ veth+ vnet+ docker+ dummy+; do 40 | iptables -t mangle -A CLASH_LOCAL -i $intf -j RETURN 41 | iptables -t mangle -A CLASH_LOCAL -o $intf -j RETURN 42 | done 43 | 44 | # Prevent cyclic redirection 45 | iptables -t mangle -A CLASH_LOCAL -m mark --mark 2 -j RETURN 46 | 47 | # Mark packets for routing 48 | iptables -t mangle -A CLASH_LOCAL -p tcp -j MARK --set-mark 1 49 | iptables -t mangle -A CLASH_LOCAL -p udp -j MARK --set-mark 1 50 | iptables -t mangle -A OUTPUT -j CLASH_LOCAL 51 | 52 | ip route add local default dev lo table 100 53 | ip rule add fwmark 1 table 100 54 | else 55 | echo "Unknown firewall, ignoring." 56 | fi 57 | } 58 | 59 | stop() { 60 | if hash nft 2>/dev/null; then 61 | nft delete table ip clash 62 | ip route del local default dev lo table 100 63 | ip rule del table 100 64 | elif hash iptables 2>/dev/null; then 65 | iptables -t filter -D INPUT -p udp --dport 443 -j REJECT 66 | iptables -t filter -D FORWARD -p udp --dport 443 -j REJECT 67 | iptables -t mangle -D PREROUTING -j CLASH 68 | iptables -t mangle -F CLASH 69 | iptables -t mangle -X CLASH 70 | 71 | iptables -t mangle -D OUTPUT -j CLASH_LOCAL 72 | iptables -t mangle -F CLASH_LOCAL 73 | iptables -t mangle -X CLASH_LOCAL 74 | 75 | ip route del local default dev lo table 100 76 | ip rule del table 100 77 | else 78 | echo "Unknown firewall, ignoring." 79 | fi 80 | } 81 | 82 | case "$1" in 83 | start) 84 | start 85 | ;; 86 | stop) 87 | stop 88 | ;; 89 | *) 90 | echo "Usage: $0 {start|stop}" 91 | exit 1 92 | ;; 93 | esac 94 | -------------------------------------------------------------------------------- /rootfs/opt/clash/config.yaml: -------------------------------------------------------------------------------- 1 | mode: rule 2 | ipv6: false 3 | log-level: error 4 | allow-lan: false 5 | tproxy-port: 7894 6 | unified-delay: true 7 | tcp-concurrent: true 8 | external-controller: 0.0.0.0:9090 9 | external-ui: ./ui 10 | 11 | # DNS server settings 12 | # This section is optional. When not present, the DNS server will be disabled. 13 | dns: 14 | enable: true 15 | listen: 0.0.0.0:7874 16 | ipv6: false 17 | # Bootstrap DNS 18 | default-nameserver: ['1.1.1.1', '1.0.0.1', '8.8.8.8', '8.8.4.4'] 19 | # Upstream DNS 20 | nameserver: ['https://dns10.quad9.net/dns-query', 'https://dns.aa.net.uk/dns-query'] 21 | 22 | # find-process-mode: off 23 | # global-client-fingerprint: chrome 24 | 25 | profile: 26 | store-selected: true 27 | store-fake-ip: true 28 | 29 | # Provides a default traffic mark for outbound connections on Linux 30 | routing-mark: 2 # Prevent cyclic redirection 31 | 32 | sniffer: 33 | enable: true 34 | sniff: 35 | HTTP: 36 | ports: [80, 8080-8880] 37 | override-destination: true 38 | TLS: 39 | ports: [443, 8443] 40 | # QUIC: 41 | # ports: [443, 8443] 42 | skip-domain: 43 | - 'Mijia Cloud' 44 | 45 | proxies: 46 | # vless 47 | - name: 'XX-reality' # change it 48 | type: vless 49 | server: xx-reality-server-IP # change it 50 | port: 443 51 | uuid: 528aeb97-a633-468d-81f7-8185d26bcb64 # change it 52 | network: tcp 53 | tls: true 54 | udp: true 55 | flow: xtls-rprx-vision 56 | servername: masking-domain.example.com # change it 57 | reality-opts: 58 | public-key: 2R_qtReOBExLOx1aZj8s4N8x-Ru_wbo-o2neemZEDB0 # change it 59 | short-id: ae380de2eeded283 # change it 60 | client-fingerprint: chrome 61 | 62 | - name: 'YY-reality' # change it 63 | type: vless 64 | server: yy-reality-server-IP # change it 65 | port: 443 66 | uuid: 3f0d4ce6-e4fe-46f9-804c-cce633e22785 # change it 67 | network: tcp 68 | tls: true 69 | udp: true 70 | flow: xtls-rprx-vision 71 | servername: masking-domain.example.org # change it 72 | reality-opts: 73 | public-key: beAHvGPT-mhlYQAvX7u_rQQfnJqTXaStmRFkTnkUolE # change it 74 | short-id: 0890fec52c6dd1ca # change it 75 | client-fingerprint: chrome 76 | 77 | proxy-groups: 78 | # Select (used for selecting proxy or proxy group) 79 | - name: PROXY 80 | type: select 81 | # disable-udp: true 82 | proxies: [XX-reality, YY-reality] # change it, add the others 83 | 84 | # Fallback 85 | - name: FALLBACK 86 | type: fallback 87 | proxies: [XX-reality, YY-reality] # change it, add the others 88 | url: 'https://www.gstatic.com/generate_204' # or https://cp.cloudflare.com/generate_204 89 | interval: 300 90 | 91 | # # Load-balance 92 | # - name: LB-PROXY 93 | # type: load-balance 94 | # proxies: [XX-reality, YY-reality] # change it, add the others 95 | # url: 'https://www.gstatic.com/generate_204' 96 | # interval: 300 97 | # strategy: consistent-hashing # or round-robin 98 | 99 | rule-providers: 100 | direct-domain: 101 | behavior: classical 102 | type: http 103 | format: text 104 | url: 'https://YOUR_URL/direct-domain.list' # change it 105 | interval: 1800 106 | path: ./ruleset/direct-domain.txt 107 | direct-ip: 108 | behavior: classical 109 | type: http 110 | format: text 111 | url: 'https://YOUR_URL/direct-ip.list' # change it 112 | interval: 1800 113 | path: ./ruleset/direct-ip.txt 114 | proxy-domain: 115 | behavior: classical 116 | type: http 117 | format: text 118 | url: 'https://YOUR_URL/proxy-domain.list' # change it 119 | interval: 1800 120 | path: ./ruleset/proxy-domain.txt 121 | proxy-ip: 122 | behavior: classical 123 | type: http 124 | format: text 125 | url: 'https://YOUR_URL/proxy-ip.list' # change it 126 | interval: 1800 127 | path: ./ruleset/proxy-ip.txt 128 | antifilter-ip: 129 | behavior: classical 130 | type: http 131 | format: text 132 | url: 'https://YOUR_URL/antifilter-ip.list' # change it 133 | interval: 43200 134 | path: ./ruleset/antifilter-ip.txt 135 | 136 | rules: 137 | - RULE-SET,direct-domain,DIRECT 138 | - RULE-SET,direct-ip,DIRECT 139 | - RULE-SET,proxy-domain,PROXY 140 | - RULE-SET,proxy-ip,PROXY 141 | - RULE-SET,antifilter-ip,PROXY 142 | - MATCH,DIRECT 143 | -------------------------------------------------------------------------------- /rootfs/opt/clash/nft.conf: -------------------------------------------------------------------------------- 1 | #!/usr/sbin/nft -f 2 | 3 | table ip clash 4 | delete table ip clash 5 | 6 | define RESERVED_IP = { 7 | 0.0.0.0/8, 8 | 10.0.0.0/8, 9 | 100.64.0.0/10, 10 | 127.0.0.0/8, 11 | 169.254.0.0/16, 12 | 172.16.0.0/12, 13 | 192.168.0.0/16, 14 | 224.0.0.0/4, 15 | 240.0.0.0/4 16 | } 17 | 18 | define RESERVED_IFACE = { 19 | "wan*", 20 | "ppp*", 21 | "tun*", 22 | "tap*", 23 | "wg*", 24 | "lxc*", 25 | "veth*", 26 | "vnet*", 27 | "docker*", 28 | "dummy*" 29 | } 30 | 31 | table ip clash { 32 | chain prerouting { 33 | type filter hook prerouting priority mangle; policy accept; 34 | 35 | # Block QUIC first (for YouTube) 36 | udp dport 443 reject 37 | 38 | # Exclude reserved IPs and interfaces 39 | ip daddr $RESERVED_IP return 40 | iifname $RESERVED_IFACE return 41 | oifname $RESERVED_IFACE return 42 | 43 | # Redirect traffic to TPROXY 44 | ip protocol tcp tproxy to 127.0.0.1:7894 meta mark set 1 45 | ip protocol udp tproxy to 127.0.0.1:7894 meta mark set 1 46 | } 47 | chain output { 48 | type route hook output priority mangle; policy accept; 49 | 50 | # Exclude reserved IPs and interfaces 51 | ip daddr $RESERVED_IP return 52 | iifname $RESERVED_IFACE return 53 | oifname $RESERVED_IFACE return 54 | 55 | # Prevent cyclic redirection 56 | meta mark 2 return 57 | 58 | # Mark packets for routing 59 | ip protocol tcp meta mark set 1 60 | ip protocol udp meta mark set 1 61 | } 62 | } -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/Twemoji_Mozilla.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zerolabnet/SSClash/5cafaf7358abc10515723fa3d6eba783f11be3e4/rootfs/opt/clash/ui/Twemoji_Mozilla.ttf -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/_headers: -------------------------------------------------------------------------------- 1 | # for netlify hosting 2 | # https://docs.netlify.com/routing/headers/#syntax-for-the-headers-file 3 | 4 | /* 5 | X-Frame-Options: DENY 6 | X-XSS-Protection: 1; mode=block 7 | X-Content-Type-Options: nosniff 8 | Referrer-Policy: same-origin 9 | /*.css 10 | Cache-Control: public, max-age=31536000, immutable 11 | /*.js 12 | Cache-Control: public, max-age=31536000, immutable 13 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zerolabnet/SSClash/5cafaf7358abc10515723fa3d6eba783f11be3e4/rootfs/opt/clash/ui/apple-touch-icon-precomposed.png -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/BaseModal-0f630377.js: -------------------------------------------------------------------------------- 1 | import{r as y,R as p,p as s,c as f,m as v,b as h,M as m,s as O}from"./index-7c6466d3.js";function l(){return l=Object.assign||function(e){for(var n=1;n=0)&&Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}function b(e,n){if(e==null)return{};var r={},t=Object.keys(e),o,a;for(a=0;a=0)&&(r[o]=e[o]);return r}var c=y.forwardRef(function(e,n){var r=e.color,t=r===void 0?"currentColor":r,o=e.size,a=o===void 0?24:o,u=g(e,["color","size"]);return p.createElement("svg",l({ref:n,xmlns:"http://www.w3.org/2000/svg",width:a,height:a,viewBox:"0 0 24 24",fill:"none",stroke:t,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},u),p.createElement("polyline",{points:"6 9 12 15 18 9"}))});c.propTypes={color:s.string,size:s.oneOfType([s.string,s.number])};c.displayName="ChevronDown";const k=c,w="_overlay_ukhe7_1",d="_cnt_ukhe7_5",_="_afterOpen_ukhe7_15",i={overlay:w,cnt:d,afterOpen:_},{useMemo:j}=O;function C({isOpen:e,onRequestClose:n,children:r}){const t=j(()=>({base:f(v.content,i.cnt),afterOpen:i.afterOpen,beforeClose:""}),[]);return h(m,{isOpen:e,onRequestClose:n,className:t,overlayClassName:f(v.overlay,i.overlay),children:r})}export{C as B,k as C}; 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/BaseModal-e9f180d4.css: -------------------------------------------------------------------------------- 1 | ._overlay_ukhe7_1{background-color:#0009}._cnt_ukhe7_5{position:absolute;background-color:var(--bg-modal);color:var(--color-text);line-height:1.4;opacity:.6;transition:all .3s ease;box-shadow:#0000001f 0 4px 4px,#0000003d 0 16px 32px}._afterOpen_ukhe7_15{opacity:1} 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/Config-3d242ed2.js: -------------------------------------------------------------------------------- 1 | import{r as E,R as h,p as v,c as re,b as n,j as c,v as le,w as V,x as G,y as oe,s as H,d as J,z as se,g as Q,A as ie,u as ce,D as de,E as x,F as ue,G as me,H as he,J as pe,K as ve,L as fe,N as ge,C as be,S as N,O as ye,B as y,P as we,Q as ke,T as _e}from"./index-7c6466d3.js";import{r as Ce}from"./logs-8ad08aa6.js";import{S as k}from"./Select-3321dc18.js";import{I as S,S as Oe}from"./Input-eec9e65c.js";import{R as P}from"./rotate-cw-76728396.js";function I(){return I=Object.assign||function(e){for(var o=1;o=0)&&Object.prototype.propertyIsEnumerable.call(e,a)&&(l[a]=e[a])}return l}function Ne(e,o){if(e==null)return{};var l={},a=Object.keys(e),t,r;for(r=0;r=0)&&(l[t]=e[t]);return l}var T=E.forwardRef(function(e,o){var l=e.color,a=l===void 0?"currentColor":l,t=e.size,r=t===void 0?24:t,p=xe(e,["color","size"]);return h.createElement("svg",I({ref:o,xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:a,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},p),h.createElement("polyline",{points:"8 17 12 21 16 17"}),h.createElement("line",{x1:"12",y1:"12",x2:"12",y2:"21"}),h.createElement("path",{d:"M20.88 18.09A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.29"}))});T.propTypes={color:v.string,size:v.oneOfType([v.string,v.number])};T.displayName="DownloadCloud";const Se=T;function L(){return L=Object.assign||function(e){for(var o=1;o=0)&&Object.prototype.propertyIsEnumerable.call(e,a)&&(l[a]=e[a])}return l}function je(e,o){if(e==null)return{};var l={},a=Object.keys(e),t,r;for(r=0;r=0)&&(l[t]=e[t]);return l}var $=E.forwardRef(function(e,o){var l=e.color,a=l===void 0?"currentColor":l,t=e.size,r=t===void 0?24:t,p=Pe(e,["color","size"]);return h.createElement("svg",L({ref:o,xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:a,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},p),h.createElement("path",{d:"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"}),h.createElement("polyline",{points:"16 17 21 12 16 7"}),h.createElement("line",{x1:"21",y1:"12",x2:"9",y2:"12"}))});$.propTypes={color:v.string,size:v.oneOfType([v.string,v.number])};$.displayName="LogOut";const Ie=$;function z(){return z=Object.assign||function(e){for(var o=1;o=0)&&Object.prototype.propertyIsEnumerable.call(e,a)&&(l[a]=e[a])}return l}function ze(e,o){if(e==null)return{};var l={},a=Object.keys(e),t,r;for(r=0;r=0)&&(l[t]=e[t]);return l}var R=E.forwardRef(function(e,o){var l=e.color,a=l===void 0?"currentColor":l,t=e.size,r=t===void 0?24:t,p=Le(e,["color","size"]);return h.createElement("svg",z({ref:o,xmlns:"http://www.w3.org/2000/svg",width:r,height:r,viewBox:"0 0 24 24",fill:"none",stroke:a,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},p),h.createElement("polyline",{points:"3 6 5 6 21 6"}),h.createElement("path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"}),h.createElement("line",{x1:"10",y1:"11",x2:"10",y2:"17"}),h.createElement("line",{x1:"14",y1:"11",x2:"14",y2:"17"}))});R.propTypes={color:v.string,size:v.oneOfType([v.string,v.number])};R.displayName="Trash2";const Ee=R,Te="_root_1vck5_4",$e="_section_1vck5_5",Re="_wrapSwitch_1vck5_30",Me="_sep_1vck5_36",De="_label_1vck5_49",i={root:Te,section:$e,wrapSwitch:Re,sep:Me,label:De},Fe="_fieldset_1hnn2_1",We="_input_1hnn2_10",Be="_cnt_1hnn2_10",j={fieldset:Fe,input:We,cnt:Be};function Ue({OptionComponent:e,optionPropsList:o,selectedIndex:l,onChange:a}){const t=re("visually-hidden",j.input),r=p=>{a(p.target.value)};return n("fieldset",{className:j.fieldset,children:o.map((p,d)=>c("label",{children:[n("input",{type:"radio",checked:l===d,name:"selection",value:d,"aria-labelledby":"traffic chart type "+d,onChange:r,className:t}),n("div",{className:j.cnt,children:n(e,{...p})})]},d))})}const{useMemo:Ae}=H,Ve={plugins:{legend:{display:!1}},scales:{x:{display:!1,type:"category"},y:{display:!1,type:"linear"}}},K=[23e3,35e3,46e3,33e3,9e4,68e3,23e3,45e3],Ge=[184e3,183e3,196e3,182e3,19e4,186e3,182e3,189e3],He=K;function Je({id:e}){const o=le.read(),l=Ae(()=>({labels:He,datasets:[{...V,...G[e].up,data:K},{...V,...G[e].down,data:Ge}]}),[e]),a="chart-"+e;return oe(o.Chart,a,l,null,Ve),n("div",{style:{width:80,padding:5},children:n("canvas",{id:a})})}const{useEffect:q,useState:Qe,useCallback:f,useRef:Ke}=H,qe=[{id:0},{id:1},{id:2},{id:3}],Xe=[["debug","Debug"],["info","Info"],["warning","Warning"],["error","Error"],["silent","Silent"]],Ye=[{key:"port",label:"Http Port"},{key:"socks-port",label:"Socks5 Port"},{key:"mixed-port",label:"Mixed Port"},{key:"redir-port",label:"Redir Port"},{key:"mitm-port",label:"MITM Port"}],Ze=[["zh-cn","简体中文"],["zh-tw","繁體中文"],["en","English"],["vi","Vietnamese"]],et=[["direct","Direct"],["rule","Rule"],["script","Script"],["global","Global"]],tt=[["gvisor","gVisor"],["mixed","Mixed"],["system","System"]],nt=e=>({configs:se(e),apiConfig:Q(e)}),at=e=>({selectedChartStyleIndex:ke(e),latencyTestUrl:_e(e),apiConfig:Q(e)}),rt=J(at)(st),ht=J(nt)(lt);function lt({dispatch:e,configs:o,apiConfig:l}){return q(()=>{e(ie(l))},[e,l]),n(rt,{configs:o})}function ot(e){return e&&e.meta&&!e.premium?"Clash.Meta ":e&&e.meta&&e.premium?"sing-box ":"Clash Premium"}function st({dispatch:e,configs:o,selectedChartStyleIndex:l,latencyTestUrl:a,apiConfig:t}){var W,B,U,A;const{t:r,i18n:p}=ce(),[d,_]=Qe(o),M=Ke(o);q(()=>{M.current!==o&&_(o),M.current=o},[o]);const X=f(()=>{e(de("apiConfig"))},[e]),C=f((s,u)=>{_({...d,[s]:u})},[d]),D=f((s,u)=>{const g={...d.tun,[s]:u};_({...d,tun:{...g}})},[d]),b=f(({name:s,value:u})=>{switch(s){case"mode":case"log-level":case"allow-lan":case"sniffing":C(s,u),e(x(t,{[s]:u})),s==="log-level"&&Ce({...t,logLevel:u});break;case"mitm-port":case"redir-port":case"socks-port":case"mixed-port":case"port":if(u!==""){const g=parseInt(u,10);if(g<0||g>65535)return}C(s,u);break;case"enable":case"stack":D(s,u),e(x(t,{tun:{[s]:u}}));break;default:return}},[t,e,C,D]),{selectChartStyleIndex:Y,updateAppConfig:F}=ue(),w=f(s=>{const{name:u,value:g}=s.target;switch(u){case"port":case"socks-port":case"mixed-port":case"redir-port":case"mitm-port":{const O=parseInt(g,10);if(O<0||O>65535)return;e(x(t,{[u]:O}));break}case"latencyTestUrl":{F(u,g);break}case"device name":case"interface name":break;default:throw new Error(`unknown input name ${u}`)}},[t,e,F]),Z=f(()=>{e(me(t))},[t,e]),ee=f(()=>{e(he(t))},[t,e]),te=f(()=>{e(pe(t))},[t,e]),ne=f(()=>{e(ve(t))},[t,e]),ae=f(()=>{e(fe(t))},[t,e]),{data:m}=ge(["/version",t],()=>we("/version",t));return c("div",{children:[n(be,{title:r("Config")}),c("div",{className:i.root,children:[m.meta&&m.premium||Ye.map(s=>d[s.key]!==void 0?c("div",{children:[n("div",{className:i.label,children:s.label}),n(S,{name:s.key,value:d[s.key],onChange:({target:{name:u,value:g}})=>b({name:u,value:g}),onBlur:w})]},s.key):null),c("div",{children:[n("div",{className:i.label,children:"Mode"}),n(k,{options:et,selected:d.mode.toLowerCase(),onChange:s=>b({name:"mode",value:s.target.value})})]}),c("div",{children:[n("div",{className:i.label,children:"Log Level"}),n(k,{options:Xe,selected:d["log-level"].toLowerCase(),onChange:s=>b({name:"log-level",value:s.target.value})})]}),m.meta&&m.premium||c("div",{children:[n("div",{className:i.label,children:r("allow_lan")}),n("div",{className:i.wrapSwitch,children:n(N,{name:"allow-lan",checked:d["allow-lan"],onChange:s=>b({name:"allow-lan",value:s})})})]}),m.meta&&!m.premium&&c("div",{children:[n("div",{className:i.label,children:r("tls_sniffing")}),n("div",{className:i.wrapSwitch,children:n(N,{name:"sniffing",checked:d.sniffing,onChange:s=>b({name:"sniffing",value:s})})})]})]}),n("div",{className:i.sep,children:n("div",{})}),m.meta&&c(ye,{children:[m.premium||c("div",{children:[c("div",{className:i.section,children:[c("div",{children:[n("div",{className:i.label,children:r("enable_tun_device")}),n("div",{className:i.wrapSwitch,children:n(N,{checked:(W=d.tun)==null?void 0:W.enable,onChange:s=>b({name:"enable",value:s})})})]}),c("div",{children:[n("div",{className:i.label,children:"TUN IP Stack"}),n(k,{options:tt,selected:(U=(B=d.tun)==null?void 0:B.stack)==null?void 0:U.toLowerCase(),onChange:s=>b({name:"stack",value:s.target.value})})]}),c("div",{children:[n("div",{className:i.label,children:"Device Name"}),n(S,{name:"device name",value:(A=d.tun)==null?void 0:A.device,onChange:w})]}),c("div",{children:[n("div",{className:i.label,children:"Interface Name"}),n(S,{name:"interface name",value:d["interface-name"]||"",onChange:w})]})]}),n("div",{className:i.sep,children:n("div",{})})]}),c("div",{className:i.section,children:[c("div",{children:[n("div",{className:i.label,children:"Reload"}),n(y,{start:n(P,{size:16}),label:r("reload_config_file"),onClick:Z})]}),m.meta&&!m.premium&&c("div",{children:[n("div",{className:i.label,children:"GEO Databases"}),n(y,{start:n(Se,{size:16}),label:r("update_geo_databases_file"),onClick:ne})]}),c("div",{children:[n("div",{className:i.label,children:"FakeIP"}),n(y,{start:n(Ee,{size:16}),label:r("flush_fake_ip_pool"),onClick:ae})]}),m.meta&&!m.premium&&c("div",{children:[n("div",{className:i.label,children:"Restart"}),n(y,{start:n(P,{size:16}),label:r("restart_core"),onClick:ee})]}),m.meta&&!m.premium&&c("div",{children:[n("div",{className:i.label,children:"⚠️ Upgrade ⚠️"}),n(y,{start:n(P,{size:16}),label:r("upgrade_core"),onClick:te})]})]}),n("div",{className:i.sep,children:n("div",{})})]}),c("div",{className:i.section,children:[c("div",{children:[n("div",{className:i.label,children:r("latency_test_url")}),n(Oe,{name:"latencyTestUrl",type:"text",value:a,onBlur:w})]}),c("div",{children:[n("div",{className:i.label,children:r("lang")}),n("div",{children:n(k,{options:Ze,selected:p.language,onChange:s=>p.changeLanguage(s.target.value)})})]}),c("div",{children:[n("div",{className:i.label,children:r("chart_style")}),n(Ue,{OptionComponent:Je,optionPropsList:qe,selectedIndex:l,onChange:Y})]}),c("div",{children:[c("div",{className:i.label,children:[r("current_backend"),n("p",{children:ot(m)+(t==null?void 0:t.baseURL)})]}),n("div",{className:i.label,children:"Action"}),n(y,{start:n(Ie,{size:16}),label:r("switch_backend"),onClick:X})]})]})]})}export{ht as default}; 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/Config-7eb3f1bb.css: -------------------------------------------------------------------------------- 1 | ._root_1vck5_4,._section_1vck5_5{display:grid;grid-template-columns:repeat(auto-fill,minmax(49%,1fr));max-width:900px;grid-gap:5px;gap:5px}@media screen and (min-width: 30em){._root_1vck5_4,._section_1vck5_5{gap:15px;grid-template-columns:repeat(auto-fill,minmax(300px,1fr))}}._root_1vck5_4,._section_1vck5_5{padding:6px 15px 10px}@media screen and (min-width: 30em){._root_1vck5_4,._section_1vck5_5{padding:10px 40px 15px}}._wrapSwitch_1vck5_30{height:40px;display:flex;align-items:center}._sep_1vck5_36{max-width:900px;padding:0 15px}@media screen and (min-width: 30em){._sep_1vck5_36{padding:0 40px}}._sep_1vck5_36>div{border-top:1px dashed #373737}._label_1vck5_49{padding:15px 0;font-size:small}._fieldset_1hnn2_1{margin:0;padding:0;border:0;display:flex;flex-wrap:wrap;flex-direction:row}._input_1hnn2_10+._cnt_1hnn2_10{border:1px solid transparent;border-radius:4px;cursor:pointer;margin-bottom:5px}._input_1hnn2_10:focus+._cnt_1hnn2_10{border-color:var(--color-focus-blue)}._input_1hnn2_10:checked+._cnt_1hnn2_10{border-color:var(--color-focus-blue)} 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/Connections-2b49f1fb.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";.react-tabs{-webkit-tap-highlight-color:transparent}.react-tabs__tab-list{margin:0;padding:0 30px}.react-tabs__tab{display:inline-flex;align-items:center;border:1px solid transparent;border-radius:5px;bottom:-1px;position:relative;list-style:none;padding:6px 10px;cursor:pointer;font-size:1.2em;opacity:.5}.react-tabs__tab--selected{opacity:1}.react-tabs__tab--disabled{color:GrayText;cursor:default}.react-tabs__tab:focus{border-color:var(--color-focus-blue);outline:none}.react-tabs__tab:focus:after{content:"";position:absolute}.react-tabs__tab-panel{display:none}.react-tabs__tab-panel--selected{display:block}._btn_lzu00_1{margin-right:10px}._placeHolder_1vhnb_1{margin-top:20%;height:100%;display:flex;align-items:center;justify-content:center;color:var(--color-background);opacity:.1}@media (max-width: 768px){._placeHolder_1vhnb_1{margin-top:35%}}._connQty_1vhnb_16{font-family:var(--font-normal);font-size:.75em;margin-left:3px;padding:2px 7px;display:inline-flex;justify-content:center;align-items:center;background-color:var(--bg-near-transparent);border-radius:30px}._header_1vhnb_28{display:grid;grid-template-columns:1fr minmax(auto,290px);align-items:center;padding-right:15px}@media (--breakpoint-not-small){._header_1vhnb_28{padding-right:25px}}._inputWrapper_1vhnb_44{margin:0;width:100%;max-width:350px;justify-self:flex-end}@media (--breakpoint-not-small){._inputWrapper_1vhnb_44{margin:0 25px}}._input_1vhnb_44{-webkit-appearance:none;background-color:var(--color-input-bg);background-image:none;border-radius:18px;border:1px solid var(--color-input-border);box-sizing:border-box;color:var(--color-text-secondary);display:inline-block;font-size:inherit;height:36px;outline:none;padding:0 15px;transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}.connections-table td.ctrl{min-width:4em;text-align:center;display:flex;justify-content:center;align-items:center}.connections-table td.ctrl svg{height:16px}.connections-table td.type,.connections-table td.start,.connections-table td.downloadSpeedCurr,.connections-table td.uploadSpeedCurr,.connections-table td.download,.connections-table td.upload{min-width:7em;text-align:center}._th_12ddc_6{height:50px;background:var(--color-background);top:0;font-size:1em;-webkit-user-select:none;-ms-user-select:none;user-select:none;text-align:center}._th_12ddc_6:hover{color:var(--color-text-highlight)}._btnSection_12ddc_18 button{margin-right:15px}._break_12ddc_22{word-wrap:break-word;word-break:break-all;align-items:center;text-align:left}._td_12ddc_29{padding:10px 5px;font-size:.9em;min-width:9em;cursor:default;text-align:left;vertical-align:middle;white-space:nowrap;font-family:var(--font-normal)}._td_12ddc_29:hover{color:var(--color-text-highlight)}._overlay_12ddc_44{background:#444}._modal_12ddc_48{background-color:var(--bg-modal)}._table_12ddc_52{border-collapse:collapse}._td_12ddc_29._odd_12ddc_56{background:var(--color-row-odd)}._center_12ddc_61{min-width:7em;text-align:center}._sortIconContainer_12ddc_66{float:right;width:1em;height:1em}._rotate180_12ddc_72{-webkit-transform:rotate(180deg);transform:rotate(180deg)}._overlay_1cbjw_1{background-color:#0009}._cnt_1cbjw_5{background-color:var(--bg-modal);color:var(--color-text);max-width:300px;line-height:1.4;-webkit-transform:scale(1.2);transform:scale(1.2);opacity:.6;transition:all .3s ease}._afterOpen_1cbjw_15{opacity:1;-webkit-transform:scale(1);transform:scale(1)}._btngrp_1cbjw_20{display:flex;align-items:center;justify-content:center;margin-top:30px}._columnManagerRow_e56pa_1{width:200px;display:flex;margin:5px 0;align-items:center}._columnManagerRow_e56pa_1 ._columnManageLabel_e56pa_7{flex:1;margin-left:10px}._columnManagerRow_e56pa_1 ._columnManageSwitch_e56pa_11{-webkit-transform:scale(.7);transform:scale(.7);height:20px;display:flex;align-items:center}._sourceipTable_2lem6_1 input{width:120px}._iptableTipContainer_2lem6_5{width:300px} 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/Fab-48def6bf.css: -------------------------------------------------------------------------------- 1 | .rtf{box-sizing:border-box;margin:25px;position:fixed;white-space:nowrap;z-index:9998;padding-left:0;list-style:none}.rtf.open .rtf--mb{box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.rtf.open .rtf--mb>ul{list-style:none;margin:0;padding:0}.rtf.open .rtf--ab__c:hover>span{transition:ease-in-out opacity .2s;opacity:.9}.rtf.open .rtf--ab__c>span.always-show{transition:ease-in-out opacity .2s;opacity:.9}.rtf.open .rtf--ab__c:nth-child(1){-webkit-transform:translateY(-60px) scale(1);transform:translateY(-60px) scale(1);transition-delay:.03s}.rtf.open .rtf--ab__c:nth-child(1).top{-webkit-transform:translateY(60px) scale(1);transform:translateY(60px) scale(1)}.rtf.open .rtf--ab__c:nth-child(2){-webkit-transform:translateY(-120px) scale(1);transform:translateY(-120px) scale(1);transition-delay:.09s}.rtf.open .rtf--ab__c:nth-child(2).top{-webkit-transform:translateY(120px) scale(1);transform:translateY(120px) scale(1)}.rtf.open .rtf--ab__c:nth-child(3){-webkit-transform:translateY(-180px) scale(1);transform:translateY(-180px) scale(1);transition-delay:.12s}.rtf.open .rtf--ab__c:nth-child(3).top{-webkit-transform:translateY(180px) scale(1);transform:translateY(180px) scale(1)}.rtf.open .rtf--ab__c:nth-child(4){-webkit-transform:translateY(-240px) scale(1);transform:translateY(-240px) scale(1);transition-delay:.15s}.rtf.open .rtf--ab__c:nth-child(4).top{-webkit-transform:translateY(240px) scale(1);transform:translateY(240px) scale(1)}.rtf.open .rtf--ab__c:nth-child(5){-webkit-transform:translateY(-300px) scale(1);transform:translateY(-300px) scale(1);transition-delay:.18s}.rtf.open .rtf--ab__c:nth-child(5).top{-webkit-transform:translateY(300px) scale(1);transform:translateY(300px) scale(1)}.rtf.open .rtf--ab__c:nth-child(6){-webkit-transform:translateY(-360px) scale(1);transform:translateY(-360px) scale(1);transition-delay:.21s}.rtf.open .rtf--ab__c:nth-child(6).top{-webkit-transform:translateY(360px) scale(1);transform:translateY(360px) scale(1)}.rtf--mb__c{padding:25px;margin:-25px}.rtf--mb__c *:last-child{margin-bottom:0}.rtf--mb__c:hover>span{transition:ease-in-out opacity .2s;opacity:.9}.rtf--mb__c>span.always-show{transition:ease-in-out opacity .2s;opacity:.9}.rtf--mb__c>span{opacity:0;transition:ease-in-out opacity .2s;position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);margin-right:6px;margin-left:4px;background:rgba(0,0,0,.75);padding:2px 4px;border-radius:2px;color:#fff;font-size:13px;box-shadow:0 0 4px #00000024,0 4px 8px #00000047}.rtf--mb__c>span.right{right:100%}.rtf--mb{width:48px;height:48px;background:var(--btn-bg);z-index:9999;display:inline-flex;justify-content:center;align-items:center;position:relative;border:none;border-radius:50%;box-shadow:0 0 4px #00000024,0 4px 8px #00000047;cursor:pointer;outline:none;padding:0;-webkit-user-drag:none;font-weight:700;color:#f1f1f1;font-size:18px}.rtf--mb>*{transition:ease-in-out transform .2s}.rtf--ab__c{display:block;position:absolute;top:0;right:1px;padding:10px 0;margin:-10px 0;transition:ease-in-out transform .2s}.rtf--ab__c>span{opacity:0;transition:ease-in-out opacity .2s;position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);margin-right:6px;background:rgba(0,0,0,.75);padding:2px 4px;border-radius:2px;color:#fff;font-size:13px;box-shadow:0 0 4px #00000024,0 4px 8px #00000047}.rtf--ab__c>span.right{right:100%}.rtf--ab__c:nth-child(1){-webkit-transform:translateY(-60px) scale(0);transform:translateY(-60px) scale(0);transition-delay:.21s}.rtf--ab__c:nth-child(1).top{-webkit-transform:translateY(60px) scale(0);transform:translateY(60px) scale(0)}.rtf--ab__c:nth-child(2){-webkit-transform:translateY(-120px) scale(0);transform:translateY(-120px) scale(0);transition-delay:.18s}.rtf--ab__c:nth-child(2).top{-webkit-transform:translateY(120px) scale(0);transform:translateY(120px) scale(0)}.rtf--ab__c:nth-child(3){-webkit-transform:translateY(-180px) scale(0);transform:translateY(-180px) scale(0);transition-delay:.15s}.rtf--ab__c:nth-child(3).top{-webkit-transform:translateY(180px) scale(0);transform:translateY(180px) scale(0)}.rtf--ab__c:nth-child(4){-webkit-transform:translateY(-240px) scale(0);transform:translateY(-240px) scale(0);transition-delay:.12s}.rtf--ab__c:nth-child(4).top{-webkit-transform:translateY(240px) scale(0);transform:translateY(240px) scale(0)}.rtf--ab__c:nth-child(5){-webkit-transform:translateY(-300px) scale(0);transform:translateY(-300px) scale(0);transition-delay:.09s}.rtf--ab__c:nth-child(5).top{-webkit-transform:translateY(300px) scale(0);transform:translateY(300px) scale(0)}.rtf--ab__c:nth-child(6){-webkit-transform:translateY(-360px) scale(0);transform:translateY(-360px) scale(0);transition-delay:.03s}.rtf--ab__c:nth-child(6).top{-webkit-transform:translateY(360px) scale(0);transform:translateY(360px) scale(0)}.rtf--ab{height:40px;width:40px;margin-right:4px;background-color:#aaa;display:inline-flex;justify-content:center;align-items:center;position:relative;border:none;border-radius:50%;box-shadow:0 0 4px #00000024,0 4px 8px #00000047;cursor:pointer;outline:none;padding:0;-webkit-user-drag:none;font-weight:700;color:#f1f1f1;font-size:16px;z-index:10000}.rtf--ab:hover{background:var(--color-focus-blue);border:1px solid var(--color-focus-blue);color:#fff}.rtf--ab:focus{border-color:var(--color-focus-blue)}._spining_4i8sg_1{position:relative;border-radius:50%;background:linear-gradient(60deg,#e66465,#9198e5);width:48px;height:48px;display:flex;justify-content:center;align-items:center}._spining_4i8sg_1:before{content:"";position:absolute;top:0;bottom:0;left:0;right:0;border:2px solid transparent;border-top-color:currentColor;border-radius:50%;-webkit-animation:_spining_keyframes_4i8sg_1 1s linear infinite;animation:_spining_keyframes_4i8sg_1 1s linear infinite}@-webkit-keyframes _spining_keyframes_4i8sg_1{0%{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes _spining_keyframes_4i8sg_1{0%{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}} 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/Fab-e6dedc20.js: -------------------------------------------------------------------------------- 1 | import{b as e,j as b,s as y,r as l}from"./index-7c6466d3.js";const E="_spining_4i8sg_1",F="_spining_keyframes_4i8sg_1",M={spining:E,spining_keyframes:F},{useState:j}=y;function B({children:s}){return e("span",{className:M.spining,children:s})}const H={right:10,bottom:10},L=({children:s,...n})=>e("button",{type:"button",...n,className:"rtf--ab",children:s}),v=({children:s,...n})=>e("button",{type:"button",className:"rtf--mb",...n,children:s}),O={bottom:24,right:24},R=({event:s="hover",style:n=O,alwaysShowTitle:o=!1,children:f,icon:g,mainButtonStyles:h,onClick:p,text:d,..._})=>{const[a,r]=j(!1),c=o||!a,u=()=>r(!0),m=()=>r(!1),k=()=>s==="hover"&&u(),x=()=>s==="hover"&&m(),N=t=>p?p(t):(t.persist(),s==="click"?a?m():u():null),$=(t,i)=>{t.persist(),r(!1),setTimeout(()=>{i(t)},1)},C=()=>l.Children.map(f,(t,i)=>l.isValidElement(t)?b("li",{className:`rtf--ab__c ${"top"in n?"top":""}`,children:[l.cloneElement(t,{"data-testid":`action-button-${i}`,"aria-label":t.props.text||`Menu button ${i+1}`,"aria-hidden":c,tabIndex:a?0:-1,...t.props,onClick:I=>{t.props.onClick&&$(I,t.props.onClick)}}),t.props.text&&e("span",{className:`${"right"in n?"right":""} ${o?"always-show":""}`,"aria-hidden":c,children:t.props.text})]}):null);return e("ul",{onMouseEnter:k,onMouseLeave:x,className:`rtf ${a?"open":"closed"}`,"data-testid":"fab",style:n,..._,children:b("li",{className:"rtf--mb__c",children:[e(v,{onClick:N,style:h,"data-testid":"main-button",role:"button","aria-label":"Floating menu",tabIndex:0,children:g}),d&&e("span",{className:`${"right"in n?"right":""} ${o?"always-show":""}`,"aria-hidden":c,children:d}),e("ul",{children:C()})]})})};export{L as A,R as F,B as I,H as p}; 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/Input-eec9e65c.js: -------------------------------------------------------------------------------- 1 | import{b as s,t as a,R as f}from"./index-7c6466d3.js";const{useState:i,useRef:l,useEffect:p,useCallback:m}=f;function C(t){return s("input",{className:a.input,...t})}function R({value:t,...r}){const[u,n]=i(t),e=l(t);p(()=>{e.current!==t&&n(t),e.current=t},[t]);const c=m(o=>n(o.target.value),[n]);return s("input",{className:a.input,value:u,onChange:c,...r})}export{C as I,R as S}; 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/Logs-4c263fad.css: -------------------------------------------------------------------------------- 1 | ._RuleSearch_ue4xf_1{padding:0 40px 5px}@media (max-width: 768px){._RuleSearch_ue4xf_1{padding:0 25px 5px}}._RuleSearchContainer_ue4xf_10{position:relative;height:40px}@media (max-width: 768px){._RuleSearchContainer_ue4xf_10{height:30px}}._inputWrapper_ue4xf_20{position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);left:0;width:100%}._input_ue4xf_20{-webkit-appearance:none;background-color:var(--color-input-bg);background-image:none;border-radius:20px;border:1px solid var(--color-input-border);box-sizing:border-box;color:var(--color-text-secondary);display:inline-block;font-size:inherit;height:40px;outline:none;padding:0 15px 0 35px;transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}._iconWrapper_ue4xf_45{position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);left:10px;line-height:0}._logMeta_pycfb_1{font-size:.8em;margin-bottom:5px;display:block;line-height:1.55em}._logType_pycfb_8{flex-shrink:0;text-align:center;width:66px;border-radius:100px;padding:3px 5px;margin:0 8px}._logTime_pycfb_17{flex-shrink:0;color:#fb923c}._logText_pycfb_22{flex-shrink:0;color:#888;align-items:center;line-height:1.35em;width:100%}@media (max-width: 768px){._logText_pycfb_22{display:inline-block}}._logsWrapper_pycfb_37{margin:45px;padding:10px;background-color:var(--bg-log-info-card);border-radius:4px;color:var(--color-text);overflow-y:auto}@media (max-width: 768px){._logsWrapper_pycfb_37{margin:25px}}._logsWrapper_pycfb_37 .log{margin-bottom:10px}._logPlaceholder_pycfb_54{display:flex;flex-direction:column;align-items:center;justify-content:center;color:#2d2d30}._logPlaceholder_pycfb_54 div:nth-child(2){color:var(--color-text-secondary);font-size:1.4em;opacity:.6}._logPlaceholderIcon_pycfb_67{opacity:.3} 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/Logs-8ed10c2c.js: -------------------------------------------------------------------------------- 1 | import{r as f,R as y,p as d,u as S,b as a,j as p,d as T,X as R,Y as w,F as L,Z as W,C as N,q as C,$ as j,a0 as O,g as I,a1 as k,s as z}from"./index-7c6466d3.js";import{r as E,s as $,f as M}from"./logs-8ad08aa6.js";import{d as F}from"./debounce-c1ba2006.js";import{u as A}from"./useRemainingViewPortHeight-aa016eed.js";import{F as H,p as B}from"./Fab-e6dedc20.js";import{P as D,a as Y}from"./play-4baa6dad.js";function v(){return v=Object.assign||function(e){for(var o=1;o=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(t[n]=e[n])}return t}function V(e,o){if(e==null)return{};var t={},n=Object.keys(e),r,s;for(s=0;s=0)&&(t[r]=e[r]);return t}var b=f.forwardRef(function(e,o){var t=e.color,n=t===void 0?"currentColor":t,r=e.size,s=r===void 0?24:r,i=q(e,["color","size"]);return y.createElement("svg",v({ref:o,xmlns:"http://www.w3.org/2000/svg",width:s,height:s,viewBox:"0 0 24 24",fill:"none",stroke:n,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},i),y.createElement("circle",{cx:"11",cy:"11",r:"8"}),y.createElement("line",{x1:"21",y1:"21",x2:"16.65",y2:"16.65"}))});b.propTypes={color:d.string,size:d.oneOfType([d.string,d.number])};b.displayName="Search";const X=b,Z="_RuleSearch_ue4xf_1",G="_RuleSearchContainer_ue4xf_10",J="_inputWrapper_ue4xf_20",K="_input_ue4xf_20",Q="_iconWrapper_ue4xf_45",g={RuleSearch:Z,RuleSearchContainer:G,inputWrapper:J,input:K,iconWrapper:Q};function U({dispatch:e,searchText:o,updateSearchText:t}){const{t:n}=S(),[r,s]=f.useState(o),i=f.useCallback(c=>{e(t(c))},[e,t]),u=f.useMemo(()=>F(i,300),[i]),m=c=>{s(c.target.value),u(c.target.value)};return a("div",{className:g.RuleSearch,children:p("div",{className:g.RuleSearchContainer,children:[a("div",{className:g.inputWrapper,children:a("input",{type:"text",value:r,onChange:m,className:g.input,placeholder:n("Search")})}),a("div",{className:g.iconWrapper,children:a(X,{size:20})})]})})}const ee=e=>({searchText:R(e),updateSearchText:w}),te=T(ee)(U),re="_logMeta_pycfb_1",oe="_logType_pycfb_8",ne="_logTime_pycfb_17",ae="_logText_pycfb_22",se="_logsWrapper_pycfb_37",ce="_logPlaceholder_pycfb_54",le="_logPlaceholderIcon_pycfb_67",l={logMeta:re,logType:oe,logTime:ne,logText:ae,logsWrapper:se,logPlaceholder:ce,logPlaceholderIcon:le},{useCallback:x,useEffect:ie}=z,pe={debug:"#389d3d",info:"#58c3f2",warning:"#cc5abb",error:"#c11c1c"},ge={debug:"debug",info:"info",warning:"warn",error:"error"};function ue({time:e,payload:o,type:t}){return p("div",{className:l.logMeta,children:[a("span",{className:l.logTime,children:e}),p("span",{className:l.logType,style:{color:pe[t]},children:["[ ",ge[t]," ]"]}),a("span",{className:l.logText,children:o})]})}function he({dispatch:e,logLevel:o,apiConfig:t,logs:n,logStreamingPaused:r}){const s=L(),i=x(()=>{r?E({...t,logLevel:o}):$(),s.app.updateAppConfig("logStreamingPaused",!r)},[t,o,r,s.app]),u=x(_=>e(W(_)),[e]);ie(()=>{M({...t,logLevel:o},u)},[t,o,u]);const[m,c]=A(),{t:h}=S();return p("div",{children:[a(N,{title:h("Logs")}),a(te,{}),a("div",{ref:m,children:n.length===0?p("div",{className:l.logPlaceholder,style:{height:c*.9},children:[a("div",{className:l.logPlaceholderIcon,children:a(C,{width:200,height:200})}),a("div",{children:h("no_logs")})]}):p("div",{className:l.logsWrapper,style:{height:c*.85},children:[n.map((_,P)=>a("div",{className:"",children:a(ue,{..._})},P)),a(H,{icon:r?a(D,{size:16}):a(Y,{size:16}),mainButtonStyles:r?{background:"#e74c3c"}:{},style:B,text:h(r?"Resume Refresh":"Pause Refresh"),onClick:i})]})})]})}const de=e=>({logs:j(e),logLevel:O(e),apiConfig:I(e),logStreamingPaused:k(e)}),xe=T(de)(he);export{xe as default}; 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/Proxies-06b60f95.css: -------------------------------------------------------------------------------- 1 | ._FlexCenter_1380a_1{display:flex;justify-content:center;align-items:center}._header_19ilz_1{display:flex;align-items:center;padding:5px}._header_19ilz_1:focus{outline:none}._header_19ilz_1 ._arrow_19ilz_9{display:inline-flex;-webkit-transform:rotate(0deg);transform:rotate(0);transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}._header_19ilz_1 ._arrow_19ilz_9._isOpen_19ilz_14{-webkit-transform:rotate(180deg);transform:rotate(180deg)}._header_19ilz_1 ._arrow_19ilz_9:focus{outline:var(--color-focus-blue) solid 1px}._btn_19ilz_21{margin-left:5px}._qty_19ilz_26{font-family:var(--font-normal);font-size:.75em;margin-left:3px;padding:2px 7px;display:inline-flex;justify-content:center;align-items:center;background-color:var(--bg-near-transparent);border-radius:30px}._header_1qjca_1{margin-bottom:12px}._group_1qjca_5{padding:10px;background-color:var(--color-bg-card);border-radius:10px;box-shadow:0 1px 5px #0000001a}._zapWrapper_1qjca_12{width:20px;height:20px;display:flex;align-items:center;justify-content:center}._arrow_1qjca_20{display:inline-flex;-webkit-transform:rotate(0deg);transform:rotate(0);transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}._arrow_1qjca_20._isOpen_1qjca_25{-webkit-transform:rotate(180deg);transform:rotate(180deg)}._arrow_1qjca_20:focus{outline:var(--color-focus-blue) solid 1px}._proxy_xgbmr_4{padding:5px;position:relative;border-radius:8px;overflow:hidden;display:flex;flex-direction:column;justify-content:space-between;outline:var(--color-proxy-border) 1px outset;border:2px solid transparent;background-color:var(--color-bg-proxy)}._proxy_xgbmr_4:focus{border-color:var(--color-focus-blue)}@media screen and (min-width: 30em){._proxy_xgbmr_4{border-radius:10px;padding:10px}}._proxy_xgbmr_4._now_xgbmr_25{background-color:var(--color-focus-blue);color:#ddd}._proxy_xgbmr_4._error_xgbmr_29{opacity:.5}._proxy_xgbmr_4._selectable_xgbmr_32{transition:-webkit-transform .2s ease-in-out;transition:transform .2s ease-in-out;transition:transform .2s ease-in-out,-webkit-transform .2s ease-in-out;cursor:pointer}._proxy_xgbmr_4._selectable_xgbmr_32:hover{border-color:var(--card-hover-border-lightness)}._proxyType_xgbmr_40{font-family:var(--font-mono);font-size:.6em}@media screen and (min-width: 30em){._proxyType_xgbmr_40{font-size:.7em}}._udpType_xgbmr_50{font-family:var(--font-mono);font-size:.6em;margin-right:3px}@media screen and (min-width: 30em){._udpType_xgbmr_50{font-size:.7em}}._tfoType_xgbmr_61{padding:2px}._row_xgbmr_65{display:flex;align-items:center;height:auto;font-weight:400;justify-content:space-between}._proxyName_xgbmr_73{width:100%;margin-bottom:5px;font-size:.75em}@media screen and (min-width: 30em){._proxyName_xgbmr_73{font-size:.85em}}._proxySmall_xgbmr_84{position:relative;width:15px;height:15px;border-radius:50%}._proxySmall_xgbmr_84 ._now_xgbmr_25{position:absolute;width:9px;height:9px;margin:auto;top:0;right:0;bottom:0;left:0;border-radius:50%;background-color:#fffdfd}._proxySmall_xgbmr_84._selectable_xgbmr_32{transition:-webkit-transform .1s ease-in-out;transition:transform .1s ease-in-out;transition:transform .1s ease-in-out,-webkit-transform .1s ease-in-out;cursor:pointer}._proxySmall_xgbmr_84._selectable_xgbmr_32:hover{-webkit-transform:scale(1.5);transform:scale(1.5)}._proxyLatency_1h5y2_4{border-radius:20px;color:#eee;font-size:.75em}@media screen and (min-width: 30em){._proxyLatency_1h5y2_4{font-size:.8em}}._list_4awfc_4{margin:8px 0;display:grid;grid-gap:10px}._detail_4awfc_10{grid-template-columns:auto auto}@media screen and (min-width: 30em){._detail_4awfc_10{grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}}._summary_4awfc_19{grid-template-columns:repeat(auto-fill,12px);padding-left:10px}._updatedAt_1d817_4{margin-bottom:12px;margin-left:5px}._updatedAt_1d817_4 small{color:#777}._body_1d817_12{margin:10px 15px;padding:10px;background-color:var(--color-bg-card);border-radius:10px;box-shadow:0 1px 5px #0000001a}@media screen and (min-width: 30em){._body_1d817_12{margin:10px 40px}}._actionFooter_1d817_25{display:flex}._actionFooter_1d817_25 button{margin:0 5px}._actionFooter_1d817_25 button:first-child{margin-left:0}._refresh_1d817_35{display:flex;justify-content:center;align-items:center;cursor:pointer}._labeledInput_cmki0_1{max-width:85vw;width:400px;display:flex;justify-content:space-between;align-items:center;font-size:13px;padding:13px 0}hr{height:1px;background-color:var(--color-separator);border:none;outline:none;margin:1rem 0px}._topBar_15n7g_4{position:-webkit-sticky;position:sticky;top:0;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;z-index:1;background-color:var(--color-background2);-webkit-backdrop-filter:blur(36px);backdrop-filter:blur(36px)}._topBarRight_15n7g_16{display:flex;align-items:center;flex-wrap:wrap;flex:1;justify-content:flex-end;margin-right:20px}._textFilterContainer_15n7g_25{max-width:350px;min-width:150px;flex:1;margin-right:8px}._group_15n7g_32{padding:10px 15px}@media screen and (min-width: 30em){._group_15n7g_32{padding:10px 40px}} 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/Proxies-ce7620dc.js: -------------------------------------------------------------------------------- 1 | import{r as k,R as X,p as $,b as s,j as u,B as _,s as x,a2 as qe,a3 as Ue,a4 as ge,a5 as He,d as S,c as P,a6 as Ge,O as E,a7 as Ke,a8 as we,a9 as ne,T as xe,N as Ve,F as G,aa as Ye,ab as Ze,ac as Q,P as Xe,ad as Ce,ae as re,af as oe,ag as Qe,ah as Je,u as se,ai as et,aj as Oe,ak as tt,g as Pe,C as ke,S as ae,al as nt,am as rt,an as ot,ao as st,ap as it}from"./index-7c6466d3.js";import{C as J,B as ce}from"./BaseModal-0f630377.js";import{F as at,p as ct,A as lt,I as ut}from"./Fab-e6dedc20.js";import{R as dt,T as ht}from"./TextFitler-2e63abd5.js";import{f as ft}from"./index-84fa0cb3.js";import{R as pt}from"./rotate-cw-76728396.js";import{S as vt}from"./Select-3321dc18.js";import"./debounce-c1ba2006.js";function ee(){return ee=Object.assign||function(e){for(var t=1;t=0)&&Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}function yt(e,t){if(e==null)return{};var n={},r=Object.keys(e),o,i;for(i=0;i=0)&&(n[o]=e[o]);return n}var ie=k.forwardRef(function(e,t){var n=e.color,r=n===void 0?"currentColor":n,o=e.size,i=o===void 0?24:o,a=mt(e,["color","size"]);return X.createElement("svg",ee({ref:t,xmlns:"http://www.w3.org/2000/svg",width:i,height:i,viewBox:"0 0 24 24",fill:"none",stroke:r,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},a),X.createElement("polygon",{points:"13 2 3 14 12 14 11 22 21 10 12 10 13 2"}))});ie.propTypes={color:$.string,size:$.oneOfType([$.string,$.number])};ie.displayName="Zap";const A=ie,_t="_FlexCenter_1380a_1",bt={FlexCenter:_t};function gt({children:e}){return s("div",{className:bt.FlexCenter,children:e})}const{useRef:le,useEffect:wt}=x;function xt({onClickPrimaryButton:e,onClickSecondaryButton:t}){const n=le(null),r=le(null);return wt(()=>{n.current.focus()},[]),u("div",{onKeyDown:i=>{i.keyCode===39?r.current.focus():i.keyCode===37&&n.current.focus()},children:[s("h2",{children:"Close Connections?"}),s("p",{children:"Click 'Yes' to close those connections that are still using the old selected proxy in this group"}),s("div",{style:{height:30}}),u(gt,{children:[s(_,{onClick:e,ref:n,children:"Yes"}),s("div",{style:{width:20}}),s(_,{onClick:t,ref:r,children:"No"})]})]})}const Ct="_header_19ilz_1",Ot="_arrow_19ilz_9",Pt="_isOpen_19ilz_14",kt="_btn_19ilz_21",Et="_qty_19ilz_26",ue={header:Ct,arrow:Ot,isOpen:Pt,btn:kt,qty:Et};function Ee({name:e,type:t,toggle:n,qty:r}){const o=k.useCallback(i=>{i.preventDefault(),(i.key==="Enter"||i.key===" ")&&n()},[n]);return u("div",{className:ue.header,onClick:n,style:{cursor:"pointer"},tabIndex:0,onKeyDown:o,role:"button",children:[s("div",{children:s(qe,{name:e,type:t})}),typeof r=="number"?s("span",{className:ue.qty,children:r}):null]})}const{useMemo:Tt}=x;function St(e,t){return e.filter(n=>{const r=t[n];return r===void 0?!0:r.number!==0})}const F=(e,t)=>{if(e&&typeof e.number=="number"&&e.number>0)return e.number;const n=t&&t.type;return n&&He.indexOf(n)>-1?-1:999999},Rt={Natural:e=>e,LatencyAsc:(e,t,n)=>e.sort((r,o)=>{const i=F(t[r],n&&n[r]),a=F(t[o],n&&n[o]);return i-a}),LatencyDesc:(e,t,n)=>e.sort((r,o)=>{const i=F(t[r],n&&n[r]);return F(t[o],n&&n[o])-i}),NameAsc:e=>e.sort(),NameDesc:e=>e.sort((t,n)=>t>n?-1:tr.trim()).filter(r=>!!r);return n.length===0?e:e.filter(r=>{let o=0;for(;o-1)return!0}return!1})}function Lt(e,t,n,r,o,i){let a=[...e];return n&&(a=St(e,t)),typeof r=="string"&&r!==""&&(a=At(a,r)),Rt[o](a,t,i)}function Te(e,t,n,r,o){const[i]=Ue(ge);return Tt(()=>Lt(e,t,n,i,r,o),[e,t,n,i,r,o])}const Mt="_header_1qjca_1",Nt="_group_1qjca_5",Dt="_zapWrapper_1qjca_12",zt="_arrow_1qjca_20",Bt="_isOpen_1qjca_25",b={header:Mt,group:Nt,zapWrapper:Dt,arrow:zt,isOpen:Bt},Se={Right:39,Left:37,Enter:13,Space:32},$t="_proxy_xgbmr_4",Ft="_now_xgbmr_25",jt="_error_xgbmr_29",It="_selectable_xgbmr_32",Wt="_proxyType_xgbmr_40",qt="_udpType_xgbmr_50",Ut="_tfoType_xgbmr_61",Ht="_row_xgbmr_65",Gt="_proxyName_xgbmr_73",Kt="_proxySmall_xgbmr_84",y={proxy:$t,now:Ft,error:jt,selectable:It,proxyType:Wt,udpType:qt,tfoType:Ut,row:Ht,proxyName:Gt,proxySmall:Kt},Vt="_proxyLatency_1h5y2_4",Yt={proxyLatency:Vt};function Zt({number:e,color:t}){return s("span",{className:Yt.proxyLatency,style:{color:t},children:u("span",{children:[e," ms"]})})}const{useMemo:W}=x,R={good:"#67c23a",normal:"#d4b75c",bad:"#e67f3c",na:"#909399"};function Re({number:e}={},t){const n={good:t?800:200,normal:t?1500:500};return e===0?R.na:eXt({number:l},o),[l]),d=W(()=>{let f=t;return r&&typeof r.number=="number"&&(f+=" "+r.number+" ms"),f},[t,r]),h=k.useCallback(()=>{i&&a&&a(t)},[t,a,i]),m=k.useCallback(f=>{f.keyCode===Se.Enter&&h()},[h]);return s("div",{title:d,className:P(y.proxySmall,{[y.selectable]:i}),style:{background:v,scale:e?"1.2":"1"},onClick:h,onKeyDown:m,role:i?"menuitem":"",children:e&&s("div",{className:y.now})})}function Jt(e){return e==="Shadowsocks"?"SS":e}const en=e=>({left:e.left+window.scrollX-5,top:e.top+window.scrollY-38});function tn({children:e,label:t,"aria-label":n}){const[r,o]=Ge();return u(E,{children:[k.cloneElement(e,r),s(Ke,{...o,label:t,"aria-label":n,position:en})]})}function nn({now:e,name:t,proxy:n,latency:r,httpsLatencyTest:o,isSelectable:i,onClick:a}){var C;const c=(C=n.history[n.history.length-1])==null?void 0:C.delay,l=(r==null?void 0:r.number)??c,v=W(()=>Re({number:l},o),[l]),d=k.useCallback(()=>{i&&a&&a(t)},[t,a,i]);function h(g,O){return g?O?"XUDP":"UDP":""}function m(g){return g?s("svg",{viewBox:"0 0 1024 1024",version:"1.1",xmlns:"http://www.w3.org/2000/svg","p-id":"2962",width:"10",height:"10",children:s("path",{d:"M648.093513 719.209284l-1.492609-40.940127 31.046263-26.739021c202.73892-174.805813 284.022131-385.860697 255.70521-561.306199-176.938111-28.786027-389.698834 51.857494-563.907604 254.511123l-26.31256 30.619803-40.38573-0.938211c-60.557271-1.407317-111.903014 12.79379-162.822297 47.0385l189.561318 127.084977-37.95491 68.489421c-9.126237 16.461343-0.554398 53.307457 29.084549 82.818465 29.5963 29.511008 67.380626 38.381369 83.287571 29.852176l68.318836-36.760822 127.639376 191.267156c36.163779-52.11337 50.450177-103.629696 48.189941-165.039887zM994.336107 16.105249l10.490908 2.686696 2.64405 10.405615c47.46496 178.089552-1.023503 451.492838-274.170913 686.898568 4.051367 111.263324-35.396151 200.222809-127.255561 291.741051l-15.779008 15.693715-145.934494-218.731157c-51.217805 27.59194-128.790816 10.405616-183.93205-44.522388-55.226525-55.013296-72.41285-132.287785-43.498885-184.529093L0.002773 430.325513l15.736362-15.65107c89.300652-88.959484 178.64395-128.108481 289.011709-125.549722C539.730114 15.806727 815.56422-31.061189 994.336107 16.105249zM214.93844 805.098259c28.572797 28.572797 22.346486 79.49208-12.537914 114.376479C156.428175 965.489735 34.034254 986.002445 34.034254 986.002445s25.331704-127.084978 66.612998-168.323627c34.8844-34.8844 85.633099-41.281295 114.291188-12.580559zM661.01524 298.549479a63.968948 63.968948 0 1 0 0 127.937897 63.968948 63.968948 0 0 0 0-127.937897z","p-id":"2963"})}):""}const p=k.useCallback(g=>{g.keyCode===Se.Enter&&d()},[d]),f=W(()=>P(y.proxy,{[y.now]:e,[y.error]:r&&r.error,[y.selectable]:i}),[i,e,r]);return u("div",{tabIndex:0,className:f,onClick:d,onKeyDown:p,role:i?"menuitem":"",children:[u("div",{className:P(y.proxyName,y.row),children:[s(tn,{label:t,"aria-label":`proxy name: ${t}`,children:s("span",{children:t})}),s("span",{className:y.proxyType,style:{paddingLeft:4,opacity:.6,color:"#51A8DD"},children:h(n.udp,n.xudp)})]}),u("div",{className:y.row,children:[u("div",{className:y.row,children:[s("span",{className:y.proxyType,style:{paddingRight:4,opacity:.6,color:"#F596AA"},children:Jt(n.type)}),m(n.tfo)]}),l?s(Zt,{number:l,color:v}):null]})]})}const Ae=(e,{name:t})=>{const n=we(e),r=ne(e),o=xe(e);return{proxy:n[t]||{name:t,history:[]},latency:r[t],httpsLatencyTest:o.startsWith("https://")}},rn=S(Ae)(nn),on=S(Ae)(Qt),sn="_list_4awfc_4",an="_detail_4awfc_10",cn="_summary_4awfc_19",q={list:sn,detail:an,summary:cn};function Le({all:e,now:t,isSelectable:n,itemOnTapCallback:r}){const o=e;return s("div",{className:P(q.list,q.detail),children:o.map(i=>s(rn,{onClick:r,isSelectable:n,name:i,now:i===t},i))})}function Me({all:e,now:t,isSelectable:n,itemOnTapCallback:r}){return s("div",{className:P(q.list,q.summary),children:e.map(o=>s(on,{onClick:r,isSelectable:n,name:o,now:o===t},o))})}const{createElement:ln,useCallback:Y,useMemo:un,useState:de,useEffect:dn}=x;function he(){return s("div",{className:b.zapWrapper,children:s(A,{size:16})})}function hn({name:e,all:t,delay:n,hideUnavailableProxies:r,proxySortBy:o,proxies:i,type:a,now:c,isOpen:l,latencyTestUrl:v,apiConfig:d,dispatch:h}){const m=Te(t,n,r,o,i),{data:p}=Ve(["/version",d],()=>Xe("/version",d)),f=un(()=>["Selector",p.meta&&"Fallback",p.meta&&"URLTest"].includes(a),[a,p.meta]),{app:{updateCollapsibleIsOpen:C},proxies:{requestDelayForProxies:g}}=G(),O=Y(()=>{C("proxyGroup",e,!l)},[l,C,e]),V=Y(B=>{f&&h(Ye(d,e,B))},[d,h,e,f]),[L,M]=de(!1),N=Y(async()=>{M(!0);try{p.meta===!0?(await Ze(d,e,v),await h(Q(d))):(await g(d,m),await h(Q(d)))}catch{}M(!1)},[m,d,h,e,p.meta]),[D,w]=de(window.innerWidth),z=()=>{w(window.innerWidth)};return dn(()=>(window.addEventListener("resize",z),()=>window.removeEventListener("resize",z)),[]),u("div",{className:b.group,children:[u("div",{style:{display:"flex",alignItems:"center",justifyContent:D>768?"start":"space-between"},children:[s(Ee,{name:e,type:a,toggle:O,qty:m.length}),s("div",{style:{display:"flex"},children:D>768?u(E,{children:[s(_,{kind:"minimal",onClick:O,className:b.btn,title:"Toggle collapsible section",children:s("span",{className:P(b.arrow,{[b.isOpen]:l}),children:s(J,{size:20})})}),s(_,{title:"Test latency",kind:"minimal",onClick:N,isLoading:L,children:s(he,{})})]}):u(E,{children:[s(_,{title:"Test latency",kind:"minimal",onClick:N,isLoading:L,children:s(he,{})}),s(_,{kind:"minimal",onClick:O,className:b.btn,title:"Toggle collapsible section",children:s("span",{className:P(b.arrow,{[b.isOpen]:l}),children:s(J,{size:20})})})]})})]}),ln(l?Le:Me,{all:m,now:c,isSelectable:f,itemOnTapCallback:V})]})}const fn=S((e,{name:t,delay:n})=>{const r=we(e),o=Ce(e),i=re(e),a=oe(e),c=xe(e),l=r[t],{all:v,type:d,now:h}=l;return{all:v,delay:n,hideUnavailableProxies:a,proxySortBy:i,proxies:r,type:d,now:h,isOpen:o[`proxyGroup:${t}`],latencyTestUrl:c}})(hn),{useCallback:Ne,useState:pn}=x;function vn({dispatch:e,apiConfig:t,name:n}){return Ne(()=>e(Qe(t,n)),[t,e,n])}function mn({dispatch:e,apiConfig:t,names:n}){const[r,o]=pn(!1);return[Ne(async()=>{if(!r){o(!0);try{await e(Je(t,n))}catch{}o(!1)}},[t,e,n,r]),r]}const{useState:yn,useCallback:_n}=x;function bn({isLoading:e}){return e?s(ut,{children:s(A,{width:16,height:16})}):s(A,{width:16,height:16})}function gn({dispatch:e,apiConfig:t}){const[n,r]=yn(!1);return[_n(()=>{n||(r(!0),e(et(t)).then(()=>r(!1),()=>r(!1)))},[t,e,n]),n]}function wn({dispatch:e,apiConfig:t,proxyProviders:n}){const{t:r}=se(),[o,i]=gn({dispatch:e,apiConfig:t}),[a,c]=mn({apiConfig:t,dispatch:e,names:n.map(l=>l.name)});return s(at,{icon:s(bn,{isLoading:i}),onClick:o,text:r("Test Latency"),style:ct,children:n.length>0?s(lt,{text:r("update_all_proxy_provider"),onClick:a,children:s(dt,{isRotating:c})}):null})}var De=function(){if(typeof Map<"u")return Map;function e(t,n){var r=-1;return t.some(function(o,i){return o[0]===n?(r=i,!0):!1}),r}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(n){var r=e(this.__entries__,n),o=this.__entries__[r];return o&&o[1]},t.prototype.set=function(n,r){var o=e(this.__entries__,n);~o?this.__entries__[o][1]=r:this.__entries__.push([n,r])},t.prototype.delete=function(n){var r=this.__entries__,o=e(r,n);~o&&r.splice(o,1)},t.prototype.has=function(n){return!!~e(this.__entries__,n)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(n,r){r===void 0&&(r=null);for(var o=0,i=this.__entries__;o0},e.prototype.connect_=function(){!te||this.connected_||(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),En?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){!te||!this.connected_||(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(t){var n=t.propertyName,r=n===void 0?"":n,o=kn.some(function(i){return!!~r.indexOf(i)});o&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),ze=function(e,t){for(var n=0,r=Object.keys(t);n"u"||!(Element instanceof Object))){if(!(t instanceof T(t).Element))throw new TypeError('parameter 1 is not of type "Element".');var n=this.observations_;n.has(t)||(n.set(t,new zn(t)),this.controller_.addObserver(this),this.controller_.refresh())}},e.prototype.unobserve=function(t){if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");if(!(typeof Element>"u"||!(Element instanceof Object))){if(!(t instanceof T(t).Element))throw new TypeError('parameter 1 is not of type "Element".');var n=this.observations_;n.has(t)&&(n.delete(t),n.size||this.controller_.removeObserver(this))}},e.prototype.disconnect=function(){this.clearActive(),this.observations_.clear(),this.controller_.removeObserver(this)},e.prototype.gatherActive=function(){var t=this;this.clearActive(),this.observations_.forEach(function(n){n.isActive()&&t.activeObservations_.push(n)})},e.prototype.broadcastActive=function(){if(this.hasActive()){var t=this.callbackCtx_,n=this.activeObservations_.map(function(r){return new Bn(r.target,r.broadcastRect())});this.callback_.call(t,n,t),this.clearActive()}},e.prototype.clearActive=function(){this.activeObservations_.splice(0)},e.prototype.hasActive=function(){return this.activeObservations_.length>0},e}(),$e=typeof WeakMap<"u"?new WeakMap:new De,Fe=function(){function e(t){if(!(this instanceof e))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var n=Tn.getInstance(),r=new $n(t,n,this);$e.set(this,r)}return e}();["observe","unobserve","disconnect"].forEach(function(e){Fe.prototype[e]=function(){var t;return(t=$e.get(this))[e].apply(t,arguments)}});var Fn=function(){return typeof U.ResizeObserver<"u"?U.ResizeObserver:Fe}();const{memo:jn,useState:In,useRef:je,useEffect:Ie}=X;function Wn(e){const t=je();return Ie(()=>void(t.current=e),[e]),t.current}function qn(){const e=je(),[t,n]=In({height:0});return Ie(()=>{const r=new Fn(([o])=>n(o.contentRect));return e.current&&r.observe(e.current),()=>r.disconnect()},[]),[e,t]}const Un={initialOpen:{height:"auto",transition:{duration:0}},open:e=>({height:e,opacity:1,visibility:"visible",transition:{duration:.3}}),closed:{height:0,opacity:0,visibility:"hidden",overflowY:"hidden",transition:{duration:.3}}},Hn={open:{},closed:{}},pe=jn(({children:e,isOpen:t})=>{const r=Oe.read().motion,o=Wn(t),[i,{height:a}]=qn();return s("div",{children:s(r.div,{animate:t&&o===t?"initialOpen":t?"open":"closed",custom:a,variants:Un,children:s(r.div,{variants:Hn,ref:i,children:e})})})}),Gn="_updatedAt_1d817_4",Kn="_body_1d817_12",Vn="_actionFooter_1d817_25",Yn="_refresh_1d817_35",I={updatedAt:Gn,body:Kn,actionFooter:Vn,refresh:Yn},{useState:Zn,useCallback:ve}=x;function Xn({name:e,proxies:t,delay:n,hideUnavailableProxies:r,proxySortBy:o,vehicleType:i,updatedAt:a,subscriptionInfo:c,isOpen:l,dispatch:v,apiConfig:d}){const h=Te(t,n,r,o),[m,p]=Zn(!1),f=vn({dispatch:v,apiConfig:d,name:e}),C=ve(async()=>{p(!0),await v(tt(d,e)),p(!1)},[d,v,e,p]),{app:{updateCollapsibleIsOpen:g}}=G(),O=ve(()=>{g("proxyProvider",e,!l)},[l,g,e]),V=ft(new Date(a),new Date),L=c?me(c.Total):0,M=c?me(c.Download+c.Upload):0,N=c?((c.Download+c.Upload)/c.Total*100).toFixed(2):0,D=()=>{if(c.Expire===0)return"Null";const w=new Date(c.Expire*1e3),z=w.getFullYear()+"-",B=(w.getMonth()+1<10?"0"+(w.getMonth()+1):w.getMonth()+1)+"-",We=(w.getDate()<10?"0"+w.getDate():w.getDate())+" ";return z+B+We};return u("div",{className:I.body,children:[u("div",{style:{display:"flex",alignItems:"center",flexWrap:"wrap",justifyContent:"space-between"},children:[s(Ee,{name:e,toggle:O,type:i,isOpen:l,qty:h.length}),u("div",{style:{display:"flex"},children:[s(_,{kind:"minimal",onClick:O,className:b.btn,title:"Toggle collapsible section",children:s("span",{className:P(b.arrow,{[b.isOpen]:l}),children:s(J,{size:20})})}),s(_,{kind:"minimal",start:s(ye,{}),onClick:f}),s(_,{kind:"minimal",start:s(A,{size:16}),onClick:C,isLoading:m})]})]}),u("div",{className:I.updatedAt,children:[c&&u("small",{children:[M," / ",L," ( ",N,"% )    Expire: ",D()," "]}),s("br",{}),u("small",{children:["Updated ",V," ago"]})]}),u(pe,{isOpen:l,children:[s(Le,{all:h}),u("div",{className:I.actionFooter,children:[s(_,{text:"Update",start:s(ye,{}),onClick:f}),s(_,{text:"Health Check",start:s(A,{size:16}),onClick:C,isLoading:m})]})]}),s(pe,{isOpen:!l,children:s(Me,{all:h})})]})}const Qn={rest:{scale:1},pressed:{scale:.95}},Jn={rest:{rotate:0},hover:{rotate:360,transition:{duration:.3}}};function me(e,t=2){if(!+e)return"0 Bytes";const n=1024,r=t<0?0:t,o=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],i=Math.floor(Math.log(e)/Math.log(n));return`${parseFloat((e/Math.pow(n,i)).toFixed(r))} ${o[i]}`}function ye(){const t=Oe.read().motion;return s(t.div,{className:I.refresh,variants:Qn,initial:"rest",whileHover:"hover",whileTap:"pressed",children:s(t.div,{className:"flexCenter",variants:Jn,children:s(pt,{size:16})})})}const er=(e,{proxies:t,name:n})=>{const r=oe(e),o=ne(e),i=Ce(e),a=Pe(e),c=re(e);return{apiConfig:a,proxies:t,delay:o,hideUnavailableProxies:r,proxySortBy:c,isOpen:i[`proxyProvider:${n}`]}},tr=S(er)(Xn);function nr({items:e}){return e.length===0?null:u(E,{children:[s(ke,{title:"Proxy Provider"}),s("div",{children:e.map(t=>s(tr,{name:t.name,proxies:t.proxies,type:t.type,vehicleType:t.vehicleType,updatedAt:t.updatedAt,subscriptionInfo:t.subscriptionInfo},t.name))})]})}const rr="_labeledInput_cmki0_1",Z={labeledInput:rr},or=[["Natural","order_natural"],["LatencyAsc","order_latency_asc"],["LatencyDesc","order_latency_desc"],["NameAsc","order_name_asc"],["NameDesc","order_name_desc"]],{useCallback:_e}=x;function sr({appConfig:e}){const{app:{updateAppConfig:t}}=G(),n=_e(i=>{t("proxySortBy",i.target.value)},[t]),r=_e(i=>{t("hideUnavailableProxies",i)},[t]),{t:o}=se();return u(E,{children:[u("div",{className:Z.labeledInput,children:[s("span",{children:o("sort_in_grp")}),s("div",{children:s(vt,{options:or.map(i=>[i[0],o(i[1])]),selected:e.proxySortBy,onChange:n})})]}),s("hr",{}),u("div",{className:Z.labeledInput,children:[s("span",{children:o("hide_unavail_proxies")}),s("div",{children:s(ae,{name:"hideUnavailableProxies",checked:e.hideUnavailableProxies,onChange:r})})]}),u("div",{className:Z.labeledInput,children:[s("span",{children:o("auto_close_conns")}),s("div",{children:s(ae,{name:"autoCloseOldConns",checked:e.autoCloseOldConns,onChange:i=>t("autoCloseOldConns",i)})})]})]})}const ir=e=>{const t=re(e),n=oe(e),r=nt(e);return{appConfig:{proxySortBy:t,hideUnavailableProxies:n,autoCloseOldConns:r}}},ar=S(ir)(sr);function cr({color:e="currentColor",size:t=24}){return u("svg",{fill:"none",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",width:t,height:t,stroke:e,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s("path",{d:"M2 6h9M18.5 6H22"}),s("circle",{cx:"16",cy:"6",r:"2"}),s("path",{d:"M22 18h-9M6 18H2"}),s("circle",{r:"2",transform:"matrix(-1 0 0 1 8 18)"})]})}const lr="_topBar_15n7g_4",ur="_topBarRight_15n7g_16",dr="_textFilterContainer_15n7g_25",hr="_group_15n7g_32",j={topBar:lr,topBarRight:ur,textFilterContainer:dr,group:hr},{useState:fr,useEffect:pr,useCallback:be,useRef:vr}=x;function mr({dispatch:e,groupNames:t,delay:n,proxyProviders:r,apiConfig:o,showModalClosePrevConns:i}){const a=vr({}),c=be(()=>{a.current.startAt=Date.now(),e(Q(o)).then(()=>{a.current.completeAt=Date.now()})},[o,e]);pr(()=>{c();const f=()=>{a.current.startAt&&Date.now()-a.current.startAt>3e4&&c()};return window.addEventListener("focus",f,!1),()=>window.removeEventListener("focus",f,!1)},[c]);const[l,v]=fr(!1),d=be(()=>{v(!1)},[]),{proxies:{closeModalClosePrevConns:h,closePrevConnsAndTheModal:m}}=G(),{t:p}=se();return u(E,{children:[s(ce,{isOpen:l,onRequestClose:d,children:s(ar,{})}),u("div",{className:j.topBar,children:[s(ke,{title:p("Proxies")}),u("div",{className:j.topBarRight,children:[s("div",{className:j.textFilterContainer,children:s(ht,{textAtom:ge,placeholder:p("Search")})}),s(rt,{label:p("settings"),children:s(_,{kind:"minimal",onClick:()=>v(!0),children:s(cr,{size:16})})})]})]}),s("div",{children:t.map(f=>s("div",{className:j.group,children:s(fn,{name:f,delay:n,apiConfig:o,dispatch:e})},f))}),s(nr,{items:r}),s("div",{style:{height:60}}),s(wn,{dispatch:e,apiConfig:o,proxyProviders:r}),s(ce,{isOpen:i,onRequestClose:h,children:s(xt,{onClickPrimaryButton:()=>m(o),onClickSecondaryButton:h})})]})}const yr=e=>({apiConfig:Pe(e),groupNames:ot(e),proxyProviders:st(e),delay:ne(e),showModalClosePrevConns:it(e)}),kr=S(yr)(mr);export{kr as default}; 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/Rules-162ef666.css: -------------------------------------------------------------------------------- 1 | ._RuleProviderItem_ly9yn_1{display:grid;grid-template-columns:40px 1fr 46px;height:100%}._left_ly9yn_7{display:inline-flex;align-items:center;color:var(--color-text-secondary);opacity:.4}._middle_ly9yn_14{display:grid;grid-template-rows:1fr auto auto;align-items:center}._gray_ly9yn_20{color:#777}._refreshButtonWrapper_ly9yn_24{display:grid;align-items:center;justify-items:center;place-items:center;opacity:0;transition:opacity .2s}._RuleProviderItem_ly9yn_1:hover ._refreshButtonWrapper_ly9yn_24{opacity:1}._rule_1e5p9_4{display:flex;align-items:center;padding:6px 15px}@media screen and (min-width: 30em){._rule_1e5p9_4{padding:10px 40px}}._left_1e5p9_15{width:40px;padding-right:15px;color:var(--color-text-secondary);opacity:.4}._a_1e5p9_22{display:flex;align-items:center;font-size:1em;opacity:.8}._b_1e5p9_29{flex-grow:1;padding:10px 0;font-family:Roboto Mono,Menlo,monospace;font-size:1em}@media screen and (min-width: 30em){._b_1e5p9_29{font-size:1em}}._type_1e5p9_41{width:110px;color:#3b5f76}._size_1e5p9_46{width:110px}._payloadAndSize_1e5p9_50{display:flex;align-items:center}._header_10x16_4{display:grid;grid-template-columns:1fr minmax(auto,290px);align-items:center;padding-right:15px}._RuleProviderItemWrapper_10x16_11{padding:6px 15px}@media screen and (min-width: 30em){._RuleProviderItemWrapper_10x16_11{padding:10px 40px}} 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/Rules-2c94a03b.js: -------------------------------------------------------------------------------- 1 | import{k as ie,h as W,aq as be,ar as se,as as Me,R as N,at as Oe,au as B,av as ze,aw as Te,ax as K,r as L,V as q,ay as Ce,N as ae,a3 as we,j as O,b as g,a2 as xe,B as Ne,u as oe,d as Pe,g as Ee,C as Ae}from"./index-7c6466d3.js";import{_ as G}from"./objectWithoutPropertiesLoose-4f48578a.js";import{R as le,T as ke}from"./TextFitler-2e63abd5.js";import{f as Le}from"./index-84fa0cb3.js";import{F as We,p as De}from"./Fab-e6dedc20.js";import{u as $e}from"./useRemainingViewPortHeight-aa016eed.js";import"./rotate-cw-76728396.js";import"./debounce-c1ba2006.js";var Fe=function(r){ie(e,r);function e(n,i){var s;return s=r.call(this)||this,s.client=n,s.setOptions(i),s.bindMethods(),s.updateResult(),s}var t=e.prototype;return t.bindMethods=function(){this.mutate=this.mutate.bind(this),this.reset=this.reset.bind(this)},t.setOptions=function(i){this.options=this.client.defaultMutationOptions(i)},t.onUnsubscribe=function(){if(!this.listeners.length){var i;(i=this.currentMutation)==null||i.removeObserver(this)}},t.onMutationUpdate=function(i){this.updateResult();var s={listeners:!0};i.type==="success"?s.onSuccess=!0:i.type==="error"&&(s.onError=!0),this.notify(s)},t.getCurrentResult=function(){return this.currentResult},t.reset=function(){this.currentMutation=void 0,this.updateResult(),this.notify({listeners:!0})},t.mutate=function(i,s){return this.mutateOptions=s,this.currentMutation&&this.currentMutation.removeObserver(this),this.currentMutation=this.client.getMutationCache().build(this.client,W({},this.options,{variables:typeof i<"u"?i:this.options.variables})),this.currentMutation.addObserver(this),this.currentMutation.execute()},t.updateResult=function(){var i=this.currentMutation?this.currentMutation.state:be(),s=W({},i,{isLoading:i.status==="loading",isSuccess:i.status==="success",isError:i.status==="error",isIdle:i.status==="idle",mutate:this.mutate,reset:this.reset});this.currentResult=s},t.notify=function(i){var s=this;se.batch(function(){s.mutateOptions&&(i.onSuccess?(s.mutateOptions.onSuccess==null||s.mutateOptions.onSuccess(s.currentResult.data,s.currentResult.variables,s.currentResult.context),s.mutateOptions.onSettled==null||s.mutateOptions.onSettled(s.currentResult.data,null,s.currentResult.variables,s.currentResult.context)):i.onError&&(s.mutateOptions.onError==null||s.mutateOptions.onError(s.currentResult.error,s.currentResult.variables,s.currentResult.context),s.mutateOptions.onSettled==null||s.mutateOptions.onSettled(void 0,s.currentResult.error,s.currentResult.variables,s.currentResult.context))),i.listeners&&s.listeners.forEach(function(o){o(s.currentResult)})})},e}(Me);function ue(r,e,t){var n=N.useRef(!1),i=N.useState(0),s=i[1],o=Oe(r,e,t),d=B(),c=N.useRef();c.current?c.current.setOptions(o):c.current=new Fe(d,o);var v=c.current.getCurrentResult();N.useEffect(function(){n.current=!0;var M=c.current.subscribe(se.batchCalls(function(){n.current&&s(function(_){return _+1})}));return function(){n.current=!1,M()}},[]);var y=N.useCallback(function(M,_){c.current.mutate(M,_).catch(ze)},[]);if(v.error&&Te(void 0,c.current.options.useErrorBoundary,[v.error]))throw v.error;return W({},v,{mutate:y,mutateAsync:v.mutate})}var J=Number.isNaN||function(e){return typeof e=="number"&&e!==e};function Ue(r,e){return!!(r===e||J(r)&&J(e))}function Be(r,e){if(r.length!==e.length)return!1;for(var t=0;t=e?r.call(null):i.id=requestAnimationFrame(n)}var i={id:requestAnimationFrame(n)};return i}var F=-1;function Y(r){if(r===void 0&&(r=!1),F===-1||r){var e=document.createElement("div"),t=e.style;t.width="50px",t.height="50px",t.overflow="scroll",document.body.appendChild(e),F=e.offsetWidth-e.clientWidth,document.body.removeChild(e)}return F}var w=null;function ee(r){if(r===void 0&&(r=!1),w===null||r){var e=document.createElement("div"),t=e.style;t.width="50px",t.height="50px",t.overflow="scroll",t.direction="rtl";var n=document.createElement("div"),i=n.style;return i.width="100px",i.height="100px",e.appendChild(n),document.body.appendChild(e),e.scrollLeft>0?w="positive-descending":(e.scrollLeft=1,e.scrollLeft===0?w="negative":w="positive-ascending"),document.body.removeChild(e),w}return w}var je=150,Qe=function(e,t){return e};function Ve(r){var e,t=r.getItemOffset,n=r.getEstimatedTotalSize,i=r.getItemSize,s=r.getOffsetForIndexAndAlignment,o=r.getStartIndexForOffset,d=r.getStopIndexForStartIndex,c=r.initInstanceProps,v=r.shouldResetStyleCacheOnItemSizeChange,y=r.validateProps;return e=function(M){ie(_,M);function _(R){var a;return a=M.call(this,R)||this,a._instanceProps=c(a.props,K(a)),a._outerRef=void 0,a._resetIsScrollingTimeoutId=null,a.state={instance:K(a),isScrolling:!1,scrollDirection:"forward",scrollOffset:typeof a.props.initialScrollOffset=="number"?a.props.initialScrollOffset:0,scrollUpdateWasRequested:!1},a._callOnItemsRendered=void 0,a._callOnItemsRendered=$(function(l,u,h,m){return a.props.onItemsRendered({overscanStartIndex:l,overscanStopIndex:u,visibleStartIndex:h,visibleStopIndex:m})}),a._callOnScroll=void 0,a._callOnScroll=$(function(l,u,h){return a.props.onScroll({scrollDirection:l,scrollOffset:u,scrollUpdateWasRequested:h})}),a._getItemStyle=void 0,a._getItemStyle=function(l){var u=a.props,h=u.direction,m=u.itemSize,S=u.layout,f=a._getItemStyleCache(v&&m,v&&S,v&&h),p;if(f.hasOwnProperty(l))p=f[l];else{var I=t(a.props,l,a._instanceProps),z=i(a.props,l,a._instanceProps),T=h==="horizontal"||S==="horizontal",A=h==="rtl",k=T?I:0;f[l]=p={position:"absolute",left:A?void 0:k,right:A?k:void 0,top:T?0:I,height:T?"100%":z,width:T?z:"100%"}}return p},a._getItemStyleCache=void 0,a._getItemStyleCache=$(function(l,u,h){return{}}),a._onScrollHorizontal=function(l){var u=l.currentTarget,h=u.clientWidth,m=u.scrollLeft,S=u.scrollWidth;a.setState(function(f){if(f.scrollOffset===m)return null;var p=a.props.direction,I=m;if(p==="rtl")switch(ee()){case"negative":I=-m;break;case"positive-descending":I=S-h-m;break}return I=Math.max(0,Math.min(I,S-h)),{isScrolling:!0,scrollDirection:f.scrollOffsetp.clientWidth?Y():0:f=p.scrollHeight>p.clientHeight?Y():0}this.scrollTo(s(this.props,a,l,S,this._instanceProps,f))},b.componentDidMount=function(){var a=this.props,l=a.direction,u=a.initialScrollOffset,h=a.layout;if(typeof u=="number"&&this._outerRef!=null){var m=this._outerRef;l==="horizontal"||h==="horizontal"?m.scrollLeft=u:m.scrollTop=u}this._callPropsCallbacks()},b.componentDidUpdate=function(){var a=this.props,l=a.direction,u=a.layout,h=this.state,m=h.scrollOffset,S=h.scrollUpdateWasRequested;if(S&&this._outerRef!=null){var f=this._outerRef;if(l==="horizontal"||u==="horizontal")if(l==="rtl")switch(ee()){case"negative":f.scrollLeft=-m;break;case"positive-ascending":f.scrollLeft=m;break;default:var p=f.clientWidth,I=f.scrollWidth;f.scrollLeft=I-p-m;break}else f.scrollLeft=m;else f.scrollTop=m}this._callPropsCallbacks()},b.componentWillUnmount=function(){this._resetIsScrollingTimeoutId!==null&&X(this._resetIsScrollingTimeoutId)},b.render=function(){var a=this.props,l=a.children,u=a.className,h=a.direction,m=a.height,S=a.innerRef,f=a.innerElementType,p=a.innerTagName,I=a.itemCount,z=a.itemData,T=a.itemKey,A=T===void 0?Qe:T,k=a.layout,ve=a.outerElementType,pe=a.outerTagName,ge=a.style,Se=a.useIsScrolling,Ie=a.width,H=this.state.isScrolling,D=h==="horizontal"||k==="horizontal",ye=D?this._onScrollHorizontal:this._onScrollVertical,j=this._getRangeToRender(),_e=j[0],Re=j[1],Q=[];if(I>0)for(var E=_e;E<=Re;E++)Q.push(L.createElement(l,{data:z,key:A(E,z),index:E,isScrolling:Se?H:void 0,style:this._getItemStyle(E)}));var V=n(this.props,this._instanceProps);return L.createElement(ve||pe||"div",{className:u,onScroll:ye,ref:this._outerRefSetter,style:W({position:"relative",height:m,width:Ie,overflow:"auto",WebkitOverflowScrolling:"touch",willChange:"transform",direction:h},ge)},L.createElement(f||p||"div",{children:Q,ref:S,style:{height:D?"100%":V,pointerEvents:H?"none":void 0,width:D?V:"100%"}}))},b._callPropsCallbacks=function(){if(typeof this.props.onItemsRendered=="function"){var a=this.props.itemCount;if(a>0){var l=this._getRangeToRender(),u=l[0],h=l[1],m=l[2],S=l[3];this._callOnItemsRendered(u,h,m,S)}}if(typeof this.props.onScroll=="function"){var f=this.state,p=f.scrollDirection,I=f.scrollOffset,z=f.scrollUpdateWasRequested;this._callOnScroll(p,I,z)}},b._getRangeToRender=function(){var a=this.props,l=a.itemCount,u=a.overscanCount,h=this.state,m=h.isScrolling,S=h.scrollDirection,f=h.scrollOffset;if(l===0)return[0,0,0,0];var p=o(this.props,f,this._instanceProps),I=d(this.props,p,f,this._instanceProps),z=!m||S==="backward"?Math.max(1,u):1,T=!m||S==="forward"?Math.max(1,u):1;return[Math.max(0,p-z),Math.max(0,Math.min(l-1,I+T)),p,I]},_}(L.PureComponent),e.defaultProps={direction:"ltr",itemData:void 0,layout:"vertical",overscanCount:2,useIsScrolling:!1},e}var Ke=function(e,t){e.children,e.direction,e.height,e.layout,e.innerTagName,e.outerTagName,e.width,t.instance},Ge=50,P=function(e,t,n){var i=e,s=i.itemSize,o=n.itemMetadataMap,d=n.lastMeasuredIndex;if(t>d){var c=0;if(d>=0){var v=o[d];c=v.offset+v.size}for(var y=d+1;y<=t;y++){var M=s(y);o[y]={offset:c,size:M},c+=M}n.lastMeasuredIndex=t}return o[t]},Je=function(e,t,n){var i=t.itemMetadataMap,s=t.lastMeasuredIndex,o=s>0?i[s].offset:0;return o>=n?ce(e,t,s,0,n):Ze(e,t,Math.max(0,s),n)},ce=function(e,t,n,i,s){for(;i<=n;){var o=i+Math.floor((n-i)/2),d=P(e,o,t).offset;if(d===s)return o;ds&&(n=o-1)}return i>0?i-1:0},Ze=function(e,t,n,i){for(var s=e.itemCount,o=1;n=n&&(o=n-1),o>=0){var c=i[o];d=c.offset+c.size}var v=n-o-1,y=v*s;return d+y},Xe=Ve({getItemOffset:function(e,t,n){return P(e,t,n).offset},getItemSize:function(e,t,n){return n.itemMetadataMap[t].size},getEstimatedTotalSize:te,getOffsetForIndexAndAlignment:function(e,t,n,i,s,o){var d=e.direction,c=e.height,v=e.layout,y=e.width,M=d==="horizontal"||v==="horizontal",_=M?y:c,b=P(e,t,s),R=te(e,s),a=Math.max(0,Math.min(R-_,b.offset)),l=Math.max(0,b.offset-_+b.size+o);switch(n==="smart"&&(i>=l-_&&i<=a+_?n="auto":n="center"),n){case"start":return a;case"end":return l;case"center":return Math.round(l+(a-l)/2);case"auto":default:return i>=l&&i<=a?i:i=0,"there is no valid rules list in the rules API response"),r.rules.map((e,t)=>({...e,id:t}))}async function lt(r,e){let t={rules:[]};try{const{url:n,init:i}=q(e),s=await fetch(n+r,i);s.ok&&(t=await s.json())}catch(n){console.log("failed to fetch rules",n)}return ot(t)}const fe=Ce({key:"ruleFilterText",default:""});function ut(r,e){const t=B(),{mutate:n,isLoading:i}=ue(de,{onSuccess:()=>{t.invalidateQueries("/providers/rules")}});return[o=>{o.preventDefault(),n({name:r,apiConfig:e})},i]}function ct(r){const e=B(),{data:t}=he(r),{mutate:n,isLoading:i}=ue(it,{onSuccess:()=>{e.invalidateQueries("/providers/rules")}});return[o=>{o.preventDefault(),n({names:t.names,apiConfig:r})},i]}function he(r){return ae(["/providers/rules",r],()=>nt("/providers/rules",r))}function dt(r){const{data:e,isFetching:t}=ae(["/rules",r],()=>lt("/rules",r)),{data:n}=he(r),[i]=we(fe);if(i==="")return{rules:e,provider:n,isFetching:t};{const s=i.toLowerCase();return{rules:e.filter(o=>o.payload.toLowerCase().indexOf(s)>=0),isFetching:t,provider:{byName:n.byName,names:n.names.filter(o=>o.toLowerCase().indexOf(s)>=0)}}}}const ft="_RuleProviderItem_ly9yn_1",ht="_left_ly9yn_7",mt="_middle_ly9yn_14",vt="_gray_ly9yn_20",pt="_refreshButtonWrapper_ly9yn_24",x={RuleProviderItem:ft,left:ht,middle:mt,gray:vt,refreshButtonWrapper:pt};function gt({idx:r,name:e,vehicleType:t,behavior:n,updatedAt:i,ruleCount:s,apiConfig:o}){const[d,c]=ut(e,o),v=Le(new Date(i),new Date);return O("div",{className:x.RuleProviderItem,children:[g("span",{className:x.left,children:r}),O("div",{className:x.middle,children:[g(xe,{name:e,type:`${t} / ${n}`}),g("div",{className:x.gray,children:s<2?`${s} rule`:`${s} rules`}),O("small",{className:x.gray,children:["Updated ",v," ago"]})]}),g("span",{className:x.refreshButtonWrapper,children:g(Ne,{onClick:d,disabled:c,children:g(le,{isRotating:c})})})]})}function St({apiConfig:r}){const[e,t]=ct(r),{t:n}=oe();return g(We,{icon:g(le,{isRotating:t}),text:n("update_all_rule_provider"),style:De,onClick:e})}const It="_rule_1e5p9_4",yt="_left_1e5p9_15",_t="_a_1e5p9_22",Rt="_b_1e5p9_29",bt="_type_1e5p9_41",Mt="_size_1e5p9_46",Ot="_payloadAndSize_1e5p9_50",C={rule:It,left:yt,a:_t,b:Rt,type:bt,size:Mt,payloadAndSize:Ot},U={_default:"#59caf9",DIRECT:"#f5bc41",REJECT:"#cb3166"};function zt({proxy:r}){let e=U._default;return U[r]&&(e=U[r]),{color:e}}function Tt({type:r,payload:e,proxy:t,id:n,size:i}){const s=zt({proxy:t});return O("div",{className:C.rule,children:[g("div",{className:C.left,children:n}),O("div",{style:{marginLeft:10},children:[O("div",{className:C.payloadAndSize,children:[g("div",{className:C.payload,children:e}),(r==="GeoSite"||r==="GeoIP")&&O("div",{style:{margin:"0 1em"},className:C.size,children:[" ","size: ",i]})]}),O("div",{className:C.a,children:[g("div",{className:C.type,children:r}),g("div",{style:s,children:t})]})]})]})}const Ct="_header_10x16_4",wt="_RuleProviderItemWrapper_10x16_11",me={header:Ct,RuleProviderItemWrapper:wt},{memo:xt}=N,ne=30;function Nt(r,{rules:e,provider:t}){const n=t.names.length;return r{const{rules:n,provider:i,apiConfig:s}=t,o=i.names.length;if(r({apiConfig:Ee(r)}),Ht=Pe(At)(kt);function kt({apiConfig:r}){const[e,t]=$e(),{rules:n,provider:i}=dt(r),s=Pt({provider:i}),{t:o}=oe();return O("div",{children:[O("div",{className:me.header,children:[g(Ae,{title:o("Rules")}),g(ke,{textAtom:fe,placeholder:o("Search")})]}),g("div",{ref:e,style:{paddingBottom:ne},children:g(Xe,{height:t-ne,width:"100%",itemCount:n.length+i.names.length,itemSize:s,itemData:{rules:n,provider:i,apiConfig:r},itemKey:Nt,children:Et})}),i&&i.names&&i.names.length>0?g(St,{apiConfig:r}):null]})}export{Ht as default}; 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/Select-07e025ab.css: -------------------------------------------------------------------------------- 1 | ._select_gfkcv_1{height:35px;line-height:1.5;width:100%;font-size:small;padding-left:15px;-webkit-appearance:none;appearance:none;background-color:var(--color-input-bg);color:var(--color-text);padding-right:20px;border-radius:4px;border:1px solid var(--color-input-border);background-image:url(data:image/svg+xml,%0A%20%20%20%20%3Csvg%20width%3D%228%22%20height%3D%2224%22%20viewBox%3D%220%200%208%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%3Cpath%20d%3D%22M4%207L7%2011H1L4%207Z%22%20fill%3D%22%23999999%22%20%2F%3E%0A%20%20%20%20%20%20%3Cpath%20d%3D%22M4%2017L1%2013L7%2013L4%2017Z%22%20fill%3D%22%23999999%22%20%2F%3E%0A%20%20%20%20%3C%2Fsvg%3E%0A%20%20);background-position:right 8px center;background-repeat:no-repeat}._select_gfkcv_1:hover,._select_gfkcv_1:focus{outline:none!important}._select_gfkcv_1:hover,._select_gfkcv_1:focus{border-color:#343434;color:var(--color-text-highlight);background-image:var(--select-bg-hover)}._select_gfkcv_1:focus{box-shadow:#4299e199 0 0 0 3px}._select_gfkcv_1 option{background-color:var(--color-background)} 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/Select-3321dc18.js: -------------------------------------------------------------------------------- 1 | import{b as c}from"./index-7c6466d3.js";const r="_select_gfkcv_1",a={select:r};function m({options:s,selected:t,onChange:l,...n}){return c("select",{className:a.select,value:t,onChange:l,...n,children:s.map(([e,o])=>c("option",{value:e,children:o},e))})}export{m as S}; 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/TextFitler-2e63abd5.js: -------------------------------------------------------------------------------- 1 | import{c as r,b as n,a3 as u,s as l}from"./index-7c6466d3.js";import{R as p}from"./rotate-cw-76728396.js";import{d as _}from"./debounce-c1ba2006.js";const x="_rotate_1dspl_1",g="_isRotating_1dspl_5",d="_rotating_1dspl_1",c={rotate:x,isRotating:g,rotating:d};function N({isRotating:t}){const e=r(c.rotate,{[c.isRotating]:t});return n("span",{className:e,children:n(p,{width:16})})}const{useCallback:m,useState:R,useMemo:h}=l;function f(t){const[,e]=u(t),[o,i]=R(""),s=h(()=>_(e,300),[e]);return[m(a=>{i(a.target.value),s(a.target.value)},[s]),o]}const T="_input_uqa0o_1",b={input:T};function j(t){const[e,o]=f(t.textAtom);return n("input",{className:b.input,type:"text",value:o,onChange:e,placeholder:t.placeholder})}export{N as R,j as T}; 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/TextFitler-a112af1a.css: -------------------------------------------------------------------------------- 1 | ._rotate_1dspl_1{display:inline-flex}._isRotating_1dspl_5{-webkit-animation:_rotating_1dspl_1 3s infinite linear;animation:_rotating_1dspl_1 3s infinite linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@-webkit-keyframes _rotating_1dspl_1{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes _rotating_1dspl_1{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}._input_uqa0o_1{-webkit-appearance:none;background-color:var(--color-input-bg);background-image:none;border-radius:20px;border:1px solid var(--color-input-border);box-sizing:border-box;color:var(--color-text-secondary);display:inline-block;font-size:inherit;outline:none;padding:8px 15px;transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%;height:36px}._input_uqa0o_1:focus{border:1px solid var(--color-focus-blue)} 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/Twemoji_Mozilla-6d90152e.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zerolabnet/SSClash/5cafaf7358abc10515723fa3d6eba783f11be3e4/rootfs/opt/clash/ui/assets/Twemoji_Mozilla-6d90152e.ttf -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/debounce-c1ba2006.js: -------------------------------------------------------------------------------- 1 | function O(e){var n=typeof e;return e!=null&&(n=="object"||n=="function")}var M=typeof global=="object"&&global&&global.Object===Object&&global;const R=M;var w=typeof self=="object"&&self&&self.Object===Object&&self,B=R||w||Function("return this")();const W=B;var F=function(){return W.Date.now()};const S=F;var G=/\s/;function U(e){for(var n=e.length;n--&&G.test(e.charAt(n)););return n}var _=/^\s+/;function D(e){return e&&e.slice(0,U(e)+1).replace(_,"")}var H=W.Symbol;const y=H;var L=Object.prototype,X=L.hasOwnProperty,q=L.toString,g=y?y.toStringTag:void 0;function z(e){var n=X.call(e,g),i=e[g];try{e[g]=void 0;var o=!0}catch{}var f=q.call(e);return o&&(n?e[g]=i:delete e[g]),f}var J=Object.prototype,K=J.toString;function Q(e){return K.call(e)}var V="[object Null]",Y="[object Undefined]",$=y?y.toStringTag:void 0;function Z(e){return e==null?e===void 0?Y:V:$&&$ in Object(e)?z(e):Q(e)}function ee(e){return e!=null&&typeof e=="object"}var ne="[object Symbol]";function te(e){return typeof e=="symbol"||ee(e)&&Z(e)==ne}var E=0/0,re=/^[-+]0x[0-9a-f]+$/i,ie=/^0b[01]+$/i,oe=/^0o[0-7]+$/i,ae=parseInt;function k(e){if(typeof e=="number")return e;if(te(e))return E;if(O(e)){var n=typeof e.valueOf=="function"?e.valueOf():e;e=O(n)?n+"":n}if(typeof e!="string")return e===0?e:+e;e=D(e);var i=ie.test(e);return i||oe.test(e)?ae(e.slice(2),i?2:8):re.test(e)?E:+e}var fe="Expected a function",ce=Math.max,ue=Math.min;function se(e,n,i){var o,f,s,u,r,c,d=0,v=!1,l=!1,T=!0;if(typeof e!="function")throw new TypeError(fe);n=k(n)||0,O(i)&&(v=!!i.leading,l="maxWait"in i,s=l?ce(k(i.maxWait)||0,n):s,T="trailing"in i?!!i.trailing:T);function j(t){var a=o,b=f;return o=f=void 0,d=t,u=e.apply(b,a),u}function N(t){return d=t,r=setTimeout(m,n),v?j(t):u}function P(t){var a=t-c,b=t-d,I=n-a;return l?ue(I,s-b):I}function h(t){var a=t-c,b=t-d;return c===void 0||a>=n||a<0||l&&b>=s}function m(){var t=S();if(h(t))return x(t);r=setTimeout(m,P(t))}function x(t){return r=void 0,T&&o?j(t):(o=f=void 0,u)}function A(){r!==void 0&&clearTimeout(r),d=0,o=c=f=r=void 0}function C(){return r===void 0?u:x(S())}function p(){var t=S(),a=h(t);if(o=arguments,f=this,c=t,a){if(r===void 0)return N(c);if(l)return clearTimeout(r),r=setTimeout(m,n),j(c)}return r===void 0&&(r=setTimeout(m,n)),u}return p.cancel=A,p.flush=C,p}export{se as d}; 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/en-1067a8eb.js: -------------------------------------------------------------------------------- 1 | const e={All:"All",Overview:"Overview",Proxies:"Proxies",Rules:"Rules",Conns:"Conns",Config:"Config",Logs:"Logs",Upload:"Upload",Download:"Download","Upload Total":"Upload Total","Download Total":"Download Total","Active Connections":"Active Connections","Memory Usage":"Memory Usage","Pause Refresh":"Pause Refresh","Resume Refresh":"Resume Refresh",close_all_connections:"Close All Connections",close_filter_connections:"Close all connections after filtering",Search:"Search",Up:"Up",Down:"Down","Test Latency":"Test Latency",settings:"settings",sort_in_grp:"Sorting in group",hide_unavail_proxies:"Hide unavailable proxies",auto_close_conns:"Automatically close old connections",order_natural:"Original order in config file",order_latency_asc:"By latency from small to big",order_latency_desc:"By latency from big to small",order_name_asc:"By name alphabetically (A-Z)",order_name_desc:"By name alphabetically (Z-A)",Connections:"Connections",current_backend:"Current Backend",Active:"Active",switch_backend:"Switch backend",Closed:"Closed",switch_theme:"Switch theme",theme:"theme",about:"about",no_logs:"No logs yet, hang tight...",chart_style:"Chart Style",latency_test_url:"Latency Test URL",lang:"Language",update_all_rule_provider:"Update all rule providers",update_all_proxy_provider:"Update all proxy providers",reload_config_file:"Reload config file",restart_core:"Restart clash core",upgrade_core:"Upgrade Alpha core",update_geo_databases_file:"Update GEO Databases ",flush_fake_ip_pool:"Flush fake-ip data",enable_tun_device:"Enable TUN Device",allow_lan:"Allow LAN",tls_sniffing:"Sniffer",c_host:"Host",c_sni:"Sniff Host",c_process:"Process",c_dl:"DL",c_ul:"UL",c_dl_speed:"DL Speed",c_ul_speed:"UP Speed",c_chains:"Chains",c_rule:"Rule",c_time:"Time",c_source:"Source",c_destination_ip:"Destination IP",c_type:"Type",c_ctrl:"Close",close_all_confirm:"Are you sure you want to close all connections?",close_all_confirm_yes:"I'm sure",close_all_confirm_no:"No",manage_column:"Custom columns",reset_column:"Reset columns",device_name:"Device Tag",delete:"Delete",add_tag:"Add tag",client_tag:"Client tags",sourceip_tip:"Prefix with / for regular expressions, otherwise it's a complete match",disconnect:"Close Connection",internel:"Internal Connection"};export{e as data}; 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/index-84fa0cb3.js: -------------------------------------------------------------------------------- 1 | function c(e,a){if(a.length1?"s":"")+" required, but only "+a.length+" present")}function y(e){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?y=function(t){return typeof t}:y=function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},y(e)}function s(e){c(1,arguments);var a=Object.prototype.toString.call(e);return e instanceof Date||y(e)==="object"&&a==="[object Date]"?new Date(e.getTime()):typeof e=="number"||a==="[object Number]"?new Date(e):((typeof e=="string"||a==="[object String]")&&typeof console<"u"&&(console.warn("Starting with v2.0.0-beta.1 date-fns doesn't accept strings as date arguments. Please use `parseISO` to parse strings. See: https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#string-arguments"),console.warn(new Error().stack)),new Date(NaN))}var C={};function A(){return C}function S(e){var a=new Date(Date.UTC(e.getFullYear(),e.getMonth(),e.getDate(),e.getHours(),e.getMinutes(),e.getSeconds(),e.getMilliseconds()));return a.setUTCFullYear(e.getFullYear()),e.getTime()-a.getTime()}function M(e,a){c(2,arguments);var t=s(e),n=s(a),i=t.getTime()-n.getTime();return i<0?-1:i>0?1:i}function _(e,a){c(2,arguments);var t=s(e),n=s(a),i=t.getFullYear()-n.getFullYear(),o=t.getMonth()-n.getMonth();return i*12+o}function X(e,a){return c(2,arguments),s(e).getTime()-s(a).getTime()}var T={ceil:Math.ceil,round:Math.round,floor:Math.floor,trunc:function(a){return a<0?Math.ceil(a):Math.floor(a)}},I="trunc";function R(e){return e?T[e]:T[I]}function E(e){c(1,arguments);var a=s(e);return a.setHours(23,59,59,999),a}function Y(e){c(1,arguments);var a=s(e),t=a.getMonth();return a.setFullYear(a.getFullYear(),t+1,0),a.setHours(23,59,59,999),a}function j(e){c(1,arguments);var a=s(e);return E(a).getTime()===Y(a).getTime()}function z(e,a){c(2,arguments);var t=s(e),n=s(a),i=M(t,n),o=Math.abs(_(t,n)),r;if(o<1)r=0;else{t.getMonth()===1&&t.getDate()>27&&t.setDate(30),t.setMonth(t.getMonth()-i*o);var l=M(t,n)===-i;j(s(e))&&o===1&&M(e,n)===1&&(l=!1),r=i*(o-Number(l))}return r===0?0:r}function V(e,a,t){c(2,arguments);var n=X(e,a)/1e3;return R(t==null?void 0:t.roundingMethod)(n)}var q={lessThanXSeconds:{one:"less than a second",other:"less than {{count}} seconds"},xSeconds:{one:"1 second",other:"{{count}} seconds"},halfAMinute:"half a minute",lessThanXMinutes:{one:"less than a minute",other:"less than {{count}} minutes"},xMinutes:{one:"1 minute",other:"{{count}} minutes"},aboutXHours:{one:"about 1 hour",other:"about {{count}} hours"},xHours:{one:"1 hour",other:"{{count}} hours"},xDays:{one:"1 day",other:"{{count}} days"},aboutXWeeks:{one:"about 1 week",other:"about {{count}} weeks"},xWeeks:{one:"1 week",other:"{{count}} weeks"},aboutXMonths:{one:"about 1 month",other:"about {{count}} months"},xMonths:{one:"1 month",other:"{{count}} months"},aboutXYears:{one:"about 1 year",other:"about {{count}} years"},xYears:{one:"1 year",other:"{{count}} years"},overXYears:{one:"over 1 year",other:"over {{count}} years"},almostXYears:{one:"almost 1 year",other:"almost {{count}} years"}},L=function(a,t,n){var i,o=q[a];return typeof o=="string"?i=o:t===1?i=o.one:i=o.other.replace("{{count}}",t.toString()),n!=null&&n.addSuffix?n.comparison&&n.comparison>0?"in "+i:i+" ago":i};const H=L;function p(e){return function(){var a=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},t=a.width?String(a.width):e.defaultWidth,n=e.formats[t]||e.formats[e.defaultWidth];return n}}var J={full:"EEEE, MMMM do, y",long:"MMMM do, y",medium:"MMM d, y",short:"MM/dd/yyyy"},U={full:"h:mm:ss a zzzz",long:"h:mm:ss a z",medium:"h:mm:ss a",short:"h:mm a"},$={full:"{{date}} 'at' {{time}}",long:"{{date}} 'at' {{time}}",medium:"{{date}}, {{time}}",short:"{{date}}, {{time}}"},Q={date:p({formats:J,defaultWidth:"full"}),time:p({formats:U,defaultWidth:"full"}),dateTime:p({formats:$,defaultWidth:"full"})};const B=Q;var G={lastWeek:"'last' eeee 'at' p",yesterday:"'yesterday at' p",today:"'today at' p",tomorrow:"'tomorrow at' p",nextWeek:"eeee 'at' p",other:"P"},K=function(a,t,n,i){return G[a]};const Z=K;function g(e){return function(a,t){var n=t!=null&&t.context?String(t.context):"standalone",i;if(n==="formatting"&&e.formattingValues){var o=e.defaultFormattingWidth||e.defaultWidth,r=t!=null&&t.width?String(t.width):o;i=e.formattingValues[r]||e.formattingValues[o]}else{var l=e.defaultWidth,u=t!=null&&t.width?String(t.width):e.defaultWidth;i=e.values[u]||e.values[l]}var f=e.argumentCallback?e.argumentCallback(a):a;return i[f]}}var ee={narrow:["B","A"],abbreviated:["BC","AD"],wide:["Before Christ","Anno Domini"]},te={narrow:["1","2","3","4"],abbreviated:["Q1","Q2","Q3","Q4"],wide:["1st quarter","2nd quarter","3rd quarter","4th quarter"]},ae={narrow:["J","F","M","A","M","J","J","A","S","O","N","D"],abbreviated:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],wide:["January","February","March","April","May","June","July","August","September","October","November","December"]},ne={narrow:["S","M","T","W","T","F","S"],short:["Su","Mo","Tu","We","Th","Fr","Sa"],abbreviated:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],wide:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]},re={narrow:{am:"a",pm:"p",midnight:"mi",noon:"n",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},abbreviated:{am:"AM",pm:"PM",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},wide:{am:"a.m.",pm:"p.m.",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"}},ie={narrow:{am:"a",pm:"p",midnight:"mi",noon:"n",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"},abbreviated:{am:"AM",pm:"PM",midnight:"midnight",noon:"noon",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"},wide:{am:"a.m.",pm:"p.m.",midnight:"midnight",noon:"noon",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"}},oe=function(a,t){var n=Number(a),i=n%100;if(i>20||i<10)switch(i%10){case 1:return n+"st";case 2:return n+"nd";case 3:return n+"rd"}return n+"th"},ue={ordinalNumber:oe,era:g({values:ee,defaultWidth:"wide"}),quarter:g({values:te,defaultWidth:"wide",argumentCallback:function(a){return a-1}}),month:g({values:ae,defaultWidth:"wide"}),day:g({values:ne,defaultWidth:"wide"}),dayPeriod:g({values:re,defaultWidth:"wide",formattingValues:ie,defaultFormattingWidth:"wide"})};const se=ue;function b(e){return function(a){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=t.width,i=n&&e.matchPatterns[n]||e.matchPatterns[e.defaultMatchWidth],o=a.match(i);if(!o)return null;var r=o[0],l=n&&e.parsePatterns[n]||e.parsePatterns[e.defaultParseWidth],u=Array.isArray(l)?de(l,function(m){return m.test(r)}):le(l,function(m){return m.test(r)}),f;f=e.valueCallback?e.valueCallback(u):u,f=t.valueCallback?t.valueCallback(f):f;var h=a.slice(r.length);return{value:f,rest:h}}}function le(e,a){for(var t in e)if(e.hasOwnProperty(t)&&a(e[t]))return t}function de(e,a){for(var t=0;t1&&arguments[1]!==void 0?arguments[1]:{},n=a.match(e.matchPattern);if(!n)return null;var i=n[0],o=a.match(e.parsePattern);if(!o)return null;var r=e.valueCallback?e.valueCallback(o[0]):o[0];r=t.valueCallback?t.valueCallback(r):r;var l=a.slice(i.length);return{value:r,rest:l}}}var me=/^(\d+)(th|st|nd|rd)?/i,ce=/\d+/i,he={narrow:/^(b|a)/i,abbreviated:/^(b\.?\s?c\.?|b\.?\s?c\.?\s?e\.?|a\.?\s?d\.?|c\.?\s?e\.?)/i,wide:/^(before christ|before common era|anno domini|common era)/i},ve={any:[/^b/i,/^(a|c)/i]},ge={narrow:/^[1234]/i,abbreviated:/^q[1234]/i,wide:/^[1234](th|st|nd|rd)? quarter/i},be={any:[/1/i,/2/i,/3/i,/4/i]},ye={narrow:/^[jfmasond]/i,abbreviated:/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i,wide:/^(january|february|march|april|may|june|july|august|september|october|november|december)/i},Me={narrow:[/^j/i,/^f/i,/^m/i,/^a/i,/^m/i,/^j/i,/^j/i,/^a/i,/^s/i,/^o/i,/^n/i,/^d/i],any:[/^ja/i,/^f/i,/^mar/i,/^ap/i,/^may/i,/^jun/i,/^jul/i,/^au/i,/^s/i,/^o/i,/^n/i,/^d/i]},we={narrow:/^[smtwf]/i,short:/^(su|mo|tu|we|th|fr|sa)/i,abbreviated:/^(sun|mon|tue|wed|thu|fri|sat)/i,wide:/^(sunday|monday|tuesday|wednesday|thursday|friday|saturday)/i},pe={narrow:[/^s/i,/^m/i,/^t/i,/^w/i,/^t/i,/^f/i,/^s/i],any:[/^su/i,/^m/i,/^tu/i,/^w/i,/^th/i,/^f/i,/^sa/i]},De={narrow:/^(a|p|mi|n|(in the|at) (morning|afternoon|evening|night))/i,any:/^([ap]\.?\s?m\.?|midnight|noon|(in the|at) (morning|afternoon|evening|night))/i},Pe={any:{am:/^a/i,pm:/^p/i,midnight:/^mi/i,noon:/^no/i,morning:/morning/i,afternoon:/afternoon/i,evening:/evening/i,night:/night/i}},Se={ordinalNumber:fe({matchPattern:me,parsePattern:ce,valueCallback:function(a){return parseInt(a,10)}}),era:b({matchPatterns:he,defaultMatchWidth:"wide",parsePatterns:ve,defaultParseWidth:"any"}),quarter:b({matchPatterns:ge,defaultMatchWidth:"wide",parsePatterns:be,defaultParseWidth:"any",valueCallback:function(a){return a+1}}),month:b({matchPatterns:ye,defaultMatchWidth:"wide",parsePatterns:Me,defaultParseWidth:"any"}),day:b({matchPatterns:we,defaultMatchWidth:"wide",parsePatterns:pe,defaultParseWidth:"any"}),dayPeriod:b({matchPatterns:De,defaultMatchWidth:"any",parsePatterns:Pe,defaultParseWidth:"any"})};const Te=Se;var We={code:"en-US",formatDistance:H,formatLong:B,formatRelative:Z,localize:se,match:Te,options:{weekStartsOn:0,firstWeekContainsDate:1}};const Ne=We;function N(e,a){if(e==null)throw new TypeError("assign requires that input parameter not be null or undefined");for(var t in a)Object.prototype.hasOwnProperty.call(a,t)&&(e[t]=a[t]);return e}function ke(e){return N({},e)}var W=1440,Oe=2520,D=43200,Fe=86400;function xe(e,a,t){var n,i;c(2,arguments);var o=A(),r=(n=(i=t==null?void 0:t.locale)!==null&&i!==void 0?i:o.locale)!==null&&n!==void 0?n:Ne;if(!r.formatDistance)throw new RangeError("locale must contain formatDistance property");var l=M(e,a);if(isNaN(l))throw new RangeError("Invalid time value");var u=N(ke(t),{addSuffix:Boolean(t==null?void 0:t.addSuffix),comparison:l}),f,h;l>0?(f=s(a),h=s(e)):(f=s(e),h=s(a));var m=V(h,f),k=(S(h)-S(f))/1e3,d=Math.round((m-k)/60),v;if(d<2)return t!=null&&t.includeSeconds?m<5?r.formatDistance("lessThanXSeconds",5,u):m<10?r.formatDistance("lessThanXSeconds",10,u):m<20?r.formatDistance("lessThanXSeconds",20,u):m<40?r.formatDistance("halfAMinute",0,u):m<60?r.formatDistance("lessThanXMinutes",1,u):r.formatDistance("xMinutes",1,u):d===0?r.formatDistance("lessThanXMinutes",1,u):r.formatDistance("xMinutes",d,u);if(d<45)return r.formatDistance("xMinutes",d,u);if(d<90)return r.formatDistance("aboutXHours",1,u);if(dMath.floor((1+Math.random())*65536).toString(16);let h=!1,i=!1,f="",s,g;function m(e,n){let t;try{t=JSON.parse(e)}catch{console.log("JSON.parse error",JSON.parse(e))}const r=new Date,l=$(r);t.time=l,t.id=+r-0+M(),t.even=h=!h,n(t)}function $(e){const n=e.getFullYear()%100,t=u(e.getMonth()+1,2),r=u(e.getDate(),2),l=u(e.getHours(),2),o=u(e.getMinutes(),2),c=u(e.getSeconds(),2);return`${n}-${t}-${r} ${l}:${o}:${c}`}function p(e,n){return e.read().then(({done:t,value:r})=>{const l=L.decode(r,{stream:!t});f+=l;const o=f.split(` 2 | `),c=o[o.length-1];for(let d=0;de[t]).join("|")}let b,a;function k(e,n){if(e.logLevel==="uninit"||i||s&&s.readyState===1)return;g=n;const t=w(e,v);s=new WebSocket(t),s.addEventListener("error",()=>{y(e,n)}),s.addEventListener("message",function(r){m(r.data,n)})}function O(){s.close(),a&&a.abort()}function R(e){!g||!s||(s.close(),i=!1,k(e,g))}function y(e,n){if(a&&S(e)!==b)a.abort();else if(i)return;i=!0,b=S(e),a=new AbortController;const t=a.signal,{url:r,init:l}=D(e);fetch(r+v+"?level="+e.logLevel,{...l,signal:t}).then(o=>{const c=o.body.getReader();p(c,n)},o=>{i=!1,!t.aborted&&console.log("GET /logs error:",o.message)})}export{k as f,R as r,O as s}; 3 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/objectWithoutPropertiesLoose-4f48578a.js: -------------------------------------------------------------------------------- 1 | function a(r,o){if(r==null)return{};var n={},i=Object.keys(r),e,t;for(t=0;t=0)&&(n[e]=r[e]);return n}export{a as _}; 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/play-4baa6dad.js: -------------------------------------------------------------------------------- 1 | import{r as g,R as s,p as a}from"./index-7c6466d3.js";function p(){return p=Object.assign||function(t){for(var o=1;o=0)&&Object.prototype.propertyIsEnumerable.call(t,e)&&(r[e]=t[e])}return r}function y(t,o){if(t==null)return{};var r={},e=Object.keys(t),n,i;for(i=0;i=0)&&(r[n]=t[n]);return r}var c=g.forwardRef(function(t,o){var r=t.color,e=r===void 0?"currentColor":r,n=t.size,i=n===void 0?24:n,l=v(t,["color","size"]);return s.createElement("svg",p({ref:o,xmlns:"http://www.w3.org/2000/svg",width:i,height:i,viewBox:"0 0 24 24",fill:"none",stroke:e,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},l),s.createElement("rect",{x:"6",y:"4",width:"4",height:"16"}),s.createElement("rect",{x:"14",y:"4",width:"4",height:"16"}))});c.propTypes={color:a.string,size:a.oneOfType([a.string,a.number])};c.displayName="Pause";const b=c;function f(){return f=Object.assign||function(t){for(var o=1;o=0)&&Object.prototype.propertyIsEnumerable.call(t,e)&&(r[e]=t[e])}return r}function O(t,o){if(t==null)return{};var r={},e=Object.keys(t),n,i;for(i=0;i=0)&&(r[n]=t[n]);return r}var u=g.forwardRef(function(t,o){var r=t.color,e=r===void 0?"currentColor":r,n=t.size,i=n===void 0?24:n,l=h(t,["color","size"]);return s.createElement("svg",f({ref:o,xmlns:"http://www.w3.org/2000/svg",width:i,height:i,viewBox:"0 0 24 24",fill:"none",stroke:e,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},l),s.createElement("polygon",{points:"5 3 19 12 5 21 5 3"}))});u.propTypes={color:a.string,size:a.oneOfType([a.string,a.number])};u.displayName="Play";const w=u;export{w as P,b as a}; 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/roboto-mono-latin-400-normal-7295944e.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zerolabnet/SSClash/5cafaf7358abc10515723fa3d6eba783f11be3e4/rootfs/opt/clash/ui/assets/roboto-mono-latin-400-normal-7295944e.woff2 -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/roboto-mono-latin-400-normal-dffdffa7.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zerolabnet/SSClash/5cafaf7358abc10515723fa3d6eba783f11be3e4/rootfs/opt/clash/ui/assets/roboto-mono-latin-400-normal-dffdffa7.woff -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/rotate-cw-76728396.js: -------------------------------------------------------------------------------- 1 | import{r as c,R as s,p as a}from"./index-7c6466d3.js";function p(){return p=Object.assign||function(t){for(var n=1;n=0)&&Object.prototype.propertyIsEnumerable.call(t,e)&&(r[e]=t[e])}return r}function g(t,n){if(t==null)return{};var r={},e=Object.keys(t),o,i;for(i=0;i=0)&&(r[o]=t[o]);return r}var l=c.forwardRef(function(t,n){var r=t.color,e=r===void 0?"currentColor":r,o=t.size,i=o===void 0?24:o,f=u(t,["color","size"]);return s.createElement("svg",p({ref:n,xmlns:"http://www.w3.org/2000/svg",width:i,height:i,viewBox:"0 0 24 24",fill:"none",stroke:e,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},f),s.createElement("polyline",{points:"23 4 23 10 17 10"}),s.createElement("path",{d:"M20.49 15a9 9 0 1 1-2.12-9.36L23 10"}))});l.propTypes={color:a.string,size:a.oneOfType([a.string,a.number])};l.displayName="RotateCw";const y=l;export{y as R}; 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/useRemainingViewPortHeight-aa016eed.js: -------------------------------------------------------------------------------- 1 | import{s as r}from"./index-7c6466d3.js";const{useState:s,useRef:u,useCallback:a,useLayoutEffect:c}=r;function d(){const t=u(null),[n,i]=s(200),e=a(()=>{const{top:o}=t.current.getBoundingClientRect();i(window.innerHeight-o)},[]);return c(()=>(e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}),[e]),[t,n]}export{d as u}; 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/vi-75c7db25.js: -------------------------------------------------------------------------------- 1 | const n={All:"Tất cả",Overview:"Tổng quan",Proxies:"Proxy",Rules:"Quy tắc",Conns:"Kết nối",Config:"Cấu hình",Logs:"Nhật ký",Upload:"Tải lên",Download:"Tải xuống","Upload Total":"Tổng tải lên","Download Total":"Tổng tải xuống","Active Connections":"Kết nối hoạt động","Memory Usage":"Sử dụng bộ nhớ","Pause Refresh":"Tạm dừng làm mới","Resume Refresh":"Tiếp tục làm mới",close_all_connections:"Đóng tất cả kết nối",close_filter_connections:"Đóng tất cả kết nối sau khi lọc",Search:"Tìm kiếm",Up:"Lên",Down:"Xuống","Test Latency":"Kiểm tra độ trễ",settings:"Cài đặt",sort_in_grp:"Sắp xếp trong nhóm",hide_unavail_proxies:"Ẩn proxy không khả dụng",auto_close_conns:"Tự động đóng kết nối cũ",order_natural:"Thứ tự ban đầu trong tệp cấu hình",order_latency_asc:"Theo độ trễ từ nhỏ đến lớn",order_latency_desc:"Theo độ trễ từ lớn đến nhỏ",order_name_asc:"Theo tên theo thứ tự bảng chữ cái (A-Z)",order_name_desc:"Theo tên theo thứ tự bảng chữ cái (Z-A)",Connections:"Kết nối",current_backend:"Backend hiện tại",Active:"Hoạt động",switch_backend:"Chuyển đổi backend",Closed:"Đã đóng",switch_theme:"Chuyển đổi giao diện",theme:"Giao diện",about:"Về chúng tôi",no_logs:"Chưa có nhật ký, hãy kiên nhẫn...",chart_style:"Kiểu biểu đồ",latency_test_url:"URL kiểm tra độ trễ",lang:"Ngôn ngữ",update_all_rule_provider:"Cập nhật tất cả nhà cung cấp quy tắc",update_all_proxy_provider:"Cập nhật tất cả nhà cung cấp proxy",reload_config_file:"Tải lại tệp cấu hình",restart_core:"Khởi động lõi lại Clash",upgrade_core:"Nâng cấp lõi Clash",update_geo_databases_file:"Cập nhật tệp cơ sở dữ liệu GEO",flush_fake_ip_pool:"Xóa bộ nhớ đệm fake-ip",enable_tun_device:"Bật thiết bị TUN",allow_lan:"Cho phép LAN",tls_sniffing:"Bộ giám sát gói tin Sniffer",c_host:"Máy chủ",c_sni:"Phát hiện máy chủ Sniff ",c_process:"Quá trình",c_dl:"Tải Xuống",c_ul:"Tải Lên",c_dl_speed:"Tốc độ Tải Xuống",c_ul_speed:"Tốc độ Tải lên",c_chains:"Chuỗi",c_rule:"Quy tắc",c_time:"Thời gian",c_source:"Nguồn",c_destination_ip:"Địa chỉ IP đích",c_type:"Loại",c_ctrl:"Đóng",close_all_confirm:"Bạn có chắc chắn muốn đóng tất cả kết nối không?",close_all_confirm_yes:"Chắc chắn",close_all_confirm_no:"Không",manage_column:"Quản lý cột",reset_column:"Đặt lại cột",device_name:"Thẻ thiết bị",delete:"Xóa",add_tag:"Thêm thẻ",client_tag:"Thẻ khách hàng",sourceip_tip:"Thêm / vào đầu để sử dụng biểu thức chính quy, nếu không sẽ là kết quả khớp chính xác(By Ohoang7)",disconnect:"Đóng kết nối",internel:"Kết nối nội bộ"};export{n as data}; 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/zh-cn-ace621d4.js: -------------------------------------------------------------------------------- 1 | const e={All:"全部",Overview:"概览",Proxies:"代理",Rules:"规则",Conns:"连接",Config:"配置",Logs:"日志",Upload:"上传",Download:"下载","Upload Total":"上传总量","Download Total":"下载总量","Active Connections":"活动连接","Memory Usage":"内存使用情况",Memory:"内存","Pause Refresh":"暂停刷新","Resume Refresh":"继续刷新",close_all_connections:"关闭所有连接",close_filter_connections:"关闭所有过滤后的连接",Search:"查找",Up:"上传",Down:"下载","Test Latency":"延迟测速",settings:"设置",sort_in_grp:"代理组条目排序",hide_unavail_proxies:"隐藏不可用代理",auto_close_conns:"切换代理时自动断开旧连接",order_natural:"原 config 文件中的排序",order_latency_asc:"按延迟从小到大",order_latency_desc:"按延迟从大到小",order_name_asc:"按名称字母排序 (A-Z)",order_name_desc:"按名称字母排序 (Z-A)",Connections:"连接",current_backend:"当前后端",Active:"活动",switch_backend:"切换后端",Closed:"已断开",switch_theme:"切换主题",theme:"主题",about:"关于",no_logs:"暂无日志...",chart_style:"流量图样式",latency_test_url:"延迟测速 URL",lang:"语言",update_all_rule_provider:"更新所有 rule provider",update_all_proxy_provider:"更新所有 proxy provider",reload_config_file:"重载配置文件",update_geo_databases_file:"更新 GEO 数据库文件",flush_fake_ip_pool:"清空 FakeIP 数据库",enable_tun_device:"开启 TUN 转发",allow_lan:"允许局域网连接",tls_sniffing:"SNI 嗅探",c_host:"域名",c_sni:"嗅探域名",c_process:"进程",c_dl:"下载",c_ul:"上传",c_dl_speed:"下载速率",c_ul_speed:"上传速率",c_chains:"节点链",c_rule:"规则",c_time:"连接时间",c_source:"来源",c_destination_ip:"目标IP",c_type:"类型",c_ctrl:"关闭",restart_core:"重启 clash 核心",upgrade_core:"更新 Alpha 核心",close_all_confirm:"确定关闭所有连接?",close_all_confirm_yes:"确定",close_all_confirm_no:"取消",manage_column:"管理列",reset_column:"重置列",device_name:"设备名",delete:"删除",add_tag:"添加标签",client_tag:"客户端标签",sourceip_tip:"/开头为正则,否则为全匹配",disconnect:"断开连接",internel:"内部链接"};export{e as data}; 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/assets/zh-tw-47d3ce5e.js: -------------------------------------------------------------------------------- 1 | const e={All:"全部",Overview:"概覽",Proxies:"代理",Rules:"規則",Conns:"連線",Config:"設定",Logs:"紀錄",Upload:"上傳",Download:"下載","Upload Total":"總上傳","Download Total":"總下載","Active Connections":"活動中連線","Memory Usage":"記憶體使用狀況",Memory:"記憶體","Pause Refresh":"暫停重整","Resume Refresh":"繼續重整",close_all_connections:"斷開所有連線",close_filter_connections:"斷開所有過濾後的連線",Search:"搜尋",Up:"上傳",Down:"下載","Test Latency":"測試延遲速度",settings:"設定",sort_in_grp:"依代理群組排序",hide_unavail_proxies:"隱藏不可用的代理伺服器",auto_close_conns:"切換代理伺服器時自動斷開舊連線",order_natural:"原 config 文件中的順序",order_latency_asc:"按延遲從小到大",order_latency_desc:"按延遲從大到小",order_name_asc:"按名稱字母順序排序 (A-Z)",order_name_desc:"按名稱字母順序排序 (Z-A)",Connections:"連線",current_backend:"當前後端",Active:"活動中",switch_backend:"切換後端",Closed:"已斷線",switch_theme:"切換主題",theme:"主題",about:"關於",no_logs:"暫時沒有紀錄…",chart_style:"流量圖樣式",latency_test_url:"延遲測速 URL",lang:"語言",update_all_rule_provider:"更新所有規則提供者",update_all_proxy_provider:"更新所有代理伺服器提供者",reload_config_file:"重新載入設定檔",update_geo_databases_file:"更新 GEO 資料庫文件",flush_fake_ip_pool:"清除 Fake IP 資料庫",enable_tun_device:"開啟 TUN 轉發",allow_lan:"允許區域網路連接",tls_sniffing:"SNI 嗅探",c_host:"網域名稱",c_sni:"嗅探網域名稱",c_process:"處理程序",c_dl:"下載",c_ul:"上傳",c_dl_speed:"下載速度",c_ul_speed:"上傳速度",c_chains:"節點鍊",c_rule:"規則",c_time:"連線時間",c_source:"來源",c_destination_ip:"目標 IP",c_type:"類型",c_ctrl:"關閉",restart_core:"重新啟動 clash 核心",upgrade_core:"更新 Alpha 核心",close_all_confirm:"確定關閉所有連接?",close_all_confirm_yes:"確定",close_all_confirm_no:"取消",manage_column:"管理列",reset_column:"重置列",device_name:"設備名稱",delete:"刪除",add_tag:"新增標籤",client_tag:"客戶端標籤",sourceip_tip:"/開頭為正規表達式,否則為全面配對",disconnect:"斷開連線",internel:"內部連線"};export{e as data}; 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | yacd 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zerolabnet/SSClash/5cafaf7358abc10515723fa3d6eba783f11be3e4/rootfs/opt/clash/ui/logo.png -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/manifest.webmanifest: -------------------------------------------------------------------------------- 1 | {"name":"yacd","short_name":"yacd","start_url":"./","display":"standalone","background_color":"#ffffff","lang":"en","scope":"./","icons":[{"src":"apple-touch-icon-precomposed.png","sizes":"512x512","type":"image/png"}]} 2 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/registerSW.js: -------------------------------------------------------------------------------- 1 | if('serviceWorker' in navigator) {window.addEventListener('load', () => {navigator.serviceWorker.register('./sw.js', { scope: './' })})} -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/sw.js: -------------------------------------------------------------------------------- 1 | try{self["workbox:core:6.5.3"]&&_()}catch{}const G=(s,...e)=>{let t=s;return e.length>0&&(t+=` :: ${JSON.stringify(e)}`),t},Q=G;class l extends Error{constructor(e,t){const n=Q(e,t);super(n),this.name=e,this.details=t}}const j=new Set;function z(s){j.add(s)}const d={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:typeof registration<"u"?registration.scope:""},E=s=>[d.prefix,s,d.suffix].filter(e=>e&&e.length>0).join("-"),J=s=>{for(const e of Object.keys(d))s(e)},x={updateDetails:s=>{J(e=>{typeof s[e]=="string"&&(d[e]=s[e])})},getGoogleAnalyticsName:s=>s||E(d.googleAnalytics),getPrecacheName:s=>s||E(d.precache),getPrefix:()=>d.prefix,getRuntimeName:s=>s||E(d.runtime),getSuffix:()=>d.suffix};function A(s,e){const t=new URL(s);for(const n of e)t.searchParams.delete(n);return t.href}async function X(s,e,t,n){const a=A(e.url,t);if(e.url===a)return s.match(e,n);const r=Object.assign(Object.assign({},n),{ignoreSearch:!0}),i=await s.keys(e,r);for(const c of i){const o=A(c.url,t);if(a===o)return s.match(c,n)}}let m;function Y(){if(m===void 0){const s=new Response("");if("body"in s)try{new Response(s.body),m=!0}catch{m=!1}m=!1}return m}function q(s){s.then(()=>{})}class Z{constructor(){this.promise=new Promise((e,t)=>{this.resolve=e,this.reject=t})}}async function ee(){for(const s of j)await s()}const te=s=>new URL(String(s),location.href).href.replace(new RegExp(`^${location.origin}`),"");function se(s){return new Promise(e=>setTimeout(e,s))}function O(s,e){const t=e();return s.waitUntil(t),t}async function ne(s,e){let t=null;if(s.url&&(t=new URL(s.url).origin),t!==self.location.origin)throw new l("cross-origin-copy-response",{origin:t});const n=s.clone(),a={headers:new Headers(n.headers),status:n.status,statusText:n.statusText},r=e?e(a):a,i=Y()?n.body:await n.blob();return new Response(i,r)}function ae(){self.addEventListener("activate",()=>self.clients.claim())}const re=(s,e)=>e.some(t=>s instanceof t);let S,v;function ie(){return S||(S=[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction])}function ce(){return v||(v=[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey])}const F=new WeakMap,P=new WeakMap,H=new WeakMap,D=new WeakMap,I=new WeakMap;function oe(s){const e=new Promise((t,n)=>{const a=()=>{s.removeEventListener("success",r),s.removeEventListener("error",i)},r=()=>{t(f(s.result)),a()},i=()=>{n(s.error),a()};s.addEventListener("success",r),s.addEventListener("error",i)});return e.then(t=>{t instanceof IDBCursor&&F.set(t,s)}).catch(()=>{}),I.set(e,s),e}function he(s){if(P.has(s))return;const e=new Promise((t,n)=>{const a=()=>{s.removeEventListener("complete",r),s.removeEventListener("error",i),s.removeEventListener("abort",i)},r=()=>{t(),a()},i=()=>{n(s.error||new DOMException("AbortError","AbortError")),a()};s.addEventListener("complete",r),s.addEventListener("error",i),s.addEventListener("abort",i)});P.set(s,e)}let k={get(s,e,t){if(s instanceof IDBTransaction){if(e==="done")return P.get(s);if(e==="objectStoreNames")return s.objectStoreNames||H.get(s);if(e==="store")return t.objectStoreNames[1]?void 0:t.objectStore(t.objectStoreNames[0])}return f(s[e])},set(s,e,t){return s[e]=t,!0},has(s,e){return s instanceof IDBTransaction&&(e==="done"||e==="store")?!0:e in s}};function le(s){k=s(k)}function ue(s){return s===IDBDatabase.prototype.transaction&&!("objectStoreNames"in IDBTransaction.prototype)?function(e,...t){const n=s.call(L(this),e,...t);return H.set(n,e.sort?e.sort():[e]),f(n)}:ce().includes(s)?function(...e){return s.apply(L(this),e),f(F.get(this))}:function(...e){return f(s.apply(L(this),e))}}function de(s){return typeof s=="function"?ue(s):(s instanceof IDBTransaction&&he(s),re(s,ie())?new Proxy(s,k):s)}function f(s){if(s instanceof IDBRequest)return oe(s);if(D.has(s))return D.get(s);const e=de(s);return e!==s&&(D.set(s,e),I.set(e,s)),e}const L=s=>I.get(s);function fe(s,e,{blocked:t,upgrade:n,blocking:a,terminated:r}={}){const i=indexedDB.open(s,e),c=f(i);return n&&i.addEventListener("upgradeneeded",o=>{n(f(i.result),o.oldVersion,o.newVersion,f(i.transaction),o)}),t&&i.addEventListener("blocked",o=>t(o.oldVersion,o.newVersion,o)),c.then(o=>{r&&o.addEventListener("close",()=>r()),a&&o.addEventListener("versionchange",h=>a(h.oldVersion,h.newVersion,h))}).catch(()=>{}),c}function pe(s,{blocked:e}={}){const t=indexedDB.deleteDatabase(s);return e&&t.addEventListener("blocked",n=>e(n.oldVersion,n)),f(t).then(()=>{})}const ge=["get","getKey","getAll","getAllKeys","count"],me=["put","add","delete","clear"],U=new Map;function W(s,e){if(!(s instanceof IDBDatabase&&!(e in s)&&typeof e=="string"))return;if(U.get(e))return U.get(e);const t=e.replace(/FromIndex$/,""),n=e!==t,a=me.includes(t);if(!(t in(n?IDBIndex:IDBObjectStore).prototype)||!(a||ge.includes(t)))return;const r=async function(i,...c){const o=this.transaction(i,a?"readwrite":"readonly");let h=o.store;return n&&(h=h.index(c.shift())),(await Promise.all([h[t](...c),a&&o.done]))[0]};return U.set(e,r),r}le(s=>({...s,get:(e,t,n)=>W(e,t)||s.get(e,t,n),has:(e,t)=>!!W(e,t)||s.has(e,t)}));try{self["workbox:expiration:6.5.3"]&&_()}catch{}const ye="workbox-expiration",y="cache-entries",B=s=>{const e=new URL(s,location.href);return e.hash="",e.href};class we{constructor(e){this._db=null,this._cacheName=e}_upgradeDb(e){const t=e.createObjectStore(y,{keyPath:"id"});t.createIndex("cacheName","cacheName",{unique:!1}),t.createIndex("timestamp","timestamp",{unique:!1})}_upgradeDbAndDeleteOldDbs(e){this._upgradeDb(e),this._cacheName&&pe(this._cacheName)}async setTimestamp(e,t){e=B(e);const n={url:e,timestamp:t,cacheName:this._cacheName,id:this._getId(e)},r=(await this.getDb()).transaction(y,"readwrite",{durability:"relaxed"});await r.store.put(n),await r.done}async getTimestamp(e){const n=await(await this.getDb()).get(y,this._getId(e));return n==null?void 0:n.timestamp}async expireEntries(e,t){const n=await this.getDb();let a=await n.transaction(y).store.index("timestamp").openCursor(null,"prev");const r=[];let i=0;for(;a;){const o=a.value;o.cacheName===this._cacheName&&(e&&o.timestamp=t?r.push(a.value):i++),a=await a.continue()}const c=[];for(const o of r)await n.delete(y,o.id),c.push(o.url);return c}_getId(e){return this._cacheName+"|"+B(e)}async getDb(){return this._db||(this._db=await fe(ye,1,{upgrade:this._upgradeDbAndDeleteOldDbs.bind(this)})),this._db}}class _e{constructor(e,t={}){this._isRunning=!1,this._rerunRequested=!1,this._maxEntries=t.maxEntries,this._maxAgeSeconds=t.maxAgeSeconds,this._matchOptions=t.matchOptions,this._cacheName=e,this._timestampModel=new we(e)}async expireEntries(){if(this._isRunning){this._rerunRequested=!0;return}this._isRunning=!0;const e=this._maxAgeSeconds?Date.now()-this._maxAgeSeconds*1e3:0,t=await this._timestampModel.expireEntries(e,this._maxEntries),n=await self.caches.open(this._cacheName);for(const a of t)await n.delete(a,this._matchOptions);this._isRunning=!1,this._rerunRequested&&(this._rerunRequested=!1,q(this.expireEntries()))}async updateTimestamp(e){await this._timestampModel.setTimestamp(e,Date.now())}async isURLExpired(e){if(this._maxAgeSeconds){const t=await this._timestampModel.getTimestamp(e),n=Date.now()-this._maxAgeSeconds*1e3;return t!==void 0?t{if(!r)return null;const i=this._isResponseDateFresh(r),c=this._getCacheExpiration(a);q(c.expireEntries());const o=c.updateTimestamp(n.url);if(t)try{t.waitUntil(o)}catch{}return i?r:null},this.cacheDidUpdate=async({cacheName:t,request:n})=>{const a=this._getCacheExpiration(t);await a.updateTimestamp(n.url),await a.expireEntries()},this._config=e,this._maxAgeSeconds=e.maxAgeSeconds,this._cacheExpirations=new Map,e.purgeOnQuotaError&&z(()=>this.deleteCacheAndMetadata())}_getCacheExpiration(e){if(e===x.getRuntimeName())throw new l("expire-custom-caches-only");let t=this._cacheExpirations.get(e);return t||(t=new _e(e,this._config),this._cacheExpirations.set(e,t)),t}_isResponseDateFresh(e){if(!this._maxAgeSeconds)return!0;const t=this._getDateHeaderTimestamp(e);if(t===null)return!0;const n=Date.now();return t>=n-this._maxAgeSeconds*1e3}_getDateHeaderTimestamp(e){if(!e.headers.has("date"))return null;const t=e.headers.get("date"),a=new Date(t).getTime();return isNaN(a)?null:a}async deleteCacheAndMetadata(){for(const[e,t]of this._cacheExpirations)await self.caches.delete(e),await t.delete();this._cacheExpirations=new Map}}try{self["workbox:precaching:6.5.3"]&&_()}catch{}const be="__WB_REVISION__";function Ce(s){if(!s)throw new l("add-to-cache-list-unexpected-type",{entry:s});if(typeof s=="string"){const r=new URL(s,location.href);return{cacheKey:r.href,url:r.href}}const{revision:e,url:t}=s;if(!t)throw new l("add-to-cache-list-unexpected-type",{entry:s});if(!e){const r=new URL(t,location.href);return{cacheKey:r.href,url:r.href}}const n=new URL(t,location.href),a=new URL(t,location.href);return n.searchParams.set(be,e),{cacheKey:n.href,url:a.href}}class xe{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:e,state:t})=>{t&&(t.originalRequest=e)},this.cachedResponseWillBeUsed=async({event:e,state:t,cachedResponse:n})=>{if(e.type==="install"&&t&&t.originalRequest&&t.originalRequest instanceof Request){const a=t.originalRequest.url;n?this.notUpdatedURLs.push(a):this.updatedURLs.push(a)}return n}}}class Ee{constructor({precacheController:e}){this.cacheKeyWillBeUsed=async({request:t,params:n})=>{const a=(n==null?void 0:n.cacheKey)||this._precacheController.getCacheKeyForURL(t.url);return a?new Request(a,{headers:t.headers}):t},this._precacheController=e}}try{self["workbox:strategies:6.5.3"]&&_()}catch{}function b(s){return typeof s=="string"?new Request(s):s}class De{constructor(e,t){this._cacheKeys={},Object.assign(this,t),this.event=t.event,this._strategy=e,this._handlerDeferred=new Z,this._extendLifetimePromises=[],this._plugins=[...e.plugins],this._pluginStateMap=new Map;for(const n of this._plugins)this._pluginStateMap.set(n,{});this.event.waitUntil(this._handlerDeferred.promise)}async fetch(e){const{event:t}=this;let n=b(e);if(n.mode==="navigate"&&t instanceof FetchEvent&&t.preloadResponse){const i=await t.preloadResponse;if(i)return i}const a=this.hasCallback("fetchDidFail")?n.clone():null;try{for(const i of this.iterateCallbacks("requestWillFetch"))n=await i({request:n.clone(),event:t})}catch(i){if(i instanceof Error)throw new l("plugin-error-request-will-fetch",{thrownErrorMessage:i.message})}const r=n.clone();try{let i;i=await fetch(n,n.mode==="navigate"?void 0:this._strategy.fetchOptions);for(const c of this.iterateCallbacks("fetchDidSucceed"))i=await c({event:t,request:r,response:i});return i}catch(i){throw a&&await this.runCallbacks("fetchDidFail",{error:i,event:t,originalRequest:a.clone(),request:r.clone()}),i}}async fetchAndCachePut(e){const t=await this.fetch(e),n=t.clone();return this.waitUntil(this.cachePut(e,n)),t}async cacheMatch(e){const t=b(e);let n;const{cacheName:a,matchOptions:r}=this._strategy,i=await this.getCacheKey(t,"read"),c=Object.assign(Object.assign({},r),{cacheName:a});n=await caches.match(i,c);for(const o of this.iterateCallbacks("cachedResponseWillBeUsed"))n=await o({cacheName:a,matchOptions:r,cachedResponse:n,request:i,event:this.event})||void 0;return n}async cachePut(e,t){const n=b(e);await se(0);const a=await this.getCacheKey(n,"write");if(!t)throw new l("cache-put-with-no-response",{url:te(a.url)});const r=await this._ensureResponseSafeToCache(t);if(!r)return!1;const{cacheName:i,matchOptions:c}=this._strategy,o=await self.caches.open(i),h=this.hasCallback("cacheDidUpdate"),g=h?await X(o,a.clone(),["__WB_REVISION__"],c):null;try{await o.put(a,h?r.clone():r)}catch(u){if(u instanceof Error)throw u.name==="QuotaExceededError"&&await ee(),u}for(const u of this.iterateCallbacks("cacheDidUpdate"))await u({cacheName:i,oldResponse:g,newResponse:r.clone(),request:a,event:this.event});return!0}async getCacheKey(e,t){const n=`${e.url} | ${t}`;if(!this._cacheKeys[n]){let a=e;for(const r of this.iterateCallbacks("cacheKeyWillBeUsed"))a=b(await r({mode:t,request:a,event:this.event,params:this.params}));this._cacheKeys[n]=a}return this._cacheKeys[n]}hasCallback(e){for(const t of this._strategy.plugins)if(e in t)return!0;return!1}async runCallbacks(e,t){for(const n of this.iterateCallbacks(e))await n(t)}*iterateCallbacks(e){for(const t of this._strategy.plugins)if(typeof t[e]=="function"){const n=this._pluginStateMap.get(t);yield r=>{const i=Object.assign(Object.assign({},r),{state:n});return t[e](i)}}}waitUntil(e){return this._extendLifetimePromises.push(e),e}async doneWaiting(){let e;for(;e=this._extendLifetimePromises.shift();)await e}destroy(){this._handlerDeferred.resolve(null)}async _ensureResponseSafeToCache(e){let t=e,n=!1;for(const a of this.iterateCallbacks("cacheWillUpdate"))if(t=await a({request:this.request,response:t,event:this.event})||void 0,n=!0,!t)break;return n||t&&t.status!==200&&(t=void 0),t}}class V{constructor(e={}){this.cacheName=x.getRuntimeName(e.cacheName),this.plugins=e.plugins||[],this.fetchOptions=e.fetchOptions,this.matchOptions=e.matchOptions}handle(e){const[t]=this.handleAll(e);return t}handleAll(e){e instanceof FetchEvent&&(e={event:e,request:e.request});const t=e.event,n=typeof e.request=="string"?new Request(e.request):e.request,a="params"in e?e.params:void 0,r=new De(this,{event:t,request:n,params:a}),i=this._getResponse(r,n,t),c=this._awaitComplete(i,r,n,t);return[i,c]}async _getResponse(e,t,n){await e.runCallbacks("handlerWillStart",{event:n,request:t});let a;try{if(a=await this._handle(t,e),!a||a.type==="error")throw new l("no-response",{url:t.url})}catch(r){if(r instanceof Error){for(const i of e.iterateCallbacks("handlerDidError"))if(a=await i({error:r,event:n,request:t}),a)break}if(!a)throw r}for(const r of e.iterateCallbacks("handlerWillRespond"))a=await r({event:n,request:t,response:a});return a}async _awaitComplete(e,t,n,a){let r,i;try{r=await e}catch{}try{await t.runCallbacks("handlerDidRespond",{event:a,request:n,response:r}),await t.doneWaiting()}catch(c){c instanceof Error&&(i=c)}if(await t.runCallbacks("handlerDidComplete",{event:a,request:n,response:r,error:i}),t.destroy(),i)throw i}}class p extends V{constructor(e={}){e.cacheName=x.getPrecacheName(e.cacheName),super(e),this._fallbackToNetwork=e.fallbackToNetwork!==!1,this.plugins.push(p.copyRedirectedCacheableResponsesPlugin)}async _handle(e,t){const n=await t.cacheMatch(e);return n||(t.event&&t.event.type==="install"?await this._handleInstall(e,t):await this._handleFetch(e,t))}async _handleFetch(e,t){let n;const a=t.params||{};if(this._fallbackToNetwork){const r=a.integrity,i=e.integrity,c=!i||i===r;n=await t.fetch(new Request(e,{integrity:e.mode!=="no-cors"?i||r:void 0})),r&&c&&e.mode!=="no-cors"&&(this._useDefaultCacheabilityPluginIfNeeded(),await t.cachePut(e,n.clone()))}else throw new l("missing-precache-entry",{cacheName:this.cacheName,url:e.url});return n}async _handleInstall(e,t){this._useDefaultCacheabilityPluginIfNeeded();const n=await t.fetch(e);if(!await t.cachePut(e,n.clone()))throw new l("bad-precaching-response",{url:e.url,status:n.status});return n}_useDefaultCacheabilityPluginIfNeeded(){let e=null,t=0;for(const[n,a]of this.plugins.entries())a!==p.copyRedirectedCacheableResponsesPlugin&&(a===p.defaultPrecacheCacheabilityPlugin&&(e=n),a.cacheWillUpdate&&t++);t===0?this.plugins.push(p.defaultPrecacheCacheabilityPlugin):t>1&&e!==null&&this.plugins.splice(e,1)}}p.defaultPrecacheCacheabilityPlugin={async cacheWillUpdate({response:s}){return!s||s.status>=400?null:s}};p.copyRedirectedCacheableResponsesPlugin={async cacheWillUpdate({response:s}){return s.redirected?await ne(s):s}};class Le{constructor({cacheName:e,plugins:t=[],fallbackToNetwork:n=!0}={}){this._urlsToCacheKeys=new Map,this._urlsToCacheModes=new Map,this._cacheKeysToIntegrities=new Map,this._strategy=new p({cacheName:x.getPrecacheName(e),plugins:[...t,new Ee({precacheController:this})],fallbackToNetwork:n}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this._strategy}precache(e){this.addToCacheList(e),this._installAndActiveListenersAdded||(self.addEventListener("install",this.install),self.addEventListener("activate",this.activate),this._installAndActiveListenersAdded=!0)}addToCacheList(e){const t=[];for(const n of e){typeof n=="string"?t.push(n):n&&n.revision===void 0&&t.push(n.url);const{cacheKey:a,url:r}=Ce(n),i=typeof n!="string"&&n.revision?"reload":"default";if(this._urlsToCacheKeys.has(r)&&this._urlsToCacheKeys.get(r)!==a)throw new l("add-to-cache-list-conflicting-entries",{firstEntry:this._urlsToCacheKeys.get(r),secondEntry:a});if(typeof n!="string"&&n.integrity){if(this._cacheKeysToIntegrities.has(a)&&this._cacheKeysToIntegrities.get(a)!==n.integrity)throw new l("add-to-cache-list-conflicting-integrities",{url:r});this._cacheKeysToIntegrities.set(a,n.integrity)}if(this._urlsToCacheKeys.set(r,a),this._urlsToCacheModes.set(r,i),t.length>0){const c=`Workbox is precaching URLs without revision info: ${t.join(", ")} 2 | This is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(c)}}}install(e){return O(e,async()=>{const t=new xe;this.strategy.plugins.push(t);for(const[r,i]of this._urlsToCacheKeys){const c=this._cacheKeysToIntegrities.get(i),o=this._urlsToCacheModes.get(r),h=new Request(r,{integrity:c,cache:o,credentials:"same-origin"});await Promise.all(this.strategy.handleAll({params:{cacheKey:i},request:h,event:e}))}const{updatedURLs:n,notUpdatedURLs:a}=t;return{updatedURLs:n,notUpdatedURLs:a}})}activate(e){return O(e,async()=>{const t=await self.caches.open(this.strategy.cacheName),n=await t.keys(),a=new Set(this._urlsToCacheKeys.values()),r=[];for(const i of n)a.has(i.url)||(await t.delete(i),r.push(i.url));return{deletedURLs:r}})}getURLsToCacheKeys(){return this._urlsToCacheKeys}getCachedURLs(){return[...this._urlsToCacheKeys.keys()]}getCacheKeyForURL(e){const t=new URL(e,location.href);return this._urlsToCacheKeys.get(t.href)}getIntegrityForCacheKey(e){return this._cacheKeysToIntegrities.get(e)}async matchPrecache(e){const t=e instanceof Request?e.url:e,n=this.getCacheKeyForURL(t);if(n)return(await self.caches.open(this.strategy.cacheName)).match(n)}createHandlerBoundToURL(e){const t=this.getCacheKeyForURL(e);if(!t)throw new l("non-precached-url",{url:e});return n=>(n.request=new Request(e),n.params=Object.assign({cacheKey:t},n.params),this.strategy.handle(n))}}let T;const M=()=>(T||(T=new Le),T);try{self["workbox:routing:6.5.3"]&&_()}catch{}const $="GET",C=s=>s&&typeof s=="object"?s:{handle:s};class R{constructor(e,t,n=$){this.handler=C(t),this.match=e,this.method=n}setCatchHandler(e){this.catchHandler=C(e)}}class Ue extends R{constructor(e,t,n){const a=({url:r})=>{const i=e.exec(r.href);if(i&&!(r.origin!==location.origin&&i.index!==0))return i.slice(1)};super(a,t,n)}}class Te{constructor(){this._routes=new Map,this._defaultHandlerMap=new Map}get routes(){return this._routes}addFetchListener(){self.addEventListener("fetch",e=>{const{request:t}=e,n=this.handleRequest({request:t,event:e});n&&e.respondWith(n)})}addCacheListener(){self.addEventListener("message",e=>{if(e.data&&e.data.type==="CACHE_URLS"){const{payload:t}=e.data,n=Promise.all(t.urlsToCache.map(a=>{typeof a=="string"&&(a=[a]);const r=new Request(...a);return this.handleRequest({request:r,event:e})}));e.waitUntil(n),e.ports&&e.ports[0]&&n.then(()=>e.ports[0].postMessage(!0))}})}handleRequest({request:e,event:t}){const n=new URL(e.url,location.href);if(!n.protocol.startsWith("http"))return;const a=n.origin===location.origin,{params:r,route:i}=this.findMatchingRoute({event:t,request:e,sameOrigin:a,url:n});let c=i&&i.handler;const o=e.method;if(!c&&this._defaultHandlerMap.has(o)&&(c=this._defaultHandlerMap.get(o)),!c)return;let h;try{h=c.handle({url:n,request:e,event:t,params:r})}catch(u){h=Promise.reject(u)}const g=i&&i.catchHandler;return h instanceof Promise&&(this._catchHandler||g)&&(h=h.catch(async u=>{if(g)try{return await g.handle({url:n,request:e,event:t,params:r})}catch(K){K instanceof Error&&(u=K)}if(this._catchHandler)return this._catchHandler.handle({url:n,request:e,event:t});throw u})),h}findMatchingRoute({url:e,sameOrigin:t,request:n,event:a}){const r=this._routes.get(n.method)||[];for(const i of r){let c;const o=i.match({url:e,sameOrigin:t,request:n,event:a});if(o)return c=o,(Array.isArray(c)&&c.length===0||o.constructor===Object&&Object.keys(o).length===0||typeof o=="boolean")&&(c=void 0),{route:i,params:c}}return{}}setDefaultHandler(e,t=$){this._defaultHandlerMap.set(t,C(e))}setCatchHandler(e){this._catchHandler=C(e)}registerRoute(e){this._routes.has(e.method)||this._routes.set(e.method,[]),this._routes.get(e.method).push(e)}unregisterRoute(e){if(!this._routes.has(e.method))throw new l("unregister-route-but-not-found-with-method",{method:e.method});const t=this._routes.get(e.method).indexOf(e);if(t>-1)this._routes.get(e.method).splice(t,1);else throw new l("unregister-route-route-not-registered")}}let w;const Pe=()=>(w||(w=new Te,w.addFetchListener(),w.addCacheListener()),w);function N(s,e,t){let n;if(typeof s=="string"){const r=new URL(s,location.href),i=({url:c})=>c.href===r.href;n=new R(i,e,t)}else if(s instanceof RegExp)n=new Ue(s,e,t);else if(typeof s=="function")n=new R(s,e,t);else if(s instanceof R)n=s;else throw new l("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});return Pe().registerRoute(n),n}function ke(s,e=[]){for(const t of[...s.searchParams.keys()])e.some(n=>n.test(t))&&s.searchParams.delete(t);return s}function*Ie(s,{ignoreURLParametersMatching:e=[/^utm_/,/^fbclid$/],directoryIndex:t="index.html",cleanURLs:n=!0,urlManipulation:a}={}){const r=new URL(s,location.href);r.hash="",yield r.href;const i=ke(r,e);if(yield i.href,t&&i.pathname.endsWith("/")){const c=new URL(i.href);c.pathname+=t,yield c.href}if(n){const c=new URL(i.href);c.pathname+=".html",yield c.href}if(a){const c=a({url:r});for(const o of c)yield o.href}}class Me extends R{constructor(e,t){const n=({request:a})=>{const r=e.getURLsToCacheKeys();for(const i of Ie(a.url,t)){const c=r.get(i);if(c){const o=e.getIntegrityForCacheKey(c);return{cacheKey:c,integrity:o}}}};super(n,e.strategy)}}function Ne(s){const e=M(),t=new Me(e,s);N(t)}function Ke(s){return M().createHandlerBoundToURL(s)}function Ae(s){M().precache(s)}function Oe(s,e){Ae(s),Ne(e)}const Se={cacheWillUpdate:async({response:s})=>s.status===200||s.status===0?s:null};class ve extends V{constructor(e={}){super(e),this.plugins.some(t=>"cacheWillUpdate"in t)||this.plugins.unshift(Se)}async _handle(e,t){const n=t.fetchAndCachePut(e).catch(()=>{});t.waitUntil(n);let a=await t.cacheMatch(e),r;if(!a)try{a=await n}catch(i){i instanceof Error&&(r=i)}if(!a)throw new l("no-response",{url:e.url,error:r});return a}}ae();Oe([{"revision":null,"url":"assets/BaseModal-0f630377.js"},{"revision":null,"url":"assets/BaseModal-e9f180d4.css"},{"revision":null,"url":"assets/chart-lib-6081a478.js"},{"revision":null,"url":"assets/Config-3d242ed2.js"},{"revision":null,"url":"assets/Config-7eb3f1bb.css"},{"revision":null,"url":"assets/Connections-2720e021.js"},{"revision":null,"url":"assets/Connections-2b49f1fb.css"},{"revision":null,"url":"assets/debounce-c1ba2006.js"},{"revision":null,"url":"assets/en-1067a8eb.js"},{"revision":null,"url":"assets/Fab-48def6bf.css"},{"revision":null,"url":"assets/Fab-e6dedc20.js"},{"revision":null,"url":"assets/index-64292e67.css"},{"revision":null,"url":"assets/index-7c6466d3.js"},{"revision":null,"url":"assets/index-84fa0cb3.js"},{"revision":null,"url":"assets/index-e51a0671.js"},{"revision":null,"url":"assets/Input-eec9e65c.js"},{"revision":null,"url":"assets/Logs-4c263fad.css"},{"revision":null,"url":"assets/logs-8ad08aa6.js"},{"revision":null,"url":"assets/Logs-8ed10c2c.js"},{"revision":null,"url":"assets/objectWithoutPropertiesLoose-4f48578a.js"},{"revision":null,"url":"assets/play-4baa6dad.js"},{"revision":null,"url":"assets/Proxies-06b60f95.css"},{"revision":null,"url":"assets/Proxies-ce7620dc.js"},{"revision":null,"url":"assets/rotate-cw-76728396.js"},{"revision":null,"url":"assets/Rules-162ef666.css"},{"revision":null,"url":"assets/Rules-2c94a03b.js"},{"revision":null,"url":"assets/Select-07e025ab.css"},{"revision":null,"url":"assets/Select-3321dc18.js"},{"revision":null,"url":"assets/TextFitler-2e63abd5.js"},{"revision":null,"url":"assets/TextFitler-a112af1a.css"},{"revision":null,"url":"assets/useRemainingViewPortHeight-aa016eed.js"},{"revision":null,"url":"assets/vi-75c7db25.js"},{"revision":null,"url":"assets/zh-cn-ace621d4.js"},{"revision":null,"url":"assets/zh-tw-47d3ce5e.js"},{"revision":"0ae55c380b3cc388cffacbfb2231c342","url":"index.html"},{"revision":"402b66900e731ca748771b6fc5e7a068","url":"registerSW.js"},{"revision":"ef24a4bbd6aba7f4424b413e8fc116ea","url":"apple-touch-icon-precomposed.png"},{"revision":"f00e213a787b40930c64ed1f84eb6c66","url":"manifest.webmanifest"}]);const We=new RegExp("/[^/?]+\\.[^/]+$");N(({request:s,url:e})=>!(s.mode!=="navigate"||e.pathname.startsWith("/_")||e.pathname.match(We)),Ke("index.html"));N(({url:s})=>s.origin===self.location.origin&&s.pathname.endsWith(".png"),new ve({cacheName:"images",plugins:[new Re({maxEntries:50})]}));self.addEventListener("message",s=>{s.data&&s.data.type==="SKIP_WAITING"&&self.skipWaiting()}); 3 | -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/yacd.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zerolabnet/SSClash/5cafaf7358abc10515723fa3d6eba783f11be3e4/rootfs/opt/clash/ui/yacd.ico -------------------------------------------------------------------------------- /rootfs/opt/clash/ui/yacd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zerolabnet/SSClash/5cafaf7358abc10515723fa3d6eba783f11be3e4/rootfs/opt/clash/ui/yacd.png -------------------------------------------------------------------------------- /rootfs/usr/share/luci/menu.d/luci-app-ssclash.json: -------------------------------------------------------------------------------- 1 | { 2 | "admin/services/ssclash": { 3 | "title": "SSClash", 4 | "action": { 5 | "type": "alias", 6 | "path": "admin/services/ssclash/config" 7 | }, 8 | "depends": { 9 | "acl": [ "luci-app-ssclash" ] 10 | } 11 | }, 12 | "admin/services/ssclash/config": { 13 | "title": "Config", 14 | "order": 10, 15 | "action": { 16 | "type": "view", 17 | "path": "ssclash/config" 18 | } 19 | }, 20 | "admin/services/ssclash/log": { 21 | "title": "Log", 22 | "order": 20, 23 | "action": { 24 | "type": "view", 25 | "path": "ssclash/log" 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /rootfs/usr/share/rpcd/acl.d/luci-app-ssclash.json: -------------------------------------------------------------------------------- 1 | { 2 | "luci-app-ssclash": { 3 | "description": "Grant access to Clash procedures", 4 | "read": { 5 | "file": { 6 | "/opt/clash/config.yaml": [ "read" ], 7 | "/sbin/logread": [ "exec" ] 8 | }, 9 | "ubus": { 10 | "file": [ "read" ], 11 | "service": [ "list" ] 12 | } 13 | }, 14 | "write": { 15 | "file": { 16 | "/opt/clash/config.yaml": [ "write" ], 17 | "/etc/init.d/clash start": [ "exec" ], 18 | "/etc/init.d/clash stop": [ "exec" ], 19 | "/etc/init.d/clash enable": [ "exec" ], 20 | "/etc/init.d/clash disable": [ "exec" ], 21 | "/etc/init.d/clash reload": [ "exec" ] 22 | }, 23 | "ubus": { 24 | "file": [ "write" ] 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /rootfs/www/luci-static/resources/view/ssclash/ace/mode-text.js: -------------------------------------------------------------------------------- 1 | ; (function() { 2 | ace.require(["ace/mode/text"], function(m) { 3 | if (typeof module == "object" && typeof exports == "object" && module) { 4 | module.exports = m; 5 | } 6 | }); 7 | })(); 8 | -------------------------------------------------------------------------------- /rootfs/www/luci-static/resources/view/ssclash/ace/mode-yaml.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/mode/yaml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"list.markup",regex:/^(?:-{3}|\.{3})\s*(?=#|$)/},{token:"list.markup",regex:/^\s*[\-?](?:$|\s)/},{token:"constant",regex:"!![\\w//]+"},{token:"constant.language",regex:"[&\\*][a-zA-Z0-9-_]+"},{token:["meta.tag","keyword"],regex:/^(\s*\w.*?)(:(?=\s|$))/},{token:["meta.tag","keyword"],regex:/(\w+?)(\s*:(?=\s|$))/},{token:"keyword.operator",regex:"<<\\w*:\\w*"},{token:"keyword.operator",regex:"-\\s*(?=[{])"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:/[|>][-+\d]*(?:$|\s+(?:$|#))/,onMatch:function(e,t,n,r){r=r.replace(/ #.*/,"");var i=/^ *((:\s*)?-(\s*[^|>])?)?/.exec(r)[0].replace(/\S\s*$/,"").length,s=parseInt(/\d+[\s+-]*$/.exec(r));return s?(i+=s-1,this.next="mlString"):this.next="mlStringPre",n.length?(n[0]=this.next,n[1]=i):(n.push(this.next),n.push(i)),this.token},next:"mlString"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:/(\b|[+\-\.])[\d_]+(?:(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)(?=[^\d-\w]|$)/},{token:"constant.numeric",regex:/[+\-]?\.inf\b|NaN\b|0x[\dA-Fa-f_]+|0b[10_]+/},{token:"constant.language.boolean",regex:"\\b(?:true|false|TRUE|FALSE|True|False|yes|no)\\b"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:/[^\s,:\[\]\{\}]+/}],mlStringPre:[{token:"indent",regex:/^ *$/},{token:"indent",regex:/^ */,onMatch:function(e,t,n){var r=n[1];return r>=e.length?(this.next="start",n.shift(),n.shift()):(n[1]=e.length-1,this.next=n[0]="mlString"),this.token},next:"mlString"},{defaultToken:"string"}],mlString:[{token:"indent",regex:/^ *$/},{token:"indent",regex:/^ */,onMatch:function(e,t,n){var r=n[1];return r>=e.length?(this.next="start",n.splice(0)):this.next="mlString",this.token},next:"mlString"},{token:"string",regex:".+"}]},this.normalizeRules()};r.inherits(s,i),t.YamlHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){"use strict";var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){return e.match(/^\s*/)[0]}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/folding/coffee",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=t.FoldMode=function(){};r.inherits(o,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=this.indentationBlock(e,n);if(r)return r;var i=/\S/,o=e.getLine(n),u=o.search(i);if(u==-1||o[u]!="#")return;var a=o.length,f=e.getLength(),l=n,c=n;while(++nl){var p=e.getLine(c).length;return new s(l,a,c,p)}},this.getFoldWidget=function(e,t,n){var r=e.getLine(n),i=r.search(/\S/),s=e.getLine(n+1),o=e.getLine(n-1),u=o.search(/\S/),a=s.search(/\S/);if(i==-1)return e.foldWidgets[n-1]=u!=-1&&u fs.exec('/etc/init.d/clash', ['enable'])) 30 | .catch(function(e) { 31 | ui.addNotification(null, E('p', _('Unable to start and enable service: %s').format(e.message)), 'error'); 32 | }) 33 | .finally(() => { 34 | if (startStopButton) startStopButton.disabled = false; 35 | }); 36 | } 37 | 38 | async function stopService() { 39 | if (startStopButton) startStopButton.disabled = true; 40 | return fs.exec('/etc/init.d/clash', ['stop']) 41 | .then(() => fs.exec('/etc/init.d/clash', ['disable'])) 42 | .catch(function(e) { 43 | ui.addNotification(null, E('p', _('Unable to stop and disable service: %s').format(e.message)), 'error'); 44 | }) 45 | .finally(() => { 46 | if (startStopButton) startStopButton.disabled = false; 47 | }); 48 | } 49 | 50 | async function toggleService() { 51 | const running = await getServiceStatus(); 52 | if (running) { 53 | await stopService(); 54 | } else { 55 | await startService(); 56 | } 57 | window.location.reload(); 58 | } 59 | 60 | async function openDashboard() { 61 | let newWindow = window.open('', '_blank'); 62 | const running = await getServiceStatus(); 63 | if (running) { 64 | let port = '9090'; 65 | let path = 'ui'; 66 | let protocol = window.location.protocol; 67 | let hostname = window.location.hostname; 68 | let url = `${protocol}//${hostname}:${port}/${path}/?hostname=${hostname}&port=${port}`; 69 | newWindow.location.href = url; 70 | } else { 71 | newWindow.close(); 72 | alert(_('Service is not running.')); 73 | } 74 | } 75 | 76 | function loadScript(src) { 77 | return new Promise((resolve, reject) => { 78 | const script = document.createElement('script'); 79 | script.src = src; 80 | script.onload = resolve; 81 | script.onerror = reject; 82 | document.head.appendChild(script); 83 | }); 84 | } 85 | 86 | async function initializeAceEditor(content) { 87 | await loadScript('/luci-static/resources/view/ssclash/ace/ace.js'); 88 | ace.config.set('basePath', '/luci-static/resources/view/ssclash/ace/'); 89 | editor = ace.edit("editor"); 90 | editor.setTheme("ace/theme/tomorrow_night_bright"); 91 | editor.session.setMode("ace/mode/yaml"); 92 | editor.setValue(content); 93 | editor.clearSelection(); 94 | editor.setOptions({ 95 | fontSize: "12px", 96 | showPrintMargin: false, 97 | wrap: true 98 | }); 99 | } 100 | 101 | return view.extend({ 102 | load: function() { 103 | return L.resolveDefault(fs.read('/opt/clash/config.yaml'), ''); 104 | }, 105 | handleSaveApply: function(ev) { 106 | var value = editor.getValue().trim() + '\n'; 107 | return fs.write('/opt/clash/config.yaml', value).then(function(rc) { 108 | ui.addNotification(null, E('p', _('Contents have been saved.')), 'info'); 109 | return fs.exec('/etc/init.d/clash', ['reload']); 110 | }).then(function() { 111 | window.location.reload(); 112 | }).catch(function(e) { 113 | ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message)), 'error'); 114 | }); 115 | }, 116 | render: async function(config) { 117 | const running = await getServiceStatus(); 118 | 119 | const view = E([ 120 | E('button', { 121 | 'class': 'btn', 122 | 'click': openDashboard 123 | }, _('Open Dashboard')), 124 | (startStopButton = E('button', { 125 | 'class': 'btn', 126 | 'click': toggleService, 127 | 'style': 'margin-left: 10px;' 128 | }, running ? _('Stop service') : _('Start service'))), 129 | E('span', { 130 | 'style': running ? 'color: green; margin-left: 10px;' : 'color: red; margin-left: 10px;' 131 | }, running ? _('Clash is running') : _('Clash stopped')), 132 | E('h2', _('Clash config')), 133 | E('p', { 'class': 'cbi-section-descr' }, _('Your current Clash config. When applied, the changes will be saved and the service will be restarted.')), 134 | E('div', { 135 | 'id': 'editor', 136 | 'style': 'width: 100%; height: 640px;' 137 | }) 138 | ]); 139 | 140 | initializeAceEditor(config); 141 | 142 | return view; 143 | }, 144 | handleSave: null, 145 | handleReset: null 146 | }); -------------------------------------------------------------------------------- /rootfs/www/luci-static/resources/view/ssclash/log.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 'require view'; 3 | 'require poll'; 4 | 'require fs'; 5 | 6 | let editor = null; 7 | let lastLogLength = 0; 8 | let loggerPath = null; 9 | 10 | function loadScript(src) { 11 | return new Promise((resolve, reject) => { 12 | const script = document.createElement('script'); 13 | script.src = src; 14 | script.onload = resolve; 15 | script.onerror = reject; 16 | document.head.appendChild(script); 17 | }); 18 | } 19 | 20 | async function initializeAceEditor() { 21 | await loadScript('/luci-static/resources/view/ssclash/ace/ace.js'); 22 | ace.config.set('basePath', '/luci-static/resources/view/ssclash/ace/'); 23 | editor = ace.edit("logfile"); 24 | editor.setTheme("ace/theme/tomorrow_night_bright"); 25 | editor.session.setMode("ace/mode/text"); 26 | editor.setOptions({ 27 | fontSize: "11px", 28 | showPrintMargin: false, 29 | readOnly: true, 30 | wrap: true 31 | }); 32 | 33 | startPolling(); 34 | } 35 | 36 | function startPolling() { 37 | poll.add(() => { 38 | if (loggerPath) { 39 | return fs.exec_direct(loggerPath, ['-e', 'clash']) 40 | .then(res => { 41 | if (res) { 42 | const lines = res.trim().split('\n'); 43 | if (lines.length > lastLogLength) { 44 | const newLines = lines.slice(lastLogLength); 45 | const processedNewLines = newLines.map(processLogLine).join('\n'); 46 | 47 | editor.session.insert({ 48 | row: editor.session.getLength(), 49 | column: 0 50 | }, (lastLogLength > 0 ? '\n' : '') + processedNewLines); 51 | 52 | lastLogLength = lines.length; 53 | editor.scrollToLine(editor.session.getLength(), false, true, function() {}); 54 | } 55 | } else if (lastLogLength > 0) { 56 | editor.setValue('', 1); 57 | lastLogLength = 0; 58 | } 59 | }) 60 | .catch(err => { 61 | console.error('Error executing logread:', err); 62 | }); 63 | } 64 | }); 65 | } 66 | 67 | function processLogLine(line) { 68 | const msgMatch = line.match(/msg="(.*?)"/); 69 | if (msgMatch) { 70 | return line.split(']: ')[0] + ']: ' + msgMatch[1]; 71 | } 72 | return line; 73 | } 74 | 75 | return view.extend({ 76 | load: function () { 77 | return fs.stat('/sbin/logread').then(stat => { 78 | loggerPath = stat && stat.path ? stat.path : null; 79 | }); 80 | }, 81 | 82 | render: function (stat) { 83 | const view = E( 84 | 'div', 85 | { class: 'cbi-map' }, 86 | E('div', { class: 'cbi-section' }, [ 87 | E('div', { 88 | id: 'logfile', 89 | style: 'width: 100% !important; height: 640px;' 90 | }) 91 | ]) 92 | ); 93 | 94 | initializeAceEditor(); 95 | 96 | return view; 97 | }, 98 | 99 | handleSaveApply: null, 100 | handleSave: null, 101 | handleReset: null, 102 | }); -------------------------------------------------------------------------------- /scr-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zerolabnet/SSClash/5cafaf7358abc10515723fa3d6eba783f11be3e4/scr-00.png -------------------------------------------------------------------------------- /scr-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zerolabnet/SSClash/5cafaf7358abc10515723fa3d6eba783f11be3e4/scr-01.png -------------------------------------------------------------------------------- /update_all_rule_providers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Add delay 4 | sleep 10 5 | 6 | # API IP address and port 7 | api_base_url="http://192.168.1.1:9090" 8 | 9 | # API URL 10 | base_url="$api_base_url/providers/rules" 11 | 12 | # Get JSON response with provider names 13 | response=$(curl -s "$base_url") 14 | 15 | # Extract provider names using standard utilities 16 | providers=$(echo "$response" | grep -o '"name":"[^"]*"' | sed 's/"name":"\([^"]*\)"/\1/') 17 | 18 | # Check if data retrieval was successful 19 | if [ -z "$providers" ]; then 20 | echo "Failed to retrieve providers or no providers found." 21 | exit 1 22 | fi 23 | 24 | # Loop through each provider name and send PUT request to update 25 | for provider in $providers; do 26 | echo "Updating provider: $provider" 27 | curl -X PUT "$base_url/$provider" 28 | 29 | # Check success and output the result 30 | if [ $? -eq 0 ]; then 31 | echo "Successfully updated $provider" 32 | else 33 | echo "Failed to update $provider" 34 | fi 35 | done 36 | 37 | # Service restart 38 | /etc/init.d/clash reload --------------------------------------------------------------------------------