├── LICENSE ├── Material ├── icon.png └── qrcode.jpg ├── README.md ├── Stay Extension ├── Info.plist ├── Resources │ ├── _locales │ │ ├── en │ │ │ └── messages.json │ │ └── zh-Hans │ │ │ └── messages.json │ ├── background.js │ ├── baidu │ │ ├── baidu-content.js │ │ └── tieba-content.js │ ├── csdn │ │ └── csdn-content.js │ ├── google │ │ └── google-content.js │ ├── iframe.html │ ├── iframe.js │ ├── images │ │ ├── accessor.png │ │ ├── icon-128.png │ │ ├── icon-256.png │ │ ├── icon-48.png │ │ ├── icon-512.png │ │ ├── icon-64.png │ │ ├── icon-96.png │ │ ├── toolbar-icon-16.png │ │ ├── toolbar-icon-19.png │ │ ├── toolbar-icon-32.png │ │ └── toolbar-icon-38.png │ ├── jianshu │ │ └── jianshu-content.js │ ├── lib │ │ └── common.js │ ├── manifest.json │ ├── popup.css │ ├── popup.html │ ├── popup.js │ ├── redirect.js │ ├── sohu │ │ └── sohu-content.js │ ├── toutiao │ │ └── toutiao-content.js │ ├── xhs │ │ └── xhs-content.js │ └── zhihu │ │ └── zhihu-content.js ├── SafariWebExtensionHandler.h └── SafariWebExtensionHandler.m ├── Stay.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── ris.xcuserdatad │ │ └── UserInterfaceState.xcuserstate ├── xcshareddata │ └── xcschemes │ │ └── Stay.xcscheme └── xcuserdata │ └── ris.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── Stay ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── 100.png │ │ ├── 1024.png │ │ ├── 114.png │ │ ├── 120.png │ │ ├── 144.png │ │ ├── 152.png │ │ ├── 167.png │ │ ├── 180.png │ │ ├── 20.png │ │ ├── 29.png │ │ ├── 40.png │ │ ├── 50.png │ │ ├── 57.png │ │ ├── 58.png │ │ ├── 60.png │ │ ├── 72.png │ │ ├── 76.png │ │ ├── 80.png │ │ ├── 87.png │ │ └── Contents.json │ ├── Contents.json │ └── LargeIcon.imageset │ │ └── Contents.json ├── Images │ ├── fastclip-icon@3x.png │ └── icon@3x.png ├── Info.plist ├── LaunchScreen.storyboard ├── NavigationController.h ├── NavigationController.m ├── Resources │ ├── Icon.png │ └── Style.css ├── SceneDelegate.h ├── SceneDelegate.m ├── ViewController.h ├── ViewController.m ├── en.lproj │ ├── Localizable.strings │ └── Main.html ├── main.m └── zh-Hans.lproj │ ├── Localizable.strings │ └── Main.html ├── StayTests └── StayTests.m └── StayUITests ├── StayUITests.m └── StayUITestsLaunchTests.m /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /Material/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Material/icon.png -------------------------------------------------------------------------------- /Material/qrcode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Material/qrcode.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 |

中文 | EN

