├── 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 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Stay Extension/Resources/iframe.js:
--------------------------------------------------------------------------------
1 | const $getQueryVariable = (variable) => {
2 | var query = window.location.search.substring(1);
3 | var vars = query.split("&");
4 | for (var i=0;i {
12 | if (!path || path.length == 0) return;
13 | browser.tabs.query({ active: true, currentWindow: true }, (tabs) => {
14 | browser.tabs.executeScript(tabs[0].id, { file: path, allFrames: true, runAt: "document_start"});
15 | });
16 | };
17 |
18 | let jsList = decodeURIComponent($getQueryVariable('js')).split(",");
19 | console.log(jsList);
20 | for (var i = 0; i < jsList.length; i++){
21 | $inject(jsList[i]);
22 | }
23 | document.querySelector("iframe").src = decodeURIComponent($getQueryVariable('url'));
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Stay Extension/Resources/images/accessor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay Extension/Resources/images/accessor.png
--------------------------------------------------------------------------------
/Stay Extension/Resources/images/icon-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay Extension/Resources/images/icon-128.png
--------------------------------------------------------------------------------
/Stay Extension/Resources/images/icon-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay Extension/Resources/images/icon-256.png
--------------------------------------------------------------------------------
/Stay Extension/Resources/images/icon-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay Extension/Resources/images/icon-48.png
--------------------------------------------------------------------------------
/Stay Extension/Resources/images/icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay Extension/Resources/images/icon-512.png
--------------------------------------------------------------------------------
/Stay Extension/Resources/images/icon-64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay Extension/Resources/images/icon-64.png
--------------------------------------------------------------------------------
/Stay Extension/Resources/images/icon-96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay Extension/Resources/images/icon-96.png
--------------------------------------------------------------------------------
/Stay Extension/Resources/images/toolbar-icon-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay Extension/Resources/images/toolbar-icon-16.png
--------------------------------------------------------------------------------
/Stay Extension/Resources/images/toolbar-icon-19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay Extension/Resources/images/toolbar-icon-19.png
--------------------------------------------------------------------------------
/Stay Extension/Resources/images/toolbar-icon-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay Extension/Resources/images/toolbar-icon-32.png
--------------------------------------------------------------------------------
/Stay Extension/Resources/images/toolbar-icon-38.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yqc007/Stay/757b912fc56e816aef21d96413f0f17d6b58820c/Stay Extension/Resources/images/toolbar-icon-38.png
--------------------------------------------------------------------------------
/Stay Extension/Resources/jianshu/jianshu-content.js:
--------------------------------------------------------------------------------
1 | function removeChoosePanel(){
2 | let pannel = document.querySelector('.download-app-guidance');
3 | if (pannel){
4 | pannel.remove();
5 | return COMPLETE;
6 | }
7 |
8 | return CONTINUE;
9 | }
10 |
11 | function removeAppJump(){
12 | let app = document.querySelector('button.call-app-btn');
13 | if (app){
14 | app.remove();
15 | return COMPLETE;
16 | }
17 |
18 | return CONTINUE;
19 | }
20 |
21 | function unfold(){
22 | let closebtn = document.querySelector('button.close-collapse-btn');
23 | if (closebtn){
24 | closebtn.remove();
25 |
26 | let content = document.querySelector('div.collapse-free-content')
27 | if (content){
28 | content.className = null;
29 | }
30 |
31 | return COMPLETE;
32 | }
33 |
34 | return CONTINUE;
35 | }
36 |
37 |
38 | document.addEventListener("DOMContentLoaded", function(event) {
39 | let tasks = [removeChoosePanel,removeAppJump,unfold];
40 | Inject.run(tasks,100,30,false).then((data) => {
41 | browser.runtime.sendMessage({from:"content",operate:"saveAppList",data:data})
42 | });
43 | });
44 |
--------------------------------------------------------------------------------
/Stay Extension/Resources/lib/common.js:
--------------------------------------------------------------------------------
1 | const COMPLETE = {status:"complete"};
2 | const CONTINUE = {status:"continue"};
3 | const CONTINUE_TIL = (count) => {
4 | return {status:"continue", til:count};
5 | };
6 | const QUIT = {status:"quit"};
7 |
8 | const $uri = (url) => {
9 | let a = document.createElement("a");
10 | a.href = url;
11 | return a;
12 | }
13 |
14 | const $getQueryVariable = (variable) => {
15 | var query = window.location.search.substring(1);
16 | var vars = query.split("&");
17 | for (var i=0;i {
25 | return window.getComputedStyle(e).getPropertyValue('height');
26 | }
27 |
28 | const $res = (name) => {
29 | return browser.runtime.getURL(name);
30 | }
31 |
32 | const $noJumpUrl = (host,url) => {
33 | if (host == "tieba.baidu.com"){
34 | return $res('iframe.html')+"?url="+encodeURIComponent(url)+"&js=common.js,tieba-content.js";
35 | }
36 | else if (host == "zhuanlan.zhihu.com"){
37 | return "https://zhuanlan.zhihu.com/R_E_D_I_R_E_C_T/?url="+encodeURIComponent(url);
38 | }
39 | else if (host == "www.zhihu.com"){
40 | return "https://www.zhihu.com/R_E_D_I_R_E_C_T/?url="+encodeURIComponent(url);
41 | }
42 | else if (host == "m.xiaohongshu.com"){
43 | return "https://m.xiaohongshu.com/R_E_D_I_R_E_C_T/?url="+encodeURIComponent(url);
44 | }
45 | else if (host == "m.bilibili.com" || host == "www.bilibili.com"){
46 | return $res('iframe.html')+"?url="+encodeURIComponent(url);
47 | }
48 |
49 | return null;
50 | }
51 |
52 |
53 |
54 | const R_E_D_I_R_E_C_T_TEST = /R_E_D_I_R_E_C_T/
55 | const ZHIHU_REG = /^(http|https):\/\/(.*\.){0,1}zhihu.com\/.*$/;
56 | const TIEBA_REG = /^(http|https):\/\/tieba.baidu.com\/.*$/;
57 | const XHS_REG = /^(http|https):\/\/m.xiaohongshu.com\/.*$/;
58 | const BILIBILI_REG = /^(http|https):\/\/(.*\.){0,1}bilibili.com\/.*$/;
59 |
60 | class Interval{
61 | constructor(tasks,millisec,maxLoop,execCount,resolve,reject,appContainer){
62 | this.tasks= tasks;
63 | this.millisec = millisec;
64 | this.maxLoop = maxLoop;
65 | this.resolve = resolve;
66 | this.reject = reject;
67 | this.appContainer = appContainer;
68 | this.execCount = execCount;
69 | }
70 |
71 | start(){
72 | var self = this;
73 | this.int = setInterval(function () { self.worker() },this.millisec)
74 | }
75 |
76 | worker(){
77 | if (this.execCount >= this.maxLoop){
78 | this.tasks.length = 0;
79 | this.resolve(this.appContainer.data());
80 | this.stop();
81 | };
82 | let taskCount = this.tasks.length;
83 | while(taskCount > 0){
84 | let task = this.tasks.shift();
85 | let ret = task();
86 | if (ret && ret.status == "quit"
87 | || ret.status == "complete"
88 | || (ret.status == "continue" && ret.til && ret.til == this.execCount)){
89 | this.appContainer.append(ret);
90 | }
91 | else{
92 | this.tasks.push(task);
93 | }
94 | taskCount--;
95 | }
96 |
97 | if (0 == this.tasks.length){
98 | this.resolve(this.appContainer.data());
99 | this.stop();
100 | }
101 |
102 | this.execCount = this.execCount + 1;
103 | }
104 |
105 | stop(){
106 | window.clearInterval(this.int);
107 | }
108 | }
109 |
110 | let myInterval;
111 |
112 | /**
113 | Inject
114 | */
115 | class Inject{
116 | /**
117 | @function run
118 | @param tasks Task list
119 | @param millisec Interval
120 | @param maxLoop The times of execute task function
121 | @param firstRun Indicate if enforce once at first time
122 | */
123 | static run(tasks,millisec,maxLoop,firstRun){
124 | return new Promise(function(resolve,reject){
125 | let appContainer = new AppContainer();
126 | if (firstRun){
127 | let taskCount = tasks.length;
128 | while(taskCount > 0){
129 | let task = tasks.shift();
130 | let ret = task();
131 | if (ret && ret.status == "quit"
132 | || ret.status == "complete"
133 | || (ret.status == "continue" && ret.til && ret.til == 1)){
134 | appContainer.append(ret);
135 | }
136 | else{
137 | tasks.push(task);
138 | }
139 | taskCount--;
140 | }
141 | }
142 | if (0 == tasks.length){
143 | resolve(appContainer.data());
144 | return;
145 | }
146 | myInterval = new Interval(tasks,
147 | millisec,
148 | firstRun ? maxLoop-1:maxLoop,
149 | firstRun ? 1:0,
150 | resolve,
151 | reject,
152 | appContainer);
153 | myInterval.start();
154 | });
155 | }
156 | }
157 |
158 | window.addEventListener('unload', function(event) {
159 | if (myInterval) myInterval.stop();
160 | });
161 |
162 | class App{
163 | constructor(){
164 | this.map = {status:"complete",type:"app"};
165 | }
166 |
167 | id(id){
168 | this.map.id = id;
169 | return this;
170 | }
171 |
172 | title(title){
173 | this.map.title = title;
174 | return this;
175 | }
176 |
177 | icon(icon){
178 | this.map.icon = icon;
179 | return this;
180 | }
181 |
182 | url(url){
183 | this.map.url = url;
184 | return this;
185 | }
186 |
187 | data(){
188 | return this.map;
189 | }
190 | }
191 |
192 | class AppContainer{
193 | constructor(){
194 | this.appJumpList = [];
195 | }
196 |
197 | append(appDataMap){
198 | if (appDataMap.type == "app"){
199 | var exist = false;
200 | for (var i = 0; i < this.appJumpList.length; i++){
201 | var app = this.appJumpList[i];
202 | if (app.id == appDataMap.id){
203 | exist = true;
204 | break;
205 | }
206 | }
207 | this.appJumpList.push(appDataMap);
208 | }
209 | }
210 |
211 | data(){
212 | return this.appJumpList;
213 | }
214 | }
215 |
216 |
217 | if (R_E_D_I_R_E_C_T_TEST.test(location.href)) {
218 | let url = decodeURIComponent($getQueryVariable("url")).replace("http:","https:");
219 | location.replace(url);
220 | }
221 |
222 |
--------------------------------------------------------------------------------
/Stay Extension/Resources/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 2,
3 | "default_locale": "en",
4 |
5 | "name": "__MSG_extension_name__",
6 | "description": "__MSG_extension_description__",
7 | "version": "1.0.0",
8 |
9 | "icons": {
10 | "48": "images/icon-48.png",
11 | "96": "images/icon-96.png",
12 | "128": "images/icon-128.png",
13 | "256": "images/icon-256.png",
14 | "512": "images/icon-512.png"
15 | },
16 |
17 | "background": {
18 | "scripts": [ "background.js" ],
19 | "persistent": false
20 | },
21 |
22 | "content_scripts": [
23 | {
24 | "js": [ "common.js","baidu-content.js"],
25 | "matches": [ "*://*.baidu.com/*" ],
26 | "exclude_globs":[ "*://tieba.baidu.com/*" ],
27 | "all_frames": true,
28 | "run_at": "document_start"
29 | },
30 | {
31 | "js": [ "common.js","tieba-content.js"],
32 | "matches": [ "*://tieba.baidu.com/*" ],
33 | "run_at": "document_start"
34 | },
35 | {
36 | "js": [ "common.js","xhs-content.js"],
37 | "matches": [ "*://*.xiaohongshu.com/*" ],
38 | "all_frames": true,
39 | "run_at": "document_start"
40 | },
41 | {
42 | "js": [ "common.js","sohu-content.js"],
43 | "matches": [ "*://*.sohu.com/*" ],
44 | "run_at": "document_start"
45 | },
46 | {
47 | "js": [ "common.js","google-content.js"],
48 | "matches": [ "*://*.google.com/*" ],
49 | "run_at": "document_start"
50 | },
51 | {
52 | "js": [ "common.js","csdn-content.js"],
53 | "matches": [ "*://*.csdn.net/*" ],
54 | "run_at": "document_start"
55 | },
56 | {
57 | "js": [ "common.js","jianshu-content.js"],
58 | "matches": [ "*://*.jianshu.com/*" ],
59 | "run_at": "document_start"
60 | },
61 | {
62 | "js": [ "common.js","toutiao-content.js"],
63 | "matches": [ "*://*.toutiao.com/*" ],
64 | "run_at": "document_start"
65 | },
66 | {
67 | "js": [ "common.js","zhihu-content.js"],
68 | "matches": [ "*://*.zhihu.com/*" ],
69 | "run_at": "document_start"
70 | }
71 | ],
72 |
73 | "browser_action": {
74 | "default_popup": "popup.html",
75 | "default_icon": {
76 | "16": "images/toolbar-icon-16.png",
77 | "19": "images/toolbar-icon-19.png",
78 | "32": "images/toolbar-icon-32.png",
79 | "38": "images/toolbar-icon-38.png"
80 | }
81 | },
82 |
83 | "web_accessible_resources": ["*"],
84 | "permissions": [""]
85 | }
86 |
--------------------------------------------------------------------------------
/Stay Extension/Resources/popup.css:
--------------------------------------------------------------------------------
1 | :root {
2 | color-scheme: light dark;
3 | }
4 |
5 | body {
6 | padding: 15px;
7 |
8 | font-family: system-ui;
9 | text-align: center;
10 | background-color:#F2F2F6;
11 | }
12 |
13 | .placeholder{
14 | font-size:16px;
15 | }
16 |
17 | .tableview{
18 | }
19 |
20 | .tableview .cell{
21 | display: -webkit-flex;
22 | display: flex;
23 | align-items: center;
24 | border-radius:10px;
25 | font-size:16px;
26 | border: 1px solid #FFFFFF;
27 | background-color:#FFFFFF;
28 | height:45px;
29 | }
30 |
31 | .tableview .cell .icon{
32 | border-radius:8px;
33 | width: 28px;
34 | height: 28px;
35 | margin-left:10px;
36 | }
37 |
38 | .tableview .cell .title{
39 | max-width:70%;
40 | overflow:hidden;
41 | text-overflow:ellipsis;
42 | white-space:nowrap;
43 | margin-left:10px;
44 | }
45 |
46 | .tableview .cell .accessor{
47 | margin-left:auto;
48 | margin-right:10px;
49 | background-image: url("safari-web-extension://__MSG_@@extension_id__/images/accessor.png");
50 | background-size:18px;
51 | width: 18px;
52 | height: 18px;
53 | }
54 |
55 | @media (prefers-color-scheme: dark) {
56 | /* Dark Mode styles go here. */
57 | body {
58 | padding: 15px;
59 |
60 | font-family: system-ui;
61 | text-align: center;
62 | background-color:#000000;
63 | }
64 |
65 | .tableview .cell{
66 | display: -webkit-flex;
67 | display: flex;
68 | align-items: center;
69 | border-radius:10px;
70 | font-size:16px;
71 | border: 1px solid #1C1C27;
72 | background-color:#1C1C27;
73 | height:45px;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/Stay Extension/Resources/popup.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 跳转到
5 |
6 |
7 |
8 |
9 |
10 | 未找到可跳转应用
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Stay Extension/Resources/popup.js:
--------------------------------------------------------------------------------
1 | const $setText = (selector,value) => {
2 | document.querySelector(selector).textContent = value;
3 | };
4 |
5 |
6 | window.addEventListener('DOMContentLoaded', () => {
7 | document.querySelector(".placeholder").style.display = "block";
8 | document.querySelector(".tableview").style.display = "none";
9 | browser.runtime.sendMessage({ from: "popup", operate: "fetchAppList" }).then((response) => {
10 | if (response.body.length > 0){
11 | document.querySelector(".placeholder").style.display = "none";
12 | document.querySelector(".tableview").style.display = "block";
13 | let app = response.body[0];
14 | $setText(".title",app.title);
15 | document.querySelector(".icon").src = app.icon;
16 | if (app.url.length){
17 | document.querySelector(".cell").addEventListener("click",function (event) {
18 | window.open(app.url);
19 | });
20 | }
21 | }
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/Stay Extension/Resources/redirect.js:
--------------------------------------------------------------------------------
1 | let url;
2 | if (R_E_D_I_R_E_C_T_TEST.test(location.href)) {
3 | url = decodeURIComponent($getQueryVariable("url")).replace("http:","https:");
4 | }
5 | window.onload = function(){
6 | if (url){
7 | let html = document.querySelector('html');
8 | html.innerHTML = '\
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 |
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 |
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 |
--------------------------------------------------------------------------------