diff --git a/.fdroid.yml b/.fdroid.yml new file mode 100644 index 0000000..219bba4 --- /dev/null +++ b/.fdroid.yml @@ -0,0 +1,44 @@ +Categories: + - Theming +License: GPL-3.0-only +AuthorName: Christoph +WebSite: https://git.cbsk-tech.de/Christoph/LockScreenWallpaper +SourceCode: https://git.cbsk-tech.de/Christoph/LockScreenWallpaper +IssueTracker: https://git.cbsk-tech.de/Christoph/LockScreenWallpaper/issues + +AutoName: WallpaperFlow + +RepoType: git +Repo: https://git.cbsk-tech.de/Christoph/LockScreenWallpaper.git + +Builds: + - versionName: 0.1.0 + versionCode: 1000 + commit: v0.1.0 + ndk: 28.2.13676358 + sudo: + - apt-get update + - apt-get install -y npm make gcc libc-dev + srclibs: + - rustup@1.28.2 + - esbuild@v0.25.12 + scandelete: + - node_modules + prebuild: + - npm ci --ignore-scripts + - $$rustup$$/rustup-init.sh -y --default-toolchain 1.95.0 --target aarch64-linux-android,armv7-linux-androideabi,i686-linux-android,x86_64-linux-android + - source $$HOME$$/.cargo/env + - cargo install tauri-cli --version 2.11.4 --locked + - pushd $$esbuild$$ && make esbuild && popd + - mv $$esbuild$$/esbuild node_modules/@esbuild/linux-x64/bin/esbuild + build: + - source $$HOME$$/.cargo/env + - export NDK_HOME=$$NDK$$ + - export ANDROID_NDK_HOME=$$NDK$$ + - cargo tauri android build --apk + output: src-tauri/gen/android/app/build/outputs/apk/universal/release/app-universal-release-unsigned.apk + +AutoUpdateMode: Version +UpdateCheckMode: Tags +CurrentVersion: 0.1.0 +CurrentVersionCode: 1000 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f6cdd22 --- /dev/null +++ b/LICENSE @@ -0,0 +1,232 @@ +GNU GENERAL PUBLIC LICENSE +Version 3, 29 June 2007 + +Copyright © 2007 Free Software Foundation, Inc. + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +Preamble + +The GNU General Public License is a free, copyleft license for software and other kinds of works. + +The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is 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. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. + +To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. + +Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. + +Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS + +0. Definitions. + +“This License” refers to version 3 of the GNU General Public License. + +“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. + +“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations. + +To “modify” a work means to copy from or adapt all or part of the work 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. + +A “covered work” means either the unmodified Program or a work based on the Program. + +To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. + +To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. + +An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the 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. + +1. Source Code. +The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work. + +A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. + +The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. + +The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically 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. Use with the GNU Affero General Public License. +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 Affero 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 special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. + +14. Revised Versions of this License. +The Free Software Foundation may publish revised and/or new versions of the GNU 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 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 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 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 + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +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. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about box”. + +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 GPL, see . + +The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . diff --git a/PRIVACY.md b/PRIVACY.md new file mode 100644 index 0000000..1c65093 --- /dev/null +++ b/PRIVACY.md @@ -0,0 +1,41 @@ +# Datenschutzerklärung / Privacy Policy + +Stand / Last updated: 21. August 2026 + +## Deutsch + +WallpaperFlow verarbeitet die vom Nutzer ausgewählten Bilder ausschließlich lokal auf dem Android-Gerät. Die Bilder werden in den privaten App-Speicher kopiert und nur dazu verwendet, Vorschaubilder anzuzeigen und das vom Nutzer gewählte Hintergrund- oder Sperrbildschirmbild zu setzen. + +WallpaperFlow: + +- erhebt keine personenbezogenen Daten, +- überträgt keine Bilder oder Einstellungen an einen Server, +- gibt keine Daten an Dritte weiter, +- enthält keine Werbung, Analyse-, Tracking- oder Profiling-Dienste und +- verlangt keine Registrierung und kein Benutzerkonto. + +Die Einstellungen und importierten Bilder können durch das Löschen einzelner Bilder innerhalb der App oder durch das Löschen der App-Daten beziehungsweise die Deinstallation der App entfernt werden. + +Die App verwendet einen sichtbaren Android-Hintergrunddienst, um den vom Nutzer aktivierten automatischen Bildwechsel auszuführen. Nach einem Geräteneustart kann die Zeitplanung wiederhergestellt werden. Dabei werden keine Daten außerhalb des Geräts verarbeitet. + +Fragen zum Datenschutz können über den Issue-Tracker des Projekts gestellt werden: +https://git.cbsk-tech.de/Christoph/LockScreenWallpaper/issues + +## English + +WallpaperFlow processes user-selected images exclusively on the local Android device. Images are copied into the app's private storage and are used only to display previews and to set the wallpaper or lock-screen image selected by the user. + +WallpaperFlow: + +- does not collect personal data, +- does not transmit images or settings to a server, +- does not share data with third parties, +- contains no advertising, analytics, tracking or profiling services, and +- requires no registration or user account. + +Settings and imported images can be removed by deleting individual images in the app, clearing the app's data or uninstalling the app. + +The app uses a visible Android background service to perform automatic wallpaper rotation after the user enables it. Scheduling may be restored after a device restart. No data is processed outside the device for this purpose. + +Privacy questions can be submitted through the project's issue tracker: +https://git.cbsk-tech.de/Christoph/LockScreenWallpaper/issues diff --git a/README.md b/README.md index 97474c7..4c51559 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# LockScreenWallpaper +# WallpaperFlow -LockScreenWallpaper ist eine Tauri-2-App für Android, die aus einer frei wählbaren Bildsammlung bei jedem Aktivieren des Displays ein neues Sperrbildschirmbild setzt. +WallpaperFlow ist eine freie Tauri-2-App für Android, die aus einer frei wählbaren Bildsammlung in einem einstellbaren Zeitintervall ein neues Sperrbildschirmbild setzt. ## Was bereits umgesetzt ist @@ -9,11 +9,12 @@ LockScreenWallpaper ist eine Tauri-2-App für Android, die aus einer frei wählb - Wechsel nur für den Sperrbildschirm oder für das allgemeine Hintergrundbild - zufällige oder fortlaufende Reihenfolge - manueller Wechsel über „Nächstes Motiv“ -- automatischer Wechsel bei `ACTION_SCREEN_ON` +- automatischer Wechsel alle 5, 15 oder 30 Minuten beziehungsweise alle 1, 3, 6 oder 12 Stunden - Neustart des Dienstes nach einem Geräte-Neustart, soweit die Android-Version Hintergrundstarts zulässt - lokale Vorschaubilder; die Originalbilder verlassen das Gerät nicht +- vollständig lokale Oberfläche in Deutsch, Englisch, Französisch, Spanisch, Italienisch, Niederländisch, Polnisch, Portugiesisch, Japanisch, Koreanisch und vereinfachtem Chinesisch -Android hält den Listener über einen Foreground Service aktiv. Solange der automatische Wechsel eingeschaltet ist, zeigt das System deshalb eine dauerhafte, stille Benachrichtigung. Auf Geräten mit aggressivem Energiesparen muss LockScreenWallpaper gegebenenfalls von der Akku-Optimierung ausgenommen werden. +Android hält den Zeitgeber über einen Foreground Service aktiv. Solange ein Wechselintervall ausgewählt ist, zeigt das System deshalb eine dauerhafte, stille Benachrichtigung. Auf Geräten mit aggressivem Energiesparen muss LockScreenWallpaper gegebenenfalls von der Akku-Optimierung ausgenommen werden. ## Entwicklung @@ -44,7 +45,25 @@ Der native Android-Code liegt als lokales Tauri-Plugin in `plugins/android`. Er ## Wichtige Android-Hinweise -- Android erlaubt keine komplett unsichtbare, dauerhaft laufende Überwachung des Display-Status. Der automatische Wechsel verwendet deshalb korrekt einen Foreground Service. +- Android erlaubt keinen komplett unsichtbaren, dauerhaft laufenden Zeitgeber. Der automatische Wechsel verwendet deshalb einen Foreground Service. - `WallpaperManager.FLAG_LOCK` ist ab Android 7 verfügbar. Auf älteren Geräten setzt die App das allgemeine Hintergrundbild. - Hersteller können Hintergrunddienste zusätzlich einschränken. Besonders bei Samsung/Xiaomi kann eine Ausnahme von der Akku-Optimierung nötig sein. - „Ohne Limit“ bedeutet: kein App-Zähler wie Samsungs 15-Bilder-Grenze. Praktisch begrenzen freier Gerätespeicher und Dateisystem die Sammlung. + +## Datenschutz + +WallpaperFlow verarbeitet die ausgewählten Bilder ausschließlich lokal auf dem Gerät. Die App enthält keine Werbung, kein Tracking und keine Analysedienste. Bilder werden weder hochgeladen noch an Dritte weitergegeben. + +Weitere Einzelheiten stehen in der [Datenschutzerklärung](PRIVACY.md). + +## Veröffentlichungen + +Für eine neue Veröffentlichung müssen die Version in `package.json`, `src-tauri/tauri.conf.json` und `src-tauri/Cargo.toml` gemeinsam erhöht und ein passender Git-Tag angelegt werden, beispielsweise `v0.1.0`. Der Android-`versionCode` muss bei jeder Veröffentlichung steigen. + +Die Metadaten für F-Droid liegen unter `fastlane/metadata/android`. Das Buildrezept für F-Droid befindet sich in `.fdroid.yml`. + +## Lizenz + +Copyright (C) 2026 Christoph + +WallpaperFlow ist freie Software und steht unter der GNU General Public License Version 3.0 (`GPL-3.0-only`). Die vollständigen Lizenzbedingungen stehen in [LICENSE](LICENSE). diff --git a/app-icon.svg b/app-icon.svg index 095d26a..90e9d58 100644 --- a/app-icon.svg +++ b/app-icon.svg @@ -1,8 +1,10 @@ - - - - - - + + + + + + + + diff --git a/design/icon-final/android-background.svg b/design/icon-final/android-background.svg new file mode 100644 index 0000000..da07fbd --- /dev/null +++ b/design/icon-final/android-background.svg @@ -0,0 +1,3 @@ + + + diff --git a/design/icon-final/android-foreground.svg b/design/icon-final/android-foreground.svg new file mode 100644 index 0000000..a84512c --- /dev/null +++ b/design/icon-final/android-foreground.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/design/icon-final/android-monochrome.svg b/design/icon-final/android-monochrome.svg new file mode 100644 index 0000000..813da04 --- /dev/null +++ b/design/icon-final/android-monochrome.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/design/icon-final/icon-manifest.json b/design/icon-final/icon-manifest.json new file mode 100644 index 0000000..bec2b96 --- /dev/null +++ b/design/icon-final/icon-manifest.json @@ -0,0 +1,8 @@ +{ + "default": "../../app-icon.svg", + "bg_color": "#edf4e9", + "android_bg": "android-background.svg", + "android_fg": "android-foreground.svg", + "android_fg_scale": 82, + "android_monochrome": "android-monochrome.svg" +} diff --git a/design/icon-proposals/01-frame-flow.png b/design/icon-proposals/01-frame-flow.png new file mode 100644 index 0000000..b77bf61 Binary files /dev/null and b/design/icon-proposals/01-frame-flow.png differ diff --git a/design/icon-proposals/01-frame-flow.svg b/design/icon-proposals/01-frame-flow.svg new file mode 100644 index 0000000..89b0ec5 --- /dev/null +++ b/design/icon-proposals/01-frame-flow.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/design/icon-proposals/02-lockscape.png b/design/icon-proposals/02-lockscape.png new file mode 100644 index 0000000..8e17054 Binary files /dev/null and b/design/icon-proposals/02-lockscape.png differ diff --git a/design/icon-proposals/02-lockscape.svg b/design/icon-proposals/02-lockscape.svg new file mode 100644 index 0000000..51d22de --- /dev/null +++ b/design/icon-proposals/02-lockscape.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/design/icon-proposals/03-wechsel-w.png b/design/icon-proposals/03-wechsel-w.png new file mode 100644 index 0000000..f7fd57a Binary files /dev/null and b/design/icon-proposals/03-wechsel-w.png differ diff --git a/design/icon-proposals/03-wechsel-w.svg b/design/icon-proposals/03-wechsel-w.svg new file mode 100644 index 0000000..2e3f64b --- /dev/null +++ b/design/icon-proposals/03-wechsel-w.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/design/icon-proposals/04-orbit-gallery.png b/design/icon-proposals/04-orbit-gallery.png new file mode 100644 index 0000000..37fd38e Binary files /dev/null and b/design/icon-proposals/04-orbit-gallery.png differ diff --git a/design/icon-proposals/04-orbit-gallery.svg b/design/icon-proposals/04-orbit-gallery.svg new file mode 100644 index 0000000..b4010b1 --- /dev/null +++ b/design/icon-proposals/04-orbit-gallery.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/design/icon-proposals/icon-proposals-board.png b/design/icon-proposals/icon-proposals-board.png new file mode 100644 index 0000000..9fbf396 Binary files /dev/null and b/design/icon-proposals/icon-proposals-board.png differ diff --git a/design/icon-proposals/icon-proposals-board.svg b/design/icon-proposals/icon-proposals-board.svg new file mode 100644 index 0000000..6a65d03 --- /dev/null +++ b/design/icon-proposals/icon-proposals-board.svg @@ -0,0 +1,39 @@ + + + WallpaperFlow · Icon-Richtungen + Vier Varianten in der bestehenden Grün-/Salbei-Farbwelt + + + + + + 1 · Frame Flow + Foto im Mittelpunkt, Wechselbewegung + modern und sofort verständlich + + + + + + 2 · Lockscape + Sperrbildschirm eindeutig erkennbar + kräftig, funktional und unverwechselbar + + + + + + 3 · Wechsel-W + Eigenständige Markenform mit W + reduziert und gut als Logo ausbaubar + + + + + + 4 · Orbit Gallery + Dynamischer automatischer Wechsel + technischer und energiegeladener + + + diff --git a/fastlane/metadata/android/de-DE/changelogs/1000.txt b/fastlane/metadata/android/de-DE/changelogs/1000.txt new file mode 100644 index 0000000..0f9a0de --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/1000.txt @@ -0,0 +1 @@ +Erste öffentliche Version von WallpaperFlow mit automatischem Bildwechsel, lokaler Galerie, Mehrfachauswahl, Intervallsteuerung und mehrsprachiger Oberfläche. diff --git a/fastlane/metadata/android/de-DE/full_description.txt b/fastlane/metadata/android/de-DE/full_description.txt new file mode 100644 index 0000000..8ebe31e --- /dev/null +++ b/fastlane/metadata/android/de-DE/full_description.txt @@ -0,0 +1,12 @@ +WallpaperFlow wechselt automatisch zwischen deinen ausgewählten Bildern und setzt sie als Sperrbildschirm- oder Hintergrundbild. + +Funktionen: +* beliebig viele Bilder aus der Android-Auswahl importieren +* Bilder alle 5, 15 oder 30 Minuten sowie stündlich wechseln +* zufällige oder fortlaufende Reihenfolge +* nur den Sperrbildschirm oder das allgemeine Hintergrundbild ändern +* Bilder gemeinsam auswählen und löschen +* Wechsel nach einem Neustart automatisch fortsetzen +* Oberfläche in mehreren europäischen und asiatischen Sprachen + +Alle Bilder und Einstellungen bleiben lokal auf deinem Gerät. WallpaperFlow enthält keine Werbung, kein Tracking und keine Analysedienste. diff --git a/fastlane/metadata/android/de-DE/images/icon.png b/fastlane/metadata/android/de-DE/images/icon.png new file mode 100644 index 0000000..137b291 Binary files /dev/null and b/fastlane/metadata/android/de-DE/images/icon.png differ diff --git a/fastlane/metadata/android/de-DE/images/phoneScreenshots/1.png b/fastlane/metadata/android/de-DE/images/phoneScreenshots/1.png new file mode 100644 index 0000000..ce618e6 Binary files /dev/null and b/fastlane/metadata/android/de-DE/images/phoneScreenshots/1.png differ diff --git a/fastlane/metadata/android/de-DE/images/phoneScreenshots/2.png b/fastlane/metadata/android/de-DE/images/phoneScreenshots/2.png new file mode 100644 index 0000000..d6cbd8f Binary files /dev/null and b/fastlane/metadata/android/de-DE/images/phoneScreenshots/2.png differ diff --git a/fastlane/metadata/android/de-DE/short_description.txt b/fastlane/metadata/android/de-DE/short_description.txt new file mode 100644 index 0000000..64995c0 --- /dev/null +++ b/fastlane/metadata/android/de-DE/short_description.txt @@ -0,0 +1 @@ +Automatischer Wechsel deiner Sperrbildschirmbilder – lokal und privat diff --git a/fastlane/metadata/android/de-DE/title.txt b/fastlane/metadata/android/de-DE/title.txt new file mode 100644 index 0000000..dca4c6e --- /dev/null +++ b/fastlane/metadata/android/de-DE/title.txt @@ -0,0 +1 @@ +WallpaperFlow diff --git a/fastlane/metadata/android/en-US/changelogs/1000.txt b/fastlane/metadata/android/en-US/changelogs/1000.txt new file mode 100644 index 0000000..9249fbd --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/1000.txt @@ -0,0 +1 @@ +First public release of WallpaperFlow with automatic rotation, a local gallery, multi-selection, configurable intervals and a multilingual interface. diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt new file mode 100644 index 0000000..2b966de --- /dev/null +++ b/fastlane/metadata/android/en-US/full_description.txt @@ -0,0 +1,12 @@ +WallpaperFlow automatically rotates through your selected images and sets them as your lock-screen or general wallpaper. + +Features: +* import any number of images using the Android system picker +* change images every 5, 15 or 30 minutes or every few hours +* shuffle or sequential order +* change only the lock screen or the general wallpaper +* select and delete several images at once +* resume rotation after a device restart +* interface in multiple European and Asian languages + +All images and settings remain locally on your device. WallpaperFlow contains no advertising, tracking or analytics services. diff --git a/fastlane/metadata/android/en-US/images/icon.png b/fastlane/metadata/android/en-US/images/icon.png new file mode 100644 index 0000000..137b291 Binary files /dev/null and b/fastlane/metadata/android/en-US/images/icon.png differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png new file mode 100644 index 0000000..b482bfd Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png new file mode 100644 index 0000000..01ff648 Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png differ diff --git a/fastlane/metadata/android/en-US/short_description.txt b/fastlane/metadata/android/en-US/short_description.txt new file mode 100644 index 0000000..662b9c5 --- /dev/null +++ b/fastlane/metadata/android/en-US/short_description.txt @@ -0,0 +1 @@ +Automatically rotate lock-screen wallpapers locally and privately diff --git a/fastlane/metadata/android/en-US/title.txt b/fastlane/metadata/android/en-US/title.txt new file mode 100644 index 0000000..dca4c6e --- /dev/null +++ b/fastlane/metadata/android/en-US/title.txt @@ -0,0 +1 @@ +WallpaperFlow diff --git a/index.html b/index.html index 4399322..626c618 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,7 @@ - + WallpaperFlow diff --git a/package-lock.json b/package-lock.json index f92bc98..fbe5bf1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "lockscreenwallpaper", "version": "0.1.0", + "license": "GPL-3.0-only", "dependencies": { "@tauri-apps/api": "^2.8.0", "lucide-react": "^0.468.0", diff --git a/package.json b/package.json index d7fc351..09e7f85 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "lockscreenwallpaper", "private": true, "version": "0.1.0", + "license": "GPL-3.0-only", "type": "module", "scripts": { "dev": "vite", diff --git a/plugins/Cargo.toml b/plugins/Cargo.toml index db8aad5..e662d2c 100644 --- a/plugins/Cargo.toml +++ b/plugins/Cargo.toml @@ -3,6 +3,7 @@ name = "tauri-plugin-wallpaper" version = "0.1.0" authors = [ "LockScreenWallpaper" ] description = "" +license = "GPL-3.0-only" edition = "2021" rust-version = "1.77.2" exclude = ["/examples", "/dist-js", "/guest-js", "/node_modules"] diff --git a/plugins/android/src/main/AndroidManifest.xml b/plugins/android/src/main/AndroidManifest.xml index 4a6068d..9f61279 100644 --- a/plugins/android/src/main/AndroidManifest.xml +++ b/plugins/android/src/main/AndroidManifest.xml @@ -7,10 +7,14 @@ - + - + + + + + diff --git a/plugins/android/src/main/java/BootReceiver.kt b/plugins/android/src/main/java/BootReceiver.kt index 1e41e5d..d61a057 100644 --- a/plugins/android/src/main/java/BootReceiver.kt +++ b/plugins/android/src/main/java/BootReceiver.kt @@ -6,6 +6,9 @@ import android.content.Intent class BootReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { - if (intent.action == Intent.ACTION_BOOT_COMPLETED && WallpaperStore.enabled(context)) runCatching { WallpaperRotationService.start(context) } + if (intent.action in setOf(Intent.ACTION_BOOT_COMPLETED, Intent.ACTION_MY_PACKAGE_REPLACED) && WallpaperStore.enabled(context)) { + WallpaperScheduler.scheduleNext(context) + runCatching { WallpaperRotationService.start(context) } + } } } diff --git a/plugins/android/src/main/java/WallpaperAlarmReceiver.kt b/plugins/android/src/main/java/WallpaperAlarmReceiver.kt new file mode 100644 index 0000000..3a6dd84 --- /dev/null +++ b/plugins/android/src/main/java/WallpaperAlarmReceiver.kt @@ -0,0 +1,34 @@ +package de.wechselbild.wallpaper + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import java.util.concurrent.Executors + +class WallpaperAlarmReceiver : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + if (!WallpaperStore.enabled(context)) { + WallpaperScheduler.cancel(context) + return + } + val applicationContext = context.applicationContext + val result = goAsync() + executor.execute { + try { + if (WallpaperScheduler.claimIfDue(applicationContext)) try { + WallpaperStore.applyNext(applicationContext) + } finally { + WallpaperScheduler.scheduleNext(applicationContext) + } + } finally { + WallpaperScheduler.ensureScheduled(applicationContext) + WallpaperRotationService.rescheduleRunningService() + result.finish() + } + } + } + + companion object { + private val executor = Executors.newSingleThreadExecutor() + } +} diff --git a/plugins/android/src/main/java/WallpaperPlugin.kt b/plugins/android/src/main/java/WallpaperPlugin.kt index ce3bd37..eb0649c 100644 --- a/plugins/android/src/main/java/WallpaperPlugin.kt +++ b/plugins/android/src/main/java/WallpaperPlugin.kt @@ -9,6 +9,8 @@ import app.tauri.annotation.Command import app.tauri.annotation.InvokeArg import app.tauri.annotation.TauriPlugin import app.tauri.plugin.Invoke +import app.tauri.plugin.JSArray +import app.tauri.plugin.JSObject import app.tauri.plugin.Plugin import java.io.File import java.util.UUID @@ -17,12 +19,18 @@ import java.util.concurrent.Executors @InvokeArg class SettingArgs { lateinit var name: String; var value: Boolean = false } +@InvokeArg +class IntervalArgs { var minutes: Int = 0 } + @InvokeArg class GalleryArgs { var offset: Int = 0; var limit: Int = 48 } @InvokeArg class DeleteImageArgs { lateinit var id: String } +@InvokeArg +class DeleteImagesArgs { var ids: Array = emptyArray() } + @InvokeArg class ImageCropArgs { lateinit var id: String @@ -36,7 +44,10 @@ class ImageCropArgs { class WallpaperPlugin(private val activity: Activity) : Plugin(activity) { private val io = Executors.newSingleThreadExecutor() - @Command fun getState(invoke: Invoke) = io.execute { invoke.resolve(WallpaperStore.state(activity)) } + @Command fun getState(invoke: Invoke) { + if (WallpaperStore.enabled(activity)) runCatching { WallpaperRotationService.start(activity) } + io.execute { invoke.resolve(WallpaperStore.state(activity)) } + } @Command fun getGallery(invoke: Invoke) = io.execute { try { @@ -63,6 +74,19 @@ class WallpaperPlugin(private val activity: Activity) : Plugin(activity) { } catch (error: Exception) { invoke.reject(error.message ?: "Bild konnte nicht gelöscht werden") } } + @Command fun getImageIds(invoke: Invoke) = io.execute { + val ids = JSArray().apply { WallpaperStore.imageIds(activity).forEach { put(it) } } + invoke.resolve(JSObject().apply { put("ids", ids) }) + } + + @Command fun deleteImages(invoke: Invoke) = io.execute { + try { + val args = invoke.parseArgs(DeleteImagesArgs::class.java) + if (WallpaperStore.deleteMany(activity, args.ids.toList()) == 0) throw IllegalArgumentException("Keine Bilder gefunden") + invoke.resolve(WallpaperStore.state(activity)) + } catch (error: Exception) { invoke.reject(error.message ?: "Bilder konnten nicht gelöscht werden") } + } + @Command fun setImageCrop(invoke: Invoke) = io.execute { try { val args = invoke.parseArgs(ImageCropArgs::class.java) @@ -96,13 +120,19 @@ class WallpaperPlugin(private val activity: Activity) : Plugin(activity) { try { val args = invoke.parseArgs(SettingArgs::class.java) WallpaperStore.set(activity, args.name, args.value) - if (args.name == "enabled") { - if (args.value) WallpaperRotationService.start(activity) else WallpaperRotationService.stop(activity) - } - invoke.resolve(WallpaperStore.state(activity)) + invoke.resolve(WallpaperStore.state(activity, includePreviews = false)) } catch (error: Exception) { invoke.reject(error.message ?: "Einstellung konnte nicht gespeichert werden") } } + @Command fun setInterval(invoke: Invoke) { + try { + val args = invoke.parseArgs(IntervalArgs::class.java) + WallpaperStore.setInterval(activity, args.minutes) + if (args.minutes > 0) WallpaperRotationService.restart(activity) else WallpaperRotationService.stop(activity) + invoke.resolve(WallpaperStore.state(activity, includePreviews = false)) + } catch (error: Exception) { invoke.reject(error.message ?: "Wechselintervall konnte nicht gespeichert werden") } + } + @Command fun nextWallpaper(invoke: Invoke) = io.execute { if (WallpaperStore.applyNext(activity)) invoke.resolve(WallpaperStore.state(activity)) else invoke.reject("Bitte wähle zuerst Bilder aus") } diff --git a/plugins/android/src/main/java/WallpaperRotationService.kt b/plugins/android/src/main/java/WallpaperRotationService.kt index e6dcaf6..21d9985 100644 --- a/plugins/android/src/main/java/WallpaperRotationService.kt +++ b/plugins/android/src/main/java/WallpaperRotationService.kt @@ -4,26 +4,39 @@ import android.app.NotificationChannel import android.app.NotificationManager import android.app.PendingIntent import android.app.Service -import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import android.content.IntentFilter import android.os.Build +import android.os.Handler import android.os.IBinder +import android.os.Looper import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat import java.util.concurrent.Executors class WallpaperRotationService : Service() { private val worker = Executors.newSingleThreadExecutor() - private val screenReceiver = object : BroadcastReceiver() { - override fun onReceive(context: Context, intent: Intent) { - if (intent.action == Intent.ACTION_SCREEN_ON && WallpaperStore.enabled(context)) worker.execute { WallpaperStore.applyNext(context) } + private val handler = Handler(Looper.getMainLooper()) + private val rotate = object : Runnable { + override fun run() { + if (!WallpaperStore.enabled(this@WallpaperRotationService)) { + stopSelf() + return + } + worker.execute { + if (WallpaperScheduler.claimIfDue(this@WallpaperRotationService)) try { + WallpaperStore.applyNext(this@WallpaperRotationService) + } finally { + WallpaperScheduler.scheduleNext(this@WallpaperRotationService) + } + handler.post { scheduleLocalTimer() } + } } } override fun onCreate() { super.onCreate() + runningService = this createChannel() val launch = packageManager.getLaunchIntentForPackage(packageName) val pending = PendingIntent.getActivity(this, 0, launch, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT) @@ -33,12 +46,34 @@ class WallpaperRotationService : Service() { .setContentText(getString(R.string.wallpaper_service_text)) .setOngoing(true).setSilent(true).setContentIntent(pending).build() startForeground(NOTIFICATION_ID, notification) - ContextCompat.registerReceiver(this, screenReceiver, IntentFilter(Intent.ACTION_SCREEN_ON), ContextCompat.RECEIVER_NOT_EXPORTED) + WallpaperScheduler.ensureScheduled(this) + scheduleLocalTimer() } - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int) = START_STICKY + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + if (!WallpaperStore.enabled(this)) { + stopSelf() + return START_NOT_STICKY + } + WallpaperScheduler.ensureScheduled(this) + scheduleLocalTimer() + return START_STICKY + } override fun onBind(intent: Intent?): IBinder? = null - override fun onDestroy() { runCatching { unregisterReceiver(screenReceiver) }; worker.shutdown(); super.onDestroy() } + + override fun onDestroy() { + handler.removeCallbacks(rotate) + worker.shutdown() + if (runningService === this) runningService = null + super.onDestroy() + } + + private fun scheduleLocalTimer() { + handler.removeCallbacks(rotate) + if (WallpaperStore.enabled(this)) { + handler.postDelayed(rotate, WallpaperScheduler.remainingDelay(this)) + } + } private fun createChannel() { if (Build.VERSION.SDK_INT >= 26) { @@ -50,7 +85,23 @@ class WallpaperRotationService : Service() { companion object { private const val CHANNEL = "wechselbild_rotation" private const val NOTIFICATION_ID = 4217 - fun start(context: Context) = ContextCompat.startForegroundService(context, Intent(context, WallpaperRotationService::class.java)) - fun stop(context: Context) { context.stopService(Intent(context, WallpaperRotationService::class.java)) } + @Volatile private var runningService: WallpaperRotationService? = null + + fun rescheduleRunningService() { + val service = runningService ?: return + service.handler.post { service.scheduleLocalTimer() } + } + fun start(context: Context) { + WallpaperScheduler.ensureScheduled(context) + ContextCompat.startForegroundService(context, Intent(context, WallpaperRotationService::class.java)) + } + fun restart(context: Context) { + WallpaperScheduler.scheduleNext(context) + start(context) + } + fun stop(context: Context) { + WallpaperScheduler.cancel(context) + context.stopService(Intent(context, WallpaperRotationService::class.java)) + } } } diff --git a/plugins/android/src/main/java/WallpaperScheduler.kt b/plugins/android/src/main/java/WallpaperScheduler.kt new file mode 100644 index 0000000..ae394eb --- /dev/null +++ b/plugins/android/src/main/java/WallpaperScheduler.kt @@ -0,0 +1,70 @@ +package de.wechselbild.wallpaper + +import android.app.AlarmManager +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.os.Build +import android.os.SystemClock + +object WallpaperScheduler { + private const val PREFS = "wechselbild" + private const val KEY_NEXT_TRIGGER = "next_rotation_elapsed" + private const val REQUEST_CODE = 4218 + + fun ensureScheduled(context: Context) { + if (!WallpaperStore.enabled(context)) { + cancel(context) + return + } + val now = SystemClock.elapsedRealtime() + val storedTrigger = preferences(context).getLong(KEY_NEXT_TRIGGER, 0L) + if (storedTrigger <= now) scheduleNext(context) + } + + fun remainingDelay(context: Context): Long { + val trigger = preferences(context).getLong(KEY_NEXT_TRIGGER, 0L) + return (trigger - SystemClock.elapsedRealtime()).coerceAtLeast(0L) + } + + @Synchronized + fun claimIfDue(context: Context): Boolean { + val preferences = preferences(context) + val trigger = preferences.getLong(KEY_NEXT_TRIGGER, 0L) + if (trigger <= 0L || trigger > SystemClock.elapsedRealtime() + 1_000L) return false + preferences.edit().putLong(KEY_NEXT_TRIGGER, Long.MAX_VALUE).commit() + return true + } + + fun scheduleNext(context: Context) { + val minutes = WallpaperStore.intervalMinutes(context) + if (minutes <= 0) { + cancel(context) + return + } + val trigger = SystemClock.elapsedRealtime() + minutes * 60_000L + val alarmManager = context.getSystemService(AlarmManager::class.java) + val operation = operation(context) + if (Build.VERSION.SDK_INT >= 23) { + alarmManager.setAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, trigger, operation) + } else { + alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, trigger, operation) + } + preferences(context).edit().putLong(KEY_NEXT_TRIGGER, trigger).apply() + } + + fun cancel(context: Context) { + context.getSystemService(AlarmManager::class.java).cancel(operation(context)) + preferences(context).edit().remove(KEY_NEXT_TRIGGER).apply() + } + + private fun operation(context: Context) = PendingIntent.getBroadcast( + context, + REQUEST_CODE, + Intent(context, WallpaperAlarmReceiver::class.java), + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, + ) + + private fun preferences(context: Context) = + context.getSharedPreferences(PREFS, Context.MODE_PRIVATE) +} diff --git a/plugins/android/src/main/java/WallpaperStore.kt b/plugins/android/src/main/java/WallpaperStore.kt index c68842b..4129267 100644 --- a/plugins/android/src/main/java/WallpaperStore.kt +++ b/plugins/android/src/main/java/WallpaperStore.kt @@ -9,6 +9,7 @@ import android.graphics.Color import android.graphics.Matrix import android.graphics.Paint import android.util.Base64 +import android.util.LruCache import app.tauri.plugin.JSArray import app.tauri.plugin.JSObject import java.io.ByteArrayOutputStream @@ -19,34 +20,48 @@ import org.json.JSONObject object WallpaperStore { private const val PREFS = "wechselbild" private const val KEY_INDEX = "current_index" + private const val KEY_INTERVAL = "interval_minutes" private const val CROP_PREFIX = "crop_" + private const val HOME_PREVIEW_LIMIT = 12 + private val thumbnailCache = LruCache(48) private data class CropSettings(val mode: String = "cover", val zoom: Double = 1.0, val x: Double = 0.5, val y: Double = 0.5) fun directory(context: Context) = File(context.filesDir, "wallpapers").apply { mkdirs() } fun files(context: Context) = directory(context).listFiles()?.filter { it.isFile }?.sortedBy { it.name } ?: emptyList() private fun prefs(context: Context) = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE) - fun enabled(context: Context) = prefs(context).getBoolean("enabled", false) + fun intervalMinutes(context: Context): Int { + val preferences = prefs(context) + return if (preferences.contains(KEY_INTERVAL)) preferences.getInt(KEY_INTERVAL, 0) + else if (preferences.getBoolean("enabled", false)) 30 else 0 + } + fun enabled(context: Context) = intervalMinutes(context) > 0 fun shuffle(context: Context) = prefs(context).getBoolean("shuffle", true) fun lockOnly(context: Context) = prefs(context).getBoolean("lockScreenOnly", true) fun set(context: Context, name: String, value: Boolean) { - require(name in setOf("enabled", "shuffle", "lockScreenOnly")) { "Unbekannte Einstellung" } + require(name in setOf("shuffle", "lockScreenOnly")) { "Unbekannte Einstellung" } prefs(context).edit().putBoolean(name, value).apply() } - fun state(context: Context): JSObject { + fun setInterval(context: Context, minutes: Int) { + require(minutes == 0 || minutes in 5..720) { "Ungültiges Wechselintervall" } + prefs(context).edit().putInt(KEY_INTERVAL, minutes).putBoolean("enabled", minutes > 0).apply() + } + + fun state(context: Context, includePreviews: Boolean = true): JSObject { val originals = files(context) val index = prefs(context).getInt(KEY_INDEX, 0).coerceIn(0, (originals.size - 1).coerceAtLeast(0)) - val previewFiles = if (index < 24) originals.take(24) else listOf(originals[index]) + originals.take(23) - val previewIndex = if (index < 24) index else 0 + val previewFiles = if (index < HOME_PREVIEW_LIMIT) originals.take(HOME_PREVIEW_LIMIT) else listOf(originals[index]) + originals.take(HOME_PREVIEW_LIMIT - 1) + val previewIndex = if (index < HOME_PREVIEW_LIMIT) index else 0 return JSObject().apply { put("imageCount", originals.size) put("enabled", enabled(context)) + put("intervalMinutes", intervalMinutes(context)) put("shuffle", shuffle(context)) put("lockScreenOnly", lockOnly(context)) put("currentIndex", previewIndex) val previews = JSArray() - previewFiles.forEach { previews.put(thumbnailDataUrl(it)) } + if (includePreviews) previewFiles.forEach { previews.put(thumbnailDataUrl(it)) } put("imageUrls", previews) } } @@ -66,6 +81,8 @@ object WallpaperStore { } } + fun imageIds(context: Context) = files(context).map { it.name } + private fun cropKey(id: String) = CROP_PREFIX + id private fun crop(context: Context, file: File): CropSettings { @@ -74,7 +91,7 @@ object WallpaperStore { val json = JSONObject(raw) CropSettings( mode = if (json.optString("mode") == "contain") "contain" else "cover", - zoom = json.optDouble("zoom", 1.0).coerceIn(0.35, 3.0), + zoom = json.optDouble("zoom", 1.0).coerceIn(1.0, 3.0), x = json.optDouble("x", 0.5).coerceIn(0.0, 1.0), y = json.optDouble("y", 0.5).coerceIn(0.0, 1.0), ) @@ -100,7 +117,7 @@ object WallpaperStore { val file = files(context).firstOrNull { it.name == id } ?: return null val normalized = CropSettings( mode = if (mode == "contain") "contain" else "cover", - zoom = zoom.coerceIn(0.35, 3.0), + zoom = zoom.coerceIn(1.0, 3.0), x = x.coerceIn(0.0, 1.0), y = y.coerceIn(0.0, 1.0), ) @@ -117,22 +134,30 @@ object WallpaperStore { @Synchronized fun delete(context: Context, id: String): Boolean { - if (id.isBlank() || File(id).name != id) return false - val originals = files(context) - val position = originals.indexOfFirst { it.name == id } - if (position < 0 || !originals[position].delete()) return false + return deleteMany(context, listOf(id)) == 1 + } + @Synchronized + fun deleteMany(context: Context, ids: List): Int { + val requested = ids.filter { it.isNotBlank() && File(it).name == it }.toSet() + if (requested.isEmpty()) return 0 + val originals = files(context) val preferences = prefs(context) val previousIndex = preferences.getInt(KEY_INDEX, 0).coerceIn(0, (originals.size - 1).coerceAtLeast(0)) - val remaining = originals.size - 1 + val currentName = originals.getOrNull(previousIndex)?.name + val deleted = originals.filter { it.name in requested && it.delete() } + if (deleted.isEmpty()) return 0 + val remaining = files(context) + val retainedCurrent = currentName?.let { name -> remaining.indexOfFirst { it.name == name } } ?: -1 val nextIndex = when { - remaining <= 0 -> 0 - position < previousIndex -> previousIndex - 1 - previousIndex >= remaining -> remaining - 1 - else -> previousIndex + remaining.isEmpty() -> 0 + retainedCurrent >= 0 -> retainedCurrent + else -> previousIndex.coerceAtMost(remaining.lastIndex) } - preferences.edit().remove(cropKey(id)).putInt(KEY_INDEX, nextIndex).apply() - return true + val editor = preferences.edit().putInt(KEY_INDEX, nextIndex) + deleted.forEach { editor.remove(cropKey(it.name)) } + editor.apply() + return deleted.size } private fun renderForScreen(context: Context, source: Bitmap, crop: CropSettings): Bitmap { @@ -174,16 +199,20 @@ object WallpaperStore { } private fun thumbnailDataUrl(file: File): String { + val cacheKey = "${file.absolutePath}:${file.lastModified()}:${file.length()}" + thumbnailCache.get(cacheKey)?.let { return it } val bounds = BitmapFactory.Options().apply { inJustDecodeBounds = true } BitmapFactory.decodeFile(file.absolutePath, bounds) var sample = 1 while (bounds.outWidth / sample > 360 || bounds.outHeight / sample > 480) sample *= 2 val bitmap = BitmapFactory.decodeFile(file.absolutePath, BitmapFactory.Options().apply { inSampleSize = sample }) ?: return "" - return ByteArrayOutputStream().use { out -> + val result = ByteArrayOutputStream().use { out -> bitmap.compress(Bitmap.CompressFormat.JPEG, 76, out) bitmap.recycle() "data:image/jpeg;base64," + Base64.encodeToString(out.toByteArray(), Base64.NO_WRAP) } + thumbnailCache.put(cacheKey, result) + return result } @Synchronized diff --git a/plugins/android/src/main/res/values-de/strings.xml b/plugins/android/src/main/res/values-de/strings.xml index 0146634..61c9dbd 100644 --- a/plugins/android/src/main/res/values-de/strings.xml +++ b/plugins/android/src/main/res/values-de/strings.xml @@ -1,5 +1,5 @@ WallpaperFlow ist aktiv - Das Motiv wechselt beim Aktivieren des Displays. + Das Motiv wechselt nach dem eingestellten Intervall. Automatischer Bildwechsel diff --git a/plugins/android/src/main/res/values-es/strings.xml b/plugins/android/src/main/res/values-es/strings.xml new file mode 100644 index 0000000..eb893e5 --- /dev/null +++ b/plugins/android/src/main/res/values-es/strings.xml @@ -0,0 +1,5 @@ + + WallpaperFlow está activo + El fondo cambia según el intervalo configurado. + Rotación automática de fondos + diff --git a/plugins/android/src/main/res/values-fr/strings.xml b/plugins/android/src/main/res/values-fr/strings.xml new file mode 100644 index 0000000..043cc13 --- /dev/null +++ b/plugins/android/src/main/res/values-fr/strings.xml @@ -0,0 +1,5 @@ + + WallpaperFlow est actif + Le fond d’écran change selon l’intervalle défini. + Rotation automatique des fonds d’écran + diff --git a/plugins/android/src/main/res/values-it/strings.xml b/plugins/android/src/main/res/values-it/strings.xml new file mode 100644 index 0000000..f98b3c5 --- /dev/null +++ b/plugins/android/src/main/res/values-it/strings.xml @@ -0,0 +1,5 @@ + + WallpaperFlow è attivo + Lo sfondo cambia all’intervallo configurato. + Rotazione automatica degli sfondi + diff --git a/plugins/android/src/main/res/values-ja/strings.xml b/plugins/android/src/main/res/values-ja/strings.xml new file mode 100644 index 0000000..2dbe9c4 --- /dev/null +++ b/plugins/android/src/main/res/values-ja/strings.xml @@ -0,0 +1,5 @@ + + WallpaperFlow は実行中です + 設定した間隔で壁紙が切り替わります。 + 壁紙の自動切り替え + diff --git a/plugins/android/src/main/res/values-ko/strings.xml b/plugins/android/src/main/res/values-ko/strings.xml new file mode 100644 index 0000000..444bc75 --- /dev/null +++ b/plugins/android/src/main/res/values-ko/strings.xml @@ -0,0 +1,5 @@ + + WallpaperFlow 실행 중 + 설정한 간격에 따라 배경화면이 변경됩니다. + 자동 배경화면 변경 + diff --git a/plugins/android/src/main/res/values-nl/strings.xml b/plugins/android/src/main/res/values-nl/strings.xml new file mode 100644 index 0000000..6547e5e --- /dev/null +++ b/plugins/android/src/main/res/values-nl/strings.xml @@ -0,0 +1,5 @@ + + WallpaperFlow is actief + De achtergrond wisselt volgens het ingestelde interval. + Automatisch achtergronden wisselen + diff --git a/plugins/android/src/main/res/values-pl/strings.xml b/plugins/android/src/main/res/values-pl/strings.xml new file mode 100644 index 0000000..ebc3921 --- /dev/null +++ b/plugins/android/src/main/res/values-pl/strings.xml @@ -0,0 +1,5 @@ + + WallpaperFlow jest aktywny + Tapeta zmienia się zgodnie z ustawionym interwałem. + Automatyczna zmiana tapety + diff --git a/plugins/android/src/main/res/values-pt/strings.xml b/plugins/android/src/main/res/values-pt/strings.xml new file mode 100644 index 0000000..3bb9f3f --- /dev/null +++ b/plugins/android/src/main/res/values-pt/strings.xml @@ -0,0 +1,5 @@ + + WallpaperFlow está ativo + O fundo muda de acordo com o intervalo definido. + Rotação automática de fundos + diff --git a/plugins/android/src/main/res/values-zh-rCN/strings.xml b/plugins/android/src/main/res/values-zh-rCN/strings.xml new file mode 100644 index 0000000..0512b61 --- /dev/null +++ b/plugins/android/src/main/res/values-zh-rCN/strings.xml @@ -0,0 +1,5 @@ + + WallpaperFlow 正在运行 + 壁纸会按照设定的间隔更换。 + 自动更换壁纸 + diff --git a/plugins/android/src/main/res/values/strings.xml b/plugins/android/src/main/res/values/strings.xml index dfec514..e6dffae 100644 --- a/plugins/android/src/main/res/values/strings.xml +++ b/plugins/android/src/main/res/values/strings.xml @@ -1,5 +1,5 @@ WallpaperFlow is active - The wallpaper changes whenever the screen wakes. + The wallpaper changes at the configured interval. Automatic wallpaper rotation diff --git a/plugins/build.rs b/plugins/build.rs index 76285f5..7146dfc 100644 --- a/plugins/build.rs +++ b/plugins/build.rs @@ -3,8 +3,11 @@ const COMMANDS: &[&str] = &[ "get_gallery", "select_images", "delete_image", + "get_image_ids", + "delete_images", "set_image_crop", "set_setting", + "set_interval", "next_wallpaper", ]; diff --git a/plugins/permissions/autogenerated/commands/delete_images.toml b/plugins/permissions/autogenerated/commands/delete_images.toml new file mode 100644 index 0000000..e374288 --- /dev/null +++ b/plugins/permissions/autogenerated/commands/delete_images.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-delete-images" +description = "Enables the delete_images command without any pre-configured scope." +commands.allow = ["delete_images"] + +[[permission]] +identifier = "deny-delete-images" +description = "Denies the delete_images command without any pre-configured scope." +commands.deny = ["delete_images"] diff --git a/plugins/permissions/autogenerated/commands/get_image_ids.toml b/plugins/permissions/autogenerated/commands/get_image_ids.toml new file mode 100644 index 0000000..e4bd637 --- /dev/null +++ b/plugins/permissions/autogenerated/commands/get_image_ids.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-get-image-ids" +description = "Enables the get_image_ids command without any pre-configured scope." +commands.allow = ["get_image_ids"] + +[[permission]] +identifier = "deny-get-image-ids" +description = "Denies the get_image_ids command without any pre-configured scope." +commands.deny = ["get_image_ids"] diff --git a/plugins/permissions/autogenerated/commands/set_interval.toml b/plugins/permissions/autogenerated/commands/set_interval.toml new file mode 100644 index 0000000..6fe5047 --- /dev/null +++ b/plugins/permissions/autogenerated/commands/set_interval.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-set-interval" +description = "Enables the set_interval command without any pre-configured scope." +commands.allow = ["set_interval"] + +[[permission]] +identifier = "deny-set-interval" +description = "Denies the set_interval command without any pre-configured scope." +commands.deny = ["set_interval"] diff --git a/plugins/permissions/autogenerated/reference.md b/plugins/permissions/autogenerated/reference.md index b501e57..e5d03f5 100644 --- a/plugins/permissions/autogenerated/reference.md +++ b/plugins/permissions/autogenerated/reference.md @@ -8,8 +8,11 @@ Allow the LockScreenWallpaper app to manage its wallpaper collection - `allow-get-gallery` - `allow-select-images` - `allow-delete-image` +- `allow-get-image-ids` +- `allow-delete-images` - `allow-set-image-crop` - `allow-set-setting` +- `allow-set-interval` - `allow-next-wallpaper` ## Permission Table @@ -50,6 +53,32 @@ Denies the delete_image command without any pre-configured scope. +`wallpaper:allow-delete-images` + + + + +Enables the delete_images command without any pre-configured scope. + + + + + + + +`wallpaper:deny-delete-images` + + + + +Denies the delete_images command without any pre-configured scope. + + + + + + + `wallpaper:allow-get-gallery` @@ -76,6 +105,32 @@ Denies the get_gallery command without any pre-configured scope. +`wallpaper:allow-get-image-ids` + + + + +Enables the get_image_ids command without any pre-configured scope. + + + + + + + +`wallpaper:deny-get-image-ids` + + + + +Denies the get_image_ids command without any pre-configured scope. + + + + + + + `wallpaper:allow-get-state` @@ -180,6 +235,32 @@ Denies the set_image_crop command without any pre-configured scope. +`wallpaper:allow-set-interval` + + + + +Enables the set_interval command without any pre-configured scope. + + + + + + + +`wallpaper:deny-set-interval` + + + + +Denies the set_interval command without any pre-configured scope. + + + + + + + `wallpaper:allow-set-setting` diff --git a/plugins/permissions/default.toml b/plugins/permissions/default.toml index d078b06..7dcd215 100644 --- a/plugins/permissions/default.toml +++ b/plugins/permissions/default.toml @@ -1,3 +1,3 @@ [default] description = "Allow the LockScreenWallpaper app to manage its wallpaper collection" -permissions = ["allow-get-state", "allow-get-gallery", "allow-select-images", "allow-delete-image", "allow-set-image-crop", "allow-set-setting", "allow-next-wallpaper"] +permissions = ["allow-get-state", "allow-get-gallery", "allow-select-images", "allow-delete-image", "allow-get-image-ids", "allow-delete-images", "allow-set-image-crop", "allow-set-setting", "allow-set-interval", "allow-next-wallpaper"] diff --git a/plugins/permissions/schemas/schema.json b/plugins/permissions/schemas/schema.json index 7e3d1a5..10e8395 100644 --- a/plugins/permissions/schemas/schema.json +++ b/plugins/permissions/schemas/schema.json @@ -306,6 +306,18 @@ "const": "deny-delete-image", "markdownDescription": "Denies the delete_image command without any pre-configured scope." }, + { + "description": "Enables the delete_images command without any pre-configured scope.", + "type": "string", + "const": "allow-delete-images", + "markdownDescription": "Enables the delete_images command without any pre-configured scope." + }, + { + "description": "Denies the delete_images command without any pre-configured scope.", + "type": "string", + "const": "deny-delete-images", + "markdownDescription": "Denies the delete_images command without any pre-configured scope." + }, { "description": "Enables the get_gallery command without any pre-configured scope.", "type": "string", @@ -318,6 +330,18 @@ "const": "deny-get-gallery", "markdownDescription": "Denies the get_gallery command without any pre-configured scope." }, + { + "description": "Enables the get_image_ids command without any pre-configured scope.", + "type": "string", + "const": "allow-get-image-ids", + "markdownDescription": "Enables the get_image_ids command without any pre-configured scope." + }, + { + "description": "Denies the get_image_ids command without any pre-configured scope.", + "type": "string", + "const": "deny-get-image-ids", + "markdownDescription": "Denies the get_image_ids command without any pre-configured scope." + }, { "description": "Enables the get_state command without any pre-configured scope.", "type": "string", @@ -366,6 +390,18 @@ "const": "deny-set-image-crop", "markdownDescription": "Denies the set_image_crop command without any pre-configured scope." }, + { + "description": "Enables the set_interval command without any pre-configured scope.", + "type": "string", + "const": "allow-set-interval", + "markdownDescription": "Enables the set_interval command without any pre-configured scope." + }, + { + "description": "Denies the set_interval command without any pre-configured scope.", + "type": "string", + "const": "deny-set-interval", + "markdownDescription": "Denies the set_interval command without any pre-configured scope." + }, { "description": "Enables the set_setting command without any pre-configured scope.", "type": "string", @@ -379,10 +415,10 @@ "markdownDescription": "Denies the set_setting command without any pre-configured scope." }, { - "description": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-next-wallpaper`", + "description": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-get-image-ids`\n- `allow-delete-images`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-set-interval`\n- `allow-next-wallpaper`", "type": "string", "const": "default", - "markdownDescription": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-next-wallpaper`" + "markdownDescription": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-get-image-ids`\n- `allow-delete-images`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-set-interval`\n- `allow-next-wallpaper`" } ] } diff --git a/plugins/src/commands.rs b/plugins/src/commands.rs index 60747d6..805955b 100644 --- a/plugins/src/commands.rs +++ b/plugins/src/commands.rs @@ -29,6 +29,14 @@ pub(crate) async fn delete_image( app.wallpaper().delete_image(DeleteImageRequest { id }) } #[command] +pub(crate) async fn get_image_ids(app: AppHandle) -> Result> { + app.wallpaper().get_image_ids() +} +#[command] +pub(crate) async fn delete_images(app: AppHandle, ids: Vec) -> Result { + app.wallpaper().delete_images(DeleteImagesRequest { ids }) +} +#[command] pub(crate) async fn set_image_crop( app: AppHandle, id: String, @@ -54,6 +62,10 @@ pub(crate) async fn set_setting( app.wallpaper().set_setting(SettingRequest { name, value }) } #[command] +pub(crate) async fn set_interval(app: AppHandle, minutes: usize) -> Result { + app.wallpaper().set_interval(IntervalRequest { minutes }) +} +#[command] pub(crate) async fn next_wallpaper(app: AppHandle) -> Result { app.wallpaper().next_wallpaper() } diff --git a/plugins/src/desktop.rs b/plugins/src/desktop.rs index 3c3aea9..4a8b18c 100644 --- a/plugins/src/desktop.rs +++ b/plugins/src/desktop.rs @@ -18,6 +18,7 @@ impl Wallpaper { WallpaperState { image_count: 3, enabled: true, + interval_minutes: 30, shuffle: true, lock_screen_only: true, current_index: 0, @@ -56,6 +57,12 @@ impl Wallpaper { pub fn delete_image(&self, _payload: DeleteImageRequest) -> crate::Result { Ok(Self::demo()) } + pub fn get_image_ids(&self) -> crate::Result> { + Ok((0..Self::demo().image_count).map(|index| format!("demo-{index}")).collect()) + } + pub fn delete_images(&self, _payload: DeleteImagesRequest) -> crate::Result { + Ok(Self::demo()) + } pub fn set_image_crop(&self, payload: ImageCropRequest) -> crate::Result { let url = Self::demo() .image_urls @@ -82,6 +89,12 @@ impl Wallpaper { }; Ok(state) } + pub fn set_interval(&self, payload: IntervalRequest) -> crate::Result { + let mut state = Self::demo(); + state.interval_minutes = payload.minutes; + state.enabled = payload.minutes > 0; + Ok(state) + } pub fn next_wallpaper(&self) -> crate::Result { let mut state = Self::demo(); state.current_index = 1; diff --git a/plugins/src/lib.rs b/plugins/src/lib.rs index 66e514e..9aaf930 100644 --- a/plugins/src/lib.rs +++ b/plugins/src/lib.rs @@ -40,8 +40,11 @@ pub fn init() -> TauriPlugin { commands::get_gallery, commands::select_images, commands::delete_image, + commands::get_image_ids, + commands::delete_images, commands::set_image_crop, commands::set_setting, + commands::set_interval, commands::next_wallpaper ]) .setup(|app, api| { diff --git a/plugins/src/mobile.rs b/plugins/src/mobile.rs index 61ee13f..8c3cdfc 100644 --- a/plugins/src/mobile.rs +++ b/plugins/src/mobile.rs @@ -43,6 +43,13 @@ impl Wallpaper { .run_mobile_plugin("deleteImage", payload) .map_err(Into::into) } + pub fn get_image_ids(&self) -> crate::Result> { + let response: ImageIdsResponse = self.0.run_mobile_plugin("getImageIds", ())?; + Ok(response.ids) + } + pub fn delete_images(&self, payload: DeleteImagesRequest) -> crate::Result { + self.0.run_mobile_plugin("deleteImages", payload).map_err(Into::into) + } pub fn set_image_crop(&self, payload: ImageCropRequest) -> crate::Result { self.0 .run_mobile_plugin("setImageCrop", payload) @@ -53,6 +60,11 @@ impl Wallpaper { .run_mobile_plugin("setSetting", payload) .map_err(Into::into) } + pub fn set_interval(&self, payload: IntervalRequest) -> crate::Result { + self.0 + .run_mobile_plugin("setInterval", payload) + .map_err(Into::into) + } pub fn next_wallpaper(&self) -> crate::Result { self.0 .run_mobile_plugin("nextWallpaper", ()) diff --git a/plugins/src/models.rs b/plugins/src/models.rs index 56a2c20..08be60a 100644 --- a/plugins/src/models.rs +++ b/plugins/src/models.rs @@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize}; pub struct WallpaperState { pub image_count: usize, pub enabled: bool, + pub interval_minutes: usize, pub shuffle: bool, pub lock_screen_only: bool, pub current_index: usize, @@ -18,6 +19,12 @@ pub struct SettingRequest { pub value: bool, } +#[derive(Debug, Clone, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct IntervalRequest { + pub minutes: usize, +} + #[derive(Debug, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct GalleryRequest { @@ -31,6 +38,18 @@ pub struct DeleteImageRequest { pub id: String, } +#[derive(Debug, Clone, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct DeleteImagesRequest { + pub ids: Vec, +} + +#[derive(Debug, Clone, Default, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct ImageIdsResponse { + pub ids: Vec, +} + #[derive(Debug, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct ImageCropRequest { diff --git a/public/app-icon.svg b/public/app-icon.svg index 095d26a..90e9d58 100644 --- a/public/app-icon.svg +++ b/public/app-icon.svg @@ -1,8 +1,10 @@ - - - - - - + + + + + + + + diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..d5a4e08 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,9 @@ +[toolchain] +channel = "1.95.0" +profile = "minimal" +targets = [ + "aarch64-linux-android", + "armv7-linux-androideabi", + "i686-linux-android", + "x86_64-linux-android", +] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 14bcb1e..5604cce 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -3,6 +3,7 @@ name = "lockscreenwallpaper" version = "0.1.0" description = "Unbegrenzter Sperrbildschirm-Wechsel für Android" authors = ["LockScreenWallpaper"] +license = "GPL-3.0-only" edition = "2021" [lib] diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/src-tauri/gen/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..0343c28 --- /dev/null +++ b/src-tauri/gen/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index 28f1aa1..54cb9f4 100644 Binary files a/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png b/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png new file mode 100644 index 0000000..bfcb36a Binary files /dev/null and b/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png index 85d0c88..02ed04f 100644 Binary files a/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png and b/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png b/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png new file mode 100644 index 0000000..d417975 Binary files /dev/null and b/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png index 28f1aa1..54cb9f4 100644 Binary files a/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and b/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 73e48db..144a73a 100644 Binary files a/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png b/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png new file mode 100644 index 0000000..ad20a82 Binary files /dev/null and b/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png index 13dd214..5bf6b19 100644 Binary files a/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png and b/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png b/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png new file mode 100644 index 0000000..f21e165 Binary files /dev/null and b/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png index 73e48db..144a73a 100644 Binary files a/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and b/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 1d98044..4f98fd0 100644 Binary files a/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png b/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png new file mode 100644 index 0000000..9b30e3b Binary files /dev/null and b/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png index a888b33..2d13c1a 100644 Binary files a/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png and b/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png b/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png new file mode 100644 index 0000000..b0fc708 Binary files /dev/null and b/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png index 1d98044..4f98fd0 100644 Binary files a/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and b/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 0818324..c003a95 100644 Binary files a/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png b/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png new file mode 100644 index 0000000..6905ff5 Binary files /dev/null and b/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png index a2a838e..f9196ef 100644 Binary files a/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png and b/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png b/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png new file mode 100644 index 0000000..4982172 Binary files /dev/null and b/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png index 0818324..c003a95 100644 Binary files a/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and b/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index b18bceb..f92075a 100644 Binary files a/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png b/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png new file mode 100644 index 0000000..10a834a Binary files /dev/null and b/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png index 3f8a57f..94dd03a 100644 Binary files a/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png and b/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png b/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png new file mode 100644 index 0000000..d86ebf2 Binary files /dev/null and b/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png differ diff --git a/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png index b18bceb..f92075a 100644 Binary files a/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and b/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/src-tauri/gen/android/app/src/main/res/values/ic_launcher_background.xml b/src-tauri/gen/android/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..fef4508 --- /dev/null +++ b/src-tauri/gen/android/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #EDF4E9 + diff --git a/src-tauri/gen/schemas/acl-manifests.json b/src-tauri/gen/schemas/acl-manifests.json index e7480d8..1a4eeb7 100644 --- a/src-tauri/gen/schemas/acl-manifests.json +++ b/src-tauri/gen/schemas/acl-manifests.json @@ -1 +1 @@ -{"core":{"default_permission":{"identifier":"default","description":"Default core plugins set.","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version","allow-identifier","allow-bundle-type","allow-register-listener","allow-remove-listener","allow-supports-multiple-windows"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-bundle-type":{"identifier":"allow-bundle-type","description":"Enables the bundle_type command without any pre-configured scope.","commands":{"allow":["bundle_type"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-fetch-data-store-identifiers":{"identifier":"allow-fetch-data-store-identifiers","description":"Enables the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":["fetch_data_store_identifiers"],"deny":[]}},"allow-identifier":{"identifier":"allow-identifier","description":"Enables the identifier command without any pre-configured scope.","commands":{"allow":["identifier"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-register-listener":{"identifier":"allow-register-listener","description":"Enables the register_listener command without any pre-configured scope.","commands":{"allow":["register_listener"],"deny":[]}},"allow-remove-data-store":{"identifier":"allow-remove-data-store","description":"Enables the remove_data_store command without any pre-configured scope.","commands":{"allow":["remove_data_store"],"deny":[]}},"allow-remove-listener":{"identifier":"allow-remove-listener","description":"Enables the remove_listener command without any pre-configured scope.","commands":{"allow":["remove_listener"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-set-dock-visibility":{"identifier":"allow-set-dock-visibility","description":"Enables the set_dock_visibility command without any pre-configured scope.","commands":{"allow":["set_dock_visibility"],"deny":[]}},"allow-supports-multiple-windows":{"identifier":"allow-supports-multiple-windows","description":"Enables the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":["supports_multiple_windows"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-bundle-type":{"identifier":"deny-bundle-type","description":"Denies the bundle_type command without any pre-configured scope.","commands":{"allow":[],"deny":["bundle_type"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-fetch-data-store-identifiers":{"identifier":"deny-fetch-data-store-identifiers","description":"Denies the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_data_store_identifiers"]}},"deny-identifier":{"identifier":"deny-identifier","description":"Denies the identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["identifier"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-register-listener":{"identifier":"deny-register-listener","description":"Denies the register_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["register_listener"]}},"deny-remove-data-store":{"identifier":"deny-remove-data-store","description":"Denies the remove_data_store command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_data_store"]}},"deny-remove-listener":{"identifier":"deny-remove-listener","description":"Denies the remove_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_listener"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-set-dock-visibility":{"identifier":"deny-set-dock-visibility","description":"Denies the set_dock_visibility command without any pre-configured scope.","commands":{"allow":[],"deny":["set_dock_visibility"]}},"deny-supports-multiple-windows":{"identifier":"deny-supports-multiple-windows","description":"Denies the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["supports_multiple_windows"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-icon-with-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-icon-with-as-template":{"identifier":"allow-set-icon-with-as-template","description":"Enables the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_with_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-icon-with-as-template":{"identifier":"deny-set-icon-with-as-template","description":"Denies the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_with_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-auto-resize":{"identifier":"allow-set-webview-auto-resize","description":"Enables the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":["set_webview_auto_resize"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-auto-resize":{"identifier":"deny-set-webview-auto-resize","description":"Denies the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_auto_resize"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-is-always-on-top","allow-activity-name","allow-scene-identifier","allow-internal-toggle-maximize"]},"permissions":{"allow-activity-name":{"identifier":"allow-activity-name","description":"Enables the activity_name command without any pre-configured scope.","commands":{"allow":["activity_name"],"deny":[]}},"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-always-on-top":{"identifier":"allow-is-always-on-top","description":"Enables the is_always_on_top command without any pre-configured scope.","commands":{"allow":["is_always_on_top"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-scene-identifier":{"identifier":"allow-scene-identifier","description":"Enables the scene_identifier command without any pre-configured scope.","commands":{"allow":["scene_identifier"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-focusable":{"identifier":"allow-set-focusable","description":"Enables the set_focusable command without any pre-configured scope.","commands":{"allow":["set_focusable"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-simple-fullscreen":{"identifier":"allow-set-simple-fullscreen","description":"Enables the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":["set_simple_fullscreen"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-activity-name":{"identifier":"deny-activity-name","description":"Denies the activity_name command without any pre-configured scope.","commands":{"allow":[],"deny":["activity_name"]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-always-on-top":{"identifier":"deny-is-always-on-top","description":"Denies the is_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["is_always_on_top"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-scene-identifier":{"identifier":"deny-scene-identifier","description":"Denies the scene_identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["scene_identifier"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-focusable":{"identifier":"deny-set-focusable","description":"Denies the set_focusable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focusable"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-simple-fullscreen":{"identifier":"deny-set-simple-fullscreen","description":"Denies the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_simple_fullscreen"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"wallpaper":{"default_permission":{"identifier":"default","description":"Allow the LockScreenWallpaper app to manage its wallpaper collection","permissions":["allow-get-state","allow-get-gallery","allow-select-images","allow-delete-image","allow-set-image-crop","allow-set-setting","allow-next-wallpaper"]},"permissions":{"allow-delete-image":{"identifier":"allow-delete-image","description":"Enables the delete_image command without any pre-configured scope.","commands":{"allow":["delete_image"],"deny":[]}},"allow-get-gallery":{"identifier":"allow-get-gallery","description":"Enables the get_gallery command without any pre-configured scope.","commands":{"allow":["get_gallery"],"deny":[]}},"allow-get-state":{"identifier":"allow-get-state","description":"Enables the get_state command without any pre-configured scope.","commands":{"allow":["get_state"],"deny":[]}},"allow-next-wallpaper":{"identifier":"allow-next-wallpaper","description":"Enables the next_wallpaper command without any pre-configured scope.","commands":{"allow":["next_wallpaper"],"deny":[]}},"allow-select-images":{"identifier":"allow-select-images","description":"Enables the select_images command without any pre-configured scope.","commands":{"allow":["select_images"],"deny":[]}},"allow-set-image-crop":{"identifier":"allow-set-image-crop","description":"Enables the set_image_crop command without any pre-configured scope.","commands":{"allow":["set_image_crop"],"deny":[]}},"allow-set-setting":{"identifier":"allow-set-setting","description":"Enables the set_setting command without any pre-configured scope.","commands":{"allow":["set_setting"],"deny":[]}},"deny-delete-image":{"identifier":"deny-delete-image","description":"Denies the delete_image command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_image"]}},"deny-get-gallery":{"identifier":"deny-get-gallery","description":"Denies the get_gallery command without any pre-configured scope.","commands":{"allow":[],"deny":["get_gallery"]}},"deny-get-state":{"identifier":"deny-get-state","description":"Denies the get_state command without any pre-configured scope.","commands":{"allow":[],"deny":["get_state"]}},"deny-next-wallpaper":{"identifier":"deny-next-wallpaper","description":"Denies the next_wallpaper command without any pre-configured scope.","commands":{"allow":[],"deny":["next_wallpaper"]}},"deny-select-images":{"identifier":"deny-select-images","description":"Denies the select_images command without any pre-configured scope.","commands":{"allow":[],"deny":["select_images"]}},"deny-set-image-crop":{"identifier":"deny-set-image-crop","description":"Denies the set_image_crop command without any pre-configured scope.","commands":{"allow":[],"deny":["set_image_crop"]}},"deny-set-setting":{"identifier":"deny-set-setting","description":"Denies the set_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["set_setting"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file +{"core":{"default_permission":{"identifier":"default","description":"Default core plugins set.","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version","allow-identifier","allow-bundle-type","allow-register-listener","allow-remove-listener","allow-supports-multiple-windows"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-bundle-type":{"identifier":"allow-bundle-type","description":"Enables the bundle_type command without any pre-configured scope.","commands":{"allow":["bundle_type"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-fetch-data-store-identifiers":{"identifier":"allow-fetch-data-store-identifiers","description":"Enables the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":["fetch_data_store_identifiers"],"deny":[]}},"allow-identifier":{"identifier":"allow-identifier","description":"Enables the identifier command without any pre-configured scope.","commands":{"allow":["identifier"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-register-listener":{"identifier":"allow-register-listener","description":"Enables the register_listener command without any pre-configured scope.","commands":{"allow":["register_listener"],"deny":[]}},"allow-remove-data-store":{"identifier":"allow-remove-data-store","description":"Enables the remove_data_store command without any pre-configured scope.","commands":{"allow":["remove_data_store"],"deny":[]}},"allow-remove-listener":{"identifier":"allow-remove-listener","description":"Enables the remove_listener command without any pre-configured scope.","commands":{"allow":["remove_listener"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-set-dock-visibility":{"identifier":"allow-set-dock-visibility","description":"Enables the set_dock_visibility command without any pre-configured scope.","commands":{"allow":["set_dock_visibility"],"deny":[]}},"allow-supports-multiple-windows":{"identifier":"allow-supports-multiple-windows","description":"Enables the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":["supports_multiple_windows"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-bundle-type":{"identifier":"deny-bundle-type","description":"Denies the bundle_type command without any pre-configured scope.","commands":{"allow":[],"deny":["bundle_type"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-fetch-data-store-identifiers":{"identifier":"deny-fetch-data-store-identifiers","description":"Denies the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_data_store_identifiers"]}},"deny-identifier":{"identifier":"deny-identifier","description":"Denies the identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["identifier"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-register-listener":{"identifier":"deny-register-listener","description":"Denies the register_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["register_listener"]}},"deny-remove-data-store":{"identifier":"deny-remove-data-store","description":"Denies the remove_data_store command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_data_store"]}},"deny-remove-listener":{"identifier":"deny-remove-listener","description":"Denies the remove_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_listener"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-set-dock-visibility":{"identifier":"deny-set-dock-visibility","description":"Denies the set_dock_visibility command without any pre-configured scope.","commands":{"allow":[],"deny":["set_dock_visibility"]}},"deny-supports-multiple-windows":{"identifier":"deny-supports-multiple-windows","description":"Denies the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["supports_multiple_windows"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-icon-with-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-icon-with-as-template":{"identifier":"allow-set-icon-with-as-template","description":"Enables the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_with_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-icon-with-as-template":{"identifier":"deny-set-icon-with-as-template","description":"Denies the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_with_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-auto-resize":{"identifier":"allow-set-webview-auto-resize","description":"Enables the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":["set_webview_auto_resize"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-auto-resize":{"identifier":"deny-set-webview-auto-resize","description":"Denies the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_auto_resize"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-is-always-on-top","allow-activity-name","allow-scene-identifier","allow-internal-toggle-maximize"]},"permissions":{"allow-activity-name":{"identifier":"allow-activity-name","description":"Enables the activity_name command without any pre-configured scope.","commands":{"allow":["activity_name"],"deny":[]}},"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-always-on-top":{"identifier":"allow-is-always-on-top","description":"Enables the is_always_on_top command without any pre-configured scope.","commands":{"allow":["is_always_on_top"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-scene-identifier":{"identifier":"allow-scene-identifier","description":"Enables the scene_identifier command without any pre-configured scope.","commands":{"allow":["scene_identifier"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-focusable":{"identifier":"allow-set-focusable","description":"Enables the set_focusable command without any pre-configured scope.","commands":{"allow":["set_focusable"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-simple-fullscreen":{"identifier":"allow-set-simple-fullscreen","description":"Enables the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":["set_simple_fullscreen"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-activity-name":{"identifier":"deny-activity-name","description":"Denies the activity_name command without any pre-configured scope.","commands":{"allow":[],"deny":["activity_name"]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-always-on-top":{"identifier":"deny-is-always-on-top","description":"Denies the is_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["is_always_on_top"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-scene-identifier":{"identifier":"deny-scene-identifier","description":"Denies the scene_identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["scene_identifier"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-focusable":{"identifier":"deny-set-focusable","description":"Denies the set_focusable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focusable"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-simple-fullscreen":{"identifier":"deny-set-simple-fullscreen","description":"Denies the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_simple_fullscreen"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"wallpaper":{"default_permission":{"identifier":"default","description":"Allow the LockScreenWallpaper app to manage its wallpaper collection","permissions":["allow-get-state","allow-get-gallery","allow-select-images","allow-delete-image","allow-get-image-ids","allow-delete-images","allow-set-image-crop","allow-set-setting","allow-set-interval","allow-next-wallpaper"]},"permissions":{"allow-delete-image":{"identifier":"allow-delete-image","description":"Enables the delete_image command without any pre-configured scope.","commands":{"allow":["delete_image"],"deny":[]}},"allow-delete-images":{"identifier":"allow-delete-images","description":"Enables the delete_images command without any pre-configured scope.","commands":{"allow":["delete_images"],"deny":[]}},"allow-get-gallery":{"identifier":"allow-get-gallery","description":"Enables the get_gallery command without any pre-configured scope.","commands":{"allow":["get_gallery"],"deny":[]}},"allow-get-image-ids":{"identifier":"allow-get-image-ids","description":"Enables the get_image_ids command without any pre-configured scope.","commands":{"allow":["get_image_ids"],"deny":[]}},"allow-get-state":{"identifier":"allow-get-state","description":"Enables the get_state command without any pre-configured scope.","commands":{"allow":["get_state"],"deny":[]}},"allow-next-wallpaper":{"identifier":"allow-next-wallpaper","description":"Enables the next_wallpaper command without any pre-configured scope.","commands":{"allow":["next_wallpaper"],"deny":[]}},"allow-select-images":{"identifier":"allow-select-images","description":"Enables the select_images command without any pre-configured scope.","commands":{"allow":["select_images"],"deny":[]}},"allow-set-image-crop":{"identifier":"allow-set-image-crop","description":"Enables the set_image_crop command without any pre-configured scope.","commands":{"allow":["set_image_crop"],"deny":[]}},"allow-set-interval":{"identifier":"allow-set-interval","description":"Enables the set_interval command without any pre-configured scope.","commands":{"allow":["set_interval"],"deny":[]}},"allow-set-setting":{"identifier":"allow-set-setting","description":"Enables the set_setting command without any pre-configured scope.","commands":{"allow":["set_setting"],"deny":[]}},"deny-delete-image":{"identifier":"deny-delete-image","description":"Denies the delete_image command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_image"]}},"deny-delete-images":{"identifier":"deny-delete-images","description":"Denies the delete_images command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_images"]}},"deny-get-gallery":{"identifier":"deny-get-gallery","description":"Denies the get_gallery command without any pre-configured scope.","commands":{"allow":[],"deny":["get_gallery"]}},"deny-get-image-ids":{"identifier":"deny-get-image-ids","description":"Denies the get_image_ids command without any pre-configured scope.","commands":{"allow":[],"deny":["get_image_ids"]}},"deny-get-state":{"identifier":"deny-get-state","description":"Denies the get_state command without any pre-configured scope.","commands":{"allow":[],"deny":["get_state"]}},"deny-next-wallpaper":{"identifier":"deny-next-wallpaper","description":"Denies the next_wallpaper command without any pre-configured scope.","commands":{"allow":[],"deny":["next_wallpaper"]}},"deny-select-images":{"identifier":"deny-select-images","description":"Denies the select_images command without any pre-configured scope.","commands":{"allow":[],"deny":["select_images"]}},"deny-set-image-crop":{"identifier":"deny-set-image-crop","description":"Denies the set_image_crop command without any pre-configured scope.","commands":{"allow":[],"deny":["set_image_crop"]}},"deny-set-interval":{"identifier":"deny-set-interval","description":"Denies the set_interval command without any pre-configured scope.","commands":{"allow":[],"deny":["set_interval"]}},"deny-set-setting":{"identifier":"deny-set-setting","description":"Denies the set_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["set_setting"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file diff --git a/src-tauri/gen/schemas/android-schema.json b/src-tauri/gen/schemas/android-schema.json index 724ce3b..a47e904 100644 --- a/src-tauri/gen/schemas/android-schema.json +++ b/src-tauri/gen/schemas/android-schema.json @@ -2193,10 +2193,10 @@ "markdownDescription": "Denies the unminimize command without any pre-configured scope." }, { - "description": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-next-wallpaper`", + "description": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-get-image-ids`\n- `allow-delete-images`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-set-interval`\n- `allow-next-wallpaper`", "type": "string", "const": "wallpaper:default", - "markdownDescription": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-next-wallpaper`" + "markdownDescription": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-get-image-ids`\n- `allow-delete-images`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-set-interval`\n- `allow-next-wallpaper`" }, { "description": "Enables the delete_image command without any pre-configured scope.", @@ -2204,12 +2204,24 @@ "const": "wallpaper:allow-delete-image", "markdownDescription": "Enables the delete_image command without any pre-configured scope." }, + { + "description": "Enables the delete_images command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:allow-delete-images", + "markdownDescription": "Enables the delete_images command without any pre-configured scope." + }, { "description": "Enables the get_gallery command without any pre-configured scope.", "type": "string", "const": "wallpaper:allow-get-gallery", "markdownDescription": "Enables the get_gallery command without any pre-configured scope." }, + { + "description": "Enables the get_image_ids command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:allow-get-image-ids", + "markdownDescription": "Enables the get_image_ids command without any pre-configured scope." + }, { "description": "Enables the get_state command without any pre-configured scope.", "type": "string", @@ -2234,6 +2246,12 @@ "const": "wallpaper:allow-set-image-crop", "markdownDescription": "Enables the set_image_crop command without any pre-configured scope." }, + { + "description": "Enables the set_interval command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:allow-set-interval", + "markdownDescription": "Enables the set_interval command without any pre-configured scope." + }, { "description": "Enables the set_setting command without any pre-configured scope.", "type": "string", @@ -2246,12 +2264,24 @@ "const": "wallpaper:deny-delete-image", "markdownDescription": "Denies the delete_image command without any pre-configured scope." }, + { + "description": "Denies the delete_images command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:deny-delete-images", + "markdownDescription": "Denies the delete_images command without any pre-configured scope." + }, { "description": "Denies the get_gallery command without any pre-configured scope.", "type": "string", "const": "wallpaper:deny-get-gallery", "markdownDescription": "Denies the get_gallery command without any pre-configured scope." }, + { + "description": "Denies the get_image_ids command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:deny-get-image-ids", + "markdownDescription": "Denies the get_image_ids command without any pre-configured scope." + }, { "description": "Denies the get_state command without any pre-configured scope.", "type": "string", @@ -2276,6 +2306,12 @@ "const": "wallpaper:deny-set-image-crop", "markdownDescription": "Denies the set_image_crop command without any pre-configured scope." }, + { + "description": "Denies the set_interval command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:deny-set-interval", + "markdownDescription": "Denies the set_interval command without any pre-configured scope." + }, { "description": "Denies the set_setting command without any pre-configured scope.", "type": "string", diff --git a/src-tauri/gen/schemas/desktop-schema.json b/src-tauri/gen/schemas/desktop-schema.json index 724ce3b..a47e904 100644 --- a/src-tauri/gen/schemas/desktop-schema.json +++ b/src-tauri/gen/schemas/desktop-schema.json @@ -2193,10 +2193,10 @@ "markdownDescription": "Denies the unminimize command without any pre-configured scope." }, { - "description": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-next-wallpaper`", + "description": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-get-image-ids`\n- `allow-delete-images`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-set-interval`\n- `allow-next-wallpaper`", "type": "string", "const": "wallpaper:default", - "markdownDescription": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-next-wallpaper`" + "markdownDescription": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-get-image-ids`\n- `allow-delete-images`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-set-interval`\n- `allow-next-wallpaper`" }, { "description": "Enables the delete_image command without any pre-configured scope.", @@ -2204,12 +2204,24 @@ "const": "wallpaper:allow-delete-image", "markdownDescription": "Enables the delete_image command without any pre-configured scope." }, + { + "description": "Enables the delete_images command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:allow-delete-images", + "markdownDescription": "Enables the delete_images command without any pre-configured scope." + }, { "description": "Enables the get_gallery command without any pre-configured scope.", "type": "string", "const": "wallpaper:allow-get-gallery", "markdownDescription": "Enables the get_gallery command without any pre-configured scope." }, + { + "description": "Enables the get_image_ids command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:allow-get-image-ids", + "markdownDescription": "Enables the get_image_ids command without any pre-configured scope." + }, { "description": "Enables the get_state command without any pre-configured scope.", "type": "string", @@ -2234,6 +2246,12 @@ "const": "wallpaper:allow-set-image-crop", "markdownDescription": "Enables the set_image_crop command without any pre-configured scope." }, + { + "description": "Enables the set_interval command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:allow-set-interval", + "markdownDescription": "Enables the set_interval command without any pre-configured scope." + }, { "description": "Enables the set_setting command without any pre-configured scope.", "type": "string", @@ -2246,12 +2264,24 @@ "const": "wallpaper:deny-delete-image", "markdownDescription": "Denies the delete_image command without any pre-configured scope." }, + { + "description": "Denies the delete_images command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:deny-delete-images", + "markdownDescription": "Denies the delete_images command without any pre-configured scope." + }, { "description": "Denies the get_gallery command without any pre-configured scope.", "type": "string", "const": "wallpaper:deny-get-gallery", "markdownDescription": "Denies the get_gallery command without any pre-configured scope." }, + { + "description": "Denies the get_image_ids command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:deny-get-image-ids", + "markdownDescription": "Denies the get_image_ids command without any pre-configured scope." + }, { "description": "Denies the get_state command without any pre-configured scope.", "type": "string", @@ -2276,6 +2306,12 @@ "const": "wallpaper:deny-set-image-crop", "markdownDescription": "Denies the set_image_crop command without any pre-configured scope." }, + { + "description": "Denies the set_interval command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:deny-set-interval", + "markdownDescription": "Denies the set_interval command without any pre-configured scope." + }, { "description": "Denies the set_setting command without any pre-configured scope.", "type": "string", diff --git a/src-tauri/gen/schemas/linux-schema.json b/src-tauri/gen/schemas/linux-schema.json index 724ce3b..a47e904 100644 --- a/src-tauri/gen/schemas/linux-schema.json +++ b/src-tauri/gen/schemas/linux-schema.json @@ -2193,10 +2193,10 @@ "markdownDescription": "Denies the unminimize command without any pre-configured scope." }, { - "description": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-next-wallpaper`", + "description": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-get-image-ids`\n- `allow-delete-images`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-set-interval`\n- `allow-next-wallpaper`", "type": "string", "const": "wallpaper:default", - "markdownDescription": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-next-wallpaper`" + "markdownDescription": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-get-image-ids`\n- `allow-delete-images`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-set-interval`\n- `allow-next-wallpaper`" }, { "description": "Enables the delete_image command without any pre-configured scope.", @@ -2204,12 +2204,24 @@ "const": "wallpaper:allow-delete-image", "markdownDescription": "Enables the delete_image command without any pre-configured scope." }, + { + "description": "Enables the delete_images command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:allow-delete-images", + "markdownDescription": "Enables the delete_images command without any pre-configured scope." + }, { "description": "Enables the get_gallery command without any pre-configured scope.", "type": "string", "const": "wallpaper:allow-get-gallery", "markdownDescription": "Enables the get_gallery command without any pre-configured scope." }, + { + "description": "Enables the get_image_ids command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:allow-get-image-ids", + "markdownDescription": "Enables the get_image_ids command without any pre-configured scope." + }, { "description": "Enables the get_state command without any pre-configured scope.", "type": "string", @@ -2234,6 +2246,12 @@ "const": "wallpaper:allow-set-image-crop", "markdownDescription": "Enables the set_image_crop command without any pre-configured scope." }, + { + "description": "Enables the set_interval command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:allow-set-interval", + "markdownDescription": "Enables the set_interval command without any pre-configured scope." + }, { "description": "Enables the set_setting command without any pre-configured scope.", "type": "string", @@ -2246,12 +2264,24 @@ "const": "wallpaper:deny-delete-image", "markdownDescription": "Denies the delete_image command without any pre-configured scope." }, + { + "description": "Denies the delete_images command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:deny-delete-images", + "markdownDescription": "Denies the delete_images command without any pre-configured scope." + }, { "description": "Denies the get_gallery command without any pre-configured scope.", "type": "string", "const": "wallpaper:deny-get-gallery", "markdownDescription": "Denies the get_gallery command without any pre-configured scope." }, + { + "description": "Denies the get_image_ids command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:deny-get-image-ids", + "markdownDescription": "Denies the get_image_ids command without any pre-configured scope." + }, { "description": "Denies the get_state command without any pre-configured scope.", "type": "string", @@ -2276,6 +2306,12 @@ "const": "wallpaper:deny-set-image-crop", "markdownDescription": "Denies the set_image_crop command without any pre-configured scope." }, + { + "description": "Denies the set_interval command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:deny-set-interval", + "markdownDescription": "Denies the set_interval command without any pre-configured scope." + }, { "description": "Denies the set_setting command without any pre-configured scope.", "type": "string", diff --git a/src-tauri/gen/schemas/mobile-schema.json b/src-tauri/gen/schemas/mobile-schema.json index 724ce3b..a47e904 100644 --- a/src-tauri/gen/schemas/mobile-schema.json +++ b/src-tauri/gen/schemas/mobile-schema.json @@ -2193,10 +2193,10 @@ "markdownDescription": "Denies the unminimize command without any pre-configured scope." }, { - "description": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-next-wallpaper`", + "description": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-get-image-ids`\n- `allow-delete-images`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-set-interval`\n- `allow-next-wallpaper`", "type": "string", "const": "wallpaper:default", - "markdownDescription": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-next-wallpaper`" + "markdownDescription": "Allow the LockScreenWallpaper app to manage its wallpaper collection\n#### This default permission set includes:\n\n- `allow-get-state`\n- `allow-get-gallery`\n- `allow-select-images`\n- `allow-delete-image`\n- `allow-get-image-ids`\n- `allow-delete-images`\n- `allow-set-image-crop`\n- `allow-set-setting`\n- `allow-set-interval`\n- `allow-next-wallpaper`" }, { "description": "Enables the delete_image command without any pre-configured scope.", @@ -2204,12 +2204,24 @@ "const": "wallpaper:allow-delete-image", "markdownDescription": "Enables the delete_image command without any pre-configured scope." }, + { + "description": "Enables the delete_images command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:allow-delete-images", + "markdownDescription": "Enables the delete_images command without any pre-configured scope." + }, { "description": "Enables the get_gallery command without any pre-configured scope.", "type": "string", "const": "wallpaper:allow-get-gallery", "markdownDescription": "Enables the get_gallery command without any pre-configured scope." }, + { + "description": "Enables the get_image_ids command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:allow-get-image-ids", + "markdownDescription": "Enables the get_image_ids command without any pre-configured scope." + }, { "description": "Enables the get_state command without any pre-configured scope.", "type": "string", @@ -2234,6 +2246,12 @@ "const": "wallpaper:allow-set-image-crop", "markdownDescription": "Enables the set_image_crop command without any pre-configured scope." }, + { + "description": "Enables the set_interval command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:allow-set-interval", + "markdownDescription": "Enables the set_interval command without any pre-configured scope." + }, { "description": "Enables the set_setting command without any pre-configured scope.", "type": "string", @@ -2246,12 +2264,24 @@ "const": "wallpaper:deny-delete-image", "markdownDescription": "Denies the delete_image command without any pre-configured scope." }, + { + "description": "Denies the delete_images command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:deny-delete-images", + "markdownDescription": "Denies the delete_images command without any pre-configured scope." + }, { "description": "Denies the get_gallery command without any pre-configured scope.", "type": "string", "const": "wallpaper:deny-get-gallery", "markdownDescription": "Denies the get_gallery command without any pre-configured scope." }, + { + "description": "Denies the get_image_ids command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:deny-get-image-ids", + "markdownDescription": "Denies the get_image_ids command without any pre-configured scope." + }, { "description": "Denies the get_state command without any pre-configured scope.", "type": "string", @@ -2276,6 +2306,12 @@ "const": "wallpaper:deny-set-image-crop", "markdownDescription": "Denies the set_image_crop command without any pre-configured scope." }, + { + "description": "Denies the set_interval command without any pre-configured scope.", + "type": "string", + "const": "wallpaper:deny-set-interval", + "markdownDescription": "Denies the set_interval command without any pre-configured scope." + }, { "description": "Denies the set_setting command without any pre-configured scope.", "type": "string", diff --git a/src-tauri/icons/128x128.png b/src-tauri/icons/128x128.png index 33bdbda..a5b6c68 100644 Binary files a/src-tauri/icons/128x128.png and b/src-tauri/icons/128x128.png differ diff --git a/src-tauri/icons/128x128@2x.png b/src-tauri/icons/128x128@2x.png index eabee4e..186f91c 100644 Binary files a/src-tauri/icons/128x128@2x.png and b/src-tauri/icons/128x128@2x.png differ diff --git a/src-tauri/icons/32x32.png b/src-tauri/icons/32x32.png index 5c45fec..7139014 100644 Binary files a/src-tauri/icons/32x32.png and b/src-tauri/icons/32x32.png differ diff --git a/src-tauri/icons/64x64.png b/src-tauri/icons/64x64.png index c9dfc21..6bb28e8 100644 Binary files a/src-tauri/icons/64x64.png and b/src-tauri/icons/64x64.png differ diff --git a/src-tauri/icons/Square107x107Logo.png b/src-tauri/icons/Square107x107Logo.png index 78aaecb..6af2159 100644 Binary files a/src-tauri/icons/Square107x107Logo.png and b/src-tauri/icons/Square107x107Logo.png differ diff --git a/src-tauri/icons/Square142x142Logo.png b/src-tauri/icons/Square142x142Logo.png index deafebf..d7e76cd 100644 Binary files a/src-tauri/icons/Square142x142Logo.png and b/src-tauri/icons/Square142x142Logo.png differ diff --git a/src-tauri/icons/Square150x150Logo.png b/src-tauri/icons/Square150x150Logo.png index c2c853d..5e4277c 100644 Binary files a/src-tauri/icons/Square150x150Logo.png and b/src-tauri/icons/Square150x150Logo.png differ diff --git a/src-tauri/icons/Square284x284Logo.png b/src-tauri/icons/Square284x284Logo.png index f305290..19d1e2e 100644 Binary files a/src-tauri/icons/Square284x284Logo.png and b/src-tauri/icons/Square284x284Logo.png differ diff --git a/src-tauri/icons/Square30x30Logo.png b/src-tauri/icons/Square30x30Logo.png index d93e33e..9c5afde 100644 Binary files a/src-tauri/icons/Square30x30Logo.png and b/src-tauri/icons/Square30x30Logo.png differ diff --git a/src-tauri/icons/Square310x310Logo.png b/src-tauri/icons/Square310x310Logo.png index 8799e55..7f47440 100644 Binary files a/src-tauri/icons/Square310x310Logo.png and b/src-tauri/icons/Square310x310Logo.png differ diff --git a/src-tauri/icons/Square44x44Logo.png b/src-tauri/icons/Square44x44Logo.png index 1f59c90..9396184 100644 Binary files a/src-tauri/icons/Square44x44Logo.png and b/src-tauri/icons/Square44x44Logo.png differ diff --git a/src-tauri/icons/Square71x71Logo.png b/src-tauri/icons/Square71x71Logo.png index c367a9c..5a76212 100644 Binary files a/src-tauri/icons/Square71x71Logo.png and b/src-tauri/icons/Square71x71Logo.png differ diff --git a/src-tauri/icons/Square89x89Logo.png b/src-tauri/icons/Square89x89Logo.png index c3537f5..81d5435 100644 Binary files a/src-tauri/icons/Square89x89Logo.png and b/src-tauri/icons/Square89x89Logo.png differ diff --git a/src-tauri/icons/StoreLogo.png b/src-tauri/icons/StoreLogo.png index 616c700..86f289c 100644 Binary files a/src-tauri/icons/StoreLogo.png and b/src-tauri/icons/StoreLogo.png differ diff --git a/src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml b/src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml index 2ffbf24..f760287 100644 --- a/src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml +++ b/src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml @@ -1,5 +1,6 @@ - - \ No newline at end of file + + + diff --git a/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png index d91e078..54cb9f4 100644 Binary files a/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png and b/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png differ diff --git a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_background.png b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_background.png new file mode 100644 index 0000000..bfcb36a Binary files /dev/null and b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_background.png differ diff --git a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png index 109a239..02ed04f 100644 Binary files a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png and b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_monochrome.png b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_monochrome.png new file mode 100644 index 0000000..d417975 Binary files /dev/null and b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_monochrome.png differ diff --git a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png index 16a4cf9..54cb9f4 100644 Binary files a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png and b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png differ diff --git a/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png index e5bfe24..144a73a 100644 Binary files a/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png and b/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png differ diff --git a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_background.png b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_background.png new file mode 100644 index 0000000..ad20a82 Binary files /dev/null and b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_background.png differ diff --git a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png index d116c22..5bf6b19 100644 Binary files a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png and b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_monochrome.png b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_monochrome.png new file mode 100644 index 0000000..f21e165 Binary files /dev/null and b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_monochrome.png differ diff --git a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png index 72c05b7..144a73a 100644 Binary files a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png and b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png differ diff --git a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png index 226f2b7..4f98fd0 100644 Binary files a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png and b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png differ diff --git a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_background.png b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_background.png new file mode 100644 index 0000000..9b30e3b Binary files /dev/null and b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_background.png differ diff --git a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png index 3dd2522..2d13c1a 100644 Binary files a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png and b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_monochrome.png b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_monochrome.png new file mode 100644 index 0000000..b0fc708 Binary files /dev/null and b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_monochrome.png differ diff --git a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png index 6a64274..4f98fd0 100644 Binary files a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png and b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png index 9f58ef8..c003a95 100644 Binary files a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png and b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_background.png b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_background.png new file mode 100644 index 0000000..6905ff5 Binary files /dev/null and b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_background.png differ diff --git a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png index d759b54..f9196ef 100644 Binary files a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png and b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_monochrome.png b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_monochrome.png new file mode 100644 index 0000000..4982172 Binary files /dev/null and b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_monochrome.png differ diff --git a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png index 6dd8c71..c003a95 100644 Binary files a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png and b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png index 6cd85f5..f92075a 100644 Binary files a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png and b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_background.png b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_background.png new file mode 100644 index 0000000..10a834a Binary files /dev/null and b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_background.png differ diff --git a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png index b0796b5..94dd03a 100644 Binary files a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png and b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_monochrome.png b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_monochrome.png new file mode 100644 index 0000000..d86ebf2 Binary files /dev/null and b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_monochrome.png differ diff --git a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png index c75fa68..f92075a 100644 Binary files a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png and b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/src-tauri/icons/android/values/ic_launcher_background.xml b/src-tauri/icons/android/values/ic_launcher_background.xml index ea9c223..fef4508 100644 --- a/src-tauri/icons/android/values/ic_launcher_background.xml +++ b/src-tauri/icons/android/values/ic_launcher_background.xml @@ -1,4 +1,4 @@ - #fff - \ No newline at end of file + #EDF4E9 + diff --git a/src-tauri/icons/icon.icns b/src-tauri/icons/icon.icns index e754391..440f4f1 100644 Binary files a/src-tauri/icons/icon.icns and b/src-tauri/icons/icon.icns differ diff --git a/src-tauri/icons/icon.ico b/src-tauri/icons/icon.ico index b1e5be4..6fc2c74 100644 Binary files a/src-tauri/icons/icon.ico and b/src-tauri/icons/icon.ico differ diff --git a/src-tauri/icons/icon.png b/src-tauri/icons/icon.png index 1955269..137b291 100644 Binary files a/src-tauri/icons/icon.png and b/src-tauri/icons/icon.png differ diff --git a/src-tauri/icons/ios/AppIcon-20x20@1x.png b/src-tauri/icons/ios/AppIcon-20x20@1x.png index f8d0a22..9aa0701 100644 Binary files a/src-tauri/icons/ios/AppIcon-20x20@1x.png and b/src-tauri/icons/ios/AppIcon-20x20@1x.png differ diff --git a/src-tauri/icons/ios/AppIcon-20x20@2x-1.png b/src-tauri/icons/ios/AppIcon-20x20@2x-1.png index 7d3d289..348a6b7 100644 Binary files a/src-tauri/icons/ios/AppIcon-20x20@2x-1.png and b/src-tauri/icons/ios/AppIcon-20x20@2x-1.png differ diff --git a/src-tauri/icons/ios/AppIcon-20x20@2x.png b/src-tauri/icons/ios/AppIcon-20x20@2x.png index 7d3d289..348a6b7 100644 Binary files a/src-tauri/icons/ios/AppIcon-20x20@2x.png and b/src-tauri/icons/ios/AppIcon-20x20@2x.png differ diff --git a/src-tauri/icons/ios/AppIcon-20x20@3x.png b/src-tauri/icons/ios/AppIcon-20x20@3x.png index 3252f8d..7492997 100644 Binary files a/src-tauri/icons/ios/AppIcon-20x20@3x.png and b/src-tauri/icons/ios/AppIcon-20x20@3x.png differ diff --git a/src-tauri/icons/ios/AppIcon-29x29@1x.png b/src-tauri/icons/ios/AppIcon-29x29@1x.png index 19e5b31..513abfa 100644 Binary files a/src-tauri/icons/ios/AppIcon-29x29@1x.png and b/src-tauri/icons/ios/AppIcon-29x29@1x.png differ diff --git a/src-tauri/icons/ios/AppIcon-29x29@2x-1.png b/src-tauri/icons/ios/AppIcon-29x29@2x-1.png index 7e9f469..03a8e6e 100644 Binary files a/src-tauri/icons/ios/AppIcon-29x29@2x-1.png and b/src-tauri/icons/ios/AppIcon-29x29@2x-1.png differ diff --git a/src-tauri/icons/ios/AppIcon-29x29@2x.png b/src-tauri/icons/ios/AppIcon-29x29@2x.png index 7e9f469..03a8e6e 100644 Binary files a/src-tauri/icons/ios/AppIcon-29x29@2x.png and b/src-tauri/icons/ios/AppIcon-29x29@2x.png differ diff --git a/src-tauri/icons/ios/AppIcon-29x29@3x.png b/src-tauri/icons/ios/AppIcon-29x29@3x.png index 334a9ce..c4760a6 100644 Binary files a/src-tauri/icons/ios/AppIcon-29x29@3x.png and b/src-tauri/icons/ios/AppIcon-29x29@3x.png differ diff --git a/src-tauri/icons/ios/AppIcon-40x40@1x.png b/src-tauri/icons/ios/AppIcon-40x40@1x.png index 7d3d289..348a6b7 100644 Binary files a/src-tauri/icons/ios/AppIcon-40x40@1x.png and b/src-tauri/icons/ios/AppIcon-40x40@1x.png differ diff --git a/src-tauri/icons/ios/AppIcon-40x40@2x-1.png b/src-tauri/icons/ios/AppIcon-40x40@2x-1.png index 9799043..3f95151 100644 Binary files a/src-tauri/icons/ios/AppIcon-40x40@2x-1.png and b/src-tauri/icons/ios/AppIcon-40x40@2x-1.png differ diff --git a/src-tauri/icons/ios/AppIcon-40x40@2x.png b/src-tauri/icons/ios/AppIcon-40x40@2x.png index 9799043..3f95151 100644 Binary files a/src-tauri/icons/ios/AppIcon-40x40@2x.png and b/src-tauri/icons/ios/AppIcon-40x40@2x.png differ diff --git a/src-tauri/icons/ios/AppIcon-40x40@3x.png b/src-tauri/icons/ios/AppIcon-40x40@3x.png index 93ddb9c..f740a1a 100644 Binary files a/src-tauri/icons/ios/AppIcon-40x40@3x.png and b/src-tauri/icons/ios/AppIcon-40x40@3x.png differ diff --git a/src-tauri/icons/ios/AppIcon-512@2x.png b/src-tauri/icons/ios/AppIcon-512@2x.png index 2c358a0..6163921 100644 Binary files a/src-tauri/icons/ios/AppIcon-512@2x.png and b/src-tauri/icons/ios/AppIcon-512@2x.png differ diff --git a/src-tauri/icons/ios/AppIcon-60x60@2x.png b/src-tauri/icons/ios/AppIcon-60x60@2x.png index 93ddb9c..f740a1a 100644 Binary files a/src-tauri/icons/ios/AppIcon-60x60@2x.png and b/src-tauri/icons/ios/AppIcon-60x60@2x.png differ diff --git a/src-tauri/icons/ios/AppIcon-60x60@3x.png b/src-tauri/icons/ios/AppIcon-60x60@3x.png index 22bb296..3fd4439 100644 Binary files a/src-tauri/icons/ios/AppIcon-60x60@3x.png and b/src-tauri/icons/ios/AppIcon-60x60@3x.png differ diff --git a/src-tauri/icons/ios/AppIcon-76x76@1x.png b/src-tauri/icons/ios/AppIcon-76x76@1x.png index d5ec860..63aea97 100644 Binary files a/src-tauri/icons/ios/AppIcon-76x76@1x.png and b/src-tauri/icons/ios/AppIcon-76x76@1x.png differ diff --git a/src-tauri/icons/ios/AppIcon-76x76@2x.png b/src-tauri/icons/ios/AppIcon-76x76@2x.png index b940f7d..51e01c5 100644 Binary files a/src-tauri/icons/ios/AppIcon-76x76@2x.png and b/src-tauri/icons/ios/AppIcon-76x76@2x.png differ diff --git a/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png b/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png index 1072008..f862e89 100644 Binary files a/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png and b/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png differ diff --git a/src/App.tsx b/src/App.tsx index 6ad231d..d74ff40 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,9 +1,9 @@ -import { useEffect, useMemo, useRef, useState } from "react"; +import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react"; import { ArrowLeft, Check, ChevronRight, Crop, Home, Images, Languages, LockKeyhole, Plus, RotateCcw, Save, Settings, Shuffle, Smartphone, Sparkles, Trash2 } from "lucide-react"; -import { deleteImage, getGallery, getState, nextWallpaper, selectImages, setImageCrop, setSetting, type GalleryImage, type WallpaperState } from "./native"; -import { initialLanguage, translations, type Language } from "./i18n"; +import { deleteImages, getGallery, getImageIds, getState, nextWallpaper, selectImages, setImageCrop, setIntervalMinutes, setSetting, type GalleryImage, type WallpaperState } from "./native"; +import { initialLanguage, languageNames, languages, translations, type Language } from "./i18n-local"; -const initial: WallpaperState = { imageCount: 0, enabled: false, shuffle: true, lockScreenOnly: true, currentIndex: 0, imageUrls: [] }; +const initial: WallpaperState = { imageCount: 0, enabled: false, intervalMinutes: 0, shuffle: true, lockScreenOnly: true, currentIndex: 0, imageUrls: [] }; function Switch({ checked, onChange, label }: { checked: boolean; onChange: (value: boolean) => void; label: string }) { return ; @@ -13,6 +13,13 @@ function SettingRow({ icon, label, value, onChange }: { icon: React.ReactNode; l return
{icon}
{label}
; } +function IntervalRow({ value, onChange, label, paused, everyMinutes }: { value: number; onChange: (value: number) => void; label: string; paused: string; everyMinutes: (minutes: number) => string }) { + return ; +} + export default function App() { const [state, setState] = useState(initial); const [tab, setTab] = useState<"home" | "settings" | "gallery" | "editor">("home"); @@ -22,11 +29,14 @@ export default function App() { const [gallery, setGallery] = useState([]); const [galleryTotal, setGalleryTotal] = useState(0); const [galleryLoading, setGalleryLoading] = useState(false); - const [deletingId, setDeletingId] = useState(""); + const [selectedIds, setSelectedIds] = useState>(() => new Set()); const [editing, setEditing] = useState(null); const phonePreviewRef = useRef(null); + const phoneImageRef = useRef(null); const previewPointers = useRef(new Map()); - const previewGesture = useRef(null); + const previewGesture = useRef(null); + const galleryScrollPosition = useRef(0); + const restoreGalleryScroll = useRef(false); useEffect(() => { getState().then(setState).catch(() => setState(initial)); }, []); useEffect(() => { @@ -39,7 +49,17 @@ export default function App() { document.documentElement.lang = language; document.title = "WallpaperFlow"; }, [language]); + useLayoutEffect(() => { + if (tab !== "editor" && tab !== "gallery") return; + const top = tab === "gallery" && restoreGalleryScroll.current ? galleryScrollPosition.current : 0; + restoreGalleryScroll.current = false; + window.scrollTo(0, top); + const frame = window.requestAnimationFrame(() => window.scrollTo(0, top)); + const settled = window.setTimeout(() => window.scrollTo(0, top), 120); + return () => { window.cancelAnimationFrame(frame); window.clearTimeout(settled); }; + }, [tab]); const t = translations[language]; + const previewDate = useMemo(() => new Intl.DateTimeFormat(language, { weekday: "long", day: "numeric", month: "long" }).format(new Date()), [language]); const current = state.imageUrls[state.currentIndex] ?? "/wallpapers/alpine.png"; const photos = useMemo(() => state.imageUrls, [state.imageUrls]); @@ -53,9 +73,23 @@ export default function App() { finally { setGalleryLoading(false); } } - async function update(name: "enabled" | "shuffle" | "lockScreenOnly", value: boolean) { + async function update(name: "shuffle" | "lockScreenOnly", value: boolean) { setState(prev => ({ ...prev, [name]: value })); - try { setState(await setSetting(name, value)); setNotice(name === "enabled" ? (value ? t.automaticEnabled : t.automaticDisabled) : t.settingSaved); } catch { setNotice(t.androidOnly); } + try { + const saved = await setSetting(name, value); + setState(prev => ({ ...saved, imageUrls: saved.imageUrls.length ? saved.imageUrls : prev.imageUrls })); + setNotice(t.settingSaved); + } catch { setNotice(t.androidOnly); } + } + + async function updateInterval(minutes: number) { + setState(prev => ({ ...prev, intervalMinutes: minutes, enabled: minutes > 0 })); + try { + const saved = await setIntervalMinutes(minutes); + setState(prev => ({ ...saved, imageUrls: saved.imageUrls.length ? saved.imageUrls : prev.imageUrls })); + setNotice(minutes > 0 ? t.intervalSaved : t.automaticDisabled); + } + catch { setNotice(t.androidOnly); } } async function choose() { @@ -68,23 +102,52 @@ export default function App() { finally { setBusy(false); } } - async function remove(image: GalleryImage) { - if (!window.confirm(t.deleteConfirm)) return; - setDeletingId(image.id); + function toggleSelected(id: string) { + setSelectedIds(previous => { + const next = new Set(previous); + if (next.has(id)) next.delete(id); else next.add(id); + return next; + }); + } + + async function selectAll() { + if (selectedIds.size === galleryTotal) { setSelectedIds(new Set()); return; } + setBusy(true); + try { setSelectedIds(new Set(await getImageIds())); } + catch { setNotice(t.galleryLoadFailed); } + finally { setBusy(false); } + } + + async function removeSelected() { + if (!selectedIds.size || !window.confirm(t.deleteSelectedConfirm)) return; + setBusy(true); try { - setState(await deleteImage(image.id)); - setGallery(previous => previous.filter(item => item.id !== image.id)); - setGalleryTotal(previous => Math.max(0, previous - 1)); - setNotice(t.imageDeleted); - } catch { setNotice(t.imageDeleteFailed); } - finally { setDeletingId(""); } + setState(await deleteImages([...selectedIds])); + setSelectedIds(new Set()); + await loadGallery(); + setNotice(t.imagesDeleted); + } catch { setNotice(t.imagesDeleteFailed); } + finally { setBusy(false); } } function openEditor(image: GalleryImage) { - setEditing({ ...image }); + galleryScrollPosition.current = window.scrollY; + setEditing({ ...image, cropZoom: Math.max(1, image.cropZoom) }); setTab("editor"); } + function returnToGallery() { + restoreGalleryScroll.current = true; + setTab("gallery"); + } + + function openGallery() { + galleryScrollPosition.current = 0; + restoreGalleryScroll.current = false; + setTab("gallery"); + void loadGallery(); + } + async function saveCrop() { if (!editing) return; setBusy(true); @@ -93,7 +156,7 @@ export default function App() { setGallery(previous => previous.map(image => image.id === saved.id ? saved : image)); setEditing(saved); setNotice(t.cropSaved); - setTab("gallery"); + returnToGallery(); } catch { setNotice(t.cropSaveFailed); } finally { setBusy(false); } } @@ -110,13 +173,35 @@ export default function App() { }; } + function gestureStart() { + const preview = phonePreviewRef.current; + const image = phoneImageRef.current; + if (!editing || !preview || !image) return null; + if (!image.naturalWidth || !image.naturalHeight) return null; + const bounds = preview.getBoundingClientRect(); + const scaleX = bounds.width / image.naturalWidth; + const scaleY = bounds.height / image.naturalHeight; + const baseScale = editing.cropMode === "contain" ? Math.min(scaleX, scaleY) : Math.max(scaleX, scaleY); + return { + ...gestureGeometry(), + x: editing.cropPositionX, + y: editing.cropPositionY, + zoom: editing.cropZoom, + left: bounds.left, + top: bounds.top, + width: bounds.width, + height: bounds.height, + baseWidth: image.naturalWidth * baseScale, + baseHeight: image.naturalHeight * baseScale, + }; + } + function beginPreviewGesture(event: React.PointerEvent) { if (!editing) return; event.preventDefault(); phonePreviewRef.current?.setPointerCapture(event.pointerId); previewPointers.current.set(event.pointerId, { x: event.clientX, y: event.clientY }); - const geometry = gestureGeometry(); - previewGesture.current = { ...geometry, x: editing.cropPositionX, y: editing.cropPositionY, zoom: editing.cropZoom }; + previewGesture.current = gestureStart(); } function movePreviewGesture(event: React.PointerEvent) { @@ -124,15 +209,21 @@ export default function App() { event.preventDefault(); previewPointers.current.set(event.pointerId, { x: event.clientX, y: event.clientY }); const gesture = previewGesture.current; - const preview = phonePreviewRef.current; - if (!gesture || !preview) return; - const bounds = preview.getBoundingClientRect(); + if (!gesture) return; const geometry = gestureGeometry(); const zoom = geometry.distance && gesture.distance - ? Math.min(3, Math.max(0.35, gesture.zoom * geometry.distance / gesture.distance)) + ? Math.min(3, Math.max(1, gesture.zoom * geometry.distance / gesture.distance)) : gesture.zoom; - const x = gesture.x - (geometry.centerX - gesture.centerX) / Math.max(1, bounds.width * zoom); - const y = gesture.y - (geometry.centerY - gesture.centerY) / Math.max(1, bounds.height * zoom); + const previousLeft = (gesture.width - gesture.baseWidth * gesture.zoom) * gesture.x; + const previousTop = (gesture.height - gesture.baseHeight * gesture.zoom) * gesture.y; + const imageX = (gesture.centerX - gesture.left - previousLeft) / gesture.zoom; + const imageY = (gesture.centerY - gesture.top - previousTop) / gesture.zoom; + const nextLeft = geometry.centerX - gesture.left - imageX * zoom; + const nextTop = geometry.centerY - gesture.top - imageY * zoom; + const horizontalTravel = gesture.width - gesture.baseWidth * zoom; + const verticalTravel = gesture.height - gesture.baseHeight * zoom; + const x = Math.abs(horizontalTravel) < 0.5 ? 0.5 : nextLeft / horizontalTravel; + const y = Math.abs(verticalTravel) < 0.5 ? 0.5 : nextTop / verticalTravel; setEditing(previous => previous ? { ...previous, cropZoom: zoom, @@ -148,8 +239,7 @@ export default function App() { previewGesture.current = null; return; } - const geometry = gestureGeometry(); - previewGesture.current = { ...geometry, x: editing.cropPositionX, y: editing.cropPositionY, zoom: editing.cropZoom }; + previewGesture.current = gestureStart(); } async function next() { @@ -159,8 +249,8 @@ export default function App() { } return
- {tab === "gallery" ?

{t.collection}

{galleryTotal} {galleryTotal === 1 ? t.image : t.images}

: tab === "editor" ? -

{t.editImage}

{t.savedForImage}

: + {tab === "gallery" ?

{selectedIds.size ? `${selectedIds.size} ${t.selected}` : t.collection}

{galleryTotal} {galleryTotal === 1 ? t.image : t.images}

{selectedIds.size ? : }
: tab === "editor" ? +

{t.editImage}

{t.savedForImage}

:

WallpaperFlow

{state.enabled ? t.automaticActive : t.automaticPaused}

}
@@ -172,30 +262,33 @@ export default function App() {
{t.currentImage}
- } label={t.changeOnWake} value={state.enabled} onChange={v => update("enabled", v)} /> + -

{t.collection}

+

{t.collection}

{photos.length ?
{photos.map((photo, index) => )}
: }

{t.collectionHint}

} label={t.shuffle} value={state.shuffle} onChange={v => update("shuffle", v)} />} label={t.lockScreenOnly} value={state.lockScreenOnly} onChange={v => update("lockScreenOnly", v)} />
- : tab === "settings" ?

{t.settings}

{t.settingsIntro}

{t.language}{language === "de" ? t.german : t.english}
} label={t.changeOnWake} value={state.enabled} onChange={v => update("enabled", v)} />} label={t.shuffle} value={state.shuffle} onChange={v => update("shuffle", v)} />} label={t.lockScreenOnly} value={state.lockScreenOnly} onChange={v => update("lockScreenOnly", v)} />

{t.noImageLimit}

{t.privacyInfo}

: tab === "gallery" ? + : tab === "settings" ?

{t.settings}

{t.settingsIntro}

} label={t.shuffle} value={state.shuffle} onChange={v => update("shuffle", v)} />} label={t.lockScreenOnly} value={state.lockScreenOnly} onChange={v => update("lockScreenOnly", v)} />

{t.noImageLimit}

{t.privacyInfo}

: tab === "gallery" ?
- {gallery.length ?
{gallery.map((image, index) =>
{`${t.image}{image.selected && {t.current}}
)}
: !galleryLoading &&

{t.emptyCollection}

{t.emptyCollectionText}

} + {!!galleryTotal &&
{selectedIds.size ? `${selectedIds.size} ${t.selected}` : t.selectImagesToDelete}
} + {gallery.length ?
{gallery.map((image, index) =>
{image.selected && {t.current}}
)}
: !galleryLoading &&

{t.emptyCollection}

{t.emptyCollectionText}

} {galleryLoading &&

{t.galleryLoading}

} {!galleryLoading && gallery.length < galleryTotal && }
: editing &&
- {t.cropPreview} -
12:34{t.previewDate}
+ {t.cropPreview} + +
12:34{previewDate}
-
+
{t.adjustOnScreen}{editing.cropZoom.toFixed(2)}×

{t.gestureHelp}

+
} diff --git a/src/i18n-local.ts b/src/i18n-local.ts new file mode 100644 index 0000000..e12de26 --- /dev/null +++ b/src/i18n-local.ts @@ -0,0 +1,301 @@ +export const languages = ["de", "en", "fr", "es", "it", "nl", "pl", "pt", "ja", "ko", "zh-CN"] as const; +export type Language = typeof languages[number]; + +export const languageNames: Record = { + de: "Deutsch", en: "English", fr: "Français", es: "Español", it: "Italiano", nl: "Nederlands", + pl: "Polski", pt: "Português", ja: "日本語", ko: "한국어", "zh-CN": "简体中文", +}; + +const en = { + automaticActive: "Your wallpapers change automatically", automaticPaused: "Automatic rotation is paused", + settings: "Settings", currentWallpaper: "Current wallpaper", currentImage: "Current image", nextImage: "Next image", + changeInterval: "Change image", paused: "Paused", selectImages: "Select images", pleaseWait: "Please wait …", + collection: "My collection", image: "image", images: "images", motif: "Image", noImages: "No images selected yet", + collectionHint: "Tap the image count to open your gallery.", shuffle: "Shuffle order", lockScreenOnly: "Lock screen only", + settingsIntro: "Choose how WallpaperFlow works in the background.", language: "Language", noImageLimit: "No image limit", + privacyInfo: "Your selection stays private on this device. The only limit is the available storage.", home: "Home", back: "Back", + addImages: "Add images", backToGallery: "Back to gallery", editImage: "Adjust image", savedForImage: "Saved only for this image", + saveCrop: "Save image crop", myImages: "My images", current: "Current", adjustImage: "Adjust image", deleteImage: "Delete image", + emptyCollection: "Your collection is empty", emptyCollectionText: "Add images that should rotate automatically on your lock screen.", + galleryLoading: "Loading gallery …", loadMore: "Load more images", editCrop: "Edit image crop", + gestureLabel: "Move the image with one finger and zoom with two fingers", cropPreview: "Image crop preview", imageFit: "Image fit", + fill: "Fill", fit: "Fit", adjustOnScreen: "Adjust directly on screen", gestureHelp: "Drag inside the display or pinch with two fingers", + zoom: "Zoom", reset: "Reset", deleteConfirm: "Do you really want to delete this image from your collection?", + galleryLoadFailed: "The gallery could not be loaded", automaticDisabled: "Automatic rotation is paused", settingSaved: "Setting saved", + intervalSaved: "Rotation interval saved", androidOnly: "This feature is available on Android", imagesAdded: "Images added to your collection", + selectionCancelled: "Selection cancelled", imageSelectionAndroid: "Image selection is available on Android", imageDeleted: "Image deleted", + imageDeleteFailed: "The image could not be deleted", cropSaved: "Image crop saved", cropSaveFailed: "The image crop could not be saved", + wallpaperUpdated: "Lock screen updated", +} satisfies Record; + +export type TranslationKey = keyof typeof en; +type Copy = Record; + +const copies: Record, Copy> = { + de: { + automaticActive: "Deine Motive wechseln automatisch", automaticPaused: "Automatischer Wechsel ist pausiert", + settings: "Einstellungen", currentWallpaper: "Aktuelles Hintergrundbild", currentImage: "Aktuelles Motiv", nextImage: "Nächstes Motiv", + changeInterval: "Bild wechseln", paused: "Pausiert", selectImages: "Bilder auswählen", pleaseWait: "Bitte warten …", + collection: "Meine Sammlung", image: "Bild", images: "Bilder", motif: "Motiv", noImages: "Noch keine Bilder ausgewählt", + collectionHint: "Tippe auf die Bildanzahl, um deine Galerie zu öffnen.", shuffle: "Zufällige Reihenfolge", lockScreenOnly: "Nur Sperrbildschirm", + settingsIntro: "Lege fest, wie WallpaperFlow im Hintergrund arbeitet.", language: "Sprache", noImageLimit: "Ohne Bilderlimit", + privacyInfo: "Deine Auswahl wird privat auf dem Gerät gespeichert. Die einzige Grenze ist der freie Speicherplatz.", home: "Start", back: "Zurück", + addImages: "Bilder hinzufügen", backToGallery: "Zurück zur Galerie", editImage: "Bild anpassen", savedForImage: "Wird nur für dieses Bild gespeichert", + saveCrop: "Bildausschnitt speichern", myImages: "Meine Bilder", current: "Aktuell", adjustImage: "Bild anpassen", deleteImage: "Bild löschen", + emptyCollection: "Deine Sammlung ist leer", emptyCollectionText: "Füge Bilder hinzu, die automatisch als Sperrbildschirm wechseln sollen.", + galleryLoading: "Galerie wird geladen …", loadMore: "Weitere Bilder laden", editCrop: "Bildausschnitt bearbeiten", + gestureLabel: "Bild mit einem Finger verschieben und mit zwei Fingern zoomen", cropPreview: "Vorschau des Bildausschnitts", imageFit: "Bildanpassung", + fill: "Ausfüllen", fit: "Einpassen", adjustOnScreen: "Direkt im Bildschirm anpassen", gestureHelp: "Im Display ziehen oder mit zwei Fingern zoomen", + zoom: "Zoom", reset: "Zurücksetzen", deleteConfirm: "Möchtest du dieses Bild wirklich aus deiner Sammlung löschen?", + galleryLoadFailed: "Galerie konnte nicht geladen werden", automaticDisabled: "Automatischer Wechsel pausiert", settingSaved: "Einstellung gespeichert", + intervalSaved: "Wechselintervall gespeichert", androidOnly: "Diese Funktion ist auf Android verfügbar", imagesAdded: "Bilder wurden zur Sammlung hinzugefügt", + selectionCancelled: "Auswahl abgebrochen", imageSelectionAndroid: "Bildauswahl ist auf Android verfügbar", imageDeleted: "Bild wurde gelöscht", + imageDeleteFailed: "Bild konnte nicht gelöscht werden", cropSaved: "Bildausschnitt wurde gespeichert", cropSaveFailed: "Bildausschnitt konnte nicht gespeichert werden", + wallpaperUpdated: "Sperrbildschirm wurde aktualisiert", + }, + fr: { + automaticActive: "Vos fonds d’écran changent automatiquement", automaticPaused: "La rotation automatique est en pause", + settings: "Paramètres", currentWallpaper: "Fond d’écran actuel", currentImage: "Image actuelle", nextImage: "Image suivante", + changeInterval: "Changer l’image", paused: "En pause", selectImages: "Sélectionner des images", pleaseWait: "Veuillez patienter…", + collection: "Ma collection", image: "image", images: "images", motif: "Image", noImages: "Aucune image sélectionnée", + collectionHint: "Touchez le nombre d’images pour ouvrir votre galerie.", shuffle: "Ordre aléatoire", lockScreenOnly: "Écran de verrouillage uniquement", + settingsIntro: "Choisissez comment WallpaperFlow fonctionne en arrière-plan.", language: "Langue", noImageLimit: "Aucune limite d’images", + privacyInfo: "Votre sélection reste privée sur cet appareil. Seul l’espace disponible la limite.", home: "Accueil", back: "Retour", + addImages: "Ajouter des images", backToGallery: "Retour à la galerie", editImage: "Ajuster l’image", savedForImage: "Enregistré uniquement pour cette image", + saveCrop: "Enregistrer le cadrage", myImages: "Mes images", current: "Actuelle", adjustImage: "Ajuster l’image", deleteImage: "Supprimer l’image", + emptyCollection: "Votre collection est vide", emptyCollectionText: "Ajoutez des images à faire défiler automatiquement sur l’écran de verrouillage.", + galleryLoading: "Chargement de la galerie…", loadMore: "Charger plus d’images", editCrop: "Modifier le cadrage", + gestureLabel: "Déplacez l’image avec un doigt et zoomez avec deux doigts", cropPreview: "Aperçu du cadrage", imageFit: "Ajustement de l’image", + fill: "Remplir", fit: "Adapter", adjustOnScreen: "Ajuster directement à l’écran", gestureHelp: "Faites glisser dans l’écran ou pincez avec deux doigts", + zoom: "Zoom", reset: "Réinitialiser", deleteConfirm: "Voulez-vous vraiment supprimer cette image de votre collection ?", + galleryLoadFailed: "Impossible de charger la galerie", automaticDisabled: "La rotation automatique est en pause", settingSaved: "Paramètre enregistré", + intervalSaved: "Intervalle enregistré", androidOnly: "Cette fonction est disponible sur Android", imagesAdded: "Images ajoutées à votre collection", + selectionCancelled: "Sélection annulée", imageSelectionAndroid: "La sélection d’images est disponible sur Android", imageDeleted: "Image supprimée", + imageDeleteFailed: "Impossible de supprimer l’image", cropSaved: "Cadrage enregistré", cropSaveFailed: "Impossible d’enregistrer le cadrage", + wallpaperUpdated: "Écran de verrouillage mis à jour", + }, + es: { + automaticActive: "Tus fondos cambian automáticamente", automaticPaused: "La rotación automática está en pausa", + settings: "Ajustes", currentWallpaper: "Fondo actual", currentImage: "Imagen actual", nextImage: "Imagen siguiente", + changeInterval: "Cambiar imagen", paused: "En pausa", selectImages: "Seleccionar imágenes", pleaseWait: "Espera…", + collection: "Mi colección", image: "imagen", images: "imágenes", motif: "Imagen", noImages: "Aún no hay imágenes seleccionadas", + collectionHint: "Toca el número de imágenes para abrir la galería.", shuffle: "Orden aleatorio", lockScreenOnly: "Solo pantalla de bloqueo", + settingsIntro: "Elige cómo funciona WallpaperFlow en segundo plano.", language: "Idioma", noImageLimit: "Sin límite de imágenes", + privacyInfo: "Tu selección permanece privada en este dispositivo. El único límite es el espacio disponible.", home: "Inicio", back: "Atrás", + addImages: "Añadir imágenes", backToGallery: "Volver a la galería", editImage: "Ajustar imagen", savedForImage: "Se guarda solo para esta imagen", + saveCrop: "Guardar recorte", myImages: "Mis imágenes", current: "Actual", adjustImage: "Ajustar imagen", deleteImage: "Eliminar imagen", + emptyCollection: "Tu colección está vacía", emptyCollectionText: "Añade imágenes para que cambien automáticamente en la pantalla de bloqueo.", + galleryLoading: "Cargando galería…", loadMore: "Cargar más imágenes", editCrop: "Editar recorte", + gestureLabel: "Mueve la imagen con un dedo y amplía con dos", cropPreview: "Vista previa del recorte", imageFit: "Ajuste de imagen", + fill: "Rellenar", fit: "Encajar", adjustOnScreen: "Ajustar directamente en pantalla", gestureHelp: "Arrastra dentro de la pantalla o pellizca con dos dedos", + zoom: "Zoom", reset: "Restablecer", deleteConfirm: "¿Quieres eliminar esta imagen de tu colección?", + galleryLoadFailed: "No se pudo cargar la galería", automaticDisabled: "La rotación automática está en pausa", settingSaved: "Ajuste guardado", + intervalSaved: "Intervalo guardado", androidOnly: "Esta función está disponible en Android", imagesAdded: "Imágenes añadidas a tu colección", + selectionCancelled: "Selección cancelada", imageSelectionAndroid: "La selección de imágenes está disponible en Android", imageDeleted: "Imagen eliminada", + imageDeleteFailed: "No se pudo eliminar la imagen", cropSaved: "Recorte guardado", cropSaveFailed: "No se pudo guardar el recorte", + wallpaperUpdated: "Pantalla de bloqueo actualizada", + }, + it: { + automaticActive: "Gli sfondi cambiano automaticamente", automaticPaused: "La rotazione automatica è in pausa", + settings: "Impostazioni", currentWallpaper: "Sfondo attuale", currentImage: "Immagine attuale", nextImage: "Immagine successiva", + changeInterval: "Cambia immagine", paused: "In pausa", selectImages: "Seleziona immagini", pleaseWait: "Attendi…", + collection: "La mia raccolta", image: "immagine", images: "immagini", motif: "Immagine", noImages: "Nessuna immagine selezionata", + collectionHint: "Tocca il numero di immagini per aprire la galleria.", shuffle: "Ordine casuale", lockScreenOnly: "Solo schermata di blocco", + settingsIntro: "Scegli come funziona WallpaperFlow in background.", language: "Lingua", noImageLimit: "Nessun limite di immagini", + privacyInfo: "La selezione resta privata su questo dispositivo. L’unico limite è lo spazio disponibile.", home: "Home", back: "Indietro", + addImages: "Aggiungi immagini", backToGallery: "Torna alla galleria", editImage: "Regola immagine", savedForImage: "Salvato solo per questa immagine", + saveCrop: "Salva ritaglio", myImages: "Le mie immagini", current: "Attuale", adjustImage: "Regola immagine", deleteImage: "Elimina immagine", + emptyCollection: "La raccolta è vuota", emptyCollectionText: "Aggiungi immagini da alternare automaticamente nella schermata di blocco.", + galleryLoading: "Caricamento galleria…", loadMore: "Carica altre immagini", editCrop: "Modifica ritaglio", + gestureLabel: "Sposta l’immagine con un dito e ingrandisci con due", cropPreview: "Anteprima ritaglio", imageFit: "Adattamento immagine", + fill: "Riempi", fit: "Adatta", adjustOnScreen: "Regola direttamente sullo schermo", gestureHelp: "Trascina nello schermo o pizzica con due dita", + zoom: "Zoom", reset: "Ripristina", deleteConfirm: "Vuoi davvero eliminare questa immagine dalla raccolta?", + galleryLoadFailed: "Impossibile caricare la galleria", automaticDisabled: "La rotazione automatica è in pausa", settingSaved: "Impostazione salvata", + intervalSaved: "Intervallo salvato", androidOnly: "Questa funzione è disponibile su Android", imagesAdded: "Immagini aggiunte alla raccolta", + selectionCancelled: "Selezione annullata", imageSelectionAndroid: "La selezione immagini è disponibile su Android", imageDeleted: "Immagine eliminata", + imageDeleteFailed: "Impossibile eliminare l’immagine", cropSaved: "Ritaglio salvato", cropSaveFailed: "Impossibile salvare il ritaglio", + wallpaperUpdated: "Schermata di blocco aggiornata", + }, + nl: { + automaticActive: "Je achtergronden wisselen automatisch", automaticPaused: "Automatisch wisselen is gepauzeerd", + settings: "Instellingen", currentWallpaper: "Huidige achtergrond", currentImage: "Huidige afbeelding", nextImage: "Volgende afbeelding", + changeInterval: "Afbeelding wisselen", paused: "Gepauzeerd", selectImages: "Afbeeldingen kiezen", pleaseWait: "Even geduld…", + collection: "Mijn collectie", image: "afbeelding", images: "afbeeldingen", motif: "Afbeelding", noImages: "Nog geen afbeeldingen gekozen", + collectionHint: "Tik op het aantal afbeeldingen om je galerij te openen.", shuffle: "Willekeurige volgorde", lockScreenOnly: "Alleen vergrendelscherm", + settingsIntro: "Kies hoe WallpaperFlow op de achtergrond werkt.", language: "Taal", noImageLimit: "Geen afbeeldingslimiet", + privacyInfo: "Je selectie blijft privé op dit apparaat. Alleen de beschikbare opslagruimte vormt een limiet.", home: "Start", back: "Terug", + addImages: "Afbeeldingen toevoegen", backToGallery: "Terug naar galerij", editImage: "Afbeelding aanpassen", savedForImage: "Alleen voor deze afbeelding opgeslagen", + saveCrop: "Uitsnede opslaan", myImages: "Mijn afbeeldingen", current: "Huidig", adjustImage: "Afbeelding aanpassen", deleteImage: "Afbeelding verwijderen", + emptyCollection: "Je collectie is leeg", emptyCollectionText: "Voeg afbeeldingen toe die automatisch op je vergrendelscherm wisselen.", + galleryLoading: "Galerij laden…", loadMore: "Meer afbeeldingen laden", editCrop: "Uitsnede bewerken", + gestureLabel: "Verplaats met één vinger en zoom met twee vingers", cropPreview: "Voorbeeld van uitsnede", imageFit: "Afbeelding passend maken", + fill: "Vullen", fit: "Passend", adjustOnScreen: "Direct op het scherm aanpassen", gestureHelp: "Sleep in het scherm of knijp met twee vingers", + zoom: "Zoom", reset: "Herstellen", deleteConfirm: "Wil je deze afbeelding echt uit je collectie verwijderen?", + galleryLoadFailed: "De galerij kon niet worden geladen", automaticDisabled: "Automatisch wisselen is gepauzeerd", settingSaved: "Instelling opgeslagen", + intervalSaved: "Wisselinterval opgeslagen", androidOnly: "Deze functie is beschikbaar op Android", imagesAdded: "Afbeeldingen aan je collectie toegevoegd", + selectionCancelled: "Selectie geannuleerd", imageSelectionAndroid: "Afbeeldingen kiezen is beschikbaar op Android", imageDeleted: "Afbeelding verwijderd", + imageDeleteFailed: "De afbeelding kon niet worden verwijderd", cropSaved: "Uitsnede opgeslagen", cropSaveFailed: "De uitsnede kon niet worden opgeslagen", + wallpaperUpdated: "Vergrendelscherm bijgewerkt", + }, + pl: { + automaticActive: "Tapety zmieniają się automatycznie", automaticPaused: "Automatyczna zmiana jest wstrzymana", + settings: "Ustawienia", currentWallpaper: "Bieżąca tapeta", currentImage: "Bieżący obraz", nextImage: "Następny obraz", + changeInterval: "Zmieniaj obraz", paused: "Wstrzymano", selectImages: "Wybierz obrazy", pleaseWait: "Proszę czekać…", + collection: "Moja kolekcja", image: "obraz", images: "obrazy", motif: "Obraz", noImages: "Nie wybrano jeszcze obrazów", + collectionHint: "Dotknij liczby obrazów, aby otworzyć galerię.", shuffle: "Losowa kolejność", lockScreenOnly: "Tylko ekran blokady", + settingsIntro: "Wybierz sposób działania WallpaperFlow w tle.", language: "Język", noImageLimit: "Bez limitu obrazów", + privacyInfo: "Wybór pozostaje prywatny na tym urządzeniu. Ogranicza go tylko dostępne miejsce.", home: "Start", back: "Wstecz", + addImages: "Dodaj obrazy", backToGallery: "Wróć do galerii", editImage: "Dopasuj obraz", savedForImage: "Zapisane tylko dla tego obrazu", + saveCrop: "Zapisz kadr", myImages: "Moje obrazy", current: "Bieżący", adjustImage: "Dopasuj obraz", deleteImage: "Usuń obraz", + emptyCollection: "Kolekcja jest pusta", emptyCollectionText: "Dodaj obrazy, które mają automatycznie zmieniać się na ekranie blokady.", + galleryLoading: "Wczytywanie galerii…", loadMore: "Wczytaj więcej obrazów", editCrop: "Edytuj kadr", + gestureLabel: "Przesuwaj jednym palcem i powiększaj dwoma", cropPreview: "Podgląd kadru", imageFit: "Dopasowanie obrazu", + fill: "Wypełnij", fit: "Dopasuj", adjustOnScreen: "Dopasuj bezpośrednio na ekranie", gestureHelp: "Przeciągnij na ekranie lub uszczypnij dwoma palcami", + zoom: "Powiększenie", reset: "Resetuj", deleteConfirm: "Czy na pewno usunąć ten obraz z kolekcji?", + galleryLoadFailed: "Nie udało się wczytać galerii", automaticDisabled: "Automatyczna zmiana jest wstrzymana", settingSaved: "Ustawienie zapisane", + intervalSaved: "Interwał zapisany", androidOnly: "Ta funkcja jest dostępna na Androidzie", imagesAdded: "Obrazy dodano do kolekcji", + selectionCancelled: "Anulowano wybór", imageSelectionAndroid: "Wybór obrazów jest dostępny na Androidzie", imageDeleted: "Obraz usunięty", + imageDeleteFailed: "Nie udało się usunąć obrazu", cropSaved: "Kadr zapisany", cropSaveFailed: "Nie udało się zapisać kadru", + wallpaperUpdated: "Ekran blokady zaktualizowany", + }, + pt: { + automaticActive: "Os seus fundos mudam automaticamente", automaticPaused: "A rotação automática está em pausa", + settings: "Definições", currentWallpaper: "Fundo atual", currentImage: "Imagem atual", nextImage: "Imagem seguinte", + changeInterval: "Mudar imagem", paused: "Em pausa", selectImages: "Selecionar imagens", pleaseWait: "Aguarde…", + collection: "A minha coleção", image: "imagem", images: "imagens", motif: "Imagem", noImages: "Ainda não há imagens selecionadas", + collectionHint: "Toque no número de imagens para abrir a galeria.", shuffle: "Ordem aleatória", lockScreenOnly: "Apenas ecrã de bloqueio", + settingsIntro: "Escolha como o WallpaperFlow funciona em segundo plano.", language: "Idioma", noImageLimit: "Sem limite de imagens", + privacyInfo: "A sua seleção permanece privada neste dispositivo. O único limite é o espaço disponível.", home: "Início", back: "Voltar", + addImages: "Adicionar imagens", backToGallery: "Voltar à galeria", editImage: "Ajustar imagem", savedForImage: "Guardado apenas para esta imagem", + saveCrop: "Guardar recorte", myImages: "As minhas imagens", current: "Atual", adjustImage: "Ajustar imagem", deleteImage: "Eliminar imagem", + emptyCollection: "A coleção está vazia", emptyCollectionText: "Adicione imagens para alternarem automaticamente no ecrã de bloqueio.", + galleryLoading: "A carregar galeria…", loadMore: "Carregar mais imagens", editCrop: "Editar recorte", + gestureLabel: "Mova a imagem com um dedo e amplie com dois", cropPreview: "Pré-visualização do recorte", imageFit: "Ajuste da imagem", + fill: "Preencher", fit: "Ajustar", adjustOnScreen: "Ajustar diretamente no ecrã", gestureHelp: "Arraste no ecrã ou aproxime dois dedos", + zoom: "Zoom", reset: "Repor", deleteConfirm: "Pretende mesmo eliminar esta imagem da coleção?", + galleryLoadFailed: "Não foi possível carregar a galeria", automaticDisabled: "A rotação automática está em pausa", settingSaved: "Definição guardada", + intervalSaved: "Intervalo guardado", androidOnly: "Esta função está disponível no Android", imagesAdded: "Imagens adicionadas à coleção", + selectionCancelled: "Seleção cancelada", imageSelectionAndroid: "A seleção de imagens está disponível no Android", imageDeleted: "Imagem eliminada", + imageDeleteFailed: "Não foi possível eliminar a imagem", cropSaved: "Recorte guardado", cropSaveFailed: "Não foi possível guardar o recorte", + wallpaperUpdated: "Ecrã de bloqueio atualizado", + }, + ja: { + automaticActive: "壁紙は自動的に切り替わります", automaticPaused: "自動切り替えは一時停止中です", + settings: "設定", currentWallpaper: "現在の壁紙", currentImage: "現在の画像", nextImage: "次の画像", + changeInterval: "画像を切り替え", paused: "一時停止", selectImages: "画像を選択", pleaseWait: "お待ちください…", + collection: "マイコレクション", image: "枚", images: "枚", motif: "画像", noImages: "画像がまだ選択されていません", + collectionHint: "画像数をタップしてギャラリーを開きます。", shuffle: "ランダムな順序", lockScreenOnly: "ロック画面のみ", + settingsIntro: "WallpaperFlow のバックグラウンド動作を設定します。", language: "言語", noImageLimit: "画像数の制限なし", + privacyInfo: "選択した画像はこの端末内にのみ保存されます。上限は空き容量だけです。", home: "ホーム", back: "戻る", + addImages: "画像を追加", backToGallery: "ギャラリーに戻る", editImage: "画像を調整", savedForImage: "この画像にのみ保存されます", + saveCrop: "切り抜きを保存", myImages: "マイ画像", current: "現在", adjustImage: "画像を調整", deleteImage: "画像を削除", + emptyCollection: "コレクションは空です", emptyCollectionText: "ロック画面で自動的に切り替える画像を追加してください。", + galleryLoading: "ギャラリーを読み込み中…", loadMore: "さらに読み込む", editCrop: "切り抜きを編集", + gestureLabel: "1本指で移動し、2本指でズームします", cropPreview: "切り抜きプレビュー", imageFit: "画像の配置", + fill: "画面を埋める", fit: "全体を表示", adjustOnScreen: "画面上で直接調整", gestureHelp: "画面内をドラッグするか、2本指でピンチします", + zoom: "ズーム", reset: "リセット", deleteConfirm: "この画像をコレクションから削除しますか?", + galleryLoadFailed: "ギャラリーを読み込めませんでした", automaticDisabled: "自動切り替えは一時停止中です", settingSaved: "設定を保存しました", + intervalSaved: "切り替え間隔を保存しました", androidOnly: "この機能は Android で利用できます", imagesAdded: "画像をコレクションに追加しました", + selectionCancelled: "選択をキャンセルしました", imageSelectionAndroid: "画像選択は Android で利用できます", imageDeleted: "画像を削除しました", + imageDeleteFailed: "画像を削除できませんでした", cropSaved: "切り抜きを保存しました", cropSaveFailed: "切り抜きを保存できませんでした", + wallpaperUpdated: "ロック画面を更新しました", + }, + ko: { + automaticActive: "배경화면이 자동으로 변경됩니다", automaticPaused: "자동 변경이 일시 중지되었습니다", + settings: "설정", currentWallpaper: "현재 배경화면", currentImage: "현재 이미지", nextImage: "다음 이미지", + changeInterval: "이미지 변경", paused: "일시 중지", selectImages: "이미지 선택", pleaseWait: "잠시 기다려 주세요…", + collection: "내 컬렉션", image: "이미지", images: "이미지", motif: "이미지", noImages: "선택한 이미지가 없습니다", + collectionHint: "이미지 수를 탭하여 갤러리를 여세요.", shuffle: "무작위 순서", lockScreenOnly: "잠금 화면만", + settingsIntro: "WallpaperFlow의 백그라운드 작동 방식을 선택하세요.", language: "언어", noImageLimit: "이미지 수 제한 없음", + privacyInfo: "선택한 이미지는 이 기기에만 비공개로 저장됩니다. 저장 공간만 사용 한도를 결정합니다.", home: "홈", back: "뒤로", + addImages: "이미지 추가", backToGallery: "갤러리로 돌아가기", editImage: "이미지 조정", savedForImage: "이 이미지에만 저장됨", + saveCrop: "자르기 저장", myImages: "내 이미지", current: "현재", adjustImage: "이미지 조정", deleteImage: "이미지 삭제", + emptyCollection: "컬렉션이 비어 있습니다", emptyCollectionText: "잠금 화면에서 자동으로 변경할 이미지를 추가하세요.", + galleryLoading: "갤러리 불러오는 중…", loadMore: "이미지 더 불러오기", editCrop: "자르기 편집", + gestureLabel: "한 손가락으로 이동하고 두 손가락으로 확대하세요", cropPreview: "자르기 미리보기", imageFit: "이미지 맞춤", + fill: "채우기", fit: "맞추기", adjustOnScreen: "화면에서 직접 조정", gestureHelp: "화면 안에서 드래그하거나 두 손가락으로 확대하세요", + zoom: "확대", reset: "초기화", deleteConfirm: "이 이미지를 컬렉션에서 삭제할까요?", + galleryLoadFailed: "갤러리를 불러올 수 없습니다", automaticDisabled: "자동 변경이 일시 중지되었습니다", settingSaved: "설정을 저장했습니다", + intervalSaved: "변경 간격을 저장했습니다", androidOnly: "이 기능은 Android에서 사용할 수 있습니다", imagesAdded: "컬렉션에 이미지를 추가했습니다", + selectionCancelled: "선택을 취소했습니다", imageSelectionAndroid: "이미지 선택은 Android에서 사용할 수 있습니다", imageDeleted: "이미지를 삭제했습니다", + imageDeleteFailed: "이미지를 삭제할 수 없습니다", cropSaved: "자르기를 저장했습니다", cropSaveFailed: "자르기를 저장할 수 없습니다", + wallpaperUpdated: "잠금 화면을 업데이트했습니다", + }, + "zh-CN": { + automaticActive: "壁纸会自动更换", automaticPaused: "自动更换已暂停", + settings: "设置", currentWallpaper: "当前壁纸", currentImage: "当前图片", nextImage: "下一张图片", + changeInterval: "更换图片", paused: "已暂停", selectImages: "选择图片", pleaseWait: "请稍候…", + collection: "我的收藏", image: "张图片", images: "张图片", motif: "图片", noImages: "尚未选择图片", + collectionHint: "点击图片数量打开图库。", shuffle: "随机顺序", lockScreenOnly: "仅锁屏", + settingsIntro: "选择 WallpaperFlow 在后台的工作方式。", language: "语言", noImageLimit: "不限图片数量", + privacyInfo: "所选图片仅保存在此设备上。唯一限制是可用存储空间。", home: "首页", back: "返回", + addImages: "添加图片", backToGallery: "返回图库", editImage: "调整图片", savedForImage: "仅为此图片保存", + saveCrop: "保存裁剪", myImages: "我的图片", current: "当前", adjustImage: "调整图片", deleteImage: "删除图片", + emptyCollection: "收藏为空", emptyCollectionText: "添加要在锁屏上自动轮换的图片。", + galleryLoading: "正在加载图库…", loadMore: "加载更多图片", editCrop: "编辑裁剪", + gestureLabel: "单指移动图片,双指缩放", cropPreview: "裁剪预览", imageFit: "图片适配", + fill: "填充", fit: "适应", adjustOnScreen: "直接在屏幕中调整", gestureHelp: "在屏幕内拖动或双指缩放", + zoom: "缩放", reset: "重置", deleteConfirm: "确定要从收藏中删除此图片吗?", + galleryLoadFailed: "无法加载图库", automaticDisabled: "自动更换已暂停", settingSaved: "设置已保存", + intervalSaved: "更换间隔已保存", androidOnly: "此功能可在 Android 上使用", imagesAdded: "图片已添加到收藏", + selectionCancelled: "已取消选择", imageSelectionAndroid: "图片选择功能可在 Android 上使用", imageDeleted: "图片已删除", + imageDeleteFailed: "无法删除图片", cropSaved: "裁剪已保存", cropSaveFailed: "无法保存裁剪", + wallpaperUpdated: "锁屏已更新", + }, +}; + +function intervalLabel(language: Language, minutes: number) { + if (language === "de") return minutes < 60 ? `Alle ${minutes} Min.` : minutes === 60 ? "Jede Stunde" : `Alle ${minutes / 60} Std.`; + if (language === "fr") return minutes < 60 ? `Toutes les ${minutes} min` : minutes === 60 ? "Toutes les heures" : `Toutes les ${minutes / 60} h`; + if (language === "es") return minutes < 60 ? `Cada ${minutes} min` : minutes === 60 ? "Cada hora" : `Cada ${minutes / 60} h`; + if (language === "it") return minutes < 60 ? `Ogni ${minutes} min` : minutes === 60 ? "Ogni ora" : `Ogni ${minutes / 60} ore`; + if (language === "nl") return minutes < 60 ? `Elke ${minutes} min.` : minutes === 60 ? "Elk uur" : `Elke ${minutes / 60} uur`; + if (language === "pl") return minutes < 60 ? `Co ${minutes} min` : minutes === 60 ? "Co godzinę" : `Co ${minutes / 60} godz.`; + if (language === "pt") return minutes < 60 ? `A cada ${minutes} min` : minutes === 60 ? "A cada hora" : `A cada ${minutes / 60} h`; + if (language === "ja") return minutes < 60 ? `${minutes}分ごと` : minutes === 60 ? "1時間ごと" : `${minutes / 60}時間ごと`; + if (language === "ko") return minutes < 60 ? `${minutes}분마다` : minutes === 60 ? "1시간마다" : `${minutes / 60}시간마다`; + if (language === "zh-CN") return minutes < 60 ? `每 ${minutes} 分钟` : minutes === 60 ? "每小时" : `每 ${minutes / 60} 小时`; + return minutes < 60 ? `Every ${minutes} min` : minutes === 60 ? "Every hour" : `Every ${minutes / 60} hours`; +} + +const selectionCopies: Record = { + de: { selected: "ausgewählt", deleteSelected: "Auswahl löschen", deleteSelectedConfirm: "Möchtest du die ausgewählten Bilder wirklich löschen?", imagesDeleted: "Ausgewählte Bilder wurden gelöscht", imagesDeleteFailed: "Bilder konnten nicht gelöscht werden", selectImagesToDelete: "Bilder zum Löschen auswählen", clearSelection: "Auswahl aufheben", selectAll: "Alle auswählen", selectImage: "Bild auswählen", deselectImage: "Bild abwählen" }, + en: { selected: "selected", deleteSelected: "Delete selection", deleteSelectedConfirm: "Do you really want to delete the selected images?", imagesDeleted: "Selected images deleted", imagesDeleteFailed: "The images could not be deleted", selectImagesToDelete: "Select images to delete", clearSelection: "Clear selection", selectAll: "Select all", selectImage: "Select image", deselectImage: "Deselect image" }, + fr: { selected: "sélectionnées", deleteSelected: "Supprimer la sélection", deleteSelectedConfirm: "Voulez-vous vraiment supprimer les images sélectionnées ?", imagesDeleted: "Images sélectionnées supprimées", imagesDeleteFailed: "Impossible de supprimer les images", selectImagesToDelete: "Sélectionnez les images à supprimer", clearSelection: "Tout désélectionner", selectAll: "Tout sélectionner", selectImage: "Sélectionner l’image", deselectImage: "Désélectionner l’image" }, + es: { selected: "seleccionadas", deleteSelected: "Eliminar selección", deleteSelectedConfirm: "¿Quieres eliminar las imágenes seleccionadas?", imagesDeleted: "Imágenes seleccionadas eliminadas", imagesDeleteFailed: "No se pudieron eliminar las imágenes", selectImagesToDelete: "Selecciona imágenes para eliminar", clearSelection: "Quitar selección", selectAll: "Seleccionar todo", selectImage: "Seleccionar imagen", deselectImage: "Deseleccionar imagen" }, + it: { selected: "selezionate", deleteSelected: "Elimina selezione", deleteSelectedConfirm: "Vuoi davvero eliminare le immagini selezionate?", imagesDeleted: "Immagini selezionate eliminate", imagesDeleteFailed: "Impossibile eliminare le immagini", selectImagesToDelete: "Seleziona le immagini da eliminare", clearSelection: "Deseleziona tutto", selectAll: "Seleziona tutto", selectImage: "Seleziona immagine", deselectImage: "Deseleziona immagine" }, + nl: { selected: "geselecteerd", deleteSelected: "Selectie verwijderen", deleteSelectedConfirm: "Wil je de geselecteerde afbeeldingen echt verwijderen?", imagesDeleted: "Geselecteerde afbeeldingen verwijderd", imagesDeleteFailed: "De afbeeldingen konden niet worden verwijderd", selectImagesToDelete: "Selecteer afbeeldingen om te verwijderen", clearSelection: "Selectie wissen", selectAll: "Alles selecteren", selectImage: "Afbeelding selecteren", deselectImage: "Afbeelding deselecteren" }, + pl: { selected: "wybrano", deleteSelected: "Usuń wybrane", deleteSelectedConfirm: "Czy na pewno usunąć wybrane obrazy?", imagesDeleted: "Wybrane obrazy usunięto", imagesDeleteFailed: "Nie udało się usunąć obrazów", selectImagesToDelete: "Wybierz obrazy do usunięcia", clearSelection: "Wyczyść wybór", selectAll: "Wybierz wszystkie", selectImage: "Wybierz obraz", deselectImage: "Odznacz obraz" }, + pt: { selected: "selecionadas", deleteSelected: "Eliminar seleção", deleteSelectedConfirm: "Pretende mesmo eliminar as imagens selecionadas?", imagesDeleted: "Imagens selecionadas eliminadas", imagesDeleteFailed: "Não foi possível eliminar as imagens", selectImagesToDelete: "Selecione imagens para eliminar", clearSelection: "Limpar seleção", selectAll: "Selecionar tudo", selectImage: "Selecionar imagem", deselectImage: "Desmarcar imagem" }, + ja: { selected: "件選択中", deleteSelected: "選択項目を削除", deleteSelectedConfirm: "選択した画像を削除しますか?", imagesDeleted: "選択した画像を削除しました", imagesDeleteFailed: "画像を削除できませんでした", selectImagesToDelete: "削除する画像を選択", clearSelection: "選択を解除", selectAll: "すべて選択", selectImage: "画像を選択", deselectImage: "画像の選択を解除" }, + ko: { selected: "개 선택됨", deleteSelected: "선택 항목 삭제", deleteSelectedConfirm: "선택한 이미지를 삭제할까요?", imagesDeleted: "선택한 이미지를 삭제했습니다", imagesDeleteFailed: "이미지를 삭제할 수 없습니다", selectImagesToDelete: "삭제할 이미지 선택", clearSelection: "선택 해제", selectAll: "모두 선택", selectImage: "이미지 선택", deselectImage: "이미지 선택 해제" }, + "zh-CN": { selected: "张已选择", deleteSelected: "删除所选", deleteSelectedConfirm: "确定要删除所选图片吗?", imagesDeleted: "已删除所选图片", imagesDeleteFailed: "无法删除图片", selectImagesToDelete: "选择要删除的图片", clearSelection: "清除选择", selectAll: "全选", selectImage: "选择图片", deselectImage: "取消选择图片" }, +}; + +export const translations = Object.fromEntries(languages.map(language => { + const copy = language === "en" ? en : copies[language]; + return [language, { ...copy, ...selectionCopies[language], everyMinutes: (minutes: number) => intervalLabel(language, minutes) }]; +})) as Record string }>; + +function normalizeLanguage(value: string): Language | undefined { + const locale = value.toLowerCase(); + if (locale.startsWith("zh")) return "zh-CN"; + return languages.find(language => language.toLowerCase() === locale || locale.startsWith(`${language.toLowerCase()}-`)); +} + +export function initialLanguage(): Language { + const stored = window.localStorage.getItem("wallpaperflow-language"); + if (stored) { + const saved = normalizeLanguage(stored); + if (saved) return saved; + } + const systemLocales = window.navigator.languages?.length ? window.navigator.languages : [window.navigator.language]; + for (const locale of systemLocales) { + const match = normalizeLanguage(locale); + if (match) return match; + } + return "en"; +} diff --git a/src/i18n.ts b/src/i18n.ts deleted file mode 100644 index f2eeae3..0000000 --- a/src/i18n.ts +++ /dev/null @@ -1,140 +0,0 @@ -export type Language = "de" | "en"; - -export const translations = { - de: { - automaticActive: "Deine Motive wechseln automatisch", - automaticPaused: "Automatischer Wechsel ist pausiert", - settings: "Einstellungen", - currentWallpaper: "Aktuelles Hintergrundbild", - currentImage: "Aktuelles Motiv", - nextImage: "Nächstes Motiv", - changeOnWake: "Bei jedem Aktivieren wechseln", - selectImages: "Bilder auswählen", - pleaseWait: "Bitte warten …", - collection: "Meine Sammlung", - image: "Bild", - images: "Bilder", - motif: "Motiv", - noImages: "Noch keine Bilder ausgewählt", - collectionHint: "Tippe auf die Bildanzahl, um deine Galerie zu öffnen.", - shuffle: "Zufällige Reihenfolge", - lockScreenOnly: "Nur Sperrbildschirm", - settingsIntro: "Lege fest, wie WallpaperFlow im Hintergrund arbeitet.", - language: "Sprache", - german: "Deutsch", - english: "Englisch", - noImageLimit: "Ohne Bilderlimit", - privacyInfo: "Deine Auswahl wird privat auf dem Gerät gespeichert. Die einzige Grenze ist der freie Speicherplatz.", - home: "Start", - back: "Zurück", - addImages: "Bilder hinzufügen", - backToGallery: "Zurück zur Galerie", - editImage: "Bild anpassen", - savedForImage: "Wird nur für dieses Bild gespeichert", - saveCrop: "Bildausschnitt speichern", - myImages: "Meine Bilder", - current: "Aktuell", - adjustImage: "Bild anpassen", - deleteImage: "Bild löschen", - emptyCollection: "Deine Sammlung ist leer", - emptyCollectionText: "Füge Bilder hinzu, die automatisch als Sperrbildschirm wechseln sollen.", - galleryLoading: "Galerie wird geladen …", - loadMore: "Weitere Bilder laden", - editCrop: "Bildausschnitt bearbeiten", - gestureLabel: "Bild mit einem Finger verschieben und mit zwei Fingern zoomen", - cropPreview: "Vorschau des Bildausschnitts", - previewDate: "Donnerstag, 20. August", - imageFit: "Bildanpassung", - fill: "Ausfüllen", - fit: "Einpassen", - adjustOnScreen: "Direkt im Bildschirm anpassen", - gestureHelp: "Mit einem Finger verschieben · mit zwei Fingern zoomen", - reset: "Zurücksetzen", - deleteConfirm: "Möchtest du dieses Bild wirklich aus deiner Sammlung löschen?", - galleryLoadFailed: "Galerie konnte nicht geladen werden", - automaticEnabled: "Automatischer Wechsel ist aktiv", - automaticDisabled: "Automatischer Wechsel pausiert", - settingSaved: "Einstellung gespeichert", - androidOnly: "Diese Funktion ist auf Android verfügbar", - imagesAdded: "Bilder wurden zur Sammlung hinzugefügt", - selectionCancelled: "Auswahl abgebrochen", - imageSelectionAndroid: "Bildauswahl ist auf Android verfügbar", - imageDeleted: "Bild wurde gelöscht", - imageDeleteFailed: "Bild konnte nicht gelöscht werden", - cropSaved: "Bildausschnitt wurde gespeichert", - cropSaveFailed: "Bildausschnitt konnte nicht gespeichert werden", - wallpaperUpdated: "Sperrbildschirm wurde aktualisiert", - }, - en: { - automaticActive: "Your wallpapers change automatically", - automaticPaused: "Automatic rotation is paused", - settings: "Settings", - currentWallpaper: "Current wallpaper", - currentImage: "Current image", - nextImage: "Next image", - changeOnWake: "Change whenever the screen wakes", - selectImages: "Select images", - pleaseWait: "Please wait …", - collection: "My collection", - image: "image", - images: "images", - motif: "Image", - noImages: "No images selected yet", - collectionHint: "Tap the image count to open your gallery.", - shuffle: "Shuffle order", - lockScreenOnly: "Lock screen only", - settingsIntro: "Choose how WallpaperFlow works in the background.", - language: "Language", - german: "German", - english: "English", - noImageLimit: "No image limit", - privacyInfo: "Your selection stays private on this device. The only limit is the available storage.", - home: "Home", - back: "Back", - addImages: "Add images", - backToGallery: "Back to gallery", - editImage: "Adjust image", - savedForImage: "Saved only for this image", - saveCrop: "Save image crop", - myImages: "My images", - current: "Current", - adjustImage: "Adjust image", - deleteImage: "Delete image", - emptyCollection: "Your collection is empty", - emptyCollectionText: "Add images that should rotate automatically on your lock screen.", - galleryLoading: "Loading gallery …", - loadMore: "Load more images", - editCrop: "Edit image crop", - gestureLabel: "Move the image with one finger and zoom with two fingers", - cropPreview: "Image crop preview", - previewDate: "Thursday, August 20", - imageFit: "Image fit", - fill: "Fill", - fit: "Fit", - adjustOnScreen: "Adjust directly on screen", - gestureHelp: "Move with one finger · zoom with two fingers", - reset: "Reset", - deleteConfirm: "Do you really want to delete this image from your collection?", - galleryLoadFailed: "The gallery could not be loaded", - automaticEnabled: "Automatic rotation is active", - automaticDisabled: "Automatic rotation is paused", - settingSaved: "Setting saved", - androidOnly: "This feature is available on Android", - imagesAdded: "Images added to your collection", - selectionCancelled: "Selection cancelled", - imageSelectionAndroid: "Image selection is available on Android", - imageDeleted: "Image deleted", - imageDeleteFailed: "The image could not be deleted", - cropSaved: "Image crop saved", - cropSaveFailed: "The image crop could not be saved", - wallpaperUpdated: "Lock screen updated", - }, -} as const; - -export type TranslationKey = keyof typeof translations.de; - -export function initialLanguage(): Language { - const stored = window.localStorage.getItem("wallpaperflow-language"); - if (stored === "de" || stored === "en") return stored; - return window.navigator.language.toLowerCase().startsWith("de") ? "de" : "en"; -} diff --git a/src/native.ts b/src/native.ts index 523da1b..6500052 100644 --- a/src/native.ts +++ b/src/native.ts @@ -3,6 +3,7 @@ import { invoke } from "@tauri-apps/api/core"; export type WallpaperState = { imageCount: number; enabled: boolean; + intervalMinutes: number; shuffle: boolean; lockScreenOnly: boolean; currentIndex: number; @@ -27,6 +28,7 @@ export type GalleryPage = { const demoState: WallpaperState = { imageCount: 3, enabled: true, + intervalMinutes: 30, shuffle: true, lockScreenOnly: true, currentIndex: 0, @@ -68,6 +70,20 @@ export async function deleteImage(id: string): Promise { return { ...demoState, imageUrls: [...demoState.imageUrls] }; } +export async function getImageIds(): Promise { + if (inTauri()) return invoke("plugin:wallpaper|get_image_ids"); + return demoState.imageUrls.map((_, index) => `demo-${index}`); +} + +export async function deleteImages(ids: string[]): Promise { + if (inTauri()) return invoke("plugin:wallpaper|delete_images", { ids }); + const indexes = new Set(ids.map(id => Number(id.replace("demo-", ""))).filter(Number.isInteger)); + demoState.imageUrls = demoState.imageUrls.filter((_, index) => !indexes.has(index)); + demoState.imageCount = demoState.imageUrls.length; + demoState.currentIndex = Math.min(demoState.currentIndex, Math.max(0, demoState.imageCount - 1)); + return { ...demoState, imageUrls: [...demoState.imageUrls] }; +} + export async function setImageCrop(image: GalleryImage): Promise { const payload = { id: image.id, @@ -86,11 +102,20 @@ export async function setImageCrop(image: GalleryImage): Promise { return { ...image }; } -export async function setSetting(name: "enabled" | "shuffle" | "lockScreenOnly", value: boolean) { +export async function setSetting(name: "shuffle" | "lockScreenOnly", value: boolean) { if (!inTauri()) return { ...demoState, [name]: value }; return invoke("plugin:wallpaper|set_setting", { name, value }); } +export async function setIntervalMinutes(value: number) { + if (!inTauri()) { + demoState.intervalMinutes = value; + demoState.enabled = value > 0; + return { ...demoState }; + } + return invoke("plugin:wallpaper|set_interval", { minutes: value }); +} + export async function nextWallpaper(): Promise { if (!inTauri()) { demoState.currentIndex = (demoState.currentIndex + 1) % demoState.imageUrls.length; diff --git a/src/styles.css b/src/styles.css index 534786b..cfb652a 100644 --- a/src/styles.css +++ b/src/styles.css @@ -2,7 +2,7 @@ * { box-sizing: border-box; } body { margin: 0; min-width: 320px; min-height: 100vh; } button { font: inherit; } -.app-shell { width: min(100%, 480px); min-height: 100dvh; margin: 0 auto; background: #f8faf7; position: relative; padding-bottom: 94px; box-shadow: 0 0 50px rgba(32, 50, 37, .12); } +.app-shell { width: min(100%, 480px); min-height: 100dvh; margin: 0 auto; background: #f8faf7; position: relative; padding-bottom: 94px; box-shadow: 0 0 50px rgba(32, 50, 37, .12); overflow-anchor: none; } header { padding: max(24px, env(safe-area-inset-top)) 24px 18px; display: flex; align-items: center; justify-content: space-between; } h1 { font-size: 34px; letter-spacing: -1.7px; line-height: 1.05; margin: 0 0 6px; font-weight: 800; } header p { margin: 0; font-size: 13px; color: #657068; font-weight: 500; } @@ -41,6 +41,7 @@ header p { margin: 0; font-size: 13px; color: #657068; font-weight: 500; } .setting-icon { width: 39px; height: 39px; flex: 0 0 auto; display: grid; place-items: center; border-radius: 50%; background: var(--sage); color: var(--green); } .setting-icon svg { width: 19px; } .setting-row > span { flex: 1; line-height: 1.3; } +.interval-row select { min-width: 118px; max-width: 145px; height: 38px; padding: 0 30px 0 11px; border: 1px solid #cbd7cc; border-radius: 11px; color: var(--green); background: white; font-size: 12px; font-weight: 750; } .switch { width: 48px; height: 28px; padding: 3px; border-radius: 30px; border: 0; background: #c7cec8; transition: .2s ease; } .switch span { display: block; width: 22px; height: 22px; background: white; border-radius: 50%; box-shadow: 0 1px 3px rgba(0,0,0,.22); transition: transform .2s ease; } .switch.on { background: var(--green); } @@ -68,6 +69,7 @@ h2 { margin: 0; font-size: 21px; letter-spacing: -.6px; } .language-setting > div:nth-child(2) { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 2px; } .language-setting strong { font-size: 15px; } .language-setting span { color: #768078; font-size: 11px; } +.locale-select { min-width: 128px; max-width: 155px; height: 38px; padding: 0 28px 0 10px; border: 1px solid #cbd7cc; border-radius: 11px; color: var(--green); background: white; font-size: 12px; font-weight: 750; } .language-toggle { padding: 3px; display: flex; border-radius: 12px; background: #e8eee7; } .language-toggle button { width: 39px; height: 31px; padding: 0; border: 0; border-radius: 9px; color: #657068; background: transparent; font-size: 12px; font-weight: 800; } .language-toggle button.active { color: white; background: var(--green); box-shadow: 0 2px 7px rgba(20,93,50,.2); } @@ -81,14 +83,24 @@ nav button.active { color: var(--green); background: var(--sage); } nav svg { width: 21px; } .snackbar { position: fixed; z-index: 20; left: 50%; transform: translateX(-50%); bottom: 92px; max-width: calc(100% - 40px); background: #26312a; color: white; border: 0; border-radius: 12px; padding: 13px 18px; font-size: 12px; box-shadow: 0 8px 26px rgba(0,0,0,.22); } .gallery-page { padding-bottom: max(24px, env(safe-area-inset-bottom)); } +.selection-toolbar { min-height: 44px; margin: 0 0 11px; padding: 0 4px; display: flex; align-items: center; justify-content: space-between; gap: 12px; color: #6c766e; font-size: 12px; } +.selection-toolbar button { min-height: 36px; padding: 0 12px; border: 0; border-radius: 11px; color: var(--green); background: var(--sage); font-size: 12px; font-weight: 800; } +.selection-toolbar button:disabled { opacity: .55; } +.delete-selection { color: #fff; background: #8e2929; } .gallery-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 9px; } .gallery-grid article { position: relative; aspect-ratio: 3 / 4; overflow: hidden; border-radius: 14px; background: #e3e9e2; border: 2px solid transparent; } .gallery-grid article.current { border-color: #73a17c; } -.gallery-grid article > img { width: 100%; height: 100%; object-fit: cover; display: block; } +.gallery-grid article.chosen { border-color: var(--green); box-shadow: 0 0 0 2px rgba(20,93,50,.14); } +.gallery-image-button { width: 100%; height: 100%; padding: 0; border: 0; background: transparent; display: block; } +.gallery-image-button img { width: 100%; height: 100%; object-fit: cover; display: block; } +.gallery-grid article.chosen .gallery-image-button img { filter: brightness(.78); } +.selection-check { position: absolute; z-index: 2; top: 7px; right: 7px; width: 27px; height: 27px; display: grid; place-items: center; border: 2px solid rgba(255,255,255,.94); border-radius: 50%; color: transparent; background: rgba(28,38,31,.28); pointer-events: none; } +.selection-check svg { width: 15px; } +.gallery-grid article.chosen .selection-check { color: white; border-color: var(--green); background: var(--green); } .delete-button { position: absolute; top: 7px; right: 7px; width: 32px; height: 32px; padding: 0; border: 0; border-radius: 50%; display: grid; place-items: center; color: white; background: rgba(94, 20, 20, .86); box-shadow: 0 3px 12px rgba(0,0,0,.24); } .delete-button svg { width: 16px; } .delete-button:disabled { opacity: .5; } -.edit-button { position: absolute; right: 7px; bottom: 7px; width: 32px; height: 32px; padding: 0; border: 0; border-radius: 50%; display: grid; place-items: center; color: var(--green); background: rgba(255,255,255,.92); box-shadow: 0 3px 12px rgba(0,0,0,.2); } +.edit-button { position: absolute; z-index: 2; right: 7px; bottom: 7px; width: 32px; height: 32px; padding: 0; border: 0; border-radius: 50%; display: grid; place-items: center; color: var(--green); background: rgba(255,255,255,.92); box-shadow: 0 3px 12px rgba(0,0,0,.2); } .edit-button svg { width: 16px; } .current-badge { position: absolute; left: 6px; bottom: 6px; display: flex; align-items: center; gap: 3px; padding: 5px 7px; border-radius: 99px; background: rgba(20, 93, 50, .9); color: white; font-size: 9px; font-weight: 750; } .current-badge svg { width: 11px; height: 11px; } @@ -106,6 +118,14 @@ nav svg { width: 21px; } .phone-preview.interactive { touch-action: none; user-select: none; cursor: grab; } .phone-preview.interactive:active { cursor: grabbing; } .phone-preview.interactive > img { pointer-events: none; user-select: none; transition: none; } +.crop-grid { position: absolute; z-index: 2; inset: 0; pointer-events: none; opacity: .48; } +.crop-grid i { position: absolute; display: block; background: rgba(255,255,255,.72); box-shadow: 0 0 2px rgba(0,0,0,.38); } +.crop-grid i:nth-child(1), .crop-grid i:nth-child(2) { top: 0; bottom: 0; width: 1px; } +.crop-grid i:nth-child(1) { left: 33.333%; } +.crop-grid i:nth-child(2) { left: 66.666%; } +.crop-grid i:nth-child(3), .crop-grid i:nth-child(4) { left: 0; right: 0; height: 1px; } +.crop-grid i:nth-child(3) { top: 33.333%; } +.crop-grid i:nth-child(4) { top: 66.666%; } .preview-clock { position: absolute; z-index: 2; top: 55px; left: 0; right: 0; color: white; text-align: center; font-size: 42px; line-height: 1; font-weight: 300; text-shadow: 0 2px 10px rgba(0,0,0,.45); pointer-events: none; } .preview-clock span { display: block; margin-top: 7px; font-size: 10px; font-weight: 600; } .crop-controls { padding: 17px; border: 1px solid var(--line); border-radius: 20px; background: white; } @@ -121,6 +141,9 @@ nav svg { width: 21px; } .direct-crop-heading svg { width: 17px; } .direct-crop-heading strong { color: var(--green); } .direct-crop-help { margin: 5px 0 11px; color: #7a837d; font-size: 10px; line-height: 1.4; } +.zoom-control { display: grid !important; grid-template-columns: 40px 1fr; align-items: center; gap: 10px; margin: 13px 0 0 !important; } +.zoom-control > span { color: #526158; font-size: 12px; font-weight: 750; } +.zoom-control input { margin: 0 !important; } .reset-crop { width: 100%; height: 42px; margin-top: 16px; border: 0; border-radius: 12px; color: #526158; background: #edf2eb; display: flex; justify-content: center; align-items: center; gap: 7px; font-size: 12px; font-weight: 750; } .reset-crop svg { width: 16px; } @media (min-width: 700px) { .app-shell { margin-top: 20px; min-height: calc(100vh - 40px); border-radius: 32px; overflow: hidden; } nav { bottom: 20px; border-radius: 0 0 32px 32px; } }