6 | 7 | # Stay 8 | Stay是一个开源的iOS Safari浏览器插件,做为一个浏览器插件示例的同时也已经上线AppStore [Stay - 网页纯浏览](https://apps.apple.com/cn/app/stay-%E7%BD%91%E9%A1%B5%E7%BA%AF%E6%B5%8F%E8%A7%88/id1591620171),并且保证免费。 9 | 10 | Stay需要运行在iOS 15及以上。 11 | 12 | 13 | ## 主要功能 14 | - 广告拦截 15 | - 阻止应用跳转 16 | - 自动展开文本 17 | 18 | 19 | ## 贡献脚本 20 | #### 苹果开发者 21 | 你可以下载源代码并且改造相关的功能部署在你的手机设备上。 22 | 23 | #### 非苹果开发者 24 | 如果你有前端开发经验,你也可以选择贡献脚本,当PR被合并后,你也会在更新的Stay应用中体验到你更新的功能。 25 | 26 | 关于如何贡献脚本来适配新的网站可以查看[good first issue](https://github.com/shenruisi/Stay/issues/2)。 27 | 28 | 29 | ## 已适配的网站 30 | - [知乎 zhihu-content.js](/Stay%20Extension/Resources/zhihu/zhihu-content.js) 31 | - [今日头条 toutiao-content.js](/Stay%20Extension/Resources/toutiao/toutiao-content.js) 32 | - [百度搜索 baidu-content.js](/Stay%20Extension/Resources/baidu/baidu-content.js) 33 | - [百度贴吧 tieba-content.js](/Stay%20Extension/Resources/baidu/tieba-content.js) 34 | - [搜狐 sohu-content.js](/Stay%20Extension/Resources/sohu/sohu-content.js) 35 | - [小红书 xhs-content.js](/Stay%20Extension/Resources/xhs/xhs-content.js) 36 | - [简书 jianshu-content.js](/Stay%20Extension/Resources/jianshu/jianshu-content.js) 37 | - [CSDN csdn-content.js](/Stay%20Extension/Resources/csdn/csdn-content.js) 38 | 39 | 40 | ## 许可证 41 | [MPL](./LICENSE) 42 | 43 | 44 | ## Safari插件开发参考资料 45 | - [Meet Safari Web Extensions on iOS](https://developer.apple.com/videos/play/wwdc2021/10104) 46 | - [CSS Selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors) 47 | - [DOMContentLoaded event](https://developer.mozilla.org/en-US/docs/Web/API/Window/DOMContentLoaded_event) 48 | - [Content scripts](https://developer.chrome.com/docs/extensions/mv3/content_scripts/) 49 | - [Safari web extensions](https://developer.apple.com/documentation/safariservices/safari_web_extensions) 50 | - [crxviewer](https://robwu.nl/crxviewer/) 51 | - [Browser support for JavaScript APIs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Browser_support_for_JavaScript_APIs) 52 | 53 | ## 用户交流 54 | 请关注公众号`效率先生`,并回复`微信群` 进群沟通。 55 | 56 | 57 | -------------------------------------------------------------------------------- /Stay Extension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSExtension 6 | 7 | NSExtensionPointIdentifier 8 | com.apple.Safari.web-extension 9 | NSExtensionPrincipalClass 10 | SafariWebExtensionHandler 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Stay Extension/Resources/_locales/en/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extension_name": { 3 | "message": "Stay", 4 | "description": "Stay - Web-only browsing" 5 | }, 6 | "extension_description": { 7 | "message": "This is Stay, make your stay in the Safari, prevent app jumping, blocking Ads, and auto unfolding the text.", 8 | "description": "Make your stay in the Safari, prevent app jumping, blocking Ads, and auto unfolding the text." 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Stay Extension/Resources/_locales/zh-Hans/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extension_name": { 3 | "message": "Stay", 4 | "description": "Stay - 网页纯浏览" 5 | }, 6 | "extension_description": { 7 | "message": "Stay可以让您留在 Safari 中,防止应用程序跳转、阻止广告和自动展开文本。", 8 | "description": "让您留在 Safari 中,防止应用程序跳转、阻止广告和自动展开文本。" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Stay Extension/Resources/background.js: -------------------------------------------------------------------------------- 1 | let appJumpList; 2 | browser.runtime.onMessage.addListener((request, sender, sendResponse) => { 3 | if ("popup" == request.from && "fetchAppList" == request.operate){ 4 | sendResponse({ body: appJumpList }); 5 | } 6 | else if ("content" == request.from && "saveAppList" == request.operate){ 7 | appJumpList = request.data; 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /Stay Extension/Resources/baidu/baidu-content.js: -------------------------------------------------------------------------------- 1 | function banAds(){ 2 | let header = document.querySelector('#header'); 3 | if (null != header){ 4 | let div = header.lastChild; 5 | if (div.nodeName == "DIV" && div.className == ""){ 6 | div.style.display = "none"; 7 | return COMPLETE; 8 | } 9 | } 10 | 11 | return CONTINUE; 12 | } 13 | 14 | function removeAppJump(){ 15 | let pageWrapper = document.querySelector('#page_wrapper'); 16 | if (pageWrapper){ 17 | console.log(pageWrapper); 18 | var app = pageWrapper.querySelector('.mL3ndd4cDuSxL'); 19 | console.log(app); 20 | if (!app){ 21 | let divs = pageWrapper.querySelectorAll('div'); 22 | for (var i = 0; i < divs.length; i++){ 23 | let p = divs[i].querySelector('p'); 24 | if (p){ 25 | if (p.innerText == "百度APP内阅读"){ 26 | app = divs[i]; 27 | break; 28 | } 29 | } 30 | } 31 | } 32 | 33 | if (app){ 34 | app.style.display = "none"; 35 | //TODO: ?? 36 | return new App() 37 | .id("baidu") 38 | .title("百度APP") 39 | .icon("https://is3-ssl.mzstatic.com/image/thumb/Purple115/v4/ed/f8/1e/edf81e19-cb51-7d84-c44f-6ff31ad1b7dd/AppIcon-0-0-1x_U007emarketing-0-0-0-7-0-0-sRGB-0-0-0-GLES2_U002c0-512MB-85-220-0-0.png/230x0w.png") 40 | .url("baiduboxapp://") 41 | .data(); 42 | } 43 | 44 | } 45 | return CONTINUE; 46 | } 47 | 48 | function unfold(){ 49 | let pageWrapper = document.querySelector('#page_wrapper'); 50 | if (pageWrapper){ 51 | let fullText = pageWrapper.querySelector('.unfoldFullText') || pageWrapper.querySelector('.wxUnfoldText'); 52 | if (fullText){ 53 | fullText.style.display = "none"; 54 | let mainContent = pageWrapper.querySelector('.mainContent'); 55 | if (mainContent){ 56 | mainContent.style.height = null; 57 | return COMPLETE; 58 | } 59 | } 60 | } 61 | return CONTINUE; 62 | } 63 | 64 | function banBottomBanner(){ 65 | let pageCopyright = document.querySelector('#page-copyright'); 66 | if (pageCopyright){ 67 | let div = pageCopyright.lastChild; 68 | if (div && div.style.position == "fixed" && div.style.bottom == "0px"){ 69 | div.style.display = "none"; 70 | return COMPLETE; 71 | } 72 | } 73 | return CONTINUE; 74 | } 75 | 76 | function banBall(){ 77 | let divs = document.querySelectorAll('.c-result'); 78 | for (var i = 0; i { 174 | browser.runtime.sendMessage({from:"content",operate:"saveAppList",data:data}) 175 | }); 176 | }); 177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /Stay Extension/Resources/baidu/tieba-content.js: -------------------------------------------------------------------------------- 1 | function removeChoosePanel(){ 2 | let pannel = document.querySelector('nav.tb-backflow-defensive'); 3 | if (pannel){ 4 | pannel.remove(); 5 | return COMPLETE; 6 | } 7 | 8 | return CONTINUE; 9 | } 10 | 11 | 12 | document.addEventListener("DOMContentLoaded", function(event) { 13 | let tasks = [removeChoosePanel]; 14 | Inject.run(tasks,100,30,false).then((data) => { 15 | console.log(data); 16 | browser.runtime.sendMessage({from:"content",operate:"saveAppList",data:data}) 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /Stay Extension/Resources/csdn/csdn-content.js: -------------------------------------------------------------------------------- 1 | function removeChoosePanel(){ 2 | let pannel = document.querySelector('.weixin-shadowbox'); 3 | if (pannel){ 4 | pannel.remove(); 5 | return COMPLETE; 6 | } 7 | 8 | return CONTINUE; 9 | } 10 | 11 | function removeAppJump(){ 12 | let app = document.querySelector('span.feed-Sign-span'); 13 | if (app){ 14 | var url = app.getAttribute("data-href"); 15 | app.remove(); 16 | return new App() 17 | .id("csdn") 18 | .title(document.title) 19 | .icon("https://is1-ssl.mzstatic.com/image/thumb/Purple125/v4/b7/1c/7d/b71c7d47-6ae3-cdc0-bdf8-7e1385707f30/AppIcon-0-0-1x_U007emarketing-0-0-0-7-0-0-sRGB-0-0-0-GLES2_U002c0-512MB-85-220-0-0.png/230x0w.png") 20 | .url(url) 21 | .data(); 22 | } 23 | 24 | return CONTINUE; 25 | } 26 | 27 | function unfold(){ 28 | let main = document.querySelector('#main'); 29 | if (main){ 30 | let content = main.querySelector(".article_content"); 31 | if (content){ 32 | content.style.overflow = null; 33 | content.style.height = null; 34 | } 35 | 36 | let readallbox = main.querySelector(".readall_box"); 37 | console.log(readallbox); 38 | if (readallbox){ 39 | readallbox.remove(); 40 | readallbox.className = "readall_box_nobg"; 41 | } 42 | 43 | let prompt = main.querySelector(".btn_open_app_prompt_div"); 44 | if (prompt){ 45 | prompt.remove(); 46 | } 47 | 48 | return COMPLETE; 49 | } 50 | 51 | return CONTINUE; 52 | } 53 | 54 | document.addEventListener("DOMContentLoaded", function(event) { 55 | let tasks = [removeChoosePanel,removeAppJump,unfold]; 56 | Inject.run(tasks,100,30,false).then((data) => { 57 | browser.runtime.sendMessage({from:"content",operate:"saveAppList",data:data}) 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /Stay Extension/Resources/google/google-content.js: -------------------------------------------------------------------------------- 1 | document.addEventListener("DOMContentLoaded", function(event) { 2 | let tasks = []; 3 | Inject.run(tasks,100,30,true).then((data) => { 4 | browser.runtime.sendMessage({from:"content",operate:"saveAppList",data:data}) 5 | }); 6 | }); 7 | -------------------------------------------------------------------------------- /Stay Extension/Resources/iframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 跳转到 5 | 6 | 7 | 8 | 9 | 10 | \ 12 | '; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Stay Extension/Resources/sohu/sohu-content.js: -------------------------------------------------------------------------------- 1 | function removeAds(){ 2 | let ad = document.querySelector(".middle-insert-ad"); 3 | if (ad){ 4 | ad.style.display = "none"; 5 | return COMPLETE; 6 | } 7 | 8 | return CONTINUE; 9 | } 10 | 11 | function unfold(){ 12 | let lookallbox = document.querySelector(".article-main .lookall-box"); 13 | console.log(lookallbox); 14 | if (lookallbox){ 15 | lookallbox.style.display = "none"; 16 | if (lookallbox){ 17 | let otherContent = document.querySelector(".article-main .hidden-content"); 18 | if (otherContent){ 19 | otherContent.className = "hidden-content"; 20 | return COMPLETE; 21 | } 22 | } 23 | } 24 | 25 | return CONTINUE; 26 | } 27 | 28 | document.addEventListener("DOMContentLoaded", function(event) { 29 | let tasks = [removeAds,unfold]; 30 | Inject.run(tasks,100,30,true).then((data) => { 31 | browser.runtime.sendMessage({from:"content",operate:"saveAppList",data:data}) 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /Stay Extension/Resources/toutiao/toutiao-content.js: -------------------------------------------------------------------------------- 1 | function removeTopBanner(){ 2 | let banner = document.querySelector('.top-banner-container'); 3 | if (banner){ 4 | banner.remove(); 5 | return new App() 6 | .id("toutiao") 7 | .title("今日头条") 8 | .icon("https://is2-ssl.mzstatic.com/image/thumb/Purple125/v4/c1/f9/e5/c1f9e5bb-b6e7-10f2-ef8e-e77e893997f6/AppIcon-News-0-0-1x_U007emarketing-0-0-0-7-0-0-sRGB-0-0-0-GLES2_U002c0-512MB-85-220-0-0.png/230x0w.png") 9 | .url("snssdk141://") 10 | .data(); 11 | } 12 | 13 | return CONTINUE; 14 | } 15 | 16 | function unfold(){ 17 | let button = document.querySelector('div.fold-btn-btn'); 18 | if (button){ 19 | button.remove(); 20 | let content = document.querySelector('div.fold-btn-content') 21 | if (content){ 22 | content.className = null; 23 | content.className = "fold-btn-content"; 24 | } 25 | return COMPLETE; 26 | } 27 | 28 | return CONTINUE; 29 | } 30 | 31 | document.addEventListener("DOMContentLoaded", function(event) { 32 | let tasks = [removeTopBanner,unfold]; 33 | Inject.run(tasks,100,30,false).then((data) => { 34 | browser.runtime.sendMessage({from:"content",operate:"saveAppList",data:data}) 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /Stay Extension/Resources/xhs/xhs-content.js: -------------------------------------------------------------------------------- 1 | function removeTopBanner(){ 2 | let app = document.querySelector("#app"); 3 | if (app){ 4 | let navbar = app.querySelector(".normal-launch-app-container"); 5 | if (navbar){ 6 | navbar.style.display = "none"; 7 | return COMPLETE; 8 | } 9 | } 10 | 11 | return CONTINUE; 12 | } 13 | 14 | function removeAppJump(){ 15 | let app = document.querySelector("#app"); 16 | if (app){ 17 | let bottombar = app.querySelector(".bottom-bar"); 18 | if (bottombar){ 19 | bottombar.remove(); 20 | var url = window.location.href; 21 | return new App() 22 | .id("xhs") 23 | .title(app.querySelector(".title").innerText || "小红书") 24 | .icon("https://is4-ssl.mzstatic.com/image/thumb/Purple125/v4/06/00/2f/06002f58-01e1-4d98-5ae2-5807eb4c059f/AppIcon-0-0-1x_U007emarketing-0-0-0-7-0-0-sRGB-0-0-0-GLES2_U002c0-512MB-85-220-0-0.png/230x0w.png") 25 | .url("xhsdiscover://item/"+url.substring(url.lastIndexOf('/')+1)) 26 | .data(); 27 | } 28 | } 29 | 30 | return CONTINUE; 31 | } 32 | 33 | function unfold(){ 34 | let app = document.querySelector("#app"); 35 | if (app){ 36 | let checkmore = app.querySelector(".check-more"); 37 | if (checkmore){ 38 | checkmore.style.display = "none"; 39 | let content = app.querySelector(".content"); 40 | if (content){ 41 | content.style.height = null; 42 | return COMPLETE; 43 | } 44 | } 45 | } 46 | 47 | return CONTINUE; 48 | } 49 | 50 | 51 | 52 | window.onload = function() { 53 | let tasks = [removeTopBanner,removeAppJump,unfold]; 54 | Inject.run(tasks,100,30,false).then((data) => { 55 | browser.runtime.sendMessage({from:"content",operate:"saveAppList",data:data}) 56 | }); 57 | } 58 | -------------------------------------------------------------------------------- /Stay Extension/Resources/zhihu/zhihu-content.js: -------------------------------------------------------------------------------- 1 | function removeChoosePanel(){ 2 | let pannels = document.querySelectorAll('.ModalWrap'); 3 | for (var i = 0; i < pannels.length; i++){ 4 | let pannel = pannels[i]; 5 | let div = pannel.querySelector('.ModalExp-modalShow'); 6 | if (div){ 7 | let btns = div.querySelectorAll('.ModalWrap-itemBtn'); 8 | 9 | for (var i=0; i < btns.length; i++){ 10 | let button = btns[i]; 11 | if (button.innerText == "继续"){ 12 | button.click(); 13 | return COMPLETE; 14 | } 15 | } 16 | } 17 | } 18 | 19 | return CONTINUE; 20 | } 21 | 22 | function removeAppJump(){ 23 | let app = document.querySelector('button.OpenInAppButton'); 24 | if (app){ 25 | var url = app.getAttribute("urlscheme"); 26 | app.remove(); 27 | return new App() 28 | .id("zhihu") 29 | .title(document.title) 30 | .icon("https://is1-ssl.mzstatic.com/image/thumb/Purple125/v4/83/24/ca/8324ca44-40d5-87ed-4f8f-a47daec7dc34/AppIcon-0-0-1x_U007emarketing-0-0-0-6-0-0-sRGB-0-0-0-GLES2_U002c0-512MB-85-220-0-0.png/230x0w.png") 31 | .url(url) 32 | .data(); 33 | } 34 | return CONTINUE; 35 | } 36 | 37 | function unfold(){ 38 | let btns = document.querySelectorAll('.ContentItem-expandButton'); 39 | for (var i = 0; i < btns.length; i++){ 40 | let btn = btns[i]; 41 | if (/展开阅读全文/.test(btn.innerText)){ 42 | let content = btn.parentNode; 43 | if (content){ 44 | content.className = "RichContent RichContent--unescapable"; 45 | let contentinner = content.querySelector('.RichContent-inner'); 46 | if (contentinner){ 47 | contentinner.style.maxHeight = "none"; 48 | } 49 | } 50 | btn.remove(); 51 | let main = document.querySelector(".Question-main"); 52 | if (main){ 53 | main.onclick = function(event){ 54 | let target = event.target; 55 | while(!/RichContent/.test(target.className) && target.tagName != "BODY"){ 56 | target = target.parentNode; 57 | } 58 | if (/RichContent/.test(target.className)){ 59 | event.preventDefault(); 60 | event.stopPropagation(); 61 | } 62 | 63 | } 64 | } 65 | 66 | return COMPLETE; 67 | } 68 | } 69 | 70 | return CONTINUE; 71 | } 72 | 73 | window.onload = function(){ 74 | let tasks = [removeChoosePanel,removeAppJump,unfold]; 75 | Inject.run(tasks,100,30,false).then((data) => { 76 | browser.runtime.sendMessage({from:"content",operate:"saveAppList",data:data}) 77 | }); 78 | } 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /Stay Extension/SafariWebExtensionHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // SafariWebExtensionHandler.h 3 | // Stay Extension 4 | // 5 | // Created by ris on 2021/10/15. 6 | // 7 | 8 | #import 9 | 10 | @interface SafariWebExtensionHandler : NSObject 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Stay Extension/SafariWebExtensionHandler.m: -------------------------------------------------------------------------------- 1 | // 2 | // SafariWebExtensionHandler.m 3 | // Stay Extension 4 | // 5 | // Created by ris on 2021/10/15. 6 | // 7 | 8 | #import "SafariWebExtensionHandler.h" 9 | 10 | #import 11 | 12 | @implementation SafariWebExtensionHandler 13 | 14 | - (void)beginRequestWithExtensionContext:(NSExtensionContext *)context 15 | { 16 | id message = [context.inputItems.firstObject userInfo][SFExtensionMessageKey]; 17 | NSLog(@"Received message from browser.runtime.sendNativeMessage: %@", message); 18 | 19 | NSExtensionItem *response = [[NSExtensionItem alloc] init]; 20 | response.userInfo = @{ SFExtensionMessageKey: @{ @"Response to": message } }; 21 | 22 | [context completeRequestReturningItems:@[ response ] completionHandler:nil]; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Stay.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 55; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 587688D92719237E00F834A4 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 587688D82719237E00F834A4 /* AppDelegate.m */; }; 11 | 587688DD2719237E00F834A4 /* Main.html in Resources */ = {isa = PBXBuildFile; fileRef = 587688DB2719237E00F834A4 /* Main.html */; }; 12 | 587688DF2719237E00F834A4 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 587688DE2719237E00F834A4 /* Icon.png */; }; 13 | 587688E12719237E00F834A4 /* Style.css in Resources */ = {isa = PBXBuildFile; fileRef = 587688E02719237E00F834A4 /* Style.css */; }; 14 | 587688E42719237E00F834A4 /* SceneDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 587688E32719237E00F834A4 /* SceneDelegate.m */; }; 15 | 587688E72719237E00F834A4 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 587688E62719237E00F834A4 /* ViewController.m */; }; 16 | 587688F12719238000F834A4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 587688F02719238000F834A4 /* main.m */; }; 17 | 587688FB2719238000F834A4 /* StayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 587688FA2719238000F834A4 /* StayTests.m */; }; 18 | 587689052719238000F834A4 /* StayUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 587689042719238000F834A4 /* StayUITests.m */; }; 19 | 587689072719238000F834A4 /* StayUITestsLaunchTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 587689062719238000F834A4 /* StayUITestsLaunchTests.m */; }; 20 | 5876890D2719238000F834A4 /* Stay Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 5876890C2719238000F834A4 /* Stay Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 21 | 587689132719238000F834A4 /* SafariWebExtensionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 587689122719238000F834A4 /* SafariWebExtensionHandler.m */; }; 22 | 587689162719238000F834A4 /* _locales in Resources */ = {isa = PBXBuildFile; fileRef = 587689152719238000F834A4 /* _locales */; }; 23 | 587689182719238000F834A4 /* images in Resources */ = {isa = PBXBuildFile; fileRef = 587689172719238000F834A4 /* images */; }; 24 | 5876891A2719238000F834A4 /* manifest.json in Resources */ = {isa = PBXBuildFile; fileRef = 587689192719238000F834A4 /* manifest.json */; }; 25 | 5876891C2719238000F834A4 /* background.js in Resources */ = {isa = PBXBuildFile; fileRef = 5876891B2719238000F834A4 /* background.js */; }; 26 | 5876891E2719238000F834A4 /* baidu-content.js in Resources */ = {isa = PBXBuildFile; fileRef = 5876891D2719238000F834A4 /* baidu-content.js */; }; 27 | 587689202719238000F834A4 /* popup.html in Resources */ = {isa = PBXBuildFile; fileRef = 5876891F2719238000F834A4 /* popup.html */; }; 28 | 587689222719238000F834A4 /* popup.css in Resources */ = {isa = PBXBuildFile; fileRef = 587689212719238000F834A4 /* popup.css */; }; 29 | 587689242719238000F834A4 /* popup.js in Resources */ = {isa = PBXBuildFile; fileRef = 587689232719238000F834A4 /* popup.js */; }; 30 | 587689262719238000F834A4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 587688EE2719238000F834A4 /* Assets.xcassets */; }; 31 | 58768939271E64EB00F834A4 /* common.js in Resources */ = {isa = PBXBuildFile; fileRef = 58768938271E64EB00F834A4 /* common.js */; }; 32 | 587689402720064D00F834A4 /* NavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5876893F2720064D00F834A4 /* NavigationController.m */; }; 33 | 5881343027294C0E0055E1CE /* iframe.html in Resources */ = {isa = PBXBuildFile; fileRef = 5881342E27294C0E0055E1CE /* iframe.html */; }; 34 | 5881343127294C0E0055E1CE /* iframe.js in Resources */ = {isa = PBXBuildFile; fileRef = 5881342F27294C0E0055E1CE /* iframe.js */; }; 35 | 58813437272AACEC0055E1CE /* fastclip-icon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 58813436272AACEC0055E1CE /* fastclip-icon@3x.png */; }; 36 | 5889731A27213C8300BE123E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5889731C27213C8300BE123E /* Localizable.strings */; }; 37 | 58897320272156C900BE123E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5889731F272156C900BE123E /* LaunchScreen.storyboard */; }; 38 | 58897323272170CC00BE123E /* xhs-content.js in Resources */ = {isa = PBXBuildFile; fileRef = 58897322272170CC00BE123E /* xhs-content.js */; }; 39 | 588973262721715F00BE123E /* zhihu-content.js in Resources */ = {isa = PBXBuildFile; fileRef = 588973252721715F00BE123E /* zhihu-content.js */; }; 40 | 5889732B272180F700BE123E /* sohu-content.js in Resources */ = {isa = PBXBuildFile; fileRef = 5889732A272180F700BE123E /* sohu-content.js */; }; 41 | 5889732E2722A94F00BE123E /* google-content.js in Resources */ = {isa = PBXBuildFile; fileRef = 5889732D2722A94F00BE123E /* google-content.js */; }; 42 | 588973312722AB4600BE123E /* csdn-content.js in Resources */ = {isa = PBXBuildFile; fileRef = 588973302722AB4600BE123E /* csdn-content.js */; }; 43 | 588973342722BFA400BE123E /* jianshu-content.js in Resources */ = {isa = PBXBuildFile; fileRef = 588973332722BFA400BE123E /* jianshu-content.js */; }; 44 | 588973372722C5EF00BE123E /* toutiao-content.js in Resources */ = {isa = PBXBuildFile; fileRef = 588973362722C5EF00BE123E /* toutiao-content.js */; }; 45 | 588973392722D74A00BE123E /* tieba-content.js in Resources */ = {isa = PBXBuildFile; fileRef = 588973382722D74A00BE123E /* tieba-content.js */; }; 46 | 5889733E2723033600BE123E /* icon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5889733D2723033600BE123E /* icon@3x.png */; }; 47 | 588973482728144000BE123E /* redirect.js in Resources */ = {isa = PBXBuildFile; fileRef = 588973472728144000BE123E /* redirect.js */; }; 48 | /* End PBXBuildFile section */ 49 | 50 | /* Begin PBXContainerItemProxy section */ 51 | 587688F72719238000F834A4 /* PBXContainerItemProxy */ = { 52 | isa = PBXContainerItemProxy; 53 | containerPortal = 587688CC2719237E00F834A4 /* Project object */; 54 | proxyType = 1; 55 | remoteGlobalIDString = 587688D32719237E00F834A4; 56 | remoteInfo = Stay; 57 | }; 58 | 587689012719238000F834A4 /* PBXContainerItemProxy */ = { 59 | isa = PBXContainerItemProxy; 60 | containerPortal = 587688CC2719237E00F834A4 /* Project object */; 61 | proxyType = 1; 62 | remoteGlobalIDString = 587688D32719237E00F834A4; 63 | remoteInfo = Stay; 64 | }; 65 | 5876890E2719238000F834A4 /* PBXContainerItemProxy */ = { 66 | isa = PBXContainerItemProxy; 67 | containerPortal = 587688CC2719237E00F834A4 /* Project object */; 68 | proxyType = 1; 69 | remoteGlobalIDString = 5876890B2719238000F834A4; 70 | remoteInfo = "Stay Extension"; 71 | }; 72 | /* End PBXContainerItemProxy section */ 73 | 74 | /* Begin PBXCopyFilesBuildPhase section */ 75 | 5876892C2719238000F834A4 /* Embed App Extensions */ = { 76 | isa = PBXCopyFilesBuildPhase; 77 | buildActionMask = 2147483647; 78 | dstPath = ""; 79 | dstSubfolderSpec = 13; 80 | files = ( 81 | 5876890D2719238000F834A4 /* Stay Extension.appex in Embed App Extensions */, 82 | ); 83 | name = "Embed App Extensions"; 84 | runOnlyForDeploymentPostprocessing = 0; 85 | }; 86 | /* End PBXCopyFilesBuildPhase section */ 87 | 88 | /* Begin PBXFileReference section */ 89 | 587688D42719237E00F834A4 /* Stay.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Stay.app; sourceTree = BUILT_PRODUCTS_DIR; }; 90 | 587688D72719237E00F834A4 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 91 | 587688D82719237E00F834A4 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 92 | 587688DE2719237E00F834A4 /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = ""; }; 93 | 587688E02719237E00F834A4 /* Style.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = Style.css; sourceTree = ""; }; 94 | 587688E22719237E00F834A4 /* SceneDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SceneDelegate.h; sourceTree = ""; }; 95 | 587688E32719237E00F834A4 /* SceneDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SceneDelegate.m; sourceTree = ""; }; 96 | 587688E52719237E00F834A4 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 97 | 587688E62719237E00F834A4 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 98 | 587688EE2719238000F834A4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 99 | 587688EF2719238000F834A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 100 | 587688F02719238000F834A4 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 101 | 587688F62719238000F834A4 /* StayTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StayTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 102 | 587688FA2719238000F834A4 /* StayTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StayTests.m; sourceTree = ""; }; 103 | 587689002719238000F834A4 /* StayUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StayUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 104 | 587689042719238000F834A4 /* StayUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StayUITests.m; sourceTree = ""; }; 105 | 587689062719238000F834A4 /* StayUITestsLaunchTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StayUITestsLaunchTests.m; sourceTree = ""; }; 106 | 5876890C2719238000F834A4 /* Stay Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Stay Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 107 | 587689112719238000F834A4 /* SafariWebExtensionHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SafariWebExtensionHandler.h; sourceTree = ""; }; 108 | 587689122719238000F834A4 /* SafariWebExtensionHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SafariWebExtensionHandler.m; sourceTree = ""; }; 109 | 587689152719238000F834A4 /* _locales */ = {isa = PBXFileReference; lastKnownFileType = folder; path = _locales; sourceTree = ""; }; 110 | 587689172719238000F834A4 /* images */ = {isa = PBXFileReference; lastKnownFileType = folder; path = images; sourceTree = ""; }; 111 | 587689192719238000F834A4 /* manifest.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = manifest.json; sourceTree = ""; }; 112 | 5876891B2719238000F834A4 /* background.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = background.js; sourceTree = ""; }; 113 | 5876891D2719238000F834A4 /* baidu-content.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "baidu-content.js"; sourceTree = ""; }; 114 | 5876891F2719238000F834A4 /* popup.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = popup.html; sourceTree = ""; }; 115 | 587689212719238000F834A4 /* popup.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = popup.css; sourceTree = ""; }; 116 | 587689232719238000F834A4 /* popup.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = popup.js; sourceTree = ""; }; 117 | 587689252719238000F834A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 118 | 58768938271E64EB00F834A4 /* common.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = common.js; sourceTree = ""; }; 119 | 5876893E2720064D00F834A4 /* NavigationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NavigationController.h; sourceTree = ""; }; 120 | 5876893F2720064D00F834A4 /* NavigationController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NavigationController.m; sourceTree = ""; }; 121 | 5881342E27294C0E0055E1CE /* iframe.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = iframe.html; sourceTree = ""; }; 122 | 5881342F27294C0E0055E1CE /* iframe.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = iframe.js; sourceTree = ""; }; 123 | 58813436272AACEC0055E1CE /* fastclip-icon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "fastclip-icon@3x.png"; sourceTree = ""; }; 124 | 5889731427213BC200BE123E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = en; path = ../en.lproj/Main.html; sourceTree = ""; }; 125 | 5889731B27213C8300BE123E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; 126 | 5889731E27213CB100BE123E /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; 127 | 5889731F272156C900BE123E /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; 128 | 58897322272170CC00BE123E /* xhs-content.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "xhs-content.js"; sourceTree = ""; }; 129 | 588973252721715F00BE123E /* zhihu-content.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "zhihu-content.js"; sourceTree = ""; }; 130 | 5889732A272180F700BE123E /* sohu-content.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "sohu-content.js"; sourceTree = ""; }; 131 | 5889732D2722A94F00BE123E /* google-content.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "google-content.js"; sourceTree = ""; }; 132 | 588973302722AB4600BE123E /* csdn-content.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "csdn-content.js"; sourceTree = ""; }; 133 | 588973332722BFA400BE123E /* jianshu-content.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "jianshu-content.js"; sourceTree = ""; }; 134 | 588973362722C5EF00BE123E /* toutiao-content.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "toutiao-content.js"; sourceTree = ""; }; 135 | 588973382722D74A00BE123E /* tieba-content.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "tieba-content.js"; sourceTree = ""; }; 136 | 5889733D2723033600BE123E /* icon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon@3x.png"; sourceTree = ""; }; 137 | 588973472728144000BE123E /* redirect.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = redirect.js; sourceTree = ""; }; 138 | /* End PBXFileReference section */ 139 | 140 | /* Begin PBXFrameworksBuildPhase section */ 141 | 587688D12719237E00F834A4 /* Frameworks */ = { 142 | isa = PBXFrameworksBuildPhase; 143 | buildActionMask = 2147483647; 144 | files = ( 145 | ); 146 | runOnlyForDeploymentPostprocessing = 0; 147 | }; 148 | 587688F32719238000F834A4 /* Frameworks */ = { 149 | isa = PBXFrameworksBuildPhase; 150 | buildActionMask = 2147483647; 151 | files = ( 152 | ); 153 | runOnlyForDeploymentPostprocessing = 0; 154 | }; 155 | 587688FD2719238000F834A4 /* Frameworks */ = { 156 | isa = PBXFrameworksBuildPhase; 157 | buildActionMask = 2147483647; 158 | files = ( 159 | ); 160 | runOnlyForDeploymentPostprocessing = 0; 161 | }; 162 | 587689092719238000F834A4 /* Frameworks */ = { 163 | isa = PBXFrameworksBuildPhase; 164 | buildActionMask = 2147483647; 165 | files = ( 166 | ); 167 | runOnlyForDeploymentPostprocessing = 0; 168 | }; 169 | /* End PBXFrameworksBuildPhase section */ 170 | 171 | /* Begin PBXGroup section */ 172 | 587688CB2719237E00F834A4 = { 173 | isa = PBXGroup; 174 | children = ( 175 | 587688D62719237E00F834A4 /* Stay */, 176 | 587688F92719238000F834A4 /* StayTests */, 177 | 587689032719238000F834A4 /* StayUITests */, 178 | 587689102719238000F834A4 /* Stay Extension */, 179 | 587688D52719237E00F834A4 /* Products */, 180 | ); 181 | sourceTree = ""; 182 | }; 183 | 587688D52719237E00F834A4 /* Products */ = { 184 | isa = PBXGroup; 185 | children = ( 186 | 587688D42719237E00F834A4 /* Stay.app */, 187 | 587688F62719238000F834A4 /* StayTests.xctest */, 188 | 587689002719238000F834A4 /* StayUITests.xctest */, 189 | 5876890C2719238000F834A4 /* Stay Extension.appex */, 190 | ); 191 | name = Products; 192 | sourceTree = ""; 193 | }; 194 | 587688D62719237E00F834A4 /* Stay */ = { 195 | isa = PBXGroup; 196 | children = ( 197 | 5889733A2722FF7600BE123E /* Images */, 198 | 5889731F272156C900BE123E /* LaunchScreen.storyboard */, 199 | 587688D72719237E00F834A4 /* AppDelegate.h */, 200 | 587688D82719237E00F834A4 /* AppDelegate.m */, 201 | 587688E22719237E00F834A4 /* SceneDelegate.h */, 202 | 587688E32719237E00F834A4 /* SceneDelegate.m */, 203 | 587688E52719237E00F834A4 /* ViewController.h */, 204 | 587688E62719237E00F834A4 /* ViewController.m */, 205 | 5876893E2720064D00F834A4 /* NavigationController.h */, 206 | 5876893F2720064D00F834A4 /* NavigationController.m */, 207 | 587688EE2719238000F834A4 /* Assets.xcassets */, 208 | 587688EF2719238000F834A4 /* Info.plist */, 209 | 587688F02719238000F834A4 /* main.m */, 210 | 587688DA2719237E00F834A4 /* Resources */, 211 | 5889731C27213C8300BE123E /* Localizable.strings */, 212 | ); 213 | path = Stay; 214 | sourceTree = ""; 215 | }; 216 | 587688DA2719237E00F834A4 /* Resources */ = { 217 | isa = PBXGroup; 218 | children = ( 219 | 587688DB2719237E00F834A4 /* Main.html */, 220 | 587688DE2719237E00F834A4 /* Icon.png */, 221 | 587688E02719237E00F834A4 /* Style.css */, 222 | ); 223 | path = Resources; 224 | sourceTree = ""; 225 | }; 226 | 587688F92719238000F834A4 /* StayTests */ = { 227 | isa = PBXGroup; 228 | children = ( 229 | 587688FA2719238000F834A4 /* StayTests.m */, 230 | ); 231 | path = StayTests; 232 | sourceTree = ""; 233 | }; 234 | 587689032719238000F834A4 /* StayUITests */ = { 235 | isa = PBXGroup; 236 | children = ( 237 | 587689042719238000F834A4 /* StayUITests.m */, 238 | 587689062719238000F834A4 /* StayUITestsLaunchTests.m */, 239 | ); 240 | path = StayUITests; 241 | sourceTree = ""; 242 | }; 243 | 587689102719238000F834A4 /* Stay Extension */ = { 244 | isa = PBXGroup; 245 | children = ( 246 | 587689112719238000F834A4 /* SafariWebExtensionHandler.h */, 247 | 587689122719238000F834A4 /* SafariWebExtensionHandler.m */, 248 | 587689252719238000F834A4 /* Info.plist */, 249 | 587689142719238000F834A4 /* Resources */, 250 | ); 251 | path = "Stay Extension"; 252 | sourceTree = ""; 253 | }; 254 | 587689142719238000F834A4 /* Resources */ = { 255 | isa = PBXGroup; 256 | children = ( 257 | 588973352722C5D800BE123E /* toutiao */, 258 | 588973322722BF7000BE123E /* jianshu */, 259 | 5889732F2722AB2E00BE123E /* csdn */, 260 | 5889732C2722A93A00BE123E /* google */, 261 | 5889732727217F3A00BE123E /* sohu */, 262 | 588973242721714600BE123E /* zhihu */, 263 | 58897321272170AF00BE123E /* xhs */, 264 | 5876893B271EBD1500F834A4 /* baidu */, 265 | 5876893A271E911600F834A4 /* lib */, 266 | 587689152719238000F834A4 /* _locales */, 267 | 587689172719238000F834A4 /* images */, 268 | 587689192719238000F834A4 /* manifest.json */, 269 | 5876891B2719238000F834A4 /* background.js */, 270 | 5881342E27294C0E0055E1CE /* iframe.html */, 271 | 5881342F27294C0E0055E1CE /* iframe.js */, 272 | 5876891F2719238000F834A4 /* popup.html */, 273 | 587689212719238000F834A4 /* popup.css */, 274 | 587689232719238000F834A4 /* popup.js */, 275 | 588973472728144000BE123E /* redirect.js */, 276 | ); 277 | path = Resources; 278 | sourceTree = ""; 279 | }; 280 | 5876893A271E911600F834A4 /* lib */ = { 281 | isa = PBXGroup; 282 | children = ( 283 | 58768938271E64EB00F834A4 /* common.js */, 284 | ); 285 | path = lib; 286 | sourceTree = ""; 287 | }; 288 | 5876893B271EBD1500F834A4 /* baidu */ = { 289 | isa = PBXGroup; 290 | children = ( 291 | 5876891D2719238000F834A4 /* baidu-content.js */, 292 | 588973382722D74A00BE123E /* tieba-content.js */, 293 | ); 294 | path = baidu; 295 | sourceTree = ""; 296 | }; 297 | 58897321272170AF00BE123E /* xhs */ = { 298 | isa = PBXGroup; 299 | children = ( 300 | 58897322272170CC00BE123E /* xhs-content.js */, 301 | ); 302 | path = xhs; 303 | sourceTree = ""; 304 | }; 305 | 588973242721714600BE123E /* zhihu */ = { 306 | isa = PBXGroup; 307 | children = ( 308 | 588973252721715F00BE123E /* zhihu-content.js */, 309 | ); 310 | path = zhihu; 311 | sourceTree = ""; 312 | }; 313 | 5889732727217F3A00BE123E /* sohu */ = { 314 | isa = PBXGroup; 315 | children = ( 316 | 5889732A272180F700BE123E /* sohu-content.js */, 317 | ); 318 | path = sohu; 319 | sourceTree = ""; 320 | }; 321 | 5889732C2722A93A00BE123E /* google */ = { 322 | isa = PBXGroup; 323 | children = ( 324 | 5889732D2722A94F00BE123E /* google-content.js */, 325 | ); 326 | path = google; 327 | sourceTree = ""; 328 | }; 329 | 5889732F2722AB2E00BE123E /* csdn */ = { 330 | isa = PBXGroup; 331 | children = ( 332 | 588973302722AB4600BE123E /* csdn-content.js */, 333 | ); 334 | path = csdn; 335 | sourceTree = ""; 336 | }; 337 | 588973322722BF7000BE123E /* jianshu */ = { 338 | isa = PBXGroup; 339 | children = ( 340 | 588973332722BFA400BE123E /* jianshu-content.js */, 341 | ); 342 | path = jianshu; 343 | sourceTree = ""; 344 | }; 345 | 588973352722C5D800BE123E /* toutiao */ = { 346 | isa = PBXGroup; 347 | children = ( 348 | 588973362722C5EF00BE123E /* toutiao-content.js */, 349 | ); 350 | path = toutiao; 351 | sourceTree = ""; 352 | }; 353 | 5889733A2722FF7600BE123E /* Images */ = { 354 | isa = PBXGroup; 355 | children = ( 356 | 58813436272AACEC0055E1CE /* fastclip-icon@3x.png */, 357 | 5889733D2723033600BE123E /* icon@3x.png */, 358 | ); 359 | path = Images; 360 | sourceTree = ""; 361 | }; 362 | /* End PBXGroup section */ 363 | 364 | /* Begin PBXNativeTarget section */ 365 | 587688D32719237E00F834A4 /* Stay */ = { 366 | isa = PBXNativeTarget; 367 | buildConfigurationList = 5876892D2719238000F834A4 /* Build configuration list for PBXNativeTarget "Stay" */; 368 | buildPhases = ( 369 | 587688D02719237E00F834A4 /* Sources */, 370 | 587688D12719237E00F834A4 /* Frameworks */, 371 | 587688D22719237E00F834A4 /* Resources */, 372 | 5876892C2719238000F834A4 /* Embed App Extensions */, 373 | ); 374 | buildRules = ( 375 | ); 376 | dependencies = ( 377 | 5876890F2719238000F834A4 /* PBXTargetDependency */, 378 | ); 379 | name = Stay; 380 | productName = Stay; 381 | productReference = 587688D42719237E00F834A4 /* Stay.app */; 382 | productType = "com.apple.product-type.application"; 383 | }; 384 | 587688F52719238000F834A4 /* StayTests */ = { 385 | isa = PBXNativeTarget; 386 | buildConfigurationList = 587689302719238000F834A4 /* Build configuration list for PBXNativeTarget "StayTests" */; 387 | buildPhases = ( 388 | 587688F22719238000F834A4 /* Sources */, 389 | 587688F32719238000F834A4 /* Frameworks */, 390 | 587688F42719238000F834A4 /* Resources */, 391 | ); 392 | buildRules = ( 393 | ); 394 | dependencies = ( 395 | 587688F82719238000F834A4 /* PBXTargetDependency */, 396 | ); 397 | name = StayTests; 398 | productName = StayTests; 399 | productReference = 587688F62719238000F834A4 /* StayTests.xctest */; 400 | productType = "com.apple.product-type.bundle.unit-test"; 401 | }; 402 | 587688FF2719238000F834A4 /* StayUITests */ = { 403 | isa = PBXNativeTarget; 404 | buildConfigurationList = 587689332719238000F834A4 /* Build configuration list for PBXNativeTarget "StayUITests" */; 405 | buildPhases = ( 406 | 587688FC2719238000F834A4 /* Sources */, 407 | 587688FD2719238000F834A4 /* Frameworks */, 408 | 587688FE2719238000F834A4 /* Resources */, 409 | ); 410 | buildRules = ( 411 | ); 412 | dependencies = ( 413 | 587689022719238000F834A4 /* PBXTargetDependency */, 414 | ); 415 | name = StayUITests; 416 | productName = StayUITests; 417 | productReference = 587689002719238000F834A4 /* StayUITests.xctest */; 418 | productType = "com.apple.product-type.bundle.ui-testing"; 419 | }; 420 | 5876890B2719238000F834A4 /* Stay Extension */ = { 421 | isa = PBXNativeTarget; 422 | buildConfigurationList = 587689292719238000F834A4 /* Build configuration list for PBXNativeTarget "Stay Extension" */; 423 | buildPhases = ( 424 | 587689082719238000F834A4 /* Sources */, 425 | 587689092719238000F834A4 /* Frameworks */, 426 | 5876890A2719238000F834A4 /* Resources */, 427 | ); 428 | buildRules = ( 429 | ); 430 | dependencies = ( 431 | ); 432 | name = "Stay Extension"; 433 | productName = "Stay Extension"; 434 | productReference = 5876890C2719238000F834A4 /* Stay Extension.appex */; 435 | productType = "com.apple.product-type.app-extension"; 436 | }; 437 | /* End PBXNativeTarget section */ 438 | 439 | /* Begin PBXProject section */ 440 | 587688CC2719237E00F834A4 /* Project object */ = { 441 | isa = PBXProject; 442 | attributes = { 443 | BuildIndependentTargetsInParallel = 1; 444 | LastUpgradeCheck = 1300; 445 | TargetAttributes = { 446 | 587688D32719237E00F834A4 = { 447 | CreatedOnToolsVersion = 13.0; 448 | }; 449 | 587688F52719238000F834A4 = { 450 | CreatedOnToolsVersion = 13.0; 451 | TestTargetID = 587688D32719237E00F834A4; 452 | }; 453 | 587688FF2719238000F834A4 = { 454 | CreatedOnToolsVersion = 13.0; 455 | TestTargetID = 587688D32719237E00F834A4; 456 | }; 457 | 5876890B2719238000F834A4 = { 458 | CreatedOnToolsVersion = 13.0; 459 | }; 460 | }; 461 | }; 462 | buildConfigurationList = 587688CF2719237E00F834A4 /* Build configuration list for PBXProject "Stay" */; 463 | compatibilityVersion = "Xcode 13.0"; 464 | developmentRegion = en; 465 | hasScannedForEncodings = 0; 466 | knownRegions = ( 467 | en, 468 | Base, 469 | "zh-Hans", 470 | ); 471 | mainGroup = 587688CB2719237E00F834A4; 472 | productRefGroup = 587688D52719237E00F834A4 /* Products */; 473 | projectDirPath = ""; 474 | projectRoot = ""; 475 | targets = ( 476 | 587688D32719237E00F834A4 /* Stay */, 477 | 587688F52719238000F834A4 /* StayTests */, 478 | 587688FF2719238000F834A4 /* StayUITests */, 479 | 5876890B2719238000F834A4 /* Stay Extension */, 480 | ); 481 | }; 482 | /* End PBXProject section */ 483 | 484 | /* Begin PBXResourcesBuildPhase section */ 485 | 587688D22719237E00F834A4 /* Resources */ = { 486 | isa = PBXResourcesBuildPhase; 487 | buildActionMask = 2147483647; 488 | files = ( 489 | 58813437272AACEC0055E1CE /* fastclip-icon@3x.png in Resources */, 490 | 587688DF2719237E00F834A4 /* Icon.png in Resources */, 491 | 5889733E2723033600BE123E /* icon@3x.png in Resources */, 492 | 587688DD2719237E00F834A4 /* Main.html in Resources */, 493 | 5889731A27213C8300BE123E /* Localizable.strings in Resources */, 494 | 58897320272156C900BE123E /* LaunchScreen.storyboard in Resources */, 495 | 587689262719238000F834A4 /* Assets.xcassets in Resources */, 496 | 587688E12719237E00F834A4 /* Style.css in Resources */, 497 | ); 498 | runOnlyForDeploymentPostprocessing = 0; 499 | }; 500 | 587688F42719238000F834A4 /* Resources */ = { 501 | isa = PBXResourcesBuildPhase; 502 | buildActionMask = 2147483647; 503 | files = ( 504 | ); 505 | runOnlyForDeploymentPostprocessing = 0; 506 | }; 507 | 587688FE2719238000F834A4 /* Resources */ = { 508 | isa = PBXResourcesBuildPhase; 509 | buildActionMask = 2147483647; 510 | files = ( 511 | ); 512 | runOnlyForDeploymentPostprocessing = 0; 513 | }; 514 | 5876890A2719238000F834A4 /* Resources */ = { 515 | isa = PBXResourcesBuildPhase; 516 | buildActionMask = 2147483647; 517 | files = ( 518 | 58768939271E64EB00F834A4 /* common.js in Resources */, 519 | 5881343027294C0E0055E1CE /* iframe.html in Resources */, 520 | 5889732B272180F700BE123E /* sohu-content.js in Resources */, 521 | 5876891C2719238000F834A4 /* background.js in Resources */, 522 | 587689222719238000F834A4 /* popup.css in Resources */, 523 | 588973342722BFA400BE123E /* jianshu-content.js in Resources */, 524 | 587689202719238000F834A4 /* popup.html in Resources */, 525 | 588973482728144000BE123E /* redirect.js in Resources */, 526 | 5881343127294C0E0055E1CE /* iframe.js in Resources */, 527 | 58897323272170CC00BE123E /* xhs-content.js in Resources */, 528 | 588973312722AB4600BE123E /* csdn-content.js in Resources */, 529 | 587689182719238000F834A4 /* images in Resources */, 530 | 5889732E2722A94F00BE123E /* google-content.js in Resources */, 531 | 588973372722C5EF00BE123E /* toutiao-content.js in Resources */, 532 | 588973392722D74A00BE123E /* tieba-content.js in Resources */, 533 | 5876891A2719238000F834A4 /* manifest.json in Resources */, 534 | 587689162719238000F834A4 /* _locales in Resources */, 535 | 5876891E2719238000F834A4 /* baidu-content.js in Resources */, 536 | 587689242719238000F834A4 /* popup.js in Resources */, 537 | 588973262721715F00BE123E /* zhihu-content.js in Resources */, 538 | ); 539 | runOnlyForDeploymentPostprocessing = 0; 540 | }; 541 | /* End PBXResourcesBuildPhase section */ 542 | 543 | /* Begin PBXSourcesBuildPhase section */ 544 | 587688D02719237E00F834A4 /* Sources */ = { 545 | isa = PBXSourcesBuildPhase; 546 | buildActionMask = 2147483647; 547 | files = ( 548 | 587688E72719237E00F834A4 /* ViewController.m in Sources */, 549 | 587688D92719237E00F834A4 /* AppDelegate.m in Sources */, 550 | 587689402720064D00F834A4 /* NavigationController.m in Sources */, 551 | 587688F12719238000F834A4 /* main.m in Sources */, 552 | 587688E42719237E00F834A4 /* SceneDelegate.m in Sources */, 553 | ); 554 | runOnlyForDeploymentPostprocessing = 0; 555 | }; 556 | 587688F22719238000F834A4 /* Sources */ = { 557 | isa = PBXSourcesBuildPhase; 558 | buildActionMask = 2147483647; 559 | files = ( 560 | 587688FB2719238000F834A4 /* StayTests.m in Sources */, 561 | ); 562 | runOnlyForDeploymentPostprocessing = 0; 563 | }; 564 | 587688FC2719238000F834A4 /* Sources */ = { 565 | isa = PBXSourcesBuildPhase; 566 | buildActionMask = 2147483647; 567 | files = ( 568 | 587689052719238000F834A4 /* StayUITests.m in Sources */, 569 | 587689072719238000F834A4 /* StayUITestsLaunchTests.m in Sources */, 570 | ); 571 | runOnlyForDeploymentPostprocessing = 0; 572 | }; 573 | 587689082719238000F834A4 /* Sources */ = { 574 | isa = PBXSourcesBuildPhase; 575 | buildActionMask = 2147483647; 576 | files = ( 577 | 587689132719238000F834A4 /* SafariWebExtensionHandler.m in Sources */, 578 | ); 579 | runOnlyForDeploymentPostprocessing = 0; 580 | }; 581 | /* End PBXSourcesBuildPhase section */ 582 | 583 | /* Begin PBXTargetDependency section */ 584 | 587688F82719238000F834A4 /* PBXTargetDependency */ = { 585 | isa = PBXTargetDependency; 586 | target = 587688D32719237E00F834A4 /* Stay */; 587 | targetProxy = 587688F72719238000F834A4 /* PBXContainerItemProxy */; 588 | }; 589 | 587689022719238000F834A4 /* PBXTargetDependency */ = { 590 | isa = PBXTargetDependency; 591 | target = 587688D32719237E00F834A4 /* Stay */; 592 | targetProxy = 587689012719238000F834A4 /* PBXContainerItemProxy */; 593 | }; 594 | 5876890F2719238000F834A4 /* PBXTargetDependency */ = { 595 | isa = PBXTargetDependency; 596 | target = 5876890B2719238000F834A4 /* Stay Extension */; 597 | targetProxy = 5876890E2719238000F834A4 /* PBXContainerItemProxy */; 598 | }; 599 | /* End PBXTargetDependency section */ 600 | 601 | /* Begin PBXVariantGroup section */ 602 | 587688DB2719237E00F834A4 /* Main.html */ = { 603 | isa = PBXVariantGroup; 604 | children = ( 605 | 5889731427213BC200BE123E /* en */, 606 | ); 607 | name = Main.html; 608 | sourceTree = ""; 609 | }; 610 | 5889731C27213C8300BE123E /* Localizable.strings */ = { 611 | isa = PBXVariantGroup; 612 | children = ( 613 | 5889731B27213C8300BE123E /* en */, 614 | 5889731E27213CB100BE123E /* zh-Hans */, 615 | ); 616 | name = Localizable.strings; 617 | sourceTree = ""; 618 | }; 619 | /* End PBXVariantGroup section */ 620 | 621 | /* Begin XCBuildConfiguration section */ 622 | 587689272719238000F834A4 /* Debug */ = { 623 | isa = XCBuildConfiguration; 624 | buildSettings = { 625 | ALWAYS_SEARCH_USER_PATHS = NO; 626 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 627 | CLANG_ANALYZER_NONNULL = YES; 628 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 629 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 630 | CLANG_CXX_LIBRARY = "libc++"; 631 | CLANG_ENABLE_MODULES = YES; 632 | CLANG_ENABLE_OBJC_ARC = YES; 633 | CLANG_ENABLE_OBJC_WEAK = YES; 634 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 635 | CLANG_WARN_BOOL_CONVERSION = YES; 636 | CLANG_WARN_COMMA = YES; 637 | CLANG_WARN_CONSTANT_CONVERSION = YES; 638 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 639 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 640 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 641 | CLANG_WARN_EMPTY_BODY = YES; 642 | CLANG_WARN_ENUM_CONVERSION = YES; 643 | CLANG_WARN_INFINITE_RECURSION = YES; 644 | CLANG_WARN_INT_CONVERSION = YES; 645 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 646 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 647 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 648 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 649 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 650 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 651 | CLANG_WARN_STRICT_PROTOTYPES = YES; 652 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 653 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 654 | CLANG_WARN_UNREACHABLE_CODE = YES; 655 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 656 | COPY_PHASE_STRIP = NO; 657 | DEBUG_INFORMATION_FORMAT = dwarf; 658 | ENABLE_STRICT_OBJC_MSGSEND = YES; 659 | ENABLE_TESTABILITY = YES; 660 | GCC_C_LANGUAGE_STANDARD = gnu11; 661 | GCC_DYNAMIC_NO_PIC = NO; 662 | GCC_NO_COMMON_BLOCKS = YES; 663 | GCC_OPTIMIZATION_LEVEL = 0; 664 | GCC_PREPROCESSOR_DEFINITIONS = ( 665 | "DEBUG=1", 666 | "$(inherited)", 667 | ); 668 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 669 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 670 | GCC_WARN_UNDECLARED_SELECTOR = YES; 671 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 672 | GCC_WARN_UNUSED_FUNCTION = YES; 673 | GCC_WARN_UNUSED_VARIABLE = YES; 674 | INFOPLIST_KEY_WKRunsIndependentlyOfCompanionApp = NO; 675 | INFOPLIST_KEY_WKWatchOnly = NO; 676 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 677 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 678 | MTL_FAST_MATH = YES; 679 | ONLY_ACTIVE_ARCH = YES; 680 | SDKROOT = iphoneos; 681 | }; 682 | name = Debug; 683 | }; 684 | 587689282719238000F834A4 /* Release */ = { 685 | isa = XCBuildConfiguration; 686 | buildSettings = { 687 | ALWAYS_SEARCH_USER_PATHS = NO; 688 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 689 | CLANG_ANALYZER_NONNULL = YES; 690 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 691 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 692 | CLANG_CXX_LIBRARY = "libc++"; 693 | CLANG_ENABLE_MODULES = YES; 694 | CLANG_ENABLE_OBJC_ARC = YES; 695 | CLANG_ENABLE_OBJC_WEAK = YES; 696 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 697 | CLANG_WARN_BOOL_CONVERSION = YES; 698 | CLANG_WARN_COMMA = YES; 699 | CLANG_WARN_CONSTANT_CONVERSION = YES; 700 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 701 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 702 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 703 | CLANG_WARN_EMPTY_BODY = YES; 704 | CLANG_WARN_ENUM_CONVERSION = YES; 705 | CLANG_WARN_INFINITE_RECURSION = YES; 706 | CLANG_WARN_INT_CONVERSION = YES; 707 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 708 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 709 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 710 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 711 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 712 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 713 | CLANG_WARN_STRICT_PROTOTYPES = YES; 714 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 715 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 716 | CLANG_WARN_UNREACHABLE_CODE = YES; 717 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 718 | COPY_PHASE_STRIP = NO; 719 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 720 | ENABLE_NS_ASSERTIONS = NO; 721 | ENABLE_STRICT_OBJC_MSGSEND = YES; 722 | GCC_C_LANGUAGE_STANDARD = gnu11; 723 | GCC_NO_COMMON_BLOCKS = YES; 724 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 725 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 726 | GCC_WARN_UNDECLARED_SELECTOR = YES; 727 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 728 | GCC_WARN_UNUSED_FUNCTION = YES; 729 | GCC_WARN_UNUSED_VARIABLE = YES; 730 | INFOPLIST_KEY_WKRunsIndependentlyOfCompanionApp = NO; 731 | INFOPLIST_KEY_WKWatchOnly = NO; 732 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 733 | MTL_ENABLE_DEBUG_INFO = NO; 734 | MTL_FAST_MATH = YES; 735 | SDKROOT = iphoneos; 736 | VALIDATE_PRODUCT = YES; 737 | }; 738 | name = Release; 739 | }; 740 | 5876892A2719238000F834A4 /* Debug */ = { 741 | isa = XCBuildConfiguration; 742 | buildSettings = { 743 | CODE_SIGN_STYLE = Automatic; 744 | CURRENT_PROJECT_VERSION = 10; 745 | DEVELOPMENT_TEAM = J25G7D7AL3; 746 | GENERATE_INFOPLIST_FILE = YES; 747 | INFOPLIST_FILE = "Stay Extension/Info.plist"; 748 | INFOPLIST_KEY_CFBundleDisplayName = "Stay Extension"; 749 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 750 | INFOPLIST_KEY_WKRunsIndependentlyOfCompanionApp = NO; 751 | INFOPLIST_KEY_WKWatchOnly = NO; 752 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 753 | LD_RUNPATH_SEARCH_PATHS = ( 754 | "$(inherited)", 755 | "@executable_path/Frameworks", 756 | "@executable_path/../../Frameworks", 757 | ); 758 | MARKETING_VERSION = 1.0.1; 759 | OTHER_LDFLAGS = ( 760 | "-framework", 761 | SafariServices, 762 | ); 763 | PRODUCT_BUNDLE_IDENTIFIER = com.dajiu.stay.pro.Extension; 764 | PRODUCT_NAME = "$(TARGET_NAME)"; 765 | SKIP_INSTALL = YES; 766 | SWIFT_EMIT_LOC_STRINGS = YES; 767 | TARGETED_DEVICE_FAMILY = 1; 768 | }; 769 | name = Debug; 770 | }; 771 | 5876892B2719238000F834A4 /* Release */ = { 772 | isa = XCBuildConfiguration; 773 | buildSettings = { 774 | CODE_SIGN_STYLE = Automatic; 775 | CURRENT_PROJECT_VERSION = 10; 776 | DEVELOPMENT_TEAM = J25G7D7AL3; 777 | GENERATE_INFOPLIST_FILE = YES; 778 | INFOPLIST_FILE = "Stay Extension/Info.plist"; 779 | INFOPLIST_KEY_CFBundleDisplayName = "Stay Extension"; 780 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 781 | INFOPLIST_KEY_WKRunsIndependentlyOfCompanionApp = NO; 782 | INFOPLIST_KEY_WKWatchOnly = NO; 783 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 784 | LD_RUNPATH_SEARCH_PATHS = ( 785 | "$(inherited)", 786 | "@executable_path/Frameworks", 787 | "@executable_path/../../Frameworks", 788 | ); 789 | MARKETING_VERSION = 1.0.1; 790 | OTHER_LDFLAGS = ( 791 | "-framework", 792 | SafariServices, 793 | ); 794 | PRODUCT_BUNDLE_IDENTIFIER = com.dajiu.stay.pro.Extension; 795 | PRODUCT_NAME = "$(TARGET_NAME)"; 796 | SKIP_INSTALL = YES; 797 | SWIFT_EMIT_LOC_STRINGS = YES; 798 | TARGETED_DEVICE_FAMILY = 1; 799 | }; 800 | name = Release; 801 | }; 802 | 5876892E2719238000F834A4 /* Debug */ = { 803 | isa = XCBuildConfiguration; 804 | buildSettings = { 805 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 806 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 807 | CODE_SIGN_STYLE = Automatic; 808 | CURRENT_PROJECT_VERSION = 10; 809 | DEVELOPMENT_TEAM = J25G7D7AL3; 810 | GENERATE_INFOPLIST_FILE = YES; 811 | INFOPLIST_FILE = Stay/Info.plist; 812 | INFOPLIST_KEY_CFBundleDisplayName = Stay; 813 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 814 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 815 | INFOPLIST_KEY_UIRequiresFullScreen = NO; 816 | INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 817 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 818 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 819 | INFOPLIST_KEY_WKRunsIndependentlyOfCompanionApp = NO; 820 | INFOPLIST_KEY_WKWatchOnly = NO; 821 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 822 | LD_RUNPATH_SEARCH_PATHS = ( 823 | "$(inherited)", 824 | "@executable_path/Frameworks", 825 | ); 826 | MARKETING_VERSION = 1.0.1; 827 | OTHER_LDFLAGS = "$(inherited)"; 828 | PRODUCT_BUNDLE_IDENTIFIER = com.dajiu.stay.pro; 829 | PRODUCT_NAME = "$(TARGET_NAME)"; 830 | SWIFT_EMIT_LOC_STRINGS = YES; 831 | TARGETED_DEVICE_FAMILY = 1; 832 | }; 833 | name = Debug; 834 | }; 835 | 5876892F2719238000F834A4 /* Release */ = { 836 | isa = XCBuildConfiguration; 837 | buildSettings = { 838 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 839 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 840 | CODE_SIGN_STYLE = Automatic; 841 | CURRENT_PROJECT_VERSION = 10; 842 | DEVELOPMENT_TEAM = J25G7D7AL3; 843 | GENERATE_INFOPLIST_FILE = YES; 844 | INFOPLIST_FILE = Stay/Info.plist; 845 | INFOPLIST_KEY_CFBundleDisplayName = Stay; 846 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 847 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 848 | INFOPLIST_KEY_UIRequiresFullScreen = NO; 849 | INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 850 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 851 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 852 | INFOPLIST_KEY_WKRunsIndependentlyOfCompanionApp = NO; 853 | INFOPLIST_KEY_WKWatchOnly = NO; 854 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 855 | LD_RUNPATH_SEARCH_PATHS = ( 856 | "$(inherited)", 857 | "@executable_path/Frameworks", 858 | ); 859 | MARKETING_VERSION = 1.0.1; 860 | OTHER_LDFLAGS = "$(inherited)"; 861 | PRODUCT_BUNDLE_IDENTIFIER = com.dajiu.stay.pro; 862 | PRODUCT_NAME = "$(TARGET_NAME)"; 863 | SWIFT_EMIT_LOC_STRINGS = YES; 864 | TARGETED_DEVICE_FAMILY = 1; 865 | }; 866 | name = Release; 867 | }; 868 | 587689312719238000F834A4 /* Debug */ = { 869 | isa = XCBuildConfiguration; 870 | buildSettings = { 871 | BUNDLE_LOADER = "$(TEST_HOST)"; 872 | CODE_SIGN_STYLE = Automatic; 873 | CURRENT_PROJECT_VERSION = 1; 874 | DEVELOPMENT_TEAM = J25G7D7AL3; 875 | GENERATE_INFOPLIST_FILE = YES; 876 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 877 | LD_RUNPATH_SEARCH_PATHS = ( 878 | "$(inherited)", 879 | "@executable_path/Frameworks", 880 | "@loader_path/Frameworks", 881 | ); 882 | MARKETING_VERSION = 1.0; 883 | PRODUCT_BUNDLE_IDENTIFIER = com.dajiu.stay.StayTests; 884 | PRODUCT_NAME = "$(TARGET_NAME)"; 885 | SWIFT_EMIT_LOC_STRINGS = NO; 886 | TARGETED_DEVICE_FAMILY = "1,2"; 887 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Stay.app/Stay"; 888 | }; 889 | name = Debug; 890 | }; 891 | 587689322719238000F834A4 /* Release */ = { 892 | isa = XCBuildConfiguration; 893 | buildSettings = { 894 | BUNDLE_LOADER = "$(TEST_HOST)"; 895 | CODE_SIGN_STYLE = Automatic; 896 | CURRENT_PROJECT_VERSION = 1; 897 | DEVELOPMENT_TEAM = J25G7D7AL3; 898 | GENERATE_INFOPLIST_FILE = YES; 899 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 900 | LD_RUNPATH_SEARCH_PATHS = ( 901 | "$(inherited)", 902 | "@executable_path/Frameworks", 903 | "@loader_path/Frameworks", 904 | ); 905 | MARKETING_VERSION = 1.0; 906 | PRODUCT_BUNDLE_IDENTIFIER = com.dajiu.stay.StayTests; 907 | PRODUCT_NAME = "$(TARGET_NAME)"; 908 | SWIFT_EMIT_LOC_STRINGS = NO; 909 | TARGETED_DEVICE_FAMILY = "1,2"; 910 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Stay.app/Stay"; 911 | }; 912 | name = Release; 913 | }; 914 | 587689342719238000F834A4 /* Debug */ = { 915 | isa = XCBuildConfiguration; 916 | buildSettings = { 917 | CODE_SIGN_STYLE = Automatic; 918 | CURRENT_PROJECT_VERSION = 1; 919 | DEVELOPMENT_TEAM = J25G7D7AL3; 920 | GENERATE_INFOPLIST_FILE = YES; 921 | LD_RUNPATH_SEARCH_PATHS = ( 922 | "$(inherited)", 923 | "@executable_path/Frameworks", 924 | "@loader_path/Frameworks", 925 | ); 926 | MARKETING_VERSION = 1.0; 927 | PRODUCT_BUNDLE_IDENTIFIER = com.dajiu.stay.StayUITests; 928 | PRODUCT_NAME = "$(TARGET_NAME)"; 929 | SWIFT_EMIT_LOC_STRINGS = NO; 930 | TARGETED_DEVICE_FAMILY = "1,2"; 931 | TEST_TARGET_NAME = Stay; 932 | }; 933 | name = Debug; 934 | }; 935 | 587689352719238000F834A4 /* Release */ = { 936 | isa = XCBuildConfiguration; 937 | buildSettings = { 938 | CODE_SIGN_STYLE = Automatic; 939 | CURRENT_PROJECT_VERSION = 1; 940 | DEVELOPMENT_TEAM = J25G7D7AL3; 941 | GENERATE_INFOPLIST_FILE = YES; 942 | LD_RUNPATH_SEARCH_PATHS = ( 943 | "$(inherited)", 944 | "@executable_path/Frameworks", 945 | "@loader_path/Frameworks", 946 | ); 947 | MARKETING_VERSION = 1.0; 948 | PRODUCT_BUNDLE_IDENTIFIER = com.dajiu.stay.StayUITests; 949 | PRODUCT_NAME = "$(TARGET_NAME)"; 950 | SWIFT_EMIT_LOC_STRINGS = NO; 951 | TARGETED_DEVICE_FAMILY = "1,2"; 952 | TEST_TARGET_NAME = Stay; 953 | }; 954 | name = Release; 955 | }; 956 | /* End XCBuildConfiguration section */ 957 | 958 | /* Begin XCConfigurationList section */ 959 | 587688CF2719237E00F834A4 /* Build configuration list for PBXProject "Stay" */ = { 960 | isa = XCConfigurationList; 961 | buildConfigurations = ( 962 | 587689272719238000F834A4 /* Debug */, 963 | 587689282719238000F834A4 /* Release */, 964 | ); 965 | defaultConfigurationIsVisible = 0; 966 | defaultConfigurationName = Release; 967 | }; 968 | 587689292719238000F834A4 /* Build configuration list for PBXNativeTarget "Stay Extension" */ = { 969 | isa = XCConfigurationList; 970 | buildConfigurations = ( 971 | 5876892A2719238000F834A4 /* Debug */, 972 | 5876892B2719238000F834A4 /* Release */, 973 | ); 974 | defaultConfigurationIsVisible = 0; 975 | defaultConfigurationName = Release; 976 | }; 977 | 5876892D2719238000F834A4 /* Build configuration list for PBXNativeTarget "Stay" */ = { 978 | isa = XCConfigurationList; 979 | buildConfigurations = ( 980 | 5876892E2719238000F834A4 /* Debug */, 981 | 5876892F2719238000F834A4 /* Release */, 982 | ); 983 | defaultConfigurationIsVisible = 0; 984 | defaultConfigurationName = Release; 985 | }; 986 | 587689302719238000F834A4 /* Build configuration list for PBXNativeTarget "StayTests" */ = { 987 | isa = XCConfigurationList; 988 | buildConfigurations = ( 989 | 587689312719238000F834A4 /* Debug */, 990 | 587689322719238000F834A4 /* Release */, 991 | ); 992 | defaultConfigurationIsVisible = 0; 993 | defaultConfigurationName = Release; 994 | }; 995 | 587689332719238000F834A4 /* Build configuration list for PBXNativeTarget "StayUITests" */ = { 996 | isa = XCConfigurationList; 997 | buildConfigurations = ( 998 | 587689342719238000F834A4 /* Debug */, 999 | 587689352719238000F834A4 /* Release */, 1000 | ); 1001 | defaultConfigurationIsVisible = 0; 1002 | defaultConfigurationName = Release; 1003 | }; 1004 | /* End XCConfigurationList section */ 1005 | }; 1006 | rootObject = 587688CC2719237E00F834A4 /* Project object */; 1007 | } 1008 | -------------------------------------------------------------------------------- /Stay.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Stay.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Stay.xcodeproj/project.xcworkspace/xcuserdata/ris.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay.xcodeproj/project.xcworkspace/xcuserdata/ris.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Stay.xcodeproj/xcshareddata/xcschemes/Stay.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 63 | 65 | 71 | 72 | 73 | 74 | 80 | 82 | 88 | 89 | 90 | 91 | 93 | 94 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /Stay.xcodeproj/xcuserdata/ris.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Stay.xcodeproj/xcuserdata/ris.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Stay.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 587688D32719237E00F834A4 16 | 17 | primary 18 | 19 | 20 | 587688F52719238000F834A4 21 | 22 | primary 23 | 24 | 25 | 587688FF2719238000F834A4 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Stay/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Stay 4 | // 5 | // Created by ris on 2021/10/15. 6 | // 7 | 8 | #import 9 | 10 | @interface AppDelegate : UIResponder 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Stay/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Stay 4 | // 5 | // Created by ris on 2021/10/15. 6 | // 7 | 8 | #import "AppDelegate.h" 9 | #import "NavigationController.h" 10 | #import "ViewController.h" 11 | #import "SceneDelegate.h" 12 | 13 | @implementation AppDelegate 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 16 | { 17 | // Override point for customization after application launch. 18 | return YES; 19 | } 20 | 21 | - (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options { 22 | return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role]; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/100.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/114.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/120.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/144.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/152.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/167.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/180.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/20.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/29.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/40.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/50.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/57.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/58.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/60.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/72.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/76.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/80.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Assets.xcassets/AppIcon.appiconset/87.png -------------------------------------------------------------------------------- /Stay/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | {"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"}]} -------------------------------------------------------------------------------- /Stay/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Stay/Assets.xcassets/LargeIcon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "scale" : "3x" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Stay/Images/fastclip-icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Images/fastclip-icon@3x.png -------------------------------------------------------------------------------- /Stay/Images/icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Images/icon@3x.png -------------------------------------------------------------------------------- /Stay/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleURLTypes 6 | 7 | 8 | CFBundleTypeRole 9 | Editor 10 | CFBundleURLSchemes 11 | 12 | prefs 13 | 14 | 15 | 16 | UIApplicationSceneManifest 17 | 18 | UIApplicationSupportsMultipleScenes 19 | 20 | UISceneConfigurations 21 | 22 | UIWindowSceneSessionRoleApplication 23 | 24 | 25 | UISceneConfigurationName 26 | Default Configuration 27 | UISceneDelegateClassName 28 | SceneDelegate 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Stay/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /Stay/NavigationController.h: -------------------------------------------------------------------------------- 1 | // 2 | // NavigationController.h 3 | // Stay 4 | // 5 | // Created by ris on 2021/10/20. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface NavigationController : UINavigationController 13 | 14 | @end 15 | 16 | NS_ASSUME_NONNULL_END 17 | -------------------------------------------------------------------------------- /Stay/NavigationController.m: -------------------------------------------------------------------------------- 1 | // 2 | // NavigationController.m 3 | // Stay 4 | // 5 | // Created by ris on 2021/10/20. 6 | // 7 | 8 | #import "NavigationController.h" 9 | 10 | @interface NavigationController () 11 | 12 | @end 13 | 14 | @implementation NavigationController 15 | 16 | - (void)viewDidLoad { 17 | [super viewDidLoad]; 18 | 19 | 20 | // self.navigationBar.backgroundColor = [UIColor whiteColor]; 21 | // Do any additional setup after loading the view. 22 | } 23 | 24 | /* 25 | #pragma mark - Navigation 26 | 27 | // In a storyboard-based application, you will often want to do a little preparation before navigation 28 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 29 | // Get the new view controller using [segue destinationViewController]. 30 | // Pass the selected object to the new view controller. 31 | } 32 | */ 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Stay/Resources/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay/Resources/Icon.png -------------------------------------------------------------------------------- /Stay/Resources/Style.css: -------------------------------------------------------------------------------- 1 | * { 2 | -webkit-user-select: none; 3 | -webkit-user-drag: none; 4 | cursor: default; 5 | } 6 | 7 | :root { 8 | color-scheme: light dark; 9 | 10 | --spacing: 20px; 11 | } 12 | 13 | html { 14 | height: 100%; 15 | } 16 | 17 | body { 18 | display: flex; 19 | align-items: center; 20 | justify-content: center; 21 | flex-direction: column; 22 | 23 | gap: var(--spacing); 24 | margin: 0 calc(var(--spacing) * 2); 25 | height: 100%; 26 | 27 | font: -apple-system-short-body; 28 | text-align: center; 29 | } 30 | -------------------------------------------------------------------------------- /Stay/SceneDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.h 3 | // Stay 4 | // 5 | // Created by ris on 2021/10/15. 6 | // 7 | 8 | #import 9 | 10 | @interface SceneDelegate : UIResponder 11 | 12 | @property (strong, nonatomic) UIWindow * window; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Stay/SceneDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.m 3 | // Stay 4 | // 5 | // Created by ris on 2021/10/15. 6 | // 7 | 8 | #import "SceneDelegate.h" 9 | #import "NavigationController.h" 10 | #import "ViewController.h" 11 | 12 | @implementation SceneDelegate 13 | 14 | - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { 15 | UINavigationBar.appearance.prefersLargeTitles = YES; 16 | UIWindowScene *windowScene = (UIWindowScene *)scene; 17 | self.window = [[UIWindow alloc] initWithWindowScene:windowScene]; 18 | self.window.frame = windowScene.coordinateSpace.bounds; 19 | self.window.rootViewController = [[NavigationController alloc] initWithRootViewController:[[ViewController alloc] init]]; 20 | [self.window makeKeyAndVisible]; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Stay/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // Stay 4 | // 5 | // Created by ris on 2021/10/15. 6 | // 7 | 8 | #import 9 | 10 | @interface ViewController : UIViewController 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Stay/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // Stay 4 | // 5 | // Created by ris on 2021/10/15. 6 | // 7 | 8 | #import "ViewController.h" 9 | 10 | 11 | @interface ViewController ()< 12 | UITableViewDelegate, 13 | UITableViewDataSource 14 | > 15 | 16 | @property (nonatomic, strong) UITableView *tableView; 17 | @property (nonatomic, strong) NSArray *dataSource; 18 | @property (nonatomic, strong) UIBarButtonItem *leftIcon; 19 | @end 20 | 21 | @implementation ViewController 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | self.title = @"Stay"; 26 | self.navigationItem.leftBarButtonItem = [self leftIcon]; 27 | [self tableView]; 28 | } 29 | 30 | 31 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ 32 | return self.dataSource.count; 33 | } 34 | 35 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 36 | return ((NSArray *)self.dataSource[section][@"cells"]).count; 37 | } 38 | 39 | - (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath { 40 | NSString *identifier = [NSString stringWithFormat:@"settings.%ld.cell",indexPath.section]; 41 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; 42 | if (nil == cell){ 43 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier]; 44 | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 45 | 46 | } 47 | 48 | NSString *icon = cell.textLabel.text = self.dataSource[indexPath.section][@"cells"][indexPath.row][@"icon"]; 49 | cell.imageView.image = icon.length > 0 ? [UIImage imageNamed:icon] : nil; 50 | cell.textLabel.text = self.dataSource[indexPath.section][@"cells"][indexPath.row][@"title"]; 51 | return cell; 52 | } 53 | 54 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 55 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 56 | NSString *url = self.dataSource[indexPath.section][@"cells"][indexPath.row][@"url"]; 57 | if (url.length > 0){ 58 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url] 59 | options:@{} completionHandler:^(BOOL succeed){}]; 60 | } 61 | } 62 | 63 | - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ 64 | return self.dataSource[section][@"section"]; 65 | } 66 | 67 | 68 | - (NSArray *)dataSource{ 69 | if (nil == _dataSource){ 70 | _dataSource = @[ 71 | @{ 72 | @"section":@"", 73 | @"cells":@[ 74 | @{@"title":NSLocalizedString(@"settings.rateApp",""),@"url":@"https://apps.apple.com/app/id1591620171?action=write-review"}, 75 | @{@"title":NSLocalizedString(@"settings.openSource",""),@"url":@"https://github.com/shenruisi/Stay"}, 76 | @{@"title":NSLocalizedString(@"settings.joinTelegram",""),@"url":@"https://t.me/fastclipchat"} 77 | ] 78 | }, 79 | @{ 80 | @"section":@"", 81 | @"cells":@[ 82 | @{@"title":NSLocalizedString(@"settings.enableStay",""),@"url":@"App-prefs:root=SAFARI"} 83 | ] 84 | }, 85 | @{ 86 | @"section":NSLocalizedString(@"settings.section.otherApps",""), 87 | @"cells":@[ 88 | @{@"icon":@"fastclip-icon",@"title":NSLocalizedString(@"settings.section.otherApps.fastclip",""),@"url":@"https://apps.apple.com/cn/app/fastclip-copy-paste-enhancer/id1476085650?l=en"} 89 | ] 90 | } 91 | ]; 92 | } 93 | 94 | return _dataSource; 95 | } 96 | 97 | - (UITableView *)tableView{ 98 | if (nil == _tableView){ 99 | _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleInsetGrouped]; 100 | _tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0); 101 | _tableView.dataSource = self; 102 | _tableView.delegate = self; 103 | [self.view addSubview:_tableView]; 104 | } 105 | 106 | return _tableView; 107 | } 108 | 109 | - (UIBarButtonItem *)leftIcon{ 110 | if (nil == _leftIcon){ 111 | UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"icon"]]; 112 | imageView.contentMode = UIViewContentModeScaleAspectFit; 113 | _leftIcon = [[UIBarButtonItem alloc] initWithCustomView:imageView]; 114 | } 115 | return _leftIcon; 116 | } 117 | 118 | 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /Stay/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | Stay 4 | 5 | Created by ris on 2021/10/21. 6 | 7 | */ 8 | 9 | //settings 10 | settings.rateApp="Rate app"; 11 | settings.openSource="Open Source"; 12 | settings.joinTelegram="Join Telegram"; 13 | settings.enableStay="Turn on Stay in Safari extensions"; 14 | 15 | 16 | settings.section.otherApps="Other applications"; 17 | 18 | settings.section.otherApps.fastclip="FastClip - Copy paste enhancer"; 19 | -------------------------------------------------------------------------------- /Stay/en.lproj/Main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Stay Icon 13 |

