Compare commits
96 Commits
v1.0.2
...
c7824c920b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7824c920b | ||
|
|
817ad978e2 | ||
|
|
1d59128e47 | ||
|
|
62537f5814 | ||
|
|
5f91160d9a | ||
|
|
64ee8189b1 | ||
|
|
665a51f962 | ||
|
|
bd77beb60a | ||
|
|
578bb926fa | ||
|
|
2c64038fda | ||
|
|
9a27ae8e69 | ||
|
|
6716456b04 | ||
|
|
ec3440a0fb | ||
|
|
598c0cbde4 | ||
|
|
bce68681ac | ||
|
|
85bc4635bc | ||
|
|
c94abdb3c5 | ||
|
|
4ed9c029ca | ||
|
|
ba7352d26e | ||
|
|
b8c370893a | ||
|
|
8b592e2e48 | ||
|
|
1e8aa3a2d4 | ||
|
|
70f4df431f | ||
|
|
6c3c15a85d | ||
|
|
b84be2ecb2 | ||
|
|
faaf254f2c | ||
|
|
0776b07b12 | ||
|
|
6ad62bfdab | ||
|
|
ab2fdb28c2 | ||
|
|
5a681067b7 | ||
|
|
bdce0ecf70 | ||
|
|
6e09c6012d | ||
|
|
851a9173af | ||
|
|
7caf726381 | ||
|
|
1a055bdca7 | ||
|
|
5d5d6d2244 | ||
|
|
862af21ec2 | ||
|
|
2037328800 | ||
|
|
bb6092e3ac | ||
|
|
014fbe78bf | ||
|
|
a89b546755 | ||
|
|
490bc0f597 | ||
|
|
d0ee140a44 | ||
|
|
e4abb578f0 | ||
|
|
fdde0037f9 | ||
|
|
e2ec85c24e | ||
|
|
3fd167e889 | ||
|
|
0e78441fa1 | ||
|
|
04de960c0f | ||
|
|
a83206bf4b | ||
|
|
6a20abae19 | ||
|
|
32ddb21ed2 | ||
|
|
68d69353e6 | ||
|
|
7f859c3eda | ||
|
|
7903977b29 | ||
|
|
104cb6cd54 | ||
|
|
b5b3e2ab0d | ||
|
|
d48270467e | ||
|
|
a45716b03c | ||
|
|
c1b1b935ff | ||
|
|
1bdbe85201 | ||
|
|
dcf08dc2c0 | ||
|
|
cb484eeb95 | ||
|
|
8c0a5bbb24 | ||
|
|
b1229b54ee | ||
|
|
7c2a16a18d | ||
|
|
b9d0071302 | ||
|
|
b8b195b663 | ||
|
|
5c6f016ab6 | ||
|
|
0f5732cc77 | ||
|
|
6050c6c965 | ||
|
|
b1105dfadc | ||
|
|
25c98a1abf | ||
|
|
9612802996 | ||
|
|
744e421eb7 | ||
|
|
b390876bd5 | ||
|
|
0d5a807afd | ||
|
|
fdbfc87481 | ||
|
|
66f2274f44 | ||
|
|
3a31651c53 | ||
|
|
c9556df363 | ||
|
|
e4eabf9578 | ||
|
|
ae7368ecbc | ||
|
|
6cc810b9b1 | ||
|
|
66bedda2b4 | ||
|
|
e741e664a3 | ||
|
|
cada2debae | ||
|
|
3b6d0b8f89 | ||
|
|
42cf89f7c5 | ||
|
|
abc6130940 | ||
|
|
2932ad3a64 | ||
|
|
83cd53d23c | ||
|
|
d7aa3b7348 | ||
|
|
9b51b5c26c | ||
|
|
f389f32d32 | ||
|
|
71a270394d |
32
CHANGELOG.md
@@ -1,3 +1,35 @@
|
|||||||
|
## v1.0.7
|
||||||
|
* 首页任务增加分类
|
||||||
|
* 增加国际化相关配置
|
||||||
|
* 登录页状态栏适配
|
||||||
|
|
||||||
|
## v1.0.6
|
||||||
|
* 支持切换账号功能
|
||||||
|
* 登录页青龙图标随颜色主题变换
|
||||||
|
* apk大小减少2/3,只支持arm架构,不再支持x86
|
||||||
|
|
||||||
|
## v1.0.5
|
||||||
|
* 优化配置文件编辑功能
|
||||||
|
* 优化文本选择样式
|
||||||
|
* 增加页面错误toast
|
||||||
|
* 修改iOS端app icon
|
||||||
|
|
||||||
|
## 1.0.4
|
||||||
|
* 增加主题切换功能,各种颜色主题随意切换
|
||||||
|
* 修改无法停止任务的bug
|
||||||
|
* 修改脚本管理页面json解析失败的bug
|
||||||
|
* 修改变更配置文件没有及时刷新UI的bug
|
||||||
|
* 增加版本更新提醒功能(需要手机能联通github)
|
||||||
|
* 登录页面长按青龙logo可以呼出网络请求日志,再次长按可关闭
|
||||||
|
* 打开系统最近任务时展示APP的名称
|
||||||
|
* 优化使用体验
|
||||||
|
|
||||||
|
## 1.0.3
|
||||||
|
|
||||||
|
* 解决2.10.12及以下版本无法登录的问题
|
||||||
|
* 适配最新版qinglong 相关接口字段
|
||||||
|
* 其他页面排版优化
|
||||||
|
|
||||||
## 1.0.2
|
## 1.0.2
|
||||||
|
|
||||||
* 支持修改用户名密码(仅限使用用户名密码登录用户)
|
* 支持修改用户名密码(仅限使用用户名密码登录用户)
|
||||||
|
|||||||
796
LICENSE
@@ -1,201 +1,661 @@
|
|||||||
Apache License
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
Version 2.0, January 2004
|
Version 3, 19 November 2007
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
1. Definitions.
|
Preamble
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
The GNU Affero General Public License is a free, copyleft license for
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
software and other kinds of works, specifically designed to ensure
|
||||||
|
cooperation with the community in the case of network server software.
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
The licenses for most software and other practical works are designed
|
||||||
the copyright owner that is granting the License.
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
our General Public Licenses are intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users.
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
When we speak of free software, we are referring to freedom, not
|
||||||
other entities that control, are controlled by, or are under common
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
control with that entity. For the purposes of this definition,
|
have the freedom to distribute copies of free software (and charge for
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
them if you wish), that you receive source code or can get it if you
|
||||||
direction or management of such entity, whether by contract or
|
want it, that you can change the software or use pieces of it in new
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
free programs, and that you know you can do these things.
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
Developers that use our General Public Licenses protect your rights
|
||||||
exercising permissions granted by this License.
|
with two steps: (1) assert copyright on the software, and (2) offer
|
||||||
|
you this License which gives you legal permission to copy, distribute
|
||||||
|
and/or modify the software.
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
A secondary benefit of defending all users' freedom is that
|
||||||
including but not limited to software source code, documentation
|
improvements made in alternate versions of the program, if they
|
||||||
source, and configuration files.
|
receive widespread use, become available for other developers to
|
||||||
|
incorporate. Many developers of free software are heartened and
|
||||||
|
encouraged by the resulting cooperation. However, in the case of
|
||||||
|
software used on network servers, this result may fail to come about.
|
||||||
|
The GNU General Public License permits making a modified version and
|
||||||
|
letting the public access it on a server without ever releasing its
|
||||||
|
source code to the public.
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
The GNU Affero General Public License is designed specifically to
|
||||||
transformation or translation of a Source form, including but
|
ensure that, in such cases, the modified source code becomes available
|
||||||
not limited to compiled object code, generated documentation,
|
to the community. It requires the operator of a network server to
|
||||||
and conversions to other media types.
|
provide the source code of the modified version running there to the
|
||||||
|
users of that server. Therefore, public use of a modified version, on
|
||||||
|
a publicly accessible server, gives the public access to the source
|
||||||
|
code of the modified version.
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
An older license, called the Affero General Public License and
|
||||||
Object form, made available under the License, as indicated by a
|
published by Affero, was designed to accomplish similar goals. This is
|
||||||
copyright notice that is included in or attached to the work
|
a different license, not a version of the Affero GPL, but Affero has
|
||||||
(an example is provided in the Appendix below).
|
released a new version of the Affero GPL which permits relicensing under
|
||||||
|
this license.
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
The precise terms and conditions for copying, distribution and
|
||||||
form, that is based on (or derived from) the Work and for which the
|
modification follow.
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
TERMS AND CONDITIONS
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
0. Definitions.
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
works, such as semiconductor masks.
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
modifications, and in Source or Object form, provided that You
|
"recipients" may be individuals or organizations.
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
Derivative Works a copy of this License; and
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
A "covered work" means either the unmodified Program or a work based
|
||||||
stating that You changed the files; and
|
on the Program.
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
To "propagate" a work means to do anything with it that, without
|
||||||
that You distribute, all copyright, patent, trademark, and
|
permission, would make you directly or secondarily liable for
|
||||||
attribution notices from the Source form of the Work,
|
infringement under applicable copyright law, except executing it on a
|
||||||
excluding those notices that do not pertain to any part of
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
the Derivative Works; and
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
To "convey" a work means any kind of propagation that enables other
|
||||||
distribution, then any Derivative Works that You distribute must
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
include a readable copy of the attribution notices contained
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
may provide additional or different license terms and conditions
|
to the extent that it includes a convenient and prominently visible
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
tells the user that there is no warranty for the work (except to the
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
extent that warranties are provided), that licensees may convey the
|
||||||
the conditions stated in this License.
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
1. Source Code.
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
The "source code" for a work means the preferred form of the work
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
for making modifications to it. "Object code" means any non-source
|
||||||
except as required for reasonable and customary use in describing the
|
form of a work.
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
A "Standard Interface" means an interface that either is an official
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
standard defined by a recognized standards body, or, in the case of
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
interfaces specified for a particular programming language, one that
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
is widely used among developers working in that language.
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
The "System Libraries" of an executable work include anything, other
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
unless required by applicable law (such as deliberate and grossly
|
packaging a Major Component, but which is not part of that Major
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
Component, and (b) serves only to enable use of the work with that
|
||||||
liable to You for damages, including any direct, indirect, special,
|
Major Component, or to implement a Standard Interface for which an
|
||||||
incidental, or consequential damages of any character arising as a
|
implementation is available to the public in source code form. A
|
||||||
result of this License or out of the use or inability to use the
|
"Major Component", in this context, means a major essential component
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
(kernel, window system, and so on) of the specific operating system
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
other commercial damages or losses), even if such Contributor
|
produce the work, or an object code interpreter used to run it.
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
The "Corresponding Source" for a work in object code form means all
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
the source code needed to generate, install, and (for an executable
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
work) run the object code and to modify the work, including scripts to
|
||||||
or other liability obligations and/or rights consistent with this
|
control those activities. However, it does not include the work's
|
||||||
License. However, in accepting such obligations, You may act only
|
System Libraries, or general-purpose tools or generally available free
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
programs which are used unmodified in performing those activities but
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
which are not part of the work. For example, Corresponding Source
|
||||||
defend, and hold each Contributor harmless for any liability
|
includes interface definition files associated with source files for
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
the work, and the source code for shared libraries and dynamically
|
||||||
of your accepting any such warranty or additional liability.
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, if you modify the
|
||||||
|
Program, your modified version must prominently offer all users
|
||||||
|
interacting with it remotely through a computer network (if your version
|
||||||
|
supports such interaction) an opportunity to receive the Corresponding
|
||||||
|
Source of your version by providing access to the Corresponding Source
|
||||||
|
from a network server at no charge, through some standard or customary
|
||||||
|
means of facilitating copying of software. This Corresponding Source
|
||||||
|
shall include the Corresponding Source for any work covered by version 3
|
||||||
|
of the GNU General Public License that is incorporated pursuant to the
|
||||||
|
following paragraph.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the work with which it is combined will remain governed by version
|
||||||
|
3 of the GNU General Public License.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU Affero General Public License from time to time. Such new versions
|
||||||
|
will be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU Affero General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU Affero General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU Affero General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
If you develop a new program, and you want it to be of the greatest
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
possible use to the public, the best way to achieve this is to make it
|
||||||
replaced with your own identifying information. (Don't include
|
free software which everyone can redistribute and change under these terms.
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
you may not use this file except in compliance with the License.
|
Copyright (C) <year> <name of author>
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published
|
||||||
|
by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
This program is distributed in the hope that it will be useful,
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
See the License for the specific language governing permissions and
|
GNU Affero General Public License for more details.
|
||||||
limitations under the License.
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If your software can interact with users remotely through a computer
|
||||||
|
network, you should also make sure that it provides a way for users to
|
||||||
|
get its source. For example, if your program is a web application, its
|
||||||
|
interface could display a "Source" link that leads users to an archive
|
||||||
|
of the code. There are many ways you could offer source, and different
|
||||||
|
solutions will be better for different programs; see section 13 for the
|
||||||
|
specific requirements.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||||
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|||||||
28
README.md
@@ -12,8 +12,8 @@ iOS端暂无上架打算,用户自行下载main分支源码编译安装
|
|||||||
|
|
||||||
|
|
||||||
<p float="left">
|
<p float="left">
|
||||||
|
<img src="./art/14.jpg" width="200" />
|
||||||
<img src="./art/1.jpg" width="200" />
|
<img src="./art/1.jpg" width="200" />
|
||||||
<img src="./art/8.jpg" width="200" />
|
|
||||||
<img src="./art/9.jpg" width="200" />
|
<img src="./art/9.jpg" width="200" />
|
||||||
</p>
|
</p>
|
||||||
<p float="left">
|
<p float="left">
|
||||||
@@ -35,11 +35,29 @@ iOS端暂无上架打算,用户自行下载main分支源码编译安装
|
|||||||
|
|
||||||
<p float="left">
|
<p float="left">
|
||||||
<img src="./art/13.jpg" width="200" />
|
<img src="./art/13.jpg" width="200" />
|
||||||
|
<img src="./art/8.jpg" width="200" />
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
### 尚未完成的功能
|
## [更新记录](./CHANGELOG.md)
|
||||||
>* 修改用户名密码
|
|
||||||
>* 两步验证
|
|
||||||
|
### 不支持的功能
|
||||||
>* 应用设置
|
>* 应用设置
|
||||||
>* 通知设置
|
>* 通知设置
|
||||||
>* 脚本管理中的增删改和调试
|
|
||||||
|
|
||||||
|
版本更新通知 https://t.me/qinglongapp
|
||||||
|
|
||||||
|
用于生成app的图标
|
||||||
|
|
||||||
|
flutter pub run flutter_launcher_icons:main
|
||||||
|
生成原生的启动页面
|
||||||
|
|
||||||
|
flutter pub run flutter_native_splash:create
|
||||||
|
修改app名称
|
||||||
|
|
||||||
|
flutter pub run flutter_app_name
|
||||||
|
|
||||||
|
生成json.jc.dart文件
|
||||||
|
flutter pub run build_runner build --delete-conflicting-outputs
|
||||||
|
|
||||||
|
|||||||
@@ -42,19 +42,35 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||||
applicationId "work.master.qinglongapp"
|
applicationId "work.master.qinglongapp"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion flutter.targetSdkVersion
|
targetSdkVersion flutter.targetSdkVersion
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
|
ndk {
|
||||||
|
abiFilters 'armeabi-v7a', 'arm64-v8a'
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
signingConfigs {
|
||||||
|
|
||||||
|
release {
|
||||||
|
storeFile file("qinglong.keystore")
|
||||||
|
storePassword "jiangyuesong"
|
||||||
|
keyAlias "jiangyuesong"
|
||||||
|
keyPassword "jiangyuesong"
|
||||||
|
|
||||||
|
// Optional, specify signing versions used
|
||||||
|
v1SigningEnabled true
|
||||||
|
v2SigningEnabled true
|
||||||
|
}
|
||||||
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
signingConfig signingConfigs.release
|
||||||
signingConfig signingConfigs.debug
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
flutter {
|
flutter {
|
||||||
|
|||||||
@@ -1,26 +1,18 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="work.master.qinglongapp">
|
package="work.master.qinglongapp">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<queries>
|
|
||||||
<intent>
|
|
||||||
<action android:name="android.intent.action.VIEW" />
|
|
||||||
<data android:scheme="https" />
|
|
||||||
</intent>
|
|
||||||
|
|
||||||
</queries>
|
|
||||||
<application
|
<application
|
||||||
|
android:label="青龙客户端"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher">
|
||||||
android:label="青龙">
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:hardwareAccelerated="true"
|
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:screenOrientation="portrait"
|
|
||||||
android:theme="@style/LaunchTheme"
|
android:theme="@style/LaunchTheme"
|
||||||
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
android:windowSoftInputMode="adjustResize">
|
android:windowSoftInputMode="adjustResize">
|
||||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||||
the Android process has started. This theme is visible to the user
|
the Android process has started. This theme is visible to the user
|
||||||
@@ -28,7 +20,8 @@
|
|||||||
to determine the Window background behind the Flutter UI. -->
|
to determine the Window background behind the Flutter UI. -->
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="io.flutter.embedding.android.NormalTheme"
|
android:name="io.flutter.embedding.android.NormalTheme"
|
||||||
android:resource="@style/NormalTheme" />
|
android:resource="@style/NormalTheme"
|
||||||
|
/>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package work.master.qinglong_app
|
||||||
|
|
||||||
|
import io.flutter.embedding.android.FlutterActivity
|
||||||
|
|
||||||
|
class MainActivity: FlutterActivity() {
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 29 KiB |
18
android/app/src/main/res/values-night-v31/styles.xml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||||
|
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||||
|
<item name="android:forceDarkAllowed">false</item>
|
||||||
|
<item name="android:windowFullscreen">false</item>
|
||||||
|
<item name="android:windowSplashScreenBackground">#000000</item>
|
||||||
|
</style>
|
||||||
|
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||||
|
This theme determines the color of the Android Window while your
|
||||||
|
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||||
|
running.
|
||||||
|
|
||||||
|
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||||
|
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||||
|
<item name="android:windowBackground">?android:colorBackground</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
<!-- Show a splash screen on the activity. Automatically removed when
|
<!-- Show a splash screen on the activity. Automatically removed when
|
||||||
Flutter draws its first frame -->
|
Flutter draws its first frame -->
|
||||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
|
<item name="android:forceDarkAllowed">false</item>
|
||||||
<item name="android:windowFullscreen">false</item>
|
<item name="android:windowFullscreen">false</item>
|
||||||
</style>
|
</style>
|
||||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||||
|
|||||||
18
android/app/src/main/res/values-v31/styles.xml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||||
|
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||||
|
<item name="android:forceDarkAllowed">false</item>
|
||||||
|
<item name="android:windowFullscreen">false</item>
|
||||||
|
<item name="android:windowSplashScreenBackground">#ffffff</item>
|
||||||
|
</style>
|
||||||
|
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||||
|
This theme determines the color of the Android Window while your
|
||||||
|
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||||
|
running.
|
||||||
|
|
||||||
|
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||||
|
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||||
|
<item name="android:windowBackground">?android:colorBackground</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
<!-- Show a splash screen on the activity. Automatically removed when
|
<!-- Show a splash screen on the activity. Automatically removed when
|
||||||
Flutter draws its first frame -->
|
Flutter draws its first frame -->
|
||||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
|
<item name="android:forceDarkAllowed">false</item>
|
||||||
<item name="android:windowFullscreen">false</item>
|
<item name="android:windowFullscreen">false</item>
|
||||||
</style>
|
</style>
|
||||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.3.50'
|
ext.kotlin_version = '1.6.10'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|||||||
BIN
apk/app-release-v1.0.6.apk
Normal file
BIN
apk/app-release-v1.0.8.apk
Normal file
BIN
art/14.jpg
Normal file
|
After Width: | Height: | Size: 168 KiB |
BIN
assets/images/chun.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
assets/images/kuai.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
assets/images/le.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 18 KiB |
BIN
assets/images/ql_splash.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
assets/images/ql_white.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
assets/images/update_bg_app_top.png
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
assets/images/update_ic_close.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
assets/images/xin.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
34
ios/.gitignore
vendored
@@ -1,34 +0,0 @@
|
|||||||
**/dgph
|
|
||||||
*.mode1v3
|
|
||||||
*.mode2v3
|
|
||||||
*.moved-aside
|
|
||||||
*.pbxuser
|
|
||||||
*.perspectivev3
|
|
||||||
**/*sync/
|
|
||||||
.sconsign.dblite
|
|
||||||
.tags*
|
|
||||||
**/.vagrant/
|
|
||||||
**/DerivedData/
|
|
||||||
Icon?
|
|
||||||
**/Pods/
|
|
||||||
**/.symlinks/
|
|
||||||
profile
|
|
||||||
xcuserdata
|
|
||||||
**/.generated/
|
|
||||||
Flutter/App.framework
|
|
||||||
Flutter/Flutter.framework
|
|
||||||
Flutter/Flutter.podspec
|
|
||||||
Flutter/Generated.xcconfig
|
|
||||||
Flutter/ephemeral/
|
|
||||||
Flutter/app.flx
|
|
||||||
Flutter/app.zip
|
|
||||||
Flutter/flutter_assets/
|
|
||||||
Flutter/flutter_export_environment.sh
|
|
||||||
ServiceDefinitions.json
|
|
||||||
Runner/GeneratedPluginRegistrant.*
|
|
||||||
|
|
||||||
# Exceptions to above rules.
|
|
||||||
!default.mode1v3
|
|
||||||
!default.mode2v3
|
|
||||||
!default.pbxuser
|
|
||||||
!default.perspectivev3
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
|
||||||
<string>en</string>
|
|
||||||
<key>CFBundleExecutable</key>
|
|
||||||
<string>App</string>
|
|
||||||
<key>CFBundleIdentifier</key>
|
|
||||||
<string>io.flutter.flutter.app</string>
|
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
|
||||||
<string>6.0</string>
|
|
||||||
<key>CFBundleName</key>
|
|
||||||
<string>App</string>
|
|
||||||
<key>CFBundlePackageType</key>
|
|
||||||
<string>FMWK</string>
|
|
||||||
<key>CFBundleShortVersionString</key>
|
|
||||||
<string>1.0</string>
|
|
||||||
<key>CFBundleSignature</key>
|
|
||||||
<string>????</string>
|
|
||||||
<key>CFBundleVersion</key>
|
|
||||||
<string>1.0</string>
|
|
||||||
<key>MinimumOSVersion</key>
|
|
||||||
<string>9.0</string>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
|
||||||
#include "Generated.xcconfig"
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
|
||||||
#include "Generated.xcconfig"
|
|
||||||
41
ios/Podfile
@@ -1,41 +0,0 @@
|
|||||||
# Uncomment this line to define a global platform for your project
|
|
||||||
# platform :ios, '9.0'
|
|
||||||
|
|
||||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
|
||||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
|
||||||
platform :ios, '9.0'
|
|
||||||
project 'Runner', {
|
|
||||||
'Debug' => :debug,
|
|
||||||
'Profile' => :release,
|
|
||||||
'Release' => :release,
|
|
||||||
}
|
|
||||||
|
|
||||||
def flutter_root
|
|
||||||
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
|
|
||||||
unless File.exist?(generated_xcode_build_settings_path)
|
|
||||||
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
|
|
||||||
end
|
|
||||||
|
|
||||||
File.foreach(generated_xcode_build_settings_path) do |line|
|
|
||||||
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
|
||||||
return matches[1].strip if matches
|
|
||||||
end
|
|
||||||
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
|
|
||||||
end
|
|
||||||
|
|
||||||
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
|
||||||
|
|
||||||
flutter_ios_podfile_setup
|
|
||||||
|
|
||||||
target 'Runner' do
|
|
||||||
use_frameworks!
|
|
||||||
use_modular_headers!
|
|
||||||
|
|
||||||
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
|
||||||
end
|
|
||||||
|
|
||||||
post_install do |installer|
|
|
||||||
installer.pods_project.targets.each do |target|
|
|
||||||
flutter_additional_ios_build_settings(target)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
PODS:
|
|
||||||
- Flutter (1.0.0)
|
|
||||||
- fluttertoast (0.0.2):
|
|
||||||
- Flutter
|
|
||||||
- Toast
|
|
||||||
- move_to_background (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- shared_preferences_ios (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- Toast (4.0.0)
|
|
||||||
|
|
||||||
DEPENDENCIES:
|
|
||||||
- Flutter (from `Flutter`)
|
|
||||||
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
|
||||||
- move_to_background (from `.symlinks/plugins/move_to_background/ios`)
|
|
||||||
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
|
|
||||||
|
|
||||||
SPEC REPOS:
|
|
||||||
trunk:
|
|
||||||
- Toast
|
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
|
||||||
Flutter:
|
|
||||||
:path: Flutter
|
|
||||||
fluttertoast:
|
|
||||||
:path: ".symlinks/plugins/fluttertoast/ios"
|
|
||||||
move_to_background:
|
|
||||||
:path: ".symlinks/plugins/move_to_background/ios"
|
|
||||||
shared_preferences_ios:
|
|
||||||
:path: ".symlinks/plugins/shared_preferences_ios/ios"
|
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
|
||||||
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
|
||||||
fluttertoast: 6122fa75143e992b1d3470f61000f591a798cc58
|
|
||||||
move_to_background: 39a5b79b26d577b0372cbe8a8c55e7aa9fcd3a2d
|
|
||||||
shared_preferences_ios: aef470a42dc4675a1cdd50e3158b42e3d1232b32
|
|
||||||
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
|
|
||||||
|
|
||||||
PODFILE CHECKSUM: aea2ed8a4b05dec076f6f7cea39202b1133ed51c
|
|
||||||
|
|
||||||
COCOAPODS: 1.11.2
|
|
||||||
@@ -1,557 +0,0 @@
|
|||||||
// !$*UTF8*$!
|
|
||||||
{
|
|
||||||
archiveVersion = 1;
|
|
||||||
classes = {
|
|
||||||
};
|
|
||||||
objectVersion = 51;
|
|
||||||
objects = {
|
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
|
||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
|
||||||
2E5B253B8F6E332504CD094A /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8A94003E0C6A5209401E856 /* Pods_Runner.framework */; };
|
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
|
||||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
|
||||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
|
||||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
|
||||||
/* End PBXBuildFile section */
|
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
|
||||||
isa = PBXCopyFilesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
dstPath = "";
|
|
||||||
dstSubfolderSpec = 10;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
name = "Embed Frameworks";
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXCopyFilesBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
|
||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
|
||||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
|
||||||
6FAEBE56016E57C6396F6C5D /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
|
||||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
|
||||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
|
||||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
|
||||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
|
||||||
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
|
||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
|
||||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
|
||||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
|
||||||
B72F12A63B85459532204337 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
BE9194DCED1166C78BAC3036 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
D8A94003E0C6A5209401E856 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
/* End PBXFileReference section */
|
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
|
||||||
isa = PBXFrameworksBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
2E5B253B8F6E332504CD094A /* Pods_Runner.framework in Frameworks */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXFrameworksBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
|
||||||
2CC5BF901E47A28826DC8B92 /* Pods */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
6FAEBE56016E57C6396F6C5D /* Pods-Runner.debug.xcconfig */,
|
|
||||||
B72F12A63B85459532204337 /* Pods-Runner.release.xcconfig */,
|
|
||||||
BE9194DCED1166C78BAC3036 /* Pods-Runner.profile.xcconfig */,
|
|
||||||
);
|
|
||||||
path = Pods;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
6AC682C528FC3A77A86CCA78 /* Frameworks */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D8A94003E0C6A5209401E856 /* Pods_Runner.framework */,
|
|
||||||
);
|
|
||||||
name = Frameworks;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
|
||||||
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
|
||||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
|
||||||
9740EEB31CF90195004384FC /* Generated.xcconfig */,
|
|
||||||
);
|
|
||||||
name = Flutter;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
97C146E51CF9000F007C117D = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
9740EEB11CF90186004384FC /* Flutter */,
|
|
||||||
97C146F01CF9000F007C117D /* Runner */,
|
|
||||||
97C146EF1CF9000F007C117D /* Products */,
|
|
||||||
2CC5BF901E47A28826DC8B92 /* Pods */,
|
|
||||||
6AC682C528FC3A77A86CCA78 /* Frameworks */,
|
|
||||||
);
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
97C146EF1CF9000F007C117D /* Products */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
|
||||||
);
|
|
||||||
name = Products;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
97C146F01CF9000F007C117D /* Runner */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
|
||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
|
||||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
|
||||||
97C147021CF9000F007C117D /* Info.plist */,
|
|
||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
|
|
||||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
|
||||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
|
|
||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
|
|
||||||
);
|
|
||||||
path = Runner;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
/* End PBXGroup section */
|
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
|
||||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
|
||||||
isa = PBXNativeTarget;
|
|
||||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
|
||||||
buildPhases = (
|
|
||||||
8CB7F14EC4C8F4D08BD21907 /* [CP] Check Pods Manifest.lock */,
|
|
||||||
9740EEB61CF901F6004384FC /* Run Script */,
|
|
||||||
97C146EA1CF9000F007C117D /* Sources */,
|
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
|
||||||
97C146EC1CF9000F007C117D /* Resources */,
|
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
|
||||||
8939D68CBA57A50D249AF20A /* [CP] Embed Pods Frameworks */,
|
|
||||||
);
|
|
||||||
buildRules = (
|
|
||||||
);
|
|
||||||
dependencies = (
|
|
||||||
);
|
|
||||||
name = Runner;
|
|
||||||
productName = Runner;
|
|
||||||
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
|
|
||||||
productType = "com.apple.product-type.application";
|
|
||||||
};
|
|
||||||
/* End PBXNativeTarget section */
|
|
||||||
|
|
||||||
/* Begin PBXProject section */
|
|
||||||
97C146E61CF9000F007C117D /* Project object */ = {
|
|
||||||
isa = PBXProject;
|
|
||||||
attributes = {
|
|
||||||
LastUpgradeCheck = 1300;
|
|
||||||
ORGANIZATIONNAME = "";
|
|
||||||
TargetAttributes = {
|
|
||||||
97C146ED1CF9000F007C117D = {
|
|
||||||
CreatedOnToolsVersion = 7.3.1;
|
|
||||||
LastSwiftMigration = 1100;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
|
||||||
compatibilityVersion = "Xcode 9.3";
|
|
||||||
developmentRegion = en;
|
|
||||||
hasScannedForEncodings = 0;
|
|
||||||
knownRegions = (
|
|
||||||
en,
|
|
||||||
Base,
|
|
||||||
);
|
|
||||||
mainGroup = 97C146E51CF9000F007C117D;
|
|
||||||
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
|
|
||||||
projectDirPath = "";
|
|
||||||
projectRoot = "";
|
|
||||||
targets = (
|
|
||||||
97C146ED1CF9000F007C117D /* Runner */,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
/* End PBXProject section */
|
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
|
||||||
97C146EC1CF9000F007C117D /* Resources */ = {
|
|
||||||
isa = PBXResourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
|
||||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
|
||||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXResourcesBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "Thin Binary";
|
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
|
||||||
};
|
|
||||||
8939D68CBA57A50D249AF20A /* [CP] Embed Pods Frameworks */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputFileListPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
|
||||||
);
|
|
||||||
name = "[CP] Embed Pods Frameworks";
|
|
||||||
outputFileListPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
8CB7F14EC4C8F4D08BD21907 /* [CP] Check Pods Manifest.lock */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputFileListPaths = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
|
||||||
"${PODS_ROOT}/Manifest.lock",
|
|
||||||
);
|
|
||||||
name = "[CP] Check Pods Manifest.lock";
|
|
||||||
outputFileListPaths = (
|
|
||||||
);
|
|
||||||
outputPaths = (
|
|
||||||
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "Run Script";
|
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
|
||||||
};
|
|
||||||
/* End PBXShellScriptBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
|
||||||
97C146EA1CF9000F007C117D /* Sources */ = {
|
|
||||||
isa = PBXSourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
|
||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXSourcesBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXVariantGroup section */
|
|
||||||
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
|
||||||
isa = PBXVariantGroup;
|
|
||||||
children = (
|
|
||||||
97C146FB1CF9000F007C117D /* Base */,
|
|
||||||
);
|
|
||||||
name = Main.storyboard;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
|
|
||||||
isa = PBXVariantGroup;
|
|
||||||
children = (
|
|
||||||
97C147001CF9000F007C117D /* Base */,
|
|
||||||
);
|
|
||||||
name = LaunchScreen.storyboard;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
/* End PBXVariantGroup section */
|
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration section */
|
|
||||||
249021D3217E4FDB00AE95B9 /* Profile */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
|
||||||
CLANG_ENABLE_MODULES = YES;
|
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
|
||||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_COMMA = YES;
|
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
|
||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
|
||||||
COPY_PHASE_STRIP = NO;
|
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
|
||||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
|
||||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
|
||||||
PRODUCT_NAME = "";
|
|
||||||
SDKROOT = iphoneos;
|
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
|
||||||
VALIDATE_PRODUCT = YES;
|
|
||||||
};
|
|
||||||
name = Profile;
|
|
||||||
};
|
|
||||||
249021D4217E4FDB00AE95B9 /* Profile */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
|
||||||
CLANG_ENABLE_MODULES = YES;
|
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
|
||||||
DEVELOPMENT_TEAM = MKUK6TT46Z;
|
|
||||||
ENABLE_BITCODE = NO;
|
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
"@executable_path/Frameworks",
|
|
||||||
);
|
|
||||||
MARKETING_VERSION = 1.0;
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = work.master.qinglongApp;
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
|
||||||
SWIFT_VERSION = 5.0;
|
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
|
||||||
};
|
|
||||||
name = Profile;
|
|
||||||
};
|
|
||||||
97C147031CF9000F007C117D /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
|
||||||
CLANG_ENABLE_MODULES = YES;
|
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
|
||||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_COMMA = YES;
|
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
|
||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
|
||||||
COPY_PHASE_STRIP = NO;
|
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
|
||||||
ENABLE_TESTABILITY = YES;
|
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
|
||||||
GCC_DYNAMIC_NO_PIC = NO;
|
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
|
||||||
GCC_OPTIMIZATION_LEVEL = 0;
|
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
|
||||||
"DEBUG=1",
|
|
||||||
"$(inherited)",
|
|
||||||
);
|
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
|
||||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
|
||||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
|
||||||
PRODUCT_NAME = "";
|
|
||||||
SDKROOT = iphoneos;
|
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
97C147041CF9000F007C117D /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
|
||||||
CLANG_ENABLE_MODULES = YES;
|
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
|
||||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_COMMA = YES;
|
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
|
||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
|
||||||
COPY_PHASE_STRIP = NO;
|
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
|
||||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
|
||||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
|
||||||
PRODUCT_NAME = "";
|
|
||||||
SDKROOT = iphoneos;
|
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
|
||||||
SWIFT_COMPILATION_MODE = wholemodule;
|
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
|
||||||
VALIDATE_PRODUCT = YES;
|
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
97C147061CF9000F007C117D /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
|
||||||
CLANG_ENABLE_MODULES = YES;
|
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
|
||||||
DEVELOPMENT_TEAM = MKUK6TT46Z;
|
|
||||||
ENABLE_BITCODE = NO;
|
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
"@executable_path/Frameworks",
|
|
||||||
);
|
|
||||||
MARKETING_VERSION = 1.0;
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = work.master.qinglongApp;
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
|
||||||
SWIFT_VERSION = 5.0;
|
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
97C147071CF9000F007C117D /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
|
||||||
CLANG_ENABLE_MODULES = YES;
|
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
|
||||||
DEVELOPMENT_TEAM = MKUK6TT46Z;
|
|
||||||
ENABLE_BITCODE = NO;
|
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
"@executable_path/Frameworks",
|
|
||||||
);
|
|
||||||
MARKETING_VERSION = 1.0;
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = work.master.qinglongApp;
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
|
||||||
SWIFT_VERSION = 5.0;
|
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
/* End XCBuildConfiguration section */
|
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
|
||||||
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
97C147031CF9000F007C117D /* Debug */,
|
|
||||||
97C147041CF9000F007C117D /* Release */,
|
|
||||||
249021D3217E4FDB00AE95B9 /* Profile */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
defaultConfigurationName = Release;
|
|
||||||
};
|
|
||||||
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
97C147061CF9000F007C117D /* Debug */,
|
|
||||||
97C147071CF9000F007C117D /* Release */,
|
|
||||||
249021D4217E4FDB00AE95B9 /* Profile */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
defaultConfigurationName = Release;
|
|
||||||
};
|
|
||||||
/* End XCConfigurationList section */
|
|
||||||
};
|
|
||||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Workspace
|
|
||||||
version = "1.0">
|
|
||||||
<FileRef
|
|
||||||
location = "self:">
|
|
||||||
</FileRef>
|
|
||||||
</Workspace>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>IDEDidComputeMac32BitWarning</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>PreviewsEnabled</key>
|
|
||||||
<false/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Scheme
|
|
||||||
LastUpgradeVersion = "1320"
|
|
||||||
version = "1.3">
|
|
||||||
<BuildAction
|
|
||||||
parallelizeBuildables = "YES"
|
|
||||||
buildImplicitDependencies = "YES">
|
|
||||||
<BuildActionEntries>
|
|
||||||
<BuildActionEntry
|
|
||||||
buildForTesting = "YES"
|
|
||||||
buildForRunning = "YES"
|
|
||||||
buildForProfiling = "YES"
|
|
||||||
buildForArchiving = "YES"
|
|
||||||
buildForAnalyzing = "YES">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
|
||||||
BuildableName = "Runner.app"
|
|
||||||
BlueprintName = "Runner"
|
|
||||||
ReferencedContainer = "container:Runner.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildActionEntry>
|
|
||||||
</BuildActionEntries>
|
|
||||||
</BuildAction>
|
|
||||||
<TestAction
|
|
||||||
buildConfiguration = "Debug"
|
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
|
||||||
<Testables>
|
|
||||||
</Testables>
|
|
||||||
</TestAction>
|
|
||||||
<LaunchAction
|
|
||||||
buildConfiguration = "Debug"
|
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
||||||
launchStyle = "0"
|
|
||||||
useCustomWorkingDirectory = "NO"
|
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
|
||||||
debugDocumentVersioning = "YES"
|
|
||||||
debugServiceExtension = "internal"
|
|
||||||
allowLocationSimulation = "YES">
|
|
||||||
<BuildableProductRunnable
|
|
||||||
runnableDebuggingMode = "0">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
|
||||||
BuildableName = "Runner.app"
|
|
||||||
BlueprintName = "Runner"
|
|
||||||
ReferencedContainer = "container:Runner.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildableProductRunnable>
|
|
||||||
</LaunchAction>
|
|
||||||
<ProfileAction
|
|
||||||
buildConfiguration = "Release"
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
|
||||||
savedToolIdentifier = ""
|
|
||||||
useCustomWorkingDirectory = "NO"
|
|
||||||
debugDocumentVersioning = "YES">
|
|
||||||
<BuildableProductRunnable
|
|
||||||
runnableDebuggingMode = "0">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
|
||||||
BuildableName = "Runner.app"
|
|
||||||
BlueprintName = "Runner"
|
|
||||||
ReferencedContainer = "container:Runner.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildableProductRunnable>
|
|
||||||
</ProfileAction>
|
|
||||||
<AnalyzeAction
|
|
||||||
buildConfiguration = "Debug">
|
|
||||||
</AnalyzeAction>
|
|
||||||
<ArchiveAction
|
|
||||||
buildConfiguration = "Release"
|
|
||||||
revealArchiveInOrganizer = "YES">
|
|
||||||
</ArchiveAction>
|
|
||||||
</Scheme>
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Scheme
|
|
||||||
LastUpgradeVersion = "1300"
|
|
||||||
version = "1.3">
|
|
||||||
<BuildAction
|
|
||||||
parallelizeBuildables = "YES"
|
|
||||||
buildImplicitDependencies = "YES">
|
|
||||||
<BuildActionEntries>
|
|
||||||
<BuildActionEntry
|
|
||||||
buildForTesting = "YES"
|
|
||||||
buildForRunning = "YES"
|
|
||||||
buildForProfiling = "YES"
|
|
||||||
buildForArchiving = "YES"
|
|
||||||
buildForAnalyzing = "YES">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
|
||||||
BuildableName = "Runner.app"
|
|
||||||
BlueprintName = "Runner"
|
|
||||||
ReferencedContainer = "container:Runner.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildActionEntry>
|
|
||||||
</BuildActionEntries>
|
|
||||||
</BuildAction>
|
|
||||||
<TestAction
|
|
||||||
buildConfiguration = "Debug"
|
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
|
||||||
<MacroExpansion>
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
|
||||||
BuildableName = "Runner.app"
|
|
||||||
BlueprintName = "Runner"
|
|
||||||
ReferencedContainer = "container:Runner.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</MacroExpansion>
|
|
||||||
<Testables>
|
|
||||||
</Testables>
|
|
||||||
</TestAction>
|
|
||||||
<LaunchAction
|
|
||||||
buildConfiguration = "Debug"
|
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
||||||
launchStyle = "0"
|
|
||||||
useCustomWorkingDirectory = "NO"
|
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
|
||||||
debugDocumentVersioning = "YES"
|
|
||||||
debugServiceExtension = "internal"
|
|
||||||
allowLocationSimulation = "YES">
|
|
||||||
<BuildableProductRunnable
|
|
||||||
runnableDebuggingMode = "0">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
|
||||||
BuildableName = "Runner.app"
|
|
||||||
BlueprintName = "Runner"
|
|
||||||
ReferencedContainer = "container:Runner.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildableProductRunnable>
|
|
||||||
</LaunchAction>
|
|
||||||
<ProfileAction
|
|
||||||
buildConfiguration = "Profile"
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
|
||||||
savedToolIdentifier = ""
|
|
||||||
useCustomWorkingDirectory = "NO"
|
|
||||||
debugDocumentVersioning = "YES">
|
|
||||||
<BuildableProductRunnable
|
|
||||||
runnableDebuggingMode = "0">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
|
||||||
BuildableName = "Runner.app"
|
|
||||||
BlueprintName = "Runner"
|
|
||||||
ReferencedContainer = "container:Runner.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildableProductRunnable>
|
|
||||||
</ProfileAction>
|
|
||||||
<AnalyzeAction
|
|
||||||
buildConfiguration = "Debug">
|
|
||||||
</AnalyzeAction>
|
|
||||||
<ArchiveAction
|
|
||||||
buildConfiguration = "Release"
|
|
||||||
revealArchiveInOrganizer = "YES">
|
|
||||||
</ArchiveAction>
|
|
||||||
</Scheme>
|
|
||||||
10
ios/Runner.xcworkspace/contents.xcworkspacedata
generated
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Workspace
|
|
||||||
version = "1.0">
|
|
||||||
<FileRef
|
|
||||||
location = "group:Runner.xcodeproj">
|
|
||||||
</FileRef>
|
|
||||||
<FileRef
|
|
||||||
location = "group:Pods/Pods.xcodeproj">
|
|
||||||
</FileRef>
|
|
||||||
</Workspace>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>IDEDidComputeMac32BitWarning</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>PreviewsEnabled</key>
|
|
||||||
<false/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import UIKit
|
|
||||||
import Flutter
|
|
||||||
|
|
||||||
@UIApplicationMain
|
|
||||||
@objc class AppDelegate: FlutterAppDelegate {
|
|
||||||
override func application(
|
|
||||||
_ application: UIApplication,
|
|
||||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
|
||||||
) -> Bool {
|
|
||||||
GeneratedPluginRegistrant.register(with: self)
|
|
||||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
{
|
|
||||||
"images" : [
|
|
||||||
{
|
|
||||||
"size" : "20x20",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-20x20@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "20x20",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-20x20@3x.png",
|
|
||||||
"scale" : "3x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-29x29@1x.png",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-29x29@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-29x29@3x.png",
|
|
||||||
"scale" : "3x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "40x40",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-40x40@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "40x40",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-40x40@3x.png",
|
|
||||||
"scale" : "3x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "60x60",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-60x60@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "60x60",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-60x60@3x.png",
|
|
||||||
"scale" : "3x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "20x20",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-20x20@1x.png",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "20x20",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-20x20@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-29x29@1x.png",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-29x29@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "40x40",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-40x40@1x.png",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "40x40",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-40x40@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "76x76",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-76x76@1x.png",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "76x76",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-76x76@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "83.5x83.5",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-83.5x83.5@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "1024x1024",
|
|
||||||
"idiom" : "ios-marketing",
|
|
||||||
"filename" : "Icon-App-1024x1024@1x.png",
|
|
||||||
"scale" : "1x"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info" : {
|
|
||||||
"version" : 1,
|
|
||||||
"author" : "xcode"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 62 KiB |
@@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"images" : [
|
|
||||||
{
|
|
||||||
"filename" : "BrandingImage.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename" : "BrandingImage@2x.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename" : "BrandingImage@3x.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "3x"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info" : {
|
|
||||||
"author" : "xcode",
|
|
||||||
"version" : 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
{
|
|
||||||
"images" : [
|
|
||||||
{
|
|
||||||
"filename" : "background.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"appearances" : [
|
|
||||||
{
|
|
||||||
"appearance" : "luminosity",
|
|
||||||
"value" : "dark"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename" : "darkbackground.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"appearances" : [
|
|
||||||
{
|
|
||||||
"appearance" : "luminosity",
|
|
||||||
"value" : "dark"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "3x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"appearances" : [
|
|
||||||
{
|
|
||||||
"appearance" : "luminosity",
|
|
||||||
"value" : "dark"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "3x"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info" : {
|
|
||||||
"author" : "xcode",
|
|
||||||
"version" : 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 68 B |
|
Before Width: | Height: | Size: 70 B |
@@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"images" : [
|
|
||||||
{
|
|
||||||
"filename" : "LaunchImage.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename" : "LaunchImage@2x.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename" : "LaunchImage@3x.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "3x"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info" : {
|
|
||||||
"author" : "xcode",
|
|
||||||
"version" : 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 71 KiB |
@@ -1,5 +0,0 @@
|
|||||||
# Launch Screen Assets
|
|
||||||
|
|
||||||
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
|
|
||||||
|
|
||||||
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
|
||||||
<dependencies>
|
|
||||||
<deployment identifier="iOS"/>
|
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
|
|
||||||
</dependencies>
|
|
||||||
<scenes>
|
|
||||||
<!--View Controller-->
|
|
||||||
<scene sceneID="EHf-IW-A2E">
|
|
||||||
<objects>
|
|
||||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
|
||||||
<layoutGuides>
|
|
||||||
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
|
|
||||||
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
|
|
||||||
</layoutGuides>
|
|
||||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
|
||||||
<subviews>
|
|
||||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" image="LaunchBackground" translatesAutoresizingMaskIntoConstraints="NO" id="tWc-Dq-wcI"/>
|
|
||||||
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4"></imageView>
|
|
||||||
</subviews>
|
|
||||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="3T2-ad-Qdv"/>
|
|
||||||
<constraint firstItem="tWc-Dq-wcI" firstAttribute="bottom" secondItem="Ze5-6b-2t3" secondAttribute="bottom" id="RPx-PI-7Xg"/>
|
|
||||||
<constraint firstItem="tWc-Dq-wcI" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="SdS-ul-q2q"/>
|
|
||||||
<constraint firstAttribute="trailing" secondItem="tWc-Dq-wcI" secondAttribute="trailing" id="Swv-Gf-Rwn"/>
|
|
||||||
<constraint firstAttribute="trailing" secondItem="YRO-k0-Ey4" secondAttribute="trailing" id="TQA-XW-tRk"/>
|
|
||||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="bottom" secondItem="Ze5-6b-2t3" secondAttribute="bottom" id="duK-uY-Gun"/>
|
|
||||||
<constraint firstItem="tWc-Dq-wcI" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="kV7-tw-vXt"/>
|
|
||||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="xPn-NY-SIU"/>
|
|
||||||
</constraints>
|
|
||||||
</view>
|
|
||||||
</viewController>
|
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
|
||||||
</objects>
|
|
||||||
<point key="canvasLocation" x="53" y="375"/>
|
|
||||||
</scene>
|
|
||||||
</scenes>
|
|
||||||
<resources>
|
|
||||||
<image name="LaunchImage" width="240" height="240"/>
|
|
||||||
<image name="LaunchBackground" width="1" height="1"/>
|
|
||||||
</resources>
|
|
||||||
</document>
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
|
|
||||||
<dependencies>
|
|
||||||
<deployment identifier="iOS"/>
|
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
|
||||||
</dependencies>
|
|
||||||
<scenes>
|
|
||||||
<!--Flutter View Controller-->
|
|
||||||
<scene sceneID="tne-QT-ifu">
|
|
||||||
<objects>
|
|
||||||
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
|
|
||||||
<layoutGuides>
|
|
||||||
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
|
||||||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
|
||||||
</layoutGuides>
|
|
||||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
|
||||||
</view>
|
|
||||||
</viewController>
|
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
|
||||||
</objects>
|
|
||||||
</scene>
|
|
||||||
</scenes>
|
|
||||||
</document>
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
|
||||||
<key>CFBundleDisplayName</key>
|
|
||||||
<string>青龙</string>
|
|
||||||
<key>CFBundleExecutable</key>
|
|
||||||
<string>$(EXECUTABLE_NAME)</string>
|
|
||||||
<key>CFBundleIdentifier</key>
|
|
||||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
|
||||||
<string>6.0</string>
|
|
||||||
<key>CFBundleName</key>
|
|
||||||
<string>青龙</string>
|
|
||||||
<key>CFBundlePackageType</key>
|
|
||||||
<string>APPL</string>
|
|
||||||
<key>CFBundleShortVersionString</key>
|
|
||||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
|
||||||
<key>CFBundleSignature</key>
|
|
||||||
<string>????</string>
|
|
||||||
<key>CFBundleVersion</key>
|
|
||||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
|
||||||
<key>LSRequiresIPhoneOS</key>
|
|
||||||
<true/>
|
|
||||||
<key>UILaunchStoryboardName</key>
|
|
||||||
<string>LaunchScreen</string>
|
|
||||||
<key>UIMainStoryboardFile</key>
|
|
||||||
<string>Main</string>
|
|
||||||
<key>LSApplicationQueriesSchemes</key>
|
|
||||||
<array>
|
|
||||||
<string>https</string>
|
|
||||||
<string>http</string>
|
|
||||||
</array>
|
|
||||||
<key>UISupportedInterfaceOrientations</key>
|
|
||||||
<array>
|
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
|
||||||
</array>
|
|
||||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
|
||||||
<array>
|
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
|
||||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
|
||||||
</array>
|
|
||||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
|
||||||
<false/>
|
|
||||||
<key>UIStatusBarHidden</key>
|
|
||||||
<false/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
#import "GeneratedPluginRegistrant.h"
|
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
import 'package:qinglong_app/base/http/http.dart';
|
import 'package:qinglong_app/base/http/http.dart';
|
||||||
|
import 'package:qinglong_app/base/http/url.dart';
|
||||||
|
import 'package:qinglong_app/main.dart';
|
||||||
import 'package:qinglong_app/module/config/config_bean.dart';
|
import 'package:qinglong_app/module/config/config_bean.dart';
|
||||||
import 'package:qinglong_app/module/env/env_bean.dart';
|
import 'package:qinglong_app/module/env/env_bean.dart';
|
||||||
|
import 'package:qinglong_app/module/home/system_bean.dart';
|
||||||
import 'package:qinglong_app/module/login/login_bean.dart';
|
import 'package:qinglong_app/module/login/login_bean.dart';
|
||||||
import 'package:qinglong_app/module/login/user_bean.dart';
|
import 'package:qinglong_app/module/login/user_bean.dart';
|
||||||
import 'package:qinglong_app/module/others/dependencies/dependency_bean.dart';
|
import 'package:qinglong_app/module/others/dependencies/dependency_bean.dart';
|
||||||
@@ -8,10 +11,16 @@ import 'package:qinglong_app/module/others/login_log/login_log_bean.dart';
|
|||||||
import 'package:qinglong_app/module/others/scripts/script_bean.dart';
|
import 'package:qinglong_app/module/others/scripts/script_bean.dart';
|
||||||
import 'package:qinglong_app/module/others/task_log/task_log_bean.dart';
|
import 'package:qinglong_app/module/others/task_log/task_log_bean.dart';
|
||||||
import 'package:qinglong_app/module/task/task_bean.dart';
|
import 'package:qinglong_app/module/task/task_bean.dart';
|
||||||
|
import 'package:qinglong_app/utils/utils.dart';
|
||||||
import 'url.dart';
|
|
||||||
|
|
||||||
class Api {
|
class Api {
|
||||||
|
static Future<HttpResponse<SystemBean>> system() async {
|
||||||
|
return await Http.get<SystemBean>(
|
||||||
|
Url.system,
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<LoginBean>> login(
|
static Future<HttpResponse<LoginBean>> login(
|
||||||
String userName,
|
String userName,
|
||||||
String passWord,
|
String passWord,
|
||||||
@@ -25,6 +34,19 @@ class Api {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<HttpResponse<LoginBean>> loginOld(
|
||||||
|
String userName,
|
||||||
|
String passWord,
|
||||||
|
) async {
|
||||||
|
return await Http.post<LoginBean>(
|
||||||
|
Url.loginOld,
|
||||||
|
{
|
||||||
|
"username": userName,
|
||||||
|
"password": passWord,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<LoginBean>> loginTwo(
|
static Future<HttpResponse<LoginBean>> loginTwo(
|
||||||
String userName,
|
String userName,
|
||||||
String passWord,
|
String passWord,
|
||||||
@@ -76,7 +98,7 @@ class Api {
|
|||||||
|
|
||||||
static Future<HttpResponse<NullResponse>> stopTasks(List<String> crons) async {
|
static Future<HttpResponse<NullResponse>> stopTasks(List<String> crons) async {
|
||||||
return await Http.put<NullResponse>(
|
return await Http.put<NullResponse>(
|
||||||
Url.runTasks,
|
Url.stopTasks,
|
||||||
crons,
|
crons,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -98,11 +120,21 @@ class Api {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<NullResponse>> addTask(String name, String command, String cron, {String? id}) async {
|
static Future<HttpResponse<NullResponse>> addTask(
|
||||||
var data = {"name": name, "command": command, "schedule": cron};
|
String name,
|
||||||
|
String command,
|
||||||
|
String cron, {
|
||||||
|
int? id,
|
||||||
|
String? nId,
|
||||||
|
}) async {
|
||||||
|
var data = <String, dynamic>{"name": name, "command": command, "schedule": cron};
|
||||||
|
|
||||||
|
if (id != null || nId != null) {
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
data["_id"] = id;
|
data["id"] = id;
|
||||||
|
} else if (nId != null) {
|
||||||
|
data["_id"] = nId;
|
||||||
|
}
|
||||||
return await Http.put<NullResponse>(
|
return await Http.put<NullResponse>(
|
||||||
Url.addTask,
|
Url.addTask,
|
||||||
data,
|
data,
|
||||||
@@ -198,15 +230,25 @@ class Api {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<NullResponse>> addEnv(String name, String value, String remarks, {String? id}) async {
|
static Future<HttpResponse<NullResponse>> addEnv(
|
||||||
var data = {
|
String name,
|
||||||
|
String value,
|
||||||
|
String remarks, {
|
||||||
|
int? id,
|
||||||
|
String? nId,
|
||||||
|
}) async {
|
||||||
|
var data = <String, dynamic>{
|
||||||
"value": value,
|
"value": value,
|
||||||
"remarks": remarks,
|
"remarks": remarks,
|
||||||
"name": name,
|
"name": name,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (id != null || nId != null) {
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
data["_id"] = id;
|
data["id"] = id;
|
||||||
|
} else if (nId != null) {
|
||||||
|
data["_id"] = nId;
|
||||||
|
}
|
||||||
return await Http.put<NullResponse>(
|
return await Http.put<NullResponse>(
|
||||||
Url.addEnv,
|
Url.addEnv,
|
||||||
data,
|
data,
|
||||||
@@ -233,19 +275,27 @@ class Api {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<List<TaskLogBean>>> taskLog() async {
|
static Future<HttpResponse<List<TaskLogBean>>> taskLog() async {
|
||||||
return await Http.get<List<TaskLogBean>>(Url.taskLog, null, serializationName: "dirs");
|
return await Http.get<List<TaskLogBean>>(Url.taskLog, null, serializationName: Utils.isUpperVersion2_12_2() ? "data" : "dirs");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<String>> taskLogDetail(String name) async {
|
static Future<HttpResponse<String>> taskLogDetail(String name, String path) async {
|
||||||
|
if (Utils.isUpperVersion2_13_0()) {
|
||||||
return await Http.get<String>(
|
return await Http.get<String>(
|
||||||
Url.taskLogDetail + name,
|
Url.taskLogDetail + name + "?path=" + path,
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return await Http.get<String>(
|
||||||
|
Url.taskLogDetail + path + "/" + name,
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<List<ScriptBean>>> scripts() async {
|
static Future<HttpResponse<List<ScriptBean>>> scripts() async {
|
||||||
|
//2.12.2以及以上版本,脚本路径url做了修改
|
||||||
return await Http.get<List<ScriptBean>>(
|
return await Http.get<List<ScriptBean>>(
|
||||||
Url.scripts,
|
Utils.isUpperVersion2_13_0() ? Url.scripts2 : Url.scripts,
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -315,6 +365,17 @@ class Api {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<HttpResponse<NullResponse>> addScript(String name, String path, String content) async {
|
||||||
|
return await Http.post<NullResponse>(
|
||||||
|
Url.addScript,
|
||||||
|
{
|
||||||
|
"filename": name,
|
||||||
|
"path": path,
|
||||||
|
"content": content,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<NullResponse>> delDependency(String id) async {
|
static Future<HttpResponse<NullResponse>> delDependency(String id) async {
|
||||||
return await Http.delete<NullResponse>(
|
return await Http.delete<NullResponse>(
|
||||||
Url.dependencies,
|
Url.dependencies,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:dio/dio.dart';
|
|||||||
import 'package:dio_log/dio_log.dart';
|
import 'package:dio_log/dio_log.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:qinglong_app/base/http/token_interceptor.dart';
|
import 'package:qinglong_app/base/http/token_interceptor.dart';
|
||||||
|
import 'package:qinglong_app/base/http/url.dart';
|
||||||
import 'package:qinglong_app/base/userinfo_viewmodel.dart';
|
import 'package:qinglong_app/base/userinfo_viewmodel.dart';
|
||||||
import 'package:qinglong_app/utils/extension.dart';
|
import 'package:qinglong_app/utils/extension.dart';
|
||||||
|
|
||||||
@@ -54,7 +55,7 @@ class Http {
|
|||||||
|
|
||||||
return decodeResponse<T>(response, serializationName, compute);
|
return decodeResponse<T>(response, serializationName, compute);
|
||||||
} on DioError catch (e) {
|
} on DioError catch (e) {
|
||||||
return exceptionHandler<T>(e);
|
return exceptionHandler<T>(e, uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +75,7 @@ class Http {
|
|||||||
compute,
|
compute,
|
||||||
);
|
);
|
||||||
} on DioError catch (e) {
|
} on DioError catch (e) {
|
||||||
return exceptionHandler<T>(e);
|
return exceptionHandler<T>(e, uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +95,7 @@ class Http {
|
|||||||
compute,
|
compute,
|
||||||
);
|
);
|
||||||
} on DioError catch (e) {
|
} on DioError catch (e) {
|
||||||
return exceptionHandler<T>(e);
|
return exceptionHandler<T>(e, uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +114,7 @@ class Http {
|
|||||||
compute,
|
compute,
|
||||||
);
|
);
|
||||||
} on DioError catch (e) {
|
} on DioError catch (e) {
|
||||||
return exceptionHandler<T>(e);
|
return exceptionHandler<T>(e, uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,8 +126,9 @@ class Http {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static HttpResponse<T> exceptionHandler<T>(DioError e) {
|
static HttpResponse<T> exceptionHandler<T>(DioError e, String path) {
|
||||||
if (e.response?.statusCode == 401) {
|
logger.e(e);
|
||||||
|
if (e.response?.statusCode == 401 && !Url.inWhiteList(path)) {
|
||||||
if (!getIt<UserInfoViewModel>().useSecretLogined) {
|
if (!getIt<UserInfoViewModel>().useSecretLogined) {
|
||||||
exitLogin();
|
exitLogin();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,18 +7,22 @@ import '../userinfo_viewmodel.dart';
|
|||||||
class TokenInterceptor extends Interceptor {
|
class TokenInterceptor extends Interceptor {
|
||||||
@override
|
@override
|
||||||
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
||||||
|
options.headers["User-Agent"] =
|
||||||
|
"qinglong_client";
|
||||||
|
|
||||||
|
options.headers["Content-Type"] = "application/json;charset=UTF-8";
|
||||||
|
|
||||||
|
if (!Url.inWhiteList(options.path)) {
|
||||||
|
options.queryParameters["t"] =
|
||||||
|
(DateTime.now().millisecondsSinceEpoch ~/ 1000).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Url.inLoginList(options.path)) {
|
||||||
if (getIt<UserInfoViewModel>().token != null &&
|
if (getIt<UserInfoViewModel>().token != null &&
|
||||||
getIt<UserInfoViewModel>().token!.isNotEmpty) {
|
getIt<UserInfoViewModel>().token!.isNotEmpty) {
|
||||||
options.headers["Authorization"] =
|
options.headers["Authorization"] =
|
||||||
"Bearer " + getIt<UserInfoViewModel>().token!;
|
"Bearer " + getIt<UserInfoViewModel>().token!;
|
||||||
}
|
}
|
||||||
|
|
||||||
options.headers["User-Agent"] = "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1";
|
|
||||||
|
|
||||||
options.headers["Content-Type"] = "application/json;charset=UTF-8";
|
|
||||||
if (options.path != Url.loginByClientId && options.path!= Url.loginTwo) {
|
|
||||||
options.queryParameters["t"] =
|
|
||||||
(DateTime.now().millisecondsSinceEpoch ~/ 1000).toString();
|
|
||||||
}
|
}
|
||||||
return handler.next(options);
|
return handler.next(options);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
import '../../main.dart';
|
import 'package:qinglong_app/base/userinfo_viewmodel.dart';
|
||||||
import '../userinfo_viewmodel.dart';
|
import 'package:qinglong_app/main.dart';
|
||||||
|
|
||||||
class Url {
|
class Url {
|
||||||
static get login => "/api/user/login";
|
static get login => "/api/user/login";
|
||||||
|
|
||||||
|
static get system => "/api/system";
|
||||||
|
|
||||||
|
static get loginOld => "/api/login";
|
||||||
|
|
||||||
static get loginTwo => "/api/user/two-factor/login";
|
static get loginTwo => "/api/user/two-factor/login";
|
||||||
static const loginByClientId = "/open/auth/token";
|
static const loginByClientId = "/open/auth/token";
|
||||||
static const user = "/api/user";
|
static const user = "/api/user";
|
||||||
@@ -50,17 +55,19 @@ class Url {
|
|||||||
static get taskLogDetail => getIt<UserInfoViewModel>().useSecretLogined ? "/open/logs/" : "/api/logs/";
|
static get taskLogDetail => getIt<UserInfoViewModel>().useSecretLogined ? "/open/logs/" : "/api/logs/";
|
||||||
|
|
||||||
static get scripts => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts/files" : "/api/scripts/files";
|
static get scripts => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts/files" : "/api/scripts/files";
|
||||||
|
|
||||||
|
static get scripts2 => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts" : "/api/scripts";
|
||||||
|
|
||||||
static get scriptUpdate => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts" : "/api/scripts";
|
static get scriptUpdate => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts" : "/api/scripts";
|
||||||
|
|
||||||
static get scriptDetail => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts/" : "/api/scripts/";
|
static get scriptDetail => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts/" : "/api/scripts/";
|
||||||
|
|
||||||
static get dependencies => getIt<UserInfoViewModel>().useSecretLogined ? "/open/dependencies" : "/api/dependencies";
|
static get dependencies => getIt<UserInfoViewModel>().useSecretLogined ? "/open/dependencies" : "/api/dependencies";
|
||||||
|
|
||||||
|
static get addScript => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts" : "/api/scripts";
|
||||||
|
|
||||||
static get dependencyReinstall => getIt<UserInfoViewModel>().useSecretLogined ? "/open/dependencies/reinstall" : "/api/dependencies/reinstall";
|
static get dependencyReinstall => getIt<UserInfoViewModel>().useSecretLogined ? "/open/dependencies/reinstall" : "/api/dependencies/reinstall";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static intimeLog(String cronId) {
|
static intimeLog(String cronId) {
|
||||||
return getIt<UserInfoViewModel>().useSecretLogined ? "/open/crons/$cronId/log" : "/api/crons/$cronId/log";
|
return getIt<UserInfoViewModel>().useSecretLogined ? "/open/crons/$cronId/log" : "/api/crons/$cronId/log";
|
||||||
}
|
}
|
||||||
@@ -68,4 +75,18 @@ class Url {
|
|||||||
static envMove(String envId) {
|
static envMove(String envId) {
|
||||||
return getIt<UserInfoViewModel>().useSecretLogined ? "/open/envs/$envId/move" : "/api/envs/$envId/move";
|
return getIt<UserInfoViewModel>().useSecretLogined ? "/open/envs/$envId/move" : "/api/envs/$envId/move";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool inWhiteList(String path) {
|
||||||
|
if (path == login || path == loginByClientId || path == loginTwo || path == loginOld) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool inLoginList(String path) {
|
||||||
|
if (path == login || path == loginByClientId || path == loginOld) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import 'package:qinglong_app/module/others/scripts/script_edit_page.dart';
|
|||||||
import 'package:qinglong_app/module/others/scripts/script_page.dart';
|
import 'package:qinglong_app/module/others/scripts/script_page.dart';
|
||||||
import 'package:qinglong_app/module/others/task_log/task_log_detail_page.dart';
|
import 'package:qinglong_app/module/others/task_log/task_log_detail_page.dart';
|
||||||
import 'package:qinglong_app/module/others/task_log/task_log_page.dart';
|
import 'package:qinglong_app/module/others/task_log/task_log_page.dart';
|
||||||
|
import 'package:qinglong_app/module/others/theme_page.dart';
|
||||||
import 'package:qinglong_app/module/others/update_password_page.dart';
|
import 'package:qinglong_app/module/others/update_password_page.dart';
|
||||||
import 'package:qinglong_app/module/task/add_task_page.dart';
|
import 'package:qinglong_app/module/task/add_task_page.dart';
|
||||||
import 'package:qinglong_app/module/task/task_bean.dart';
|
import 'package:qinglong_app/module/task/task_bean.dart';
|
||||||
@@ -39,13 +40,22 @@ class Routes {
|
|||||||
static const String routeDependency = "/Dependency";
|
static const String routeDependency = "/Dependency";
|
||||||
static const String routeUpdatePassword = "/updatePassword";
|
static const String routeUpdatePassword = "/updatePassword";
|
||||||
static const String routeAbout = "/about";
|
static const String routeAbout = "/about";
|
||||||
|
static const String routeTheme = "/theme";
|
||||||
|
|
||||||
static Route<dynamic>? generateRoute(RouteSettings settings) {
|
static Route<dynamic>? generateRoute(RouteSettings settings) {
|
||||||
switch (settings.name) {
|
switch (settings.name) {
|
||||||
case routeHomePage:
|
case routeHomePage:
|
||||||
return MaterialPageRoute(builder: (context) => const HomePage());
|
return MaterialPageRoute(builder: (context) => const HomePage());
|
||||||
case routeLogin:
|
case routeLogin:
|
||||||
|
if (settings.arguments != null) {
|
||||||
|
return MaterialPageRoute(
|
||||||
|
builder: (context) => const LoginPage(
|
||||||
|
doNotLoadLocalData: true,
|
||||||
|
));
|
||||||
|
} else {
|
||||||
return MaterialPageRoute(builder: (context) => const LoginPage());
|
return MaterialPageRoute(builder: (context) => const LoginPage());
|
||||||
|
}
|
||||||
|
|
||||||
case routeAddTask:
|
case routeAddTask:
|
||||||
if (settings.arguments != null) {
|
if (settings.arguments != null) {
|
||||||
return CupertinoPageRoute(
|
return CupertinoPageRoute(
|
||||||
@@ -56,7 +66,8 @@ class Routes {
|
|||||||
return CupertinoPageRoute(builder: (context) => const AddTaskPage());
|
return CupertinoPageRoute(builder: (context) => const AddTaskPage());
|
||||||
}
|
}
|
||||||
case routeAddDependency:
|
case routeAddDependency:
|
||||||
return CupertinoPageRoute(builder: (context) => const AddDependencyPage());
|
return CupertinoPageRoute(
|
||||||
|
builder: (context) => const AddDependencyPage());
|
||||||
case routeAddEnv:
|
case routeAddEnv:
|
||||||
if (settings.arguments != null) {
|
if (settings.arguments != null) {
|
||||||
return CupertinoPageRoute(
|
return CupertinoPageRoute(
|
||||||
@@ -92,7 +103,8 @@ class Routes {
|
|||||||
case routeTaskLogDetail:
|
case routeTaskLogDetail:
|
||||||
return CupertinoPageRoute(
|
return CupertinoPageRoute(
|
||||||
builder: (context) => TaskLogDetailPage(
|
builder: (context) => TaskLogDetailPage(
|
||||||
title: settings.arguments as String,
|
title: (settings.arguments as Map)['title'],
|
||||||
|
path: (settings.arguments as Map)['path'],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
case routeScriptDetail:
|
case routeScriptDetail:
|
||||||
@@ -122,6 +134,10 @@ class Routes {
|
|||||||
return CupertinoPageRoute(
|
return CupertinoPageRoute(
|
||||||
builder: (context) => const AboutPage(),
|
builder: (context) => const AboutPage(),
|
||||||
);
|
);
|
||||||
|
case routeTheme:
|
||||||
|
return CupertinoPageRoute(
|
||||||
|
builder: (context) => const ThemePage(),
|
||||||
|
);
|
||||||
case routeScriptUpdate:
|
case routeScriptUpdate:
|
||||||
return CupertinoPageRoute(
|
return CupertinoPageRoute(
|
||||||
builder: (context) => ScriptEditPage(
|
builder: (context) => ScriptEditPage(
|
||||||
|
|||||||
@@ -4,3 +4,5 @@ String spUserName = "username";
|
|||||||
String spPassWord = "password";
|
String spPassWord = "password";
|
||||||
String spTheme = "dart_mode";
|
String spTheme = "dart_mode";
|
||||||
String spSecretLogined = "secret_logined";
|
String spSecretLogined = "secret_logined";
|
||||||
|
String spCustomColor = "customColor";
|
||||||
|
String spLoginHistory = "loginHistory";
|
||||||
|
|||||||
@@ -3,21 +3,27 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:qinglong_app/base/sp_const.dart';
|
import 'package:qinglong_app/base/sp_const.dart';
|
||||||
|
import 'package:qinglong_app/base/userinfo_viewmodel.dart';
|
||||||
|
import 'package:qinglong_app/main.dart';
|
||||||
import 'package:qinglong_app/utils/codeeditor_theme.dart';
|
import 'package:qinglong_app/utils/codeeditor_theme.dart';
|
||||||
import 'package:qinglong_app/utils/sp_utils.dart';
|
import 'package:qinglong_app/utils/sp_utils.dart';
|
||||||
|
|
||||||
var themeProvider = ChangeNotifierProvider((ref) => ThemeViewModel());
|
var themeProvider = ChangeNotifierProvider((ref) => ThemeViewModel());
|
||||||
const Color _primaryColor = Color(0xFF299343);
|
|
||||||
|
|
||||||
get primaryColor => _primaryColor;
|
Color commonColor = const Color(0xFF299343);
|
||||||
|
Color _primaryColor = commonColor;
|
||||||
|
|
||||||
class ThemeViewModel extends ChangeNotifier {
|
class ThemeViewModel extends ChangeNotifier {
|
||||||
ThemeData currentTheme = lightTheme;
|
late ThemeData currentTheme;
|
||||||
|
|
||||||
bool _isInDarkMode = false;
|
bool _isInDarkMode = false;
|
||||||
|
Color primaryColor = commonColor;
|
||||||
|
|
||||||
ThemeColors themeColor = LightThemeColors();
|
ThemeColors themeColor = LightThemeColors();
|
||||||
|
|
||||||
ThemeViewModel() {
|
ThemeViewModel() {
|
||||||
|
_primaryColor = Color(getIt<UserInfoViewModel>().primaryColor);
|
||||||
|
primaryColor = Color(getIt<UserInfoViewModel>().primaryColor);
|
||||||
var brightness = SchedulerBinding.instance!.window.platformBrightness;
|
var brightness = SchedulerBinding.instance!.window.platformBrightness;
|
||||||
_isInDarkMode = brightness == Brightness.dark;
|
_isInDarkMode = brightness == Brightness.dark;
|
||||||
changeThemeReal(_isInDarkMode, false);
|
changeThemeReal(_isInDarkMode, false);
|
||||||
@@ -31,10 +37,10 @@ class ThemeViewModel extends ChangeNotifier {
|
|||||||
_isInDarkMode = dark;
|
_isInDarkMode = dark;
|
||||||
SpUtil.putBool(spTheme, dark);
|
SpUtil.putBool(spTheme, dark);
|
||||||
if (!dark) {
|
if (!dark) {
|
||||||
currentTheme = lightTheme;
|
currentTheme = getLightTheme();
|
||||||
themeColor = LightThemeColors();
|
themeColor = LightThemeColors();
|
||||||
} else {
|
} else {
|
||||||
currentTheme = darkTheme;
|
currentTheme = getDartTheme();
|
||||||
themeColor = DartThemeColors();
|
themeColor = DartThemeColors();
|
||||||
}
|
}
|
||||||
if (notify) {
|
if (notify) {
|
||||||
@@ -44,12 +50,100 @@ class ThemeViewModel extends ChangeNotifier {
|
|||||||
|
|
||||||
get darkMode => _isInDarkMode;
|
get darkMode => _isInDarkMode;
|
||||||
|
|
||||||
|
void changePrimaryColor(Color color) {
|
||||||
|
_primaryColor = color;
|
||||||
|
primaryColor = color;
|
||||||
|
getIt<UserInfoViewModel>().updateCustomColor(color.value);
|
||||||
|
changeThemeReal(SpUtil.getBool(spTheme, defValue: false), true);
|
||||||
|
}
|
||||||
|
|
||||||
void changeTheme() {
|
void changeTheme() {
|
||||||
changeThemeReal(!SpUtil.getBool(spTheme, defValue: false), true);
|
changeThemeReal(!SpUtil.getBool(spTheme, defValue: false), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ThemeData getLightTheme() {
|
||||||
|
return ThemeData.light().copyWith(
|
||||||
|
brightness: Brightness.light,
|
||||||
|
primaryColor: _primaryColor,
|
||||||
|
colorScheme: ColorScheme.light(
|
||||||
|
secondary: _primaryColor,
|
||||||
|
primary: _primaryColor,
|
||||||
|
),
|
||||||
|
scaffoldBackgroundColor: const Color(0xfff5f5f5),
|
||||||
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
|
labelStyle: TextStyle(
|
||||||
|
color: _primaryColor,
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
focusedBorder: UnderlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: _primaryColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
border: const UnderlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Color(0xff999999),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: const UnderlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Color(0xff999999),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
appBarTheme: AppBarTheme(
|
||||||
|
backgroundColor: _primaryColor,
|
||||||
|
titleTextStyle: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 18,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
bottomNavigationBarTheme: BottomNavigationBarThemeData(
|
||||||
|
selectedItemColor: _primaryColor,
|
||||||
|
),
|
||||||
|
buttonTheme: ButtonThemeData(
|
||||||
|
buttonColor: _primaryColor,
|
||||||
|
),
|
||||||
|
progressIndicatorTheme: ProgressIndicatorThemeData(
|
||||||
|
color: _primaryColor,
|
||||||
|
),
|
||||||
|
tabBarTheme: TabBarTheme(
|
||||||
|
labelStyle: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
unselectedLabelStyle: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
labelColor: _primaryColor,
|
||||||
|
unselectedLabelColor: const Color(0xff999999),
|
||||||
|
indicator: UnderlineTabIndicator(
|
||||||
|
borderSide: BorderSide(color: _primaryColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
toggleableActiveColor: _primaryColor,
|
||||||
|
checkboxTheme: CheckboxThemeData(
|
||||||
|
checkColor: MaterialStateProperty.resolveWith(
|
||||||
|
(Set<MaterialState> states) {
|
||||||
|
if (states.contains(MaterialState.disabled)) {
|
||||||
|
return Colors.transparent;
|
||||||
|
}
|
||||||
|
if (states.contains(MaterialState.selected)) {
|
||||||
|
return Colors.white;
|
||||||
|
}
|
||||||
|
return Colors.black;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
cupertinoOverrideTheme: NoDefaultCupertinoThemeData(
|
||||||
|
brightness: Brightness.light,
|
||||||
|
primaryColor: _primaryColor,
|
||||||
|
scaffoldBackgroundColor: const Color(0xfff5f5f5),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThemeData darkTheme = ThemeData.dark().copyWith(
|
ThemeData getDartTheme() {
|
||||||
|
return ThemeData.dark().copyWith(
|
||||||
brightness: Brightness.dark,
|
brightness: Brightness.dark,
|
||||||
primaryColor: const Color(0xffffffff),
|
primaryColor: const Color(0xffffffff),
|
||||||
scaffoldBackgroundColor: Colors.black,
|
scaffoldBackgroundColor: Colors.black,
|
||||||
@@ -60,19 +154,22 @@ ThemeData darkTheme = ThemeData.dark().copyWith(
|
|||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
inputDecorationTheme: const InputDecorationTheme(
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
labelStyle: TextStyle(color: _primaryColor),
|
labelStyle: TextStyle(
|
||||||
|
color: _primaryColor,
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
focusedBorder: UnderlineInputBorder(
|
focusedBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: _primaryColor,
|
color: _primaryColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
border: UnderlineInputBorder(
|
border: const UnderlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: Color(0xff999999),
|
color: Color(0xff999999),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
enabledBorder: UnderlineInputBorder(
|
enabledBorder: const UnderlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: Color(0xff999999),
|
color: Color(0xff999999),
|
||||||
),
|
),
|
||||||
@@ -88,7 +185,7 @@ ThemeData darkTheme = ThemeData.dark().copyWith(
|
|||||||
labelColor: Color(0xffffffff),
|
labelColor: Color(0xffffffff),
|
||||||
unselectedLabelColor: Color(0xff999999),
|
unselectedLabelColor: Color(0xff999999),
|
||||||
),
|
),
|
||||||
colorScheme: const ColorScheme.light(
|
colorScheme: ColorScheme.light(
|
||||||
secondary: _primaryColor,
|
secondary: _primaryColor,
|
||||||
primary: _primaryColor,
|
primary: _primaryColor,
|
||||||
),
|
),
|
||||||
@@ -112,89 +209,20 @@ ThemeData darkTheme = ThemeData.dark().copyWith(
|
|||||||
scaffoldBackgroundColor: Colors.black,
|
scaffoldBackgroundColor: Colors.black,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
ThemeData lightTheme = ThemeData.light().copyWith(
|
|
||||||
brightness: Brightness.light,
|
|
||||||
primaryColor: _primaryColor,
|
|
||||||
colorScheme: const ColorScheme.light(
|
|
||||||
secondary: _primaryColor,
|
|
||||||
primary: _primaryColor,
|
|
||||||
),
|
|
||||||
scaffoldBackgroundColor: const Color(0xfff5f5f5),
|
|
||||||
inputDecorationTheme: const InputDecorationTheme(
|
|
||||||
labelStyle: TextStyle(color: _primaryColor),
|
|
||||||
focusedBorder: UnderlineInputBorder(
|
|
||||||
borderSide: BorderSide(
|
|
||||||
color: _primaryColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
border: UnderlineInputBorder(
|
|
||||||
borderSide: BorderSide(
|
|
||||||
color: Color(0xff999999),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
enabledBorder: UnderlineInputBorder(
|
|
||||||
borderSide: BorderSide(
|
|
||||||
color: Color(0xff999999),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
appBarTheme: const AppBarTheme(
|
|
||||||
backgroundColor: _primaryColor,
|
|
||||||
titleTextStyle: TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 18,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
|
|
||||||
selectedItemColor: _primaryColor,
|
|
||||||
),
|
|
||||||
buttonTheme: const ButtonThemeData(
|
|
||||||
buttonColor: _primaryColor,
|
|
||||||
),
|
|
||||||
progressIndicatorTheme: const ProgressIndicatorThemeData(
|
|
||||||
color: _primaryColor,
|
|
||||||
),
|
|
||||||
tabBarTheme: const TabBarTheme(
|
|
||||||
labelStyle: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
),
|
|
||||||
unselectedLabelStyle: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
),
|
|
||||||
labelColor: _primaryColor,
|
|
||||||
unselectedLabelColor: Color(0xff999999),
|
|
||||||
indicator: UnderlineTabIndicator(
|
|
||||||
borderSide: BorderSide(color: _primaryColor),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
toggleableActiveColor: _primaryColor,
|
|
||||||
checkboxTheme: CheckboxThemeData(
|
|
||||||
checkColor: MaterialStateProperty.resolveWith(
|
|
||||||
(Set<MaterialState> states) {
|
|
||||||
if (states.contains(MaterialState.disabled)) {
|
|
||||||
return Colors.transparent;
|
|
||||||
}
|
}
|
||||||
if (states.contains(MaterialState.selected)) {
|
|
||||||
return Colors.white;
|
|
||||||
}
|
}
|
||||||
return Colors.black;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
cupertinoOverrideTheme: const NoDefaultCupertinoThemeData(
|
|
||||||
brightness: Brightness.light,
|
|
||||||
primaryColor: _primaryColor,
|
|
||||||
scaffoldBackgroundColor: Color(0xfff5f5f5),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
abstract class ThemeColors {
|
abstract class ThemeColors {
|
||||||
Color settingBgColor();
|
Color settingBgColor();
|
||||||
|
|
||||||
|
Color settingBordorColor();
|
||||||
|
|
||||||
Color titleColor();
|
Color titleColor();
|
||||||
|
|
||||||
Color descColor();
|
Color descColor();
|
||||||
|
|
||||||
|
Color tabBarColor();
|
||||||
|
|
||||||
Color pinColor();
|
Color pinColor();
|
||||||
|
|
||||||
Color buttonBgColor();
|
Color buttonBgColor();
|
||||||
@@ -232,6 +260,16 @@ class LightThemeColors extends ThemeColors {
|
|||||||
Color buttonBgColor() {
|
Color buttonBgColor() {
|
||||||
return _primaryColor;
|
return _primaryColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color settingBordorColor() {
|
||||||
|
return Colors.white;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color tabBarColor() {
|
||||||
|
return const Color(0xffF7F7F7);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DartThemeColors extends ThemeColors {
|
class DartThemeColors extends ThemeColors {
|
||||||
@@ -264,4 +302,14 @@ class DartThemeColors extends ThemeColors {
|
|||||||
Color buttonBgColor() {
|
Color buttonBgColor() {
|
||||||
return const Color(0xff333333);
|
return const Color(0xff333333);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color settingBordorColor() {
|
||||||
|
return Color(0xff333333);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color tabBarColor() {
|
||||||
|
return Colors.black;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
170
lib/base/ui/source_code_view.dart
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart' as url_launcher;
|
||||||
|
import 'syntax_highlighter.dart';
|
||||||
|
|
||||||
|
class SourceCodeView extends StatefulWidget {
|
||||||
|
final String filePath;
|
||||||
|
final String? codeLinkPrefix;
|
||||||
|
final bool showLabelText;
|
||||||
|
final Color? iconBackgroundColor;
|
||||||
|
final Color? iconForegroundColor;
|
||||||
|
final Color? labelBackgroundColor;
|
||||||
|
final TextStyle? labelTextStyle;
|
||||||
|
final SyntaxHighlighterStyle? syntaxHighlighterStyle;
|
||||||
|
|
||||||
|
const SourceCodeView({
|
||||||
|
Key? key,
|
||||||
|
required this.filePath,
|
||||||
|
this.codeLinkPrefix,
|
||||||
|
this.showLabelText = false,
|
||||||
|
this.iconBackgroundColor,
|
||||||
|
this.iconForegroundColor,
|
||||||
|
this.labelBackgroundColor,
|
||||||
|
this.labelTextStyle,
|
||||||
|
this.syntaxHighlighterStyle,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
String? get codeLink => codeLinkPrefix == null
|
||||||
|
? null
|
||||||
|
: '$codeLinkPrefix/$filePath';
|
||||||
|
|
||||||
|
@override
|
||||||
|
_SourceCodeViewState createState() {
|
||||||
|
return _SourceCodeViewState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SourceCodeViewState extends State<SourceCodeView> {
|
||||||
|
double _textScaleFactor = 1.0;
|
||||||
|
|
||||||
|
Widget _getCodeView(String codeContent, BuildContext context) {
|
||||||
|
codeContent = codeContent.replaceAll('\r\n', '\n');
|
||||||
|
final SyntaxHighlighterStyle style = widget.syntaxHighlighterStyle ??
|
||||||
|
(Theme.of(context).brightness == Brightness.dark
|
||||||
|
? SyntaxHighlighterStyle.darkThemeStyle()
|
||||||
|
: SyntaxHighlighterStyle.lightThemeStyle());
|
||||||
|
return Container(
|
||||||
|
constraints: BoxConstraints.expand(),
|
||||||
|
child: Scrollbar(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
child: SelectableText.rich(
|
||||||
|
TextSpan(
|
||||||
|
style: GoogleFonts.droidSansMono(fontSize: 12)
|
||||||
|
.apply(fontSizeFactor: this._textScaleFactor),
|
||||||
|
children: <TextSpan>[
|
||||||
|
DartSyntaxHighlighter(style).format(codeContent)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
style: DefaultTextStyle.of(context)
|
||||||
|
.style
|
||||||
|
.apply(fontSizeFactor: this._textScaleFactor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SpeedDialChild> _buildFloatingButtons({
|
||||||
|
TextStyle? labelTextStyle,
|
||||||
|
Color? iconBackgroundColor,
|
||||||
|
Color? iconForegroundColor,
|
||||||
|
Color? labelBackgroundColor,
|
||||||
|
required bool showLabelText,
|
||||||
|
}) =>
|
||||||
|
[
|
||||||
|
if (this.widget.codeLink != null)
|
||||||
|
SpeedDialChild(
|
||||||
|
child: Icon(Icons.content_copy),
|
||||||
|
labelWidget: showLabelText ? Text('Copy code to clipboard') : null,
|
||||||
|
backgroundColor: iconBackgroundColor,
|
||||||
|
foregroundColor: iconForegroundColor,
|
||||||
|
labelBackgroundColor: labelBackgroundColor,
|
||||||
|
labelStyle: labelTextStyle,
|
||||||
|
onTap: () async {
|
||||||
|
Clipboard.setData(ClipboardData(
|
||||||
|
text: await DefaultAssetBundle.of(context)
|
||||||
|
.loadString(widget.filePath)));
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||||
|
content: Text('Code copied to clipboard!'),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (this.widget.codeLink != null)
|
||||||
|
SpeedDialChild(
|
||||||
|
child: Icon(Icons.open_in_new),
|
||||||
|
labelWidget: showLabelText ? Text('View code in browser') : null,
|
||||||
|
backgroundColor: iconBackgroundColor,
|
||||||
|
foregroundColor: iconForegroundColor,
|
||||||
|
labelBackgroundColor: labelBackgroundColor,
|
||||||
|
labelStyle: labelTextStyle,
|
||||||
|
onTap: () => url_launcher.launch(this.widget.codeLink!),
|
||||||
|
),
|
||||||
|
SpeedDialChild(
|
||||||
|
child: Icon(Icons.zoom_out),
|
||||||
|
label: showLabelText ? 'Zoom out' : null,
|
||||||
|
// labelWidget: showLabelText ? Text('Zoom out') : null,
|
||||||
|
backgroundColor: iconBackgroundColor,
|
||||||
|
foregroundColor: iconForegroundColor,
|
||||||
|
labelBackgroundColor: labelBackgroundColor,
|
||||||
|
labelStyle: labelTextStyle,
|
||||||
|
onTap: () => setState(() {
|
||||||
|
this._textScaleFactor = max(0.8, this._textScaleFactor - 0.1);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
SpeedDialChild(
|
||||||
|
child: Icon(Icons.zoom_in),
|
||||||
|
labelWidget: showLabelText ? Text('Zoom in') : null,
|
||||||
|
backgroundColor: iconBackgroundColor,
|
||||||
|
foregroundColor: iconForegroundColor,
|
||||||
|
labelBackgroundColor: labelBackgroundColor,
|
||||||
|
labelStyle: labelTextStyle,
|
||||||
|
onTap: () => setState(() {
|
||||||
|
this._textScaleFactor += 0.1;
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FutureBuilder(
|
||||||
|
future: DefaultAssetBundle.of(context).loadString(widget.filePath),
|
||||||
|
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
return Scaffold(
|
||||||
|
body: Padding(
|
||||||
|
padding: EdgeInsets.all(4.0),
|
||||||
|
child: _getCodeView(snapshot.data!, context),
|
||||||
|
),
|
||||||
|
floatingActionButton: SpeedDial(
|
||||||
|
renderOverlay: false,
|
||||||
|
overlayOpacity: 0,
|
||||||
|
children: _buildFloatingButtons(
|
||||||
|
labelTextStyle: widget.labelTextStyle,
|
||||||
|
iconBackgroundColor: widget.iconBackgroundColor,
|
||||||
|
iconForegroundColor: widget.iconForegroundColor,
|
||||||
|
labelBackgroundColor: widget.labelBackgroundColor,
|
||||||
|
showLabelText: widget.showLabelText,
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.blue,
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
activeBackgroundColor: Colors.red,
|
||||||
|
activeForegroundColor: Colors.white,
|
||||||
|
icon: Icons.menu,
|
||||||
|
activeIcon: Icons.close,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
384
lib/base/ui/syntax_highlighter.dart
Normal file
@@ -0,0 +1,384 @@
|
|||||||
|
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:string_scanner/string_scanner.dart';
|
||||||
|
|
||||||
|
class SyntaxHighlighterStyle {
|
||||||
|
SyntaxHighlighterStyle(
|
||||||
|
{this.baseStyle,
|
||||||
|
this.numberStyle,
|
||||||
|
this.commentStyle,
|
||||||
|
this.keywordStyle,
|
||||||
|
this.stringStyle,
|
||||||
|
this.punctuationStyle,
|
||||||
|
this.classStyle,
|
||||||
|
this.constantStyle});
|
||||||
|
|
||||||
|
static SyntaxHighlighterStyle lightThemeStyle() => SyntaxHighlighterStyle(
|
||||||
|
baseStyle: const TextStyle(color: const Color(0xFF000000),height: 1,),
|
||||||
|
numberStyle: const TextStyle(color: const Color(0xFF1565C0)),
|
||||||
|
commentStyle: const TextStyle(color: const Color(0xFF9E9E9E)),
|
||||||
|
keywordStyle: const TextStyle(color: const Color(0xFF9C27B0)),
|
||||||
|
stringStyle: const TextStyle(color: const Color(0xFF43A047)),
|
||||||
|
punctuationStyle: const TextStyle(color: const Color(0xFF000000)),
|
||||||
|
classStyle: const TextStyle(color: const Color(0xFF512DA8)),
|
||||||
|
constantStyle: const TextStyle(color: const Color(0xFF795548)),
|
||||||
|
);
|
||||||
|
|
||||||
|
static SyntaxHighlighterStyle darkThemeStyle() => SyntaxHighlighterStyle(
|
||||||
|
baseStyle: const TextStyle(color: const Color(0xFFFFFFFF)),
|
||||||
|
numberStyle: const TextStyle(color: const Color(0xFF1565C0)),
|
||||||
|
commentStyle: const TextStyle(color: const Color(0xFF9E9E9E)),
|
||||||
|
keywordStyle: const TextStyle(color: const Color(0xFF80CBC4)),
|
||||||
|
stringStyle: const TextStyle(color: const Color(0xFF009688)),
|
||||||
|
punctuationStyle: const TextStyle(color: const Color(0xFFFFFFFF)),
|
||||||
|
classStyle: const TextStyle(color: const Color(0xFF009688)),
|
||||||
|
constantStyle: const TextStyle(color: const Color(0xFF795548)),
|
||||||
|
);
|
||||||
|
|
||||||
|
SyntaxHighlighterStyle copyWith({
|
||||||
|
TextStyle? baseStyle,
|
||||||
|
TextStyle? numberStyle,
|
||||||
|
TextStyle? commentStyle,
|
||||||
|
TextStyle? keywordStyle,
|
||||||
|
TextStyle? stringStyle,
|
||||||
|
TextStyle? punctuationStyle,
|
||||||
|
TextStyle? classStyle,
|
||||||
|
TextStyle? constantStyle,
|
||||||
|
}) =>
|
||||||
|
SyntaxHighlighterStyle(
|
||||||
|
baseStyle: baseStyle ?? this.baseStyle,
|
||||||
|
numberStyle: numberStyle ?? this.numberStyle,
|
||||||
|
commentStyle: commentStyle ?? this.commentStyle,
|
||||||
|
keywordStyle: keywordStyle ?? this.keywordStyle,
|
||||||
|
stringStyle: stringStyle ?? this.stringStyle,
|
||||||
|
punctuationStyle: punctuationStyle ?? this.punctuationStyle,
|
||||||
|
classStyle: classStyle ?? this.classStyle,
|
||||||
|
constantStyle: constantStyle ?? this.constantStyle,
|
||||||
|
);
|
||||||
|
|
||||||
|
final TextStyle? baseStyle;
|
||||||
|
final TextStyle? numberStyle;
|
||||||
|
final TextStyle? commentStyle;
|
||||||
|
final TextStyle? keywordStyle;
|
||||||
|
final TextStyle? stringStyle;
|
||||||
|
final TextStyle? punctuationStyle;
|
||||||
|
final TextStyle? classStyle;
|
||||||
|
final TextStyle? constantStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class SyntaxHighlighter {
|
||||||
|
// ignore: one_member_abstracts
|
||||||
|
TextSpan format(String src);
|
||||||
|
}
|
||||||
|
|
||||||
|
class DartSyntaxHighlighter extends SyntaxHighlighter {
|
||||||
|
DartSyntaxHighlighter([this._style]) {
|
||||||
|
_spans = <_HighlightSpan>[];
|
||||||
|
_style ??= SyntaxHighlighterStyle.darkThemeStyle();
|
||||||
|
}
|
||||||
|
|
||||||
|
SyntaxHighlighterStyle? _style;
|
||||||
|
|
||||||
|
static const List<String> _keywords = const <String>[
|
||||||
|
'abstract',
|
||||||
|
'as',
|
||||||
|
'assert',
|
||||||
|
'async',
|
||||||
|
'await',
|
||||||
|
'break',
|
||||||
|
'case',
|
||||||
|
'catch',
|
||||||
|
'class',
|
||||||
|
'const',
|
||||||
|
'continue',
|
||||||
|
'default',
|
||||||
|
'deferred',
|
||||||
|
'do',
|
||||||
|
'dynamic',
|
||||||
|
'else',
|
||||||
|
'enum',
|
||||||
|
'export',
|
||||||
|
'external',
|
||||||
|
'extends',
|
||||||
|
'factory',
|
||||||
|
'false',
|
||||||
|
'final',
|
||||||
|
'finally',
|
||||||
|
'for',
|
||||||
|
'get',
|
||||||
|
'if',
|
||||||
|
'implements',
|
||||||
|
'import',
|
||||||
|
'in',
|
||||||
|
'is',
|
||||||
|
'library',
|
||||||
|
'new',
|
||||||
|
'null',
|
||||||
|
'operator',
|
||||||
|
'part',
|
||||||
|
'rethrow',
|
||||||
|
'return',
|
||||||
|
'set',
|
||||||
|
'static',
|
||||||
|
'super',
|
||||||
|
'switch',
|
||||||
|
'sync',
|
||||||
|
'this',
|
||||||
|
'throw',
|
||||||
|
'true',
|
||||||
|
'try',
|
||||||
|
'typedef',
|
||||||
|
'var',
|
||||||
|
'void',
|
||||||
|
'while',
|
||||||
|
'with',
|
||||||
|
'yield'
|
||||||
|
];
|
||||||
|
|
||||||
|
static const List<String> _builtInTypes = const <String>[
|
||||||
|
'int',
|
||||||
|
'double',
|
||||||
|
'num',
|
||||||
|
'bool'
|
||||||
|
];
|
||||||
|
|
||||||
|
late String _src;
|
||||||
|
late StringScanner _scanner;
|
||||||
|
|
||||||
|
late List<_HighlightSpan> _spans;
|
||||||
|
|
||||||
|
@override
|
||||||
|
TextSpan format(String src) {
|
||||||
|
_src = src;
|
||||||
|
_scanner = StringScanner(_src);
|
||||||
|
|
||||||
|
if (_generateSpans()) {
|
||||||
|
// Successfully parsed the code
|
||||||
|
final List<TextSpan> formattedText = <TextSpan>[];
|
||||||
|
int currentPosition = 0;
|
||||||
|
|
||||||
|
for (_HighlightSpan span in _spans) {
|
||||||
|
if (currentPosition != span.start)
|
||||||
|
formattedText
|
||||||
|
.add(TextSpan(text: _src.substring(currentPosition, span.start)));
|
||||||
|
|
||||||
|
formattedText.add(TextSpan(
|
||||||
|
style: span.textStyle(_style), text: span.textForSpan(_src)));
|
||||||
|
|
||||||
|
currentPosition = span.end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPosition != _src.length)
|
||||||
|
formattedText
|
||||||
|
.add(TextSpan(text: _src.substring(currentPosition, _src.length)));
|
||||||
|
|
||||||
|
return TextSpan(style: _style!.baseStyle, children: formattedText);
|
||||||
|
} else {
|
||||||
|
// Parsing failed, return with only basic formatting
|
||||||
|
return TextSpan(style: _style!.baseStyle, text: src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _generateSpans() {
|
||||||
|
int lastLoopPosition = _scanner.position;
|
||||||
|
|
||||||
|
while (!_scanner.isDone) {
|
||||||
|
// Skip White space
|
||||||
|
_scanner.scan(RegExp(r'\s+'));
|
||||||
|
|
||||||
|
// Block comments
|
||||||
|
if (_scanner.scan(RegExp(r'/\*(.|\n)*\*/'))) {
|
||||||
|
_spans.add(_HighlightSpan(_HighlightType.comment,
|
||||||
|
_scanner.lastMatch!.start, _scanner.lastMatch!.end));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Line comments
|
||||||
|
if (_scanner.scan('##')) {
|
||||||
|
final int startComment = _scanner.lastMatch!.start;
|
||||||
|
|
||||||
|
bool eof = false;
|
||||||
|
int endComment;
|
||||||
|
if (_scanner.scan(RegExp(r'.*\n'))) {
|
||||||
|
endComment = _scanner.lastMatch!.end - 1;
|
||||||
|
} else {
|
||||||
|
eof = true;
|
||||||
|
endComment = _src.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
_spans.add(
|
||||||
|
_HighlightSpan(_HighlightType.comment, startComment, endComment));
|
||||||
|
|
||||||
|
if (eof) break;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Raw r"String"
|
||||||
|
if (_scanner.scan(RegExp(r'r".*"'))) {
|
||||||
|
_spans.add(_HighlightSpan(_HighlightType.string,
|
||||||
|
_scanner.lastMatch!.start, _scanner.lastMatch!.end));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Raw r'String'
|
||||||
|
if (_scanner.scan(RegExp(r"r'.*'"))) {
|
||||||
|
_spans.add(_HighlightSpan(_HighlightType.string,
|
||||||
|
_scanner.lastMatch!.start, _scanner.lastMatch!.end));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiline """String"""
|
||||||
|
if (_scanner.scan(RegExp(r'"""(?:[^"\\]|\\(.|\n))*"""'))) {
|
||||||
|
_spans.add(_HighlightSpan(_HighlightType.string,
|
||||||
|
_scanner.lastMatch!.start, _scanner.lastMatch!.end));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiline '''String'''
|
||||||
|
if (_scanner.scan(RegExp(r"'''(?:[^'\\]|\\(.|\n))*'''"))) {
|
||||||
|
_spans.add(_HighlightSpan(_HighlightType.string,
|
||||||
|
_scanner.lastMatch!.start, _scanner.lastMatch!.end));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "String"
|
||||||
|
if (_scanner.scan(RegExp(r'"(?:[^"\\]|\\.)*"'))) {
|
||||||
|
_spans.add(_HighlightSpan(_HighlightType.string,
|
||||||
|
_scanner.lastMatch!.start, _scanner.lastMatch!.end));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'String'
|
||||||
|
if (_scanner.scan(RegExp(r"'(?:[^'\\]|\\.)*'"))) {
|
||||||
|
_spans.add(_HighlightSpan(_HighlightType.string,
|
||||||
|
_scanner.lastMatch!.start, _scanner.lastMatch!.end));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Double
|
||||||
|
if (_scanner.scan(RegExp(r'\d+\.\d+'))) {
|
||||||
|
_spans.add(_HighlightSpan(_HighlightType.number,
|
||||||
|
_scanner.lastMatch!.start, _scanner.lastMatch!.end));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Integer
|
||||||
|
if (_scanner.scan(RegExp(r'\d+'))) {
|
||||||
|
_spans.add(_HighlightSpan(_HighlightType.number,
|
||||||
|
_scanner.lastMatch!.start, _scanner.lastMatch!.end));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Punctuation
|
||||||
|
if (_scanner.scan(RegExp(r'[\[\]{}().!=<>&\|\?\+\-\*/%\^~;:,]'))) {
|
||||||
|
_spans.add(_HighlightSpan(_HighlightType.punctuation,
|
||||||
|
_scanner.lastMatch!.start, _scanner.lastMatch!.end));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Meta data
|
||||||
|
if (_scanner.scan(RegExp(r'@\w+'))) {
|
||||||
|
_spans.add(_HighlightSpan(_HighlightType.keyword,
|
||||||
|
_scanner.lastMatch!.start, _scanner.lastMatch!.end));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Words
|
||||||
|
if (_scanner.scan(RegExp(r'\w+'))) {
|
||||||
|
_HighlightType? type;
|
||||||
|
|
||||||
|
String word = _scanner.lastMatch![0]!;
|
||||||
|
if (word.startsWith('_')) word = word.substring(1);
|
||||||
|
|
||||||
|
if (_keywords.contains(word))
|
||||||
|
type = _HighlightType.keyword;
|
||||||
|
else if (_builtInTypes.contains(word))
|
||||||
|
type = _HighlightType.keyword;
|
||||||
|
else if (_firstLetterIsUpperCase(word))
|
||||||
|
type = _HighlightType.klass;
|
||||||
|
else if (word.length >= 2 &&
|
||||||
|
word.startsWith('k') &&
|
||||||
|
_firstLetterIsUpperCase(word.substring(1)))
|
||||||
|
type = _HighlightType.constant;
|
||||||
|
|
||||||
|
if (type != null) {
|
||||||
|
_spans.add(_HighlightSpan(
|
||||||
|
type, _scanner.lastMatch!.start, _scanner.lastMatch!.end));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this loop did anything
|
||||||
|
if (lastLoopPosition == _scanner.position) {
|
||||||
|
// Failed to parse this file, abort gracefully
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
lastLoopPosition = _scanner.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
_simplify();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _simplify() {
|
||||||
|
for (int i = _spans.length - 2; i >= 0; i -= 1) {
|
||||||
|
if (_spans[i].type == _spans[i + 1].type &&
|
||||||
|
_spans[i].end == _spans[i + 1].start) {
|
||||||
|
_spans[i] =
|
||||||
|
_HighlightSpan(_spans[i].type, _spans[i].start, _spans[i + 1].end);
|
||||||
|
_spans.removeAt(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _firstLetterIsUpperCase(String str) {
|
||||||
|
if (str.isNotEmpty) {
|
||||||
|
final String first = str.substring(0, 1);
|
||||||
|
return first == first.toUpperCase();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum _HighlightType {
|
||||||
|
number,
|
||||||
|
comment,
|
||||||
|
keyword,
|
||||||
|
string,
|
||||||
|
punctuation,
|
||||||
|
klass,
|
||||||
|
constant
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HighlightSpan {
|
||||||
|
_HighlightSpan(this.type, this.start, this.end);
|
||||||
|
final _HighlightType type;
|
||||||
|
final int start;
|
||||||
|
final int end;
|
||||||
|
|
||||||
|
String textForSpan(String src) {
|
||||||
|
return src.substring(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextStyle? textStyle(SyntaxHighlighterStyle? style) {
|
||||||
|
if (type == _HighlightType.number)
|
||||||
|
return style!.numberStyle;
|
||||||
|
else if (type == _HighlightType.comment)
|
||||||
|
return style!.commentStyle;
|
||||||
|
else if (type == _HighlightType.keyword)
|
||||||
|
return style!.keywordStyle;
|
||||||
|
else if (type == _HighlightType.string)
|
||||||
|
return style!.stringStyle;
|
||||||
|
else if (type == _HighlightType.punctuation)
|
||||||
|
return style!.punctuationStyle;
|
||||||
|
else if (type == _HighlightType.klass)
|
||||||
|
return style!.classStyle;
|
||||||
|
else if (type == _HighlightType.constant)
|
||||||
|
return style!.constantStyle;
|
||||||
|
else
|
||||||
|
return style!.baseStyle;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +1,37 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:qinglong_app/utils/extension.dart';
|
||||||
import 'package:qinglong_app/utils/sp_utils.dart';
|
import 'package:qinglong_app/utils/sp_utils.dart';
|
||||||
|
|
||||||
|
import '../main.dart';
|
||||||
import 'sp_const.dart';
|
import 'sp_const.dart';
|
||||||
|
import 'theme.dart';
|
||||||
|
|
||||||
class UserInfoViewModel {
|
class UserInfoViewModel {
|
||||||
|
int _primaryColor = commonColor.value;
|
||||||
String? _token;
|
String? _token;
|
||||||
String? _host = "";
|
String? _host = "";
|
||||||
String? _userName;
|
String? _userName;
|
||||||
String? _passWord;
|
String? _passWord;
|
||||||
bool _useSecertLogined = false;
|
bool _useSecertLogined = false;
|
||||||
|
|
||||||
|
List<UserInfoBean> historyAccounts = [];
|
||||||
|
|
||||||
UserInfoViewModel() {
|
UserInfoViewModel() {
|
||||||
String userInfoJson = SpUtil.getString(spUserInfo);
|
_token = SpUtil.getString(spUserInfo);
|
||||||
_userName = SpUtil.getString(spUserName);
|
_userName = SpUtil.getString(spUserName);
|
||||||
_passWord = SpUtil.getString(spPassWord);
|
_passWord = SpUtil.getString(spPassWord);
|
||||||
|
_primaryColor = SpUtil.getInt(spCustomColor, defValue: commonColor.value);
|
||||||
|
|
||||||
_useSecertLogined = SpUtil.getBool(spSecretLogined, defValue: false);
|
_useSecertLogined = SpUtil.getBool(spSecretLogined, defValue: false);
|
||||||
_host = SpUtil.getString(spHost, defValue: '');
|
_host = SpUtil.getString(spHost, defValue: '');
|
||||||
|
|
||||||
if (userInfoJson.isNotEmpty) {
|
List<dynamic>? tempList = jsonDecode(SpUtil.getString(spLoginHistory, defValue: '[]'));
|
||||||
_token = userInfoJson;
|
|
||||||
|
if (tempList != null && tempList.isNotEmpty) {
|
||||||
|
for (Map<String, dynamic> value in tempList) {
|
||||||
|
historyAccounts.add(UserInfoBean.fromJson(value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,18 +40,27 @@ class UserInfoViewModel {
|
|||||||
SpUtil.putString(spUserInfo, token);
|
SpUtil.putString(spUserInfo, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateUserName(String userName, String password) {
|
void updateUserName(String host, String userName, String password, bool secretLogin) {
|
||||||
|
updateHost(host);
|
||||||
|
_useSecretLogin(secretLogin);
|
||||||
_userName = userName;
|
_userName = userName;
|
||||||
_passWord = password;
|
_passWord = password;
|
||||||
SpUtil.putString(spUserName, userName);
|
SpUtil.putString(spUserName, userName);
|
||||||
SpUtil.putString(spPassWord, password);
|
SpUtil.putString(spPassWord, password);
|
||||||
|
|
||||||
|
save2HistoryAccount();
|
||||||
}
|
}
|
||||||
|
|
||||||
void useSecretLogin(bool use) {
|
void _useSecretLogin(bool use) {
|
||||||
_useSecertLogined = use;
|
_useSecertLogined = use;
|
||||||
SpUtil.putBool(spSecretLogined, _useSecertLogined);
|
SpUtil.putBool(spSecretLogined, _useSecertLogined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateCustomColor(int color) {
|
||||||
|
_primaryColor = color;
|
||||||
|
SpUtil.putInt(spCustomColor, color);
|
||||||
|
}
|
||||||
|
|
||||||
void updateHost(String host) {
|
void updateHost(String host) {
|
||||||
_host = host;
|
_host = host;
|
||||||
SpUtil.putString(spHost, host);
|
SpUtil.putString(spHost, host);
|
||||||
@@ -54,7 +76,62 @@ class UserInfoViewModel {
|
|||||||
|
|
||||||
bool get useSecretLogined => _useSecertLogined;
|
bool get useSecretLogined => _useSecertLogined;
|
||||||
|
|
||||||
|
int get primaryColor => _primaryColor;
|
||||||
|
|
||||||
bool isLogined() {
|
bool isLogined() {
|
||||||
return token != null && token!.isNotEmpty;
|
return token != null && token!.isNotEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void save2HistoryAccount() {
|
||||||
|
if (_host == null || _host!.isEmpty) return;
|
||||||
|
if (_userName == null || _userName!.isEmpty) return;
|
||||||
|
if (_passWord == null || _passWord!.isEmpty) return;
|
||||||
|
|
||||||
|
//如果已经存在host,那就更新
|
||||||
|
|
||||||
|
"login success $_host $userName $passWord".log();
|
||||||
|
|
||||||
|
historyAccounts.removeWhere((element) => element.host == _host);
|
||||||
|
|
||||||
|
historyAccounts.insert(0, UserInfoBean(userName: _userName, password: _passWord, useSecretLogined: _useSecertLogined, host: _host));
|
||||||
|
|
||||||
|
while (historyAccounts.length > 3) {
|
||||||
|
historyAccounts.removeLast();
|
||||||
|
}
|
||||||
|
|
||||||
|
SpUtil.putString(spLoginHistory, jsonEncode(historyAccounts));
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeHistoryAccount(String? host) {
|
||||||
|
if (host == null || host.isEmpty) return;
|
||||||
|
|
||||||
|
historyAccounts.removeWhere((element) => element.host == host);
|
||||||
|
|
||||||
|
SpUtil.putString(spLoginHistory, jsonEncode(historyAccounts));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UserInfoBean {
|
||||||
|
String? userName;
|
||||||
|
String? password;
|
||||||
|
bool useSecretLogined = false;
|
||||||
|
String? host;
|
||||||
|
|
||||||
|
UserInfoBean({this.userName, this.password, this.useSecretLogined = false, this.host});
|
||||||
|
|
||||||
|
UserInfoBean.fromJson(Map<String, dynamic> json) {
|
||||||
|
userName = json['userName'];
|
||||||
|
password = json['password'];
|
||||||
|
useSecretLogined = json['useSecretLogined'] ?? false;
|
||||||
|
host = json['host'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['userName'] = this.userName;
|
||||||
|
data['password'] = this.password;
|
||||||
|
data['useSecretLogined'] = this.useSecretLogined;
|
||||||
|
data['host'] = this.host;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import 'package:qinglong_app/module/config/config_bean.dart';
|
import 'package:qinglong_app/module/config/config_bean.dart';
|
||||||
import 'package:qinglong_app/module/env/env_bean.dart';
|
import 'package:qinglong_app/module/env/env_bean.dart';
|
||||||
|
import 'package:qinglong_app/module/home/system_bean.dart';
|
||||||
import 'package:qinglong_app/module/login/login_bean.dart';
|
import 'package:qinglong_app/module/login/login_bean.dart';
|
||||||
import 'package:qinglong_app/module/login/user_bean.dart';
|
import 'package:qinglong_app/module/login/user_bean.dart';
|
||||||
import 'package:qinglong_app/module/others/dependencies/dependency_bean.dart';
|
import 'package:qinglong_app/module/others/dependencies/dependency_bean.dart';
|
||||||
@@ -33,6 +34,10 @@ class JsonConversion$Json {
|
|||||||
return EnvBean.jsonConversion(json) as M;
|
return EnvBean.jsonConversion(json) as M;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(type == (SystemBean).toString()){
|
||||||
|
return SystemBean.jsonConversion(json) as M;
|
||||||
|
}
|
||||||
|
|
||||||
if(type == (LoginBean).toString()){
|
if(type == (LoginBean).toString()){
|
||||||
return LoginBean.jsonConversion(json) as M;
|
return LoginBean.jsonConversion(json) as M;
|
||||||
}
|
}
|
||||||
@@ -73,6 +78,10 @@ class JsonConversion$Json {
|
|||||||
return data.map<EnvBean>((e) => EnvBean.jsonConversion(e)).toList() as M;
|
return data.map<EnvBean>((e) => EnvBean.jsonConversion(e)).toList() as M;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(<SystemBean>[] is M){
|
||||||
|
return data.map<SystemBean>((e) => SystemBean.jsonConversion(e)).toList() as M;
|
||||||
|
}
|
||||||
|
|
||||||
if(<LoginBean>[] is M){
|
if(<LoginBean>[] is M){
|
||||||
return data.map<LoginBean>((e) => LoginBean.jsonConversion(e)).toList() as M;
|
return data.map<LoginBean>((e) => LoginBean.jsonConversion(e)).toList() as M;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import 'package:logger/logger.dart';
|
|||||||
import 'package:qinglong_app/base/theme.dart';
|
import 'package:qinglong_app/base/theme.dart';
|
||||||
import 'package:qinglong_app/module/login/login_page.dart';
|
import 'package:qinglong_app/module/login/login_page.dart';
|
||||||
import 'package:qinglong_app/utils/sp_utils.dart';
|
import 'package:qinglong_app/utils/sp_utils.dart';
|
||||||
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
|
|
||||||
import 'base/routes.dart';
|
import 'base/routes.dart';
|
||||||
import 'base/userinfo_viewmodel.dart';
|
import 'base/userinfo_viewmodel.dart';
|
||||||
@@ -25,6 +26,12 @@ void main() async {
|
|||||||
await SpUtil.getInstance();
|
await SpUtil.getInstance();
|
||||||
getIt.registerSingleton<UserInfoViewModel>(UserInfoViewModel());
|
getIt.registerSingleton<UserInfoViewModel>(UserInfoViewModel());
|
||||||
|
|
||||||
|
await SystemChrome.setPreferredOrientations(
|
||||||
|
[
|
||||||
|
DeviceOrientation.portraitUp,
|
||||||
|
DeviceOrientation.portraitDown,
|
||||||
|
],
|
||||||
|
);
|
||||||
runApp(
|
runApp(
|
||||||
ProviderScope(
|
ProviderScope(
|
||||||
overrides: [
|
overrides: [
|
||||||
@@ -55,10 +62,22 @@ class QlAppState extends ConsumerState<QlApp> {
|
|||||||
FocusScope.of(context).requestFocus(FocusNode());
|
FocusScope.of(context).requestFocus(FocusNode());
|
||||||
},
|
},
|
||||||
child: MediaQuery(
|
child: MediaQuery(
|
||||||
data: MediaQueryData.fromWindow(WidgetsBinding.instance!.window).copyWith(textScaleFactor: 1,),
|
data: MediaQueryData.fromWindow(WidgetsBinding.instance!.window).copyWith(
|
||||||
|
textScaleFactor: 1,
|
||||||
|
),
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
locale: const Locale('zh', 'cn'),
|
title: "青龙",
|
||||||
|
locale: const Locale('zh', 'CN'),
|
||||||
navigatorKey: navigatorState,
|
navigatorKey: navigatorState,
|
||||||
|
localizationsDelegates: const [
|
||||||
|
GlobalMaterialLocalizations.delegate,
|
||||||
|
GlobalWidgetsLocalizations.delegate,
|
||||||
|
GlobalCupertinoLocalizations.delegate,
|
||||||
|
],
|
||||||
|
supportedLocales: const [
|
||||||
|
Locale('zh', 'CN'),
|
||||||
|
Locale('en', 'US'),
|
||||||
|
],
|
||||||
theme: ref.watch<ThemeViewModel>(themeProvider).currentTheme,
|
theme: ref.watch<ThemeViewModel>(themeProvider).currentTheme,
|
||||||
onGenerateRoute: (setting) {
|
onGenerateRoute: (setting) {
|
||||||
return Routes.generateRoute(setting);
|
return Routes.generateRoute(setting);
|
||||||
@@ -66,7 +85,7 @@ class QlAppState extends ConsumerState<QlApp> {
|
|||||||
home: Builder(
|
home: Builder(
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
if (!kReleaseMode) {
|
if (!kReleaseMode) {
|
||||||
showDebugBtn(context, btnColor: Colors.blue);
|
showDebugBtn(context);
|
||||||
}
|
}
|
||||||
return getIt<UserInfoViewModel>().isLogined() ? const HomePage() : const LoginPage();
|
return getIt<UserInfoViewModel>().isLogined() ? const HomePage() : const LoginPage();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
|
import 'package:code_text_field/code_text_field.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:highlight/languages/powershell.dart';
|
||||||
import 'package:qinglong_app/base/http/api.dart';
|
import 'package:qinglong_app/base/http/api.dart';
|
||||||
import 'package:qinglong_app/base/http/http.dart';
|
import 'package:qinglong_app/base/http/http.dart';
|
||||||
import 'package:qinglong_app/base/ql_app_bar.dart';
|
import 'package:qinglong_app/base/ql_app_bar.dart';
|
||||||
import 'package:qinglong_app/base/theme.dart';
|
import 'package:qinglong_app/base/theme.dart';
|
||||||
import 'package:qinglong_app/module/config/config_viewmodel.dart';
|
|
||||||
import 'package:qinglong_app/utils/extension.dart';
|
import 'package:qinglong_app/utils/extension.dart';
|
||||||
|
|
||||||
class ConfigEditPage extends ConsumerStatefulWidget {
|
class ConfigEditPage extends ConsumerStatefulWidget {
|
||||||
@@ -18,22 +19,38 @@ class ConfigEditPage extends ConsumerStatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ConfigEditPageState extends ConsumerState<ConfigEditPage> {
|
class _ConfigEditPageState extends ConsumerState<ConfigEditPage> {
|
||||||
late TextEditingController _controller;
|
CodeController? _codeController;
|
||||||
FocusNode node = FocusNode();
|
late String result;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_codeController?.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_controller = TextEditingController(text: widget.content);
|
result = widget.content;
|
||||||
|
|
||||||
super.initState();
|
super.initState();
|
||||||
WidgetsBinding.instance?.addPostFrameCallback(
|
|
||||||
(timeStamp) {
|
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
||||||
node.requestFocus();
|
focusNode.requestFocus();
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
_codeController ??= CodeController(
|
||||||
|
text: widget.content,
|
||||||
|
language: powershell,
|
||||||
|
onChange: (value) {
|
||||||
|
result = value;
|
||||||
|
},
|
||||||
|
theme: ref.watch(themeProvider).themeColor.codeEditorTheme(),
|
||||||
|
stringMap: {
|
||||||
|
"export": const TextStyle(fontWeight: FontWeight.normal, color: Color(0xff6B2375)),
|
||||||
|
},
|
||||||
|
);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: QlAppBar(
|
appBar: QlAppBar(
|
||||||
canBack: true,
|
canBack: true,
|
||||||
@@ -44,12 +61,10 @@ class _ConfigEditPageState extends ConsumerState<ConfigEditPage> {
|
|||||||
actions: [
|
actions: [
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
HttpResponse<NullResponse> response =
|
HttpResponse<NullResponse> response = await Api.saveFile(widget.title, result);
|
||||||
await Api.saveFile(widget.title, _controller.text);
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
"提交成功".toast();
|
"提交成功".toast();
|
||||||
ref.read(configProvider).loadContent(widget.title);
|
Navigator.of(context).pop(widget.title);
|
||||||
Navigator.of(context).pop();
|
|
||||||
} else {
|
} else {
|
||||||
(response.message ?? "").toast();
|
(response.message ?? "").toast();
|
||||||
}
|
}
|
||||||
@@ -71,24 +86,16 @@ class _ConfigEditPageState extends ConsumerState<ConfigEditPage> {
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: Container(
|
body: SafeArea(
|
||||||
padding: const EdgeInsets.only(
|
top: false,
|
||||||
left: 15,
|
child: CodeField(
|
||||||
right: 15,
|
controller: _codeController!,
|
||||||
),
|
expands: true,
|
||||||
child: SingleChildScrollView(
|
background: ref.watch(themeProvider).themeColor.settingBgColor(),
|
||||||
child: TextField(
|
|
||||||
focusNode: node,
|
|
||||||
style: TextStyle(
|
|
||||||
color: ref.read(themeProvider).themeColor.descColor(),
|
|
||||||
fontSize: 14,
|
|
||||||
),
|
|
||||||
controller: _controller,
|
|
||||||
minLines: 1,
|
|
||||||
maxLines: 100,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FocusNode focusNode = FocusNode();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_highlight/flutter_highlight.dart';
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:qinglong_app/base/base_state_widget.dart';
|
import 'package:qinglong_app/base/base_state_widget.dart';
|
||||||
import 'package:qinglong_app/base/routes.dart';
|
import 'package:qinglong_app/base/routes.dart';
|
||||||
import 'package:qinglong_app/base/theme.dart';
|
|
||||||
import 'package:qinglong_app/base/ui/abs_underline_tabindicator.dart';
|
import 'package:qinglong_app/base/ui/abs_underline_tabindicator.dart';
|
||||||
|
import 'package:qinglong_app/base/ui/empty_widget.dart';
|
||||||
import 'package:qinglong_app/main.dart';
|
import 'package:qinglong_app/main.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
|
import '../../base/ui/syntax_highlighter.dart';
|
||||||
import 'config_viewmodel.dart';
|
import 'config_viewmodel.dart';
|
||||||
|
|
||||||
class ConfigPage extends StatefulWidget {
|
class ConfigPage extends StatefulWidget {
|
||||||
@@ -17,8 +20,9 @@ class ConfigPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ConfigPageState extends State<ConfigPage>
|
class ConfigPageState extends State<ConfigPage>
|
||||||
with SingleTickerProviderStateMixin {
|
with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin {
|
||||||
TabController? _tabController;
|
int _initIndex = 0;
|
||||||
|
BuildContext? childContext;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -29,13 +33,18 @@ class ConfigPageState extends State<ConfigPage>
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BaseStateWidget<ConfigViewModel>(
|
return BaseStateWidget<ConfigViewModel>(
|
||||||
builder: (ref, model, child) {
|
builder: (ref, model, child) {
|
||||||
_tabController ??=
|
if (model.list.isEmpty) {
|
||||||
TabController(length: model.list.length, vsync: this);
|
return const EmptyWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
return DefaultTabController(
|
||||||
|
length: model.list.length,
|
||||||
|
initialIndex: _initIndex,
|
||||||
|
child: Builder(builder: (context) {
|
||||||
|
childContext = context;
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
TabBar(
|
TabBar(
|
||||||
controller: _tabController,
|
|
||||||
tabs: model.list
|
tabs: model.list
|
||||||
.map((e) => Tab(
|
.map((e) => Tab(
|
||||||
text: e.title,
|
text: e.title,
|
||||||
@@ -52,22 +61,10 @@ class ConfigPageState extends State<ConfigPage>
|
|||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TabBarView(
|
child: TabBarView(
|
||||||
controller: _tabController,
|
|
||||||
children: model.list
|
children: model.list
|
||||||
.map(
|
.map(
|
||||||
(e) => SingleChildScrollView(
|
(e) => CodeWidget(
|
||||||
child: HighlightView(
|
content: model.content[e.title] ?? "",
|
||||||
model.content[e.title] ?? "",
|
|
||||||
language: "sh",
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 15,
|
|
||||||
),
|
|
||||||
theme: ref
|
|
||||||
.watch(themeProvider)
|
|
||||||
.themeColor
|
|
||||||
.codeEditorTheme(),
|
|
||||||
tabSize: 14,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.toList(),
|
.toList(),
|
||||||
@@ -75,6 +72,8 @@ class ConfigPageState extends State<ConfigPage>
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
model: configProvider,
|
model: configProvider,
|
||||||
onReady: (viewModel) {
|
onReady: (viewModel) {
|
||||||
@@ -84,11 +83,63 @@ class ConfigPageState extends State<ConfigPage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
void editMe(WidgetRef ref) {
|
void editMe(WidgetRef ref) {
|
||||||
if (_tabController == null || _tabController!.length == 0) return;
|
if (childContext == null) return;
|
||||||
navigatorState.currentState?.pushNamed(Routes.routeConfigEdit, arguments: {
|
navigatorState.currentState?.pushNamed(Routes.routeConfigEdit, arguments: {
|
||||||
"title": ref.read(configProvider).list[_tabController?.index ?? 0].title,
|
"title": ref
|
||||||
"content": ref.read(configProvider).content[
|
.read(configProvider)
|
||||||
ref.read(configProvider).list[_tabController?.index ?? 0].title]
|
.list[DefaultTabController.of(childContext!)?.index ?? 0]
|
||||||
|
.title,
|
||||||
|
"content": ref.read(configProvider).content[ref
|
||||||
|
.read(configProvider)
|
||||||
|
.list[DefaultTabController.of(childContext!)?.index ?? 0]
|
||||||
|
.title]
|
||||||
|
}).then((value) async {
|
||||||
|
if (value != null && (value as String).isNotEmpty) {
|
||||||
|
await ref.read(configProvider).loadContent(value);
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get wantKeepAlive => true;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CodeWidget extends StatefulWidget {
|
||||||
|
final String content;
|
||||||
|
|
||||||
|
const CodeWidget({
|
||||||
|
Key? key,
|
||||||
|
required this.content,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<CodeWidget> createState() => _CodeWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CodeWidgetState extends State<CodeWidget>
|
||||||
|
with AutomaticKeepAliveClientMixin {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SelectableText.rich(
|
||||||
|
TextSpan(
|
||||||
|
style: GoogleFonts.droidSansMono(fontSize: 14).apply(
|
||||||
|
fontSizeFactor: 1,
|
||||||
|
),
|
||||||
|
children: <TextSpan>[
|
||||||
|
DartSyntaxHighlighter(SyntaxHighlighterStyle.lightThemeStyle())
|
||||||
|
.format(widget.content)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
style: DefaultTextStyle.of(context).style.apply(
|
||||||
|
fontSizeFactor: 1,
|
||||||
|
),
|
||||||
|
selectionWidthStyle: BoxWidthStyle.max,
|
||||||
|
selectionHeightStyle: BoxHeightStyle.max,
|
||||||
|
autofocus: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get wantKeepAlive => true;
|
||||||
}
|
}
|
||||||
|
|||||||
2
lib/module/env/add_env_page.dart
vendored
@@ -187,7 +187,7 @@ class _AddEnvPageState extends ConsumerState<AddEnvPage> {
|
|||||||
envBean.remarks = _remarkController.text;
|
envBean.remarks = _remarkController.text;
|
||||||
HttpResponse<NullResponse> response = await Api.addEnv(
|
HttpResponse<NullResponse> response = await Api.addEnv(
|
||||||
_nameController.text, _valueController.text, _remarkController.text,
|
_nameController.text, _valueController.text, _remarkController.text,
|
||||||
id: envBean.sId);
|
id: envBean.id,nId: envBean.nId,);
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
(envBean.sId == null) ? "新增成功" : "修改成功".toast();
|
(envBean.sId == null) ? "新增成功" : "修改成功".toast();
|
||||||
|
|||||||
19
lib/module/env/env_bean.dart
vendored
@@ -4,25 +4,24 @@ import 'package:json_conversion_annotation/json_conversion_annotation.dart';
|
|||||||
class EnvBean {
|
class EnvBean {
|
||||||
String? value;
|
String? value;
|
||||||
String? sId;
|
String? sId;
|
||||||
|
String? _id;
|
||||||
|
int? id;
|
||||||
int? created;
|
int? created;
|
||||||
int? status;
|
int? status;
|
||||||
String? timestamp;
|
String? timestamp;
|
||||||
String? name;
|
String? name;
|
||||||
String? remarks;
|
String? remarks;
|
||||||
|
|
||||||
EnvBean(
|
EnvBean({this.value, this.sId, this.created, this.status, this.timestamp, this.name, this.remarks});
|
||||||
{this.value,
|
|
||||||
this.sId,
|
get nId => _id;
|
||||||
this.created,
|
|
||||||
this.status,
|
|
||||||
this.timestamp,
|
|
||||||
this.name,
|
|
||||||
this.remarks});
|
|
||||||
|
|
||||||
EnvBean.fromJson(Map<String, dynamic> json) {
|
EnvBean.fromJson(Map<String, dynamic> json) {
|
||||||
value = json['value'];
|
value = json['value'];
|
||||||
sId = json['_id'];
|
id = json['id'];
|
||||||
created = json['created'];
|
_id = json['_id'];
|
||||||
|
sId = json.containsKey('_id') ? json['_id'].toString() : (json.containsKey('id') ? json['id'].toString() : "");
|
||||||
|
created = int.tryParse(json['created'].toString());
|
||||||
status = json['status'];
|
status = json['status'];
|
||||||
timestamp = json['timestamp'];
|
timestamp = json['timestamp'];
|
||||||
name = json['name'];
|
name = json['name'];
|
||||||
|
|||||||
6
lib/module/env/env_detail_page.dart
vendored
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
@@ -249,7 +251,7 @@ class _TaskDetailPageState extends ConsumerState<EnvDetailPage> {
|
|||||||
child: Text(
|
child: Text(
|
||||||
"确定",
|
"确定",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: primaryColor,
|
color: ref.watch(themeProvider).primaryColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@@ -312,6 +314,8 @@ class EnvDetailCell extends ConsumerWidget {
|
|||||||
child: SelectableText(
|
child: SelectableText(
|
||||||
desc!,
|
desc!,
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
|
selectionHeightStyle: BoxHeightStyle.max,
|
||||||
|
selectionWidthStyle: BoxWidthStyle.max,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (taped != null) {
|
if (taped != null) {
|
||||||
taped!();
|
taped!();
|
||||||
|
|||||||
160
lib/module/env/env_page.dart
vendored
@@ -23,6 +23,14 @@ class EnvPage extends StatefulWidget {
|
|||||||
class _EnvPageState extends State<EnvPage> {
|
class _EnvPageState extends State<EnvPage> {
|
||||||
final TextEditingController _searchController = TextEditingController();
|
final TextEditingController _searchController = TextEditingController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_searchController.addListener(() {
|
||||||
|
setState(() {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BaseStateWidget<EnvViewModel>(
|
return BaseStateWidget<EnvViewModel>(
|
||||||
@@ -37,7 +45,7 @@ class _EnvPageState extends State<EnvPage> {
|
|||||||
(value.remarks?.contains(_searchController.text) ?? false)) {
|
(value.remarks?.contains(_searchController.text) ?? false)) {
|
||||||
list.add(EnvItemCell(
|
list.add(EnvItemCell(
|
||||||
value,
|
value,
|
||||||
i + 1,
|
i,
|
||||||
ref,
|
ref,
|
||||||
key: ValueKey(value.sId),
|
key: ValueKey(value.sId),
|
||||||
));
|
));
|
||||||
@@ -51,6 +59,7 @@ class _EnvPageState extends State<EnvPage> {
|
|||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
return model.loadData(false);
|
return model.loadData(false);
|
||||||
},
|
},
|
||||||
|
child: SlidableAutoCloseBehavior(
|
||||||
child: ReorderableListView(
|
child: ReorderableListView(
|
||||||
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
|
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
|
||||||
header: searchCell(ref),
|
header: searchCell(ref),
|
||||||
@@ -72,6 +81,7 @@ class _EnvPageState extends State<EnvPage> {
|
|||||||
},
|
},
|
||||||
children: list,
|
children: list,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
model: envProvider,
|
model: envProvider,
|
||||||
@@ -133,39 +143,32 @@ class EnvItemCell extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return ColoredBox(
|
||||||
onTap: () {
|
|
||||||
Navigator.of(context).pushNamed(Routes.routeEnvDetail, arguments: bean);
|
|
||||||
},
|
|
||||||
child: ColoredBox(
|
|
||||||
color: ref.watch(themeProvider).themeColor.settingBgColor(),
|
color: ref.watch(themeProvider).themeColor.settingBgColor(),
|
||||||
child: Slidable(
|
child: Slidable(
|
||||||
key: ValueKey(bean.sId),
|
key: ValueKey(bean.sId),
|
||||||
endActionPane: ActionPane(
|
endActionPane: ActionPane(
|
||||||
motion: const ScrollMotion(),
|
motion: const StretchMotion(),
|
||||||
extentRatio: 0.45,
|
extentRatio: 0.5,
|
||||||
children: [
|
children: [
|
||||||
SlidableAction(
|
SlidableAction(
|
||||||
backgroundColor: Colors.grey,
|
backgroundColor: const Color(0xff5D5E70),
|
||||||
flex: 1,
|
|
||||||
onPressed: (_) {
|
onPressed: (_) {
|
||||||
Navigator.of(context).pushNamed(Routes.routeAddEnv, arguments: bean);
|
Navigator.of(context).pushNamed(Routes.routeAddEnv, arguments: bean);
|
||||||
},
|
},
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
icon: CupertinoIcons.pencil,
|
icon: CupertinoIcons.pencil_outline,
|
||||||
),
|
),
|
||||||
SlidableAction(
|
SlidableAction(
|
||||||
backgroundColor: Colors.orange,
|
backgroundColor: const Color(0xffA356D6),
|
||||||
flex: 1,
|
|
||||||
onPressed: (_) {
|
onPressed: (_) {
|
||||||
enableEnv();
|
enableEnv(context);
|
||||||
},
|
},
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
icon: bean.status == 0 ? Icons.dnd_forwardslash : Icons.check_circle_outline_sharp,
|
icon: bean.status == 0 ? Icons.dnd_forwardslash : Icons.check_circle_outline_sharp,
|
||||||
),
|
),
|
||||||
SlidableAction(
|
SlidableAction(
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: const Color(0xffEA4D3E),
|
||||||
flex: 1,
|
|
||||||
onPressed: (_) {
|
onPressed: (_) {
|
||||||
delEnv(context, ref);
|
delEnv(context, ref);
|
||||||
},
|
},
|
||||||
@@ -180,7 +183,13 @@ class EnvItemCell extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Material(
|
||||||
|
color: ref.watch(themeProvider).themeColor.settingBgColor(),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.of(context).pushNamed(Routes.routeEnvDetail, arguments: bean);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 15,
|
horizontal: 15,
|
||||||
vertical: 8,
|
vertical: 8,
|
||||||
@@ -196,6 +205,28 @@ class EnvItemCell extends StatelessWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
|
bean.status == 1
|
||||||
|
? const Icon(
|
||||||
|
Icons.dnd_forwardslash,
|
||||||
|
size: 18,
|
||||||
|
color: Color(0xffEA4D3E),
|
||||||
|
)
|
||||||
|
: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 5,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
border: Border.all(color: ref.watch(themeProvider).primaryColor, width: 1),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
"${getIndexByIndex(context, index)}",
|
||||||
|
style: TextStyle(color: ref.watch(themeProvider).primaryColor, fontSize: 12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 5,
|
||||||
|
),
|
||||||
Material(
|
Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: Text(
|
child: Text(
|
||||||
@@ -204,7 +235,28 @@ class EnvItemCell extends StatelessWidget {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
color: ref.watch(themeProvider).themeColor.titleColor(),
|
color: ref.watch(themeProvider).themeColor.titleColor(),
|
||||||
fontSize: 18,
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 5,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Visibility(
|
||||||
|
visible: bean.remarks != null && bean.remarks!.isNotEmpty,
|
||||||
|
child: Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Text(
|
||||||
|
"(${bean.remarks})",
|
||||||
|
maxLines: 1,
|
||||||
|
style: TextStyle(
|
||||||
|
height: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
color: ref.watch(themeProvider).themeColor.descColor(),
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -212,7 +264,7 @@ class EnvItemCell extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 5,
|
width: 15,
|
||||||
),
|
),
|
||||||
Material(
|
Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
@@ -228,55 +280,8 @@ class EnvItemCell extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 8.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 5,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(5),
|
|
||||||
border: Border.all(color: primaryColor, width: 1),
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
"$index",
|
|
||||||
style: TextStyle(color: primaryColor, fontSize: 12),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 5,
|
height: 15,
|
||||||
),
|
|
||||||
Material(
|
|
||||||
color: Colors.transparent,
|
|
||||||
child: Text(
|
|
||||||
bean.remarks ?? "-",
|
|
||||||
maxLines: 1,
|
|
||||||
style: TextStyle(
|
|
||||||
height: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
color: ref.watch(themeProvider).themeColor.descColor(),
|
|
||||||
fontSize: 12,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 5,
|
|
||||||
),
|
|
||||||
bean.status == 1
|
|
||||||
? const Icon(
|
|
||||||
Icons.dnd_forwardslash,
|
|
||||||
size: 12,
|
|
||||||
color: Colors.red,
|
|
||||||
)
|
|
||||||
: const SizedBox.shrink(),
|
|
||||||
const Spacer(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
),
|
||||||
Material(
|
Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
@@ -293,6 +298,8 @@ class EnvItemCell extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
const Divider(
|
const Divider(
|
||||||
height: 1,
|
height: 1,
|
||||||
indent: 15,
|
indent: 15,
|
||||||
@@ -301,16 +308,16 @@ class EnvItemCell extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void enableEnv() {
|
void enableEnv(BuildContext context) {
|
||||||
ref.read(envProvider).enableEnv(bean.sId!, bean.status!);
|
ref.read(envProvider).enableEnv(bean.sId!, bean.status!);
|
||||||
}
|
}
|
||||||
|
|
||||||
void delEnv(BuildContext context, WidgetRef ref) {
|
void delEnv(BuildContext context, WidgetRef ref) {
|
||||||
showCupertinoDialog(
|
showCupertinoDialog(
|
||||||
|
useRootNavigator: false,
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => CupertinoAlertDialog(
|
builder: (context) => CupertinoAlertDialog(
|
||||||
title: const Text("确认删除"),
|
title: const Text("确认删除"),
|
||||||
@@ -331,7 +338,7 @@ class EnvItemCell extends StatelessWidget {
|
|||||||
child: Text(
|
child: Text(
|
||||||
"确定",
|
"确定",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: primaryColor,
|
color: ref.watch(themeProvider).primaryColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@@ -343,4 +350,17 @@ class EnvItemCell extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getIndexByIndex(BuildContext context, int index) {
|
||||||
|
var list = ref.watch(envProvider.notifier).list;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i <= index; i++) {
|
||||||
|
if (list.length > index && list[i].status == 0) {
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:qinglong_app/base/http/api.dart';
|
||||||
import 'package:qinglong_app/base/ql_app_bar.dart';
|
import 'package:qinglong_app/base/ql_app_bar.dart';
|
||||||
import 'package:qinglong_app/base/routes.dart';
|
import 'package:qinglong_app/base/routes.dart';
|
||||||
import 'package:qinglong_app/module/config/config_page.dart';
|
import 'package:qinglong_app/module/config/config_page.dart';
|
||||||
@@ -9,6 +11,9 @@ import 'package:qinglong_app/module/env/env_page.dart';
|
|||||||
import 'package:qinglong_app/module/others/other_page.dart';
|
import 'package:qinglong_app/module/others/other_page.dart';
|
||||||
import 'package:qinglong_app/module/task/task_page.dart';
|
import 'package:qinglong_app/module/task/task_page.dart';
|
||||||
import 'package:move_to_background/move_to_background.dart';
|
import 'package:move_to_background/move_to_background.dart';
|
||||||
|
import 'dart:math' as math;
|
||||||
|
|
||||||
|
import '../../utils/utils.dart';
|
||||||
|
|
||||||
class HomePage extends ConsumerStatefulWidget {
|
class HomePage extends ConsumerStatefulWidget {
|
||||||
const HomePage({Key? key}) : super(key: key);
|
const HomePage({Key? key}) : super(key: key);
|
||||||
@@ -17,19 +22,37 @@ class HomePage extends ConsumerStatefulWidget {
|
|||||||
_HomePageState createState() => _HomePageState();
|
_HomePageState createState() => _HomePageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _HomePageState extends ConsumerState<HomePage> {
|
class _HomePageState extends ConsumerState<HomePage>
|
||||||
|
with TickerProviderStateMixin {
|
||||||
int _index = 0;
|
int _index = 0;
|
||||||
String _title = "";
|
String _title = "";
|
||||||
|
bool isNewYear = false;
|
||||||
|
|
||||||
List<IndexBean> titles = [];
|
List<IndexBean> titles = [];
|
||||||
|
|
||||||
GlobalKey<ConfigPageState> configKey = GlobalKey();
|
GlobalKey<ConfigPageState> configKey = GlobalKey();
|
||||||
|
|
||||||
|
late final AnimationController _controller = AnimationController(
|
||||||
|
duration: const Duration(milliseconds: 1000),
|
||||||
|
vsync: this,
|
||||||
|
)..repeat();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
isNewYearDuration();
|
||||||
|
|
||||||
initTitles();
|
initTitles();
|
||||||
_title = titles[0].title;
|
_title = titles[0].title;
|
||||||
super.initState();
|
super.initState();
|
||||||
|
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
||||||
|
getSystemBean();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -136,8 +159,30 @@ class _HomePageState extends ConsumerState<HomePage> {
|
|||||||
items: titles
|
items: titles
|
||||||
.map(
|
.map(
|
||||||
(e) => BottomNavigationBarItem(
|
(e) => BottomNavigationBarItem(
|
||||||
icon: Icon(e.icon),
|
icon: (e.celebrate.isNotEmpty)
|
||||||
activeIcon: Icon(e.checkedIcon),
|
? Image.asset(
|
||||||
|
e.celebrate,
|
||||||
|
width: 35,
|
||||||
|
height: 35,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
)
|
||||||
|
: Icon(e.icon),
|
||||||
|
activeIcon: (e.celebrate.isNotEmpty)
|
||||||
|
? AnimatedBuilder(
|
||||||
|
builder: (context, _) {
|
||||||
|
return Transform.rotate(
|
||||||
|
angle: _controller.value * 2.0 * math.pi,
|
||||||
|
child: Image.asset(
|
||||||
|
e.celebrate,
|
||||||
|
width: 35,
|
||||||
|
height: 35,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
animation: _controller,
|
||||||
|
)
|
||||||
|
: Icon(e.checkedIcon),
|
||||||
label: e.title,
|
label: e.title,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -148,7 +193,12 @@ class _HomePageState extends ConsumerState<HomePage> {
|
|||||||
_title = titles[index].title;
|
_title = titles[index].title;
|
||||||
setState(() {});
|
setState(() {});
|
||||||
},
|
},
|
||||||
|
elevation: 0,
|
||||||
|
selectedFontSize: 12,
|
||||||
|
unselectedFontSize: 12,
|
||||||
type: BottomNavigationBarType.fixed,
|
type: BottomNavigationBarType.fixed,
|
||||||
|
showSelectedLabels: !isNewYear,
|
||||||
|
showUnselectedLabels: !isNewYear,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -161,6 +211,7 @@ class _HomePageState extends ConsumerState<HomePage> {
|
|||||||
CupertinoIcons.timer,
|
CupertinoIcons.timer,
|
||||||
CupertinoIcons.timer_fill,
|
CupertinoIcons.timer_fill,
|
||||||
"定时任务",
|
"定时任务",
|
||||||
|
celebrate: !isNewYear ? "" : "assets/images/xin.png",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
titles.add(
|
titles.add(
|
||||||
@@ -168,6 +219,7 @@ class _HomePageState extends ConsumerState<HomePage> {
|
|||||||
CupertinoIcons.hammer,
|
CupertinoIcons.hammer,
|
||||||
CupertinoIcons.hammer_fill,
|
CupertinoIcons.hammer_fill,
|
||||||
"环境变量",
|
"环境变量",
|
||||||
|
celebrate: !isNewYear ? "" : "assets/images/chun.png",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
titles.add(
|
titles.add(
|
||||||
@@ -175,22 +227,44 @@ class _HomePageState extends ConsumerState<HomePage> {
|
|||||||
CupertinoIcons.settings,
|
CupertinoIcons.settings,
|
||||||
CupertinoIcons.settings_solid,
|
CupertinoIcons.settings_solid,
|
||||||
"配置文件",
|
"配置文件",
|
||||||
|
celebrate: !isNewYear ? "" : "assets/images/kuai.png",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
titles.add(
|
titles.add(
|
||||||
IndexBean(
|
IndexBean(
|
||||||
CupertinoIcons.cube,
|
CupertinoIcons.cube,
|
||||||
CupertinoIcons.cube_fill,
|
CupertinoIcons.cube_fill,
|
||||||
"其他",
|
"其他功能",
|
||||||
|
celebrate: !isNewYear ? "" : "assets/images/le.png",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void isNewYearDuration() {
|
||||||
|
DateTime date = DateTime.now();
|
||||||
|
DateTime dateYear1 = DateTime(2022, 1, 29);
|
||||||
|
DateTime dateYear2 = DateTime(2022, 2, 6);
|
||||||
|
|
||||||
|
if (date.isAfter(dateYear1) && date.isBefore(dateYear2)) {
|
||||||
|
isNewYear = true;
|
||||||
|
} else {
|
||||||
|
isNewYear = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void getSystemBean() async {
|
||||||
|
var bean = await Api.system();
|
||||||
|
if (bean.success) {
|
||||||
|
Utils.systemBean.version = bean.bean?.version ?? "2.10.13";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class IndexBean {
|
class IndexBean {
|
||||||
IconData icon;
|
IconData icon;
|
||||||
IconData checkedIcon;
|
IconData checkedIcon;
|
||||||
String title;
|
String title;
|
||||||
|
String celebrate;
|
||||||
|
|
||||||
IndexBean(this.icon, this.checkedIcon, this.title);
|
IndexBean(this.icon, this.checkedIcon, this.title, {this.celebrate = ""});
|
||||||
}
|
}
|
||||||
|
|||||||
116
lib/module/home/system_bean.dart
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
/// @author NewTab
|
||||||
|
|
||||||
|
import 'package:json_conversion_annotation/json_conversion_annotation.dart';
|
||||||
|
|
||||||
|
@JsonConversion()
|
||||||
|
class SystemBean {
|
||||||
|
String? version;
|
||||||
|
|
||||||
|
SystemBean({this.version});
|
||||||
|
|
||||||
|
SystemBean.fromJson(Map<String, dynamic> json) {
|
||||||
|
version = json['version'];
|
||||||
|
}
|
||||||
|
|
||||||
|
//2.12.2 以及以上版本,日志从dirs换成了data
|
||||||
|
bool isUpperVersion2_12_2() {
|
||||||
|
try {
|
||||||
|
List<String>? version1 = version?.split("\.");
|
||||||
|
|
||||||
|
String f = version1?[0] ?? "2";
|
||||||
|
String s = version1?[1] ?? "10";
|
||||||
|
String t = version1?[2] ?? "0";
|
||||||
|
|
||||||
|
if (f.length == 1) {
|
||||||
|
f = "0$f";
|
||||||
|
}
|
||||||
|
if (s.length == 1) {
|
||||||
|
s = "0$s";
|
||||||
|
}
|
||||||
|
if (t.length == 1) {
|
||||||
|
t = "0$t";
|
||||||
|
}
|
||||||
|
|
||||||
|
String tempSum = "$f$s$t";
|
||||||
|
|
||||||
|
if ((int.tryParse(tempSum) ?? 1) >= 021202) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//2.13.0 以及以上版本日志详情接口参数有变化
|
||||||
|
bool isUpperVersion2_13_0() {
|
||||||
|
try {
|
||||||
|
List<String>? version1 = version?.split("\.");
|
||||||
|
|
||||||
|
String f = version1?[0] ?? "2";
|
||||||
|
String s = version1?[1] ?? "10";
|
||||||
|
String t = version1?[2] ?? "0";
|
||||||
|
|
||||||
|
if (f.length == 1) {
|
||||||
|
f = "0$f";
|
||||||
|
}
|
||||||
|
if (s.length == 1) {
|
||||||
|
s = "0$s";
|
||||||
|
}
|
||||||
|
if (t.length == 1) {
|
||||||
|
t = "0$t";
|
||||||
|
}
|
||||||
|
|
||||||
|
String tempSum = "$f$s$t";
|
||||||
|
|
||||||
|
if ((int.tryParse(tempSum) ?? 1) >= 021300) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.10.13以上版本,针对任务,环境变量编辑做了修改
|
||||||
|
bool isUpperVersion() {
|
||||||
|
try {
|
||||||
|
List<String>? version1 = version?.split("\.");
|
||||||
|
|
||||||
|
String f = version1?[0] ?? "2";
|
||||||
|
String s = version1?[1] ?? "10";
|
||||||
|
String t = version1?[2] ?? "0";
|
||||||
|
|
||||||
|
if (f.length == 1) {
|
||||||
|
f = "0$f";
|
||||||
|
}
|
||||||
|
if (s.length == 1) {
|
||||||
|
s = "0$s";
|
||||||
|
}
|
||||||
|
if (t.length == 1) {
|
||||||
|
t = "0$t";
|
||||||
|
}
|
||||||
|
|
||||||
|
String tempSum = "$f$s$t";
|
||||||
|
|
||||||
|
if ((int.tryParse(tempSum) ?? 1) > 021013) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['version'] = this.version;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SystemBean jsonConversion(Map<String, dynamic> json) {
|
||||||
|
return SystemBean.fromJson(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,7 +21,7 @@ class LoginBean {
|
|||||||
token = json['token'];
|
token = json['token'];
|
||||||
lastip = json['lastip'];
|
lastip = json['lastip'];
|
||||||
lastaddr = json['lastaddr'];
|
lastaddr = json['lastaddr'];
|
||||||
lastlogon = json['lastlogon'];
|
lastlogon = int.tryParse(json['lastlogon'].toString());
|
||||||
retries = json['retries'];
|
retries = json['retries'];
|
||||||
platform = json['platform'];
|
platform = json['platform'];
|
||||||
}
|
}
|
||||||
|
|||||||