You can turn on Stay’s Safari extension in Settings.

14 | 15 | 16 | -------------------------------------------------------------------------------- /Stay/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Stay 4 | // 5 | // Created by ris on 2021/10/15. 6 | // 7 | 8 | #import 9 | #import "AppDelegate.h" 10 | 11 | int main(int argc, char * argv[]) { 12 | NSString * appDelegateClassName; 13 | @autoreleasepool { 14 | // Setup code that might create autoreleased objects goes here. 15 | appDelegateClassName = NSStringFromClass([AppDelegate class]); 16 | } return UIApplicationMain(argc, argv, nil, appDelegateClassName); 17 | } 18 | -------------------------------------------------------------------------------- /Stay/zh-Hans.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | Stay 4 | 5 | Created by ris on 2021/10/21. 6 | 7 | */ 8 | 9 | //settings 10 | settings.rateApp="评价应用"; 11 | settings.openSource="开源代码"; 12 | settings.joinTelegram="加入Telegram"; 13 | settings.enableStay="在Safari浏览器扩展中激活Stay"; 14 | 15 | settings.section.otherApps="旗下应用"; 16 | 17 | settings.section.otherApps.fastclip="FastClip - 复制粘贴增强器"; 18 | -------------------------------------------------------------------------------- /Stay/zh-Hans.lproj/Main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Stay Icon 13 |

You can turn on Stay’s Safari extension in Settings.

14 | 15 | 16 | -------------------------------------------------------------------------------- /StayTests/StayTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // StayTests.m 3 | // StayTests 4 | // 5 | // Created by ris on 2021/10/15. 6 | // 7 | 8 | #import 9 | 10 | @interface StayTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation StayTests 15 | 16 | - (void)setUp { 17 | // Put setup code here. This method is called before the invocation of each test method in the class. 18 | } 19 | 20 | - (void)tearDown { 21 | // Put teardown code here. This method is called after the invocation of each test method in the class. 22 | } 23 | 24 | - (void)testExample { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | - (void)testPerformanceExample { 30 | // This is an example of a performance test case. 31 | [self measureBlock:^{ 32 | // Put the code you want to measure the time of here. 33 | }]; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /StayUITests/StayUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // StayUITests.m 3 | // StayUITests 4 | // 5 | // Created by ris on 2021/10/15. 6 | // 7 | 8 | #import 9 | 10 | @interface StayUITests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation StayUITests 15 | 16 | - (void)setUp { 17 | // Put setup code here. This method is called before the invocation of each test method in the class. 18 | 19 | // In UI tests it is usually best to stop immediately when a failure occurs. 20 | self.continueAfterFailure = NO; 21 | 22 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 23 | } 24 | 25 | - (void)tearDown { 26 | // Put teardown code here. This method is called after the invocation of each test method in the class. 27 | } 28 | 29 | - (void)testExample { 30 | // UI tests must launch the application that they test. 31 | XCUIApplication *app = [[XCUIApplication alloc] init]; 32 | [app launch]; 33 | 34 | // Use recording to get started writing UI tests. 35 | // Use XCTAssert and related functions to verify your tests produce the correct results. 36 | } 37 | 38 | - (void)testLaunchPerformance { 39 | if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *)) { 40 | // This measures how long it takes to launch your application. 41 | [self measureWithMetrics:@[[[XCTApplicationLaunchMetric alloc] init]] block:^{ 42 | [[[XCUIApplication alloc] init] launch]; 43 | }]; 44 | } 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /StayUITests/StayUITestsLaunchTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // StayUITestsLaunchTests.m 3 | // StayUITests 4 | // 5 | // Created by ris on 2021/10/15. 6 | // 7 | 8 | #import 9 | 10 | @interface StayUITestsLaunchTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation StayUITestsLaunchTests 15 | 16 | + (BOOL)runsForEachTargetApplicationUIConfiguration { 17 | return YES; 18 | } 19 | 20 | - (void)setUp { 21 | self.continueAfterFailure = NO; 22 | } 23 | 24 | - (void)testLaunch { 25 | XCUIApplication *app = [[XCUIApplication alloc] init]; 26 | [app launch]; 27 | 28 | // Insert steps here to perform after app launch but before taking a screenshot, 29 | // such as logging into a test account or navigating somewhere in the app 30 | 31 | XCTAttachment *attachment = [XCTAttachment attachmentWithScreenshot:XCUIScreen.mainScreen.screenshot]; 32 | attachment.name = @"Launch Screen"; 33 | attachment.lifetime = XCTAttachmentLifetimeKeepAlways; 34 | [self addAttachment:attachment]; 35 | } 36 | 37 | @end 38 | --------------------------------------------------------------------------------