111 Commits

Author SHA1 Message Date
ShirkNeko
4bec5ae7b1 ksud: Update version code calculations to adjust historical version offsets 2025-06-22 18:45:58 +08:00
ShirkNeko
f9b3478dbb Fix text parameter formatting in KstatConfigItemCard, remove redundant “parameter:” prefixes 2025-06-22 18:33:50 +08:00
ShirkNeko
561c82de0a manager: Refactoring the SuSFS configuration layout and simplifying functions 2025-06-22 18:31:11 +08:00
Amicia De Rune
e96ceb84c9 Update Indonesia Translate (#204)
* Update Indonesia Translate

* Update manager/app/src/main/res/values-in/strings.xml

<string name="show_kpm_info">Sembunyikan fungsi KPM</string>

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update manager/app/src/main/res/values-in/strings.xml

<string name="show_kpm_info_summary">Sembunyikan fungsi informasi KPM dan menu KPM di bilah navigasi</string>

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update manager/app/src/main/res/values-in/strings.xml

<string name="home_ContributionCard_kernelsu">Antusias Untuk SukiSU Ultra</string>

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update manager/app/src/main/res/values-in/strings.xml

<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra akan menjadi cabang KSU yang relatif independen di masa mendatang, tetapi kami tetap menghargai KernelSU dan MKSU resmi dan sebagainya atas kontribusi mereka!</string>

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update manager/app/src/main/res/values-in/strings.xml

<string name="engine_force_ksu">Penggunaan wajib KSU WebUI</string>

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update manager/app/src/main/res/values-in/strings.xml

<string name="language_changed">Bahasa dirubah, mulai ulang aplikasi untuk menerapkan</string>

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update manager/app/src/main/res/values-in/strings.xml

<string name="icon_switch_summary">Ubah ikon peluncur aplikasi ke ikon KernelSU</string>

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update manager/app/src/main/res/values-in/strings.xml

<string name="show_more_module_info_summary">Pajang info modul tambahan seperti URL pembaruan JSON</string>

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-21 23:40:11 +08:00
ShirkNeko
ddbbeafc64 manager: Added the SUS Mount Hide Control feature added in SuSFS version 1.5.8 2025-06-21 23:39:19 +08:00
ShirkNeko
285478a778 manager: Remove deprecated OverlayFS checks for automatic kernel stats support.
- Updating the LKM build

- New Crowdin updates
2025-06-21 18:34:37 +08:00
Rifat Azad
00ffa86705 kernel/Makefile: check kernelsu driver version from online git repo first, if fails then check local .git and if that also fails then use hardcoded fallback 2025-06-21 17:09:16 +08:00
ShirkNeko
74ec20745c Uniformly use surfaceContainerHigh as the background color of the popup window 2025-06-21 16:34:38 +08:00
ShirkNeko
b7b995bf73 Updating the Crowdin Workflow Configuration 2025-06-21 15:37:33 +08:00
ShirkNeko
29b7f9e0ad New Crowdin updates (#200)
* New translations strings.xml (Japanese)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Chinese Traditional, Hong Kong)

* New translations strings.xml (Russian)
2025-06-21 14:51:13 +08:00
ShirkNeko
00a4c69227 Remove unused strings 2025-06-21 14:18:51 +08:00
愛莉希雅
9c204496c3 完善補充正體中文-香港 (#3) (#194) 2025-06-21 12:41:41 +08:00
ShirkNeko
519401cf39 Fixing SUS Path Execution Errors
- Simplify SuSFS configuration management
2025-06-21 00:21:14 +08:00
愛莉希雅
f69eb5c115 完善補充正體中文-香港#2 (#191) 2025-06-20 21:23:29 +08:00
NkBe
82e96f4394 manger: 完善補充正體中文 (#189)
* manger: Pangu Format

Pangu Format maintained for new text.

* manger: 完善正體中文
2025-06-20 19:11:30 +08:00
Prslc
8e3db00b9b README: Sync README_EN with README (#190) 2025-06-20 19:11:20 +08:00
ShirkNeko
adf299d9f3 manager: Update the feature definition
- remove the unused FEATURE_SUS_OVERLAYFS
- add FEATURE_SUSFS_HAS_MAGIC_MOUNT
2025-06-20 01:52:00 +08:00
rsuntk
483a39c7ac kernel: core_hook: fix refcount leaks on try_umount (#2635)
Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Signed-off-by: rsuntk <rsuntk@yukiprjkt.my.id>
Co-authored-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-19 18:28:21 +08:00
ShirkNeko
c83baad6d5 manager: Add SuSFS Kstat-related configuration 2025-06-19 11:26:15 +08:00
ShirkNeko
2ff3b5ee06 manager: Fix the character processing logic in the clear command of FlashScreen. 2025-06-18 15:52:48 +08:00
ShirkNeko
b537b51034 manager:Add SuSFS to obtain slot uname and build time information 2025-06-18 15:41:08 +08:00
ShirkNeko
bfb6ea3613 manager:Adjust the text display of setting items to allow multi-line text descriptions 2025-06-18 00:12:27 +08:00
ShirkNeko
edf7685e9a strings: Updates the string resources at the current execution location and modifies the associated text display 2025-06-17 23:58:42 +08:00
ShirkNeko
f65f62360a strings: Update path setting related strings and comments 2025-06-17 23:38:37 +08:00
ShirkNeko
af97488d58 manager: Add pseudo kernel and build time execution location settings 2025-06-17 23:30:29 +08:00
ShirkNeko
6b1f73aa3d manager: Small increase in app acquisition speed 2025-06-17 22:34:47 +08:00
Re*Index. (ot_inc)
4eeece9559 Fix Japanese (#186) 2025-06-17 10:52:16 +08:00
ShirkNeko
4d7d5547ac New Crowdin updates (#184)
* New translations strings.xml (Turkish)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)
2025-06-17 00:56:15 +08:00
NkBe
7b74e70f97 manger: 更新正體中文 (#183)
* manger: 更新正體中文

* 保证 pangu 格式
2025-06-17 00:25:12 +08:00
ShirkNeko
d92f8fc8fd New Crowdin updates (#181)
* New translations strings.xml (Romanian)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (Arabic)

* New translations strings.xml (Danish)

* New translations strings.xml (German)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Italian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Korean)

* New translations strings.xml (Lithuanian)

* New translations strings.xml (Dutch)

* New translations strings.xml (Polish)

* New translations strings.xml (Russian)

* New translations strings.xml (Slovenian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Persian)

* New translations strings.xml (Marathi)

* New translations strings.xml (Thai)

* New translations strings.xml (Croatian)

* New translations strings.xml (Estonian)

* New translations strings.xml (Latvian)

* New translations strings.xml (Azerbaijani)

* New translations strings.xml (Hindi)

* New translations strings.xml (Malay)

* New translations strings.xml (Filipino)

* New translations strings.xml (Chinese Traditional, Hong Kong)

* New translations strings.xml (Bosnian)

* New translations strings.xml (Kannada)
2025-06-16 21:55:31 +08:00
ShirkNeko
55f9de2fa9 manager: split susfs module creation scripts
- Add a small number of scripts from the susfs4ksu module that lack a weak BL.
2025-06-16 21:50:51 +08:00
ShirkNeko
a12b14ef46 manager: Refactoring get the status of SUSFS functions
- More precise status cases
- Requires a recompile of your kernel to use it.
2025-06-16 20:16:25 +08:00
ShirkNeko
4ce6ff6286 manager: add ability to read and parse /proc/config.gz file, optimize function status checking 2025-06-15 22:48:56 +08:00
ShirkNeko
ce3566640c Add the ability to display more module information, support copying the update configuration address to the clipboard 2025-06-15 22:21:14 +08:00
ShirkNeko
a0a9fb01f4 manager: Add the function of hiding module label rows, optimize the module lagging problem 2025-06-15 21:50:09 +08:00
ShirkNeko
e1bd16d94f manager: Contrasting scroll to top and bottom functions 2025-06-15 20:05:40 +08:00
ShirkNeko
776ae8744c manager: add folder size labels for module items to optimize the display of module information 2025-06-15 19:27:26 +08:00
ShirkNeko
9285945e8b manager: Optimize the animation of floating action buttons, add zoom and transparency animation 2025-06-15 18:47:51 +08:00
ShirkNeko
75e56038ec manager: Add visibility state management for floating action buttons
- Get change button style from Apatch
2025-06-15 18:32:17 +08:00
ShirkNeko
730d58f18b dec++-ify jni part
- Refactoring to c

Co-authored-by: lamadaemon <i@lama.icu>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-15 17:17:19 +08:00
ShirkNeko
67a05e8813 strings: Modifying SuSFS Configuration to Optimize Boot Self-Start Description 2025-06-15 16:05:04 +08:00
ShirkNeko
e95a469bdb manager: Add a default tab item to the AppItem
- Maybe make the spacing consistent? I'm not sure.

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-15 15:52:43 +08:00
HSSkyBoy
2ff122e235 manger: 更新正體中文 (#169)
* manger: 更新正體中文

翻譯已更新內容,優化原本翻譯

* Update strings.xml

* 保证 Pangu 格式

* 補全新內容
2025-06-15 15:08:51 +08:00
ShirkNeko
2319452306 manager: Refactor the bootstrap script to automatically create a KSU module to execute instead
- Add Shamiko's Hidden Weakness Bl Scripts

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-15 14:41:14 +08:00
ShirkNeko
a0752d10c7 Merge branch 'main' of https://github.com/SukiSU-Ultra/SukiSU-Ultra 2025-06-15 03:39:13 +08:00
ShirkNeko
9110d89d61 manager: Add configuration for SuSFS logging feature, support enable/disable logging 2025-06-15 03:38:51 +08:00
米凛MiRin
39d6962320 modified: docs/README-en.md (#170)
modified:   docs/README.md
2025-06-15 01:35:25 +08:00
ShirkNeko
7b314116e9 manager: Refactored SuSFS pop-up window and changed to interface to optimize visual experience 2025-06-15 01:32:38 +08:00
ShirkNeko
ef4101cbf9 manager: Optimizing SuSFS Feature Status Display
- Use labels instead of Text

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-14 22:35:36 +08:00
ShirkNeko
85f5459c1d manager: Add support for automatic selection of corresponding SuSFS version and build time artifacts 2025-06-14 22:04:40 +08:00
ShirkNeko
97e367aa92 manager: Update and add SuSFS related settings and functions. 2025-06-14 20:00:16 +08:00
ShirkNeko
7097986cf5 manager: Add loading animation and empty state component
- Improve user experience when app has no content

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-14 15:39:06 +08:00
ShirkNeko
d6c8ef3737 manager: Add configure susfs uname value in more settings
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-14 01:10:40 +08:00
ShirkNeko
d7a5e80d34 manager: Modifying the getHookType function to return a string type
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-13 15:36:15 +08:00
ShirkNeko
2d9783e3d4 manager: Add the ability to get the hook type 2025-06-13 14:39:16 +08:00
backslashxx
9f407a94e3 kernel: throne_tracker: avoid cross-fs traversal using s_magic check (#2633)
Skip directories that does NOT have the same magic as /data/app.
This is to avoid scanning incfs and any other stacked filesystems.

While this is way dumber, it's way cheaper.
no kern_path(), no missable path_put(), no ref handling.

This supercedes
`throne_tracker: avoid cross fs access
(https://github.com/tiann/KernelSU/pull/2626)`
- upstream
0b6998b474

Signed-off-by: backslashxx
<118538522+backslashxx@users.noreply.github.com>
2025-06-13 02:38:02 +08:00
ShirkNeko
99726a2c4e [skip ci] docs: Updated README file to reflect instructions for the susfs-main branch
kernel: Added sukisu_set_manager_uid function to set the management UID
2025-06-13 02:36:50 +08:00
ShirkNeko
f3675e7f6e Revert "throne_tracker: avoid cross fs access 2025-06-11 18:55:25 +08:00
ShirkNeko
b84d528d99 [skip ci] manager: update values-tr/strings.xml (#161)
Co-authored-by: cvnertnc <148134890+cvnertnc@users.noreply.github.com>
2025-06-11 18:48:08 +08:00
ShirkNeko
0aab0c1d6b manager: Optimize the layout of PullToRefreshBox in SuperUserScreen to remove redundant padding 2025-06-11 00:47:03 +08:00
ShirkNeko
ab2367f7fa manager: Refactor AppItem layout and improve label display 2025-06-11 00:21:13 +08:00
Wang Han
1bac30930f Switch to prepare_creds/commit_creds
Update API as per kernel doc recommends, also fix setup_groups refcount
leak while at it.
2025-06-10 23:39:08 +08:00
ShirkNeko
6a9186300b [skip ci]New Crowdin updates (#156)
* New translations strings.xml (Romanian)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (Arabic)

* New translations strings.xml (Danish)

* New translations strings.xml (German)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Italian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Korean)

* New translations strings.xml (Lithuanian)

* New translations strings.xml (Dutch)

* New translations strings.xml (Polish)

* New translations strings.xml (Russian)

* New translations strings.xml (Slovenian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Persian)

* New translations strings.xml (Marathi)

* New translations strings.xml (Thai)

* New translations strings.xml (Croatian)

* New translations strings.xml (Estonian)

* New translations strings.xml (Latvian)

* New translations strings.xml (Azerbaijani)

* New translations strings.xml (Hindi)

* New translations strings.xml (Malay)

* New translations strings.xml (Filipino)

* New translations strings.xml (Chinese Traditional, Hong Kong)

* New translations strings.xml (Bosnian)

* New translations strings.xml (Kannada)

* New translations strings.xml (Romanian)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (Arabic)

* New translations strings.xml (Danish)

* New translations strings.xml (German)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Italian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Korean)

* New translations strings.xml (Lithuanian)

* New translations strings.xml (Dutch)

* New translations strings.xml (Polish)

* New translations strings.xml (Russian)

* New translations strings.xml (Slovenian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Persian)

* New translations strings.xml (Marathi)

* New translations strings.xml (Thai)

* New translations strings.xml (Croatian)

* New translations strings.xml (Estonian)

* New translations strings.xml (Latvian)

* New translations strings.xml (Azerbaijani)

* New translations strings.xml (Hindi)

* New translations strings.xml (Malay)

* New translations strings.xml (Filipino)

* New translations strings.xml (Chinese Traditional, Hong Kong)

* New translations strings.xml (Bosnian)

* New translations strings.xml (Kannada)

* New translations strings.xml (Japanese)

* New translations strings.xml (Russian)

* New translations strings.xml (Vietnamese)
2025-06-10 23:33:35 +08:00
WenHao2130
e6dea3c29e [skip ci]manager: Drop QQ group invitation link (#158)
Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-06-10 23:33:04 +08:00
ShirkNeko
c873ff74cb manager: Add status tracking to ensure that brush-write operations are performed correctly 2025-06-09 02:25:02 +08:00
ShirkNeko
7b6f451cfb manager: Optimize the function of app classification and sorting method 2025-06-09 01:27:33 +08:00
ShirkNeko
73dea0b8e7 Adjusting component spacing and interaction effects 2025-06-08 23:13:41 +08:00
米凛MiRin
f71d617cb3 manager: fix color (#154) 2025-06-08 22:07:29 +08:00
WenHao2130
f0d8e42026 manager: Fix get Google device model issues (#153)
- Inconsistent case of BRAND and MANUFACTURER information on Google devices results in unintended behavior (e.g. Google Google Pixel 9 XL)

Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-06-08 21:08:05 +08:00
ShirkNeko
5bbd95e821 manager: Updated superuser interface, added sidebar categories 2025-06-08 20:28:05 +08:00
WenHao2130
fa060dca58 manager: Refactoring the get device name logic (#152)
* manager: Import `getDeviceInfo()` from bmax/APatch

Co-authored-by: GarfieldHan <2652609017@qq.com>
Signed-off-by: WenHao2130 <wenhao2130@outlook.com>

* manager: Use `getDeviceInfo()` instead `Build.DEVICE`

Signed-off-by: WenHao2130 <wenhao2130@outlook.com>

---------

Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
Co-authored-by: GarfieldHan <2652609017@qq.com>
2025-06-08 15:47:48 +08:00
ShirkNeko
9c7ba5b998 [skip ci]: docs: Updating the README file to add a description of support for non-GKI device builds
完整正體中文本地化

對缺失內容的完整翻譯,對現有內容參考 SukiSU-Ultra 簡體中文優化

New Crowdin updates (#140)

Co-authored-by: HSSkyBoy <HSSkyBoy@outlook.com>
Co-authored-by: cvnertnc <148134890+cvnertnc@users.noreply.github.com>
Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-07 22:23:49 +08:00
ShirkNeko
061136900a [skip ci]: New Crowdin updates (#138)
* New translations strings.xml (Romanian)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (Arabic)

* New translations strings.xml (Danish)

* New translations strings.xml (German)

* New translations strings.xml (Romanian)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (Arabic)

* New translations strings.xml (Danish)

* New translations strings.xml (German)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Italian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Korean)

* New translations strings.xml (Lithuanian)

* New translations strings.xml (Dutch)

* New translations strings.xml (Polish)

* New translations strings.xml (Russian)

* New translations strings.xml (Slovenian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Persian)

* New translations strings.xml (Marathi)

* New translations strings.xml (Thai)

* New translations strings.xml (Croatian)

* New translations strings.xml (Estonian)

* New translations strings.xml (Latvian)

* New translations strings.xml (Azerbaijani)

* New translations strings.xml (Hindi)

* New translations strings.xml (Malay)

* New translations strings.xml (Filipino)

* New translations strings.xml (Chinese Traditional, Hong Kong)

* New translations strings.xml (Bosnian)

* New translations strings.xml (Kannada)
2025-06-03 17:16:15 +08:00
ShirkNeko
6375bf4b7c manager: Simplify state management of components for installation method selection
Remove unnecessary LKM upload logic
2025-06-03 16:57:41 +08:00
ShirkNeko
17288c086a manager: Simplify Home data initialization logic and remove unnecessary caching time 2025-06-03 16:29:41 +08:00
ShirkNeko
15747ceaa5 manager: Simplify KPM display judgment in Home messages 2025-06-03 15:48:21 +08:00
ShirkNeko
675bb20f52 manager: Modify the Show KPM function to hidden and update the related settings. 2025-06-03 15:26:03 +08:00
ShirkNeko
ec0b26a174 manager: Optimize slot selection dialog to remove unnecessary information 2025-06-03 15:15:48 +08:00
ShirkNeko
92f6f2f51e manager: Add card shadow effect control 2025-06-03 14:04:55 +08:00
5ec1cff
587e73b449 manager: persist show system app settings 2025-06-03 13:53:45 +08:00
ShirkNeko
07c9cce4b9 manager: Fixed flickering on activity refresh using a clever method.
- Add Activity lifecycle callback and method to refresh current Activity
2025-06-03 01:43:31 +08:00
ShirkNeko
1d34ea4995 Rename files and update package structure
Add tool classes related to displaying and refreshing data
2025-06-03 01:02:08 +08:00
5ec1cff
d58ec6952c throne_tracker: avoid cross fs access 2025-06-03 00:03:16 +08:00
ShirkNeko
50631aade6 Manager: Refactoring of hidden messages and display of KPM settings status management 2025-06-03 00:00:39 +08:00
ShirkNeko
6df8f6f5d4 refactor: simplify handling and add app restart utility 2025-06-02 22:47:30 +08:00
米凛MiRin
4aee26b48e manager: auto restart after Display KPM Function and Hide other info (#136) 2025-06-02 22:24:17 +08:00
ShirkNeko
3bbe415c7e Merge branch 'main' of https://github.com/SukiSU-Ultra/SukiSU-Ultra 2025-06-02 21:33:55 +08:00
ShirkNeko
892fa9040f docs: add troubleshooting section for KernelSU Manager uninstallation issues 2025-06-02 21:33:48 +08:00
ShirkNeko
cadc123eab [skip ci] New Crowdin updates (#135)
* New translations strings.xml (Romanian)

* New translations strings.xml (Romanian)

* New translations strings.xml (Russian)

* New translations strings.xml (Vietnamese)
2025-06-02 21:30:13 +08:00
ShirkNeko
3a27537648 [skip ci] strings: update the description of the hidden additional information 2025-06-02 21:06:08 +08:00
ShirkNeko
6fa1a5c8b8 Optimize the logic of badge display in the bottom navigation bar
Add support for settings to hide other information

README: add notice about stuck device solution (#134)

Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Co-authored-by: =?UTF-8?q?=E7=B1=B3=E5=87=9BMiRin?= <148533509+MiRinChan@users.noreply.github.com>

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-02 20:46:49 +08:00
ShirkNeko
b772c8ece1 manager: Refactoring data refresh management
New AppData object to optimize data fetching and state management.
2025-06-02 17:49:34 +08:00
ShirkNeko
c0e839dd8e manager: Implement module count refresh
- update count data periodically and optimize the bottom bar display
2025-06-02 17:24:34 +08:00
ShirkNeko
a6ed7befdc manager: Add count icon to bottom bar
- Remove count icon from Home
- Add put back button for more settings
2025-06-02 16:43:31 +08:00
米凛MiRin
c210b00d54 manager: accessibility optimization (#131)
manager: style optimization
2025-06-02 14:47:59 +08:00
ShirkNeko
13b5290598 [skip ci]New Crowdin updates (#133)
* New translations strings.xml (Romanian)

* New translations strings.xml (French)

* New translations strings.xml (Spanish)

* New translations strings.xml (Arabic)

* New translations strings.xml (Danish)

* New translations strings.xml (German)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Italian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Korean)

* New translations strings.xml (Lithuanian)

* New translations strings.xml (Dutch)

* New translations strings.xml (Polish)

* New translations strings.xml (Russian)

* New translations strings.xml (Slovenian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Portuguese, Brazilian)

* New translations strings.xml (Persian)

* New translations strings.xml (Marathi)

* New translations strings.xml (Thai)

* New translations strings.xml (Croatian)

* New translations strings.xml (Estonian)

* New translations strings.xml (Latvian)

* New translations strings.xml (Azerbaijani)

* New translations strings.xml (Hindi)

* New translations strings.xml (Malay)

* New translations strings.xml (Filipino)

* New translations strings.xml (Bosnian)

* New translations strings.xml (Kannada)

* New translations strings.xml (Japanese)

* New translations strings.xml (Chinese Simplified)
2025-06-02 14:34:41 +08:00
ShirkNeko
b99516da69 [skip ci]: New Crowdin updates (#130)
* Update source file strings.xml

* New translations strings.xml (Romanian)

* New translations strings.xml (Danish)

* New translations strings.xml (Hungarian)

* New translations strings.xml (Italian)

* New translations strings.xml (Japanese)

* New translations strings.xml (Korean)

* New translations strings.xml (Lithuanian)

* New translations strings.xml (Dutch)

* New translations strings.xml (Polish)

* New translations strings.xml (Russian)

* New translations strings.xml (Slovenian)

* New translations strings.xml (Ukrainian)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Persian)

* New translations strings.xml (Marathi)

* New translations strings.xml (Thai)

* New translations strings.xml (Croatian)

* New translations strings.xml (Estonian)

* New translations strings.xml (Latvian)

* New translations strings.xml (Azerbaijani)

* New translations strings.xml (Hindi)

* New translations strings.xml (Malay)

* New translations strings.xml (Filipino)

* New translations strings.xml (Chinese Traditional, Hong Kong)

* New translations strings.xml (Bosnian)

* New translations strings.xml (Kannada)
2025-06-02 14:03:10 +08:00
lshwjgpt25
fe8b5f2135 [skip ci]: Align superuser app spacing with module spacing (#132) 2025-06-02 13:31:41 +08:00
ShirkNeko
04e1b9bf77 manager: Update back navigation logic in FlashScreen for module flashing 2025-06-02 04:10:41 +08:00
ShirkNeko
b8aaf918fe Merge branch 'main' of https://github.com/SukiSU-Ultra/SukiSU-Ultra 2025-06-02 02:11:40 +08:00
ShirkNeko
54925188e8 Optimize interface element spacing and styles 2025-06-02 02:09:46 +08:00
yycgit1
3443e48ef1 manager: Add alternate app icon toggle (#129)
Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
Co-authored-by: MiRinChan <148533509+MiRinChan@users.noreply.github.com>
2025-06-01 22:43:08 +08:00
ShirkNeko
53b3e84890 Optimize button styles in SuperUser 2025-06-01 22:36:23 +08:00
ShirkNeko
a5b85bfdad manager: Update theme color display in MoreSettings screen and adjust title style 2025-06-01 21:56:56 +08:00
ShirkNeko
2817583e3c Optimize icon handling for settings cards
Allow icons to be optional and remove redundant group title displays
2025-06-01 21:24:21 +08:00
ShirkNeko
8a6116b4ec manager: Update surface colors to use cardAlpha for improved theme consistency 2025-06-01 20:58:28 +08:00
cvnertnc
6a4270787a [skip ci]Manager: update values-tr/strings.xml (#126) 2025-06-01 20:29:03 +08:00
ShirkNeko
5457a4772b manager: Refactor card elevation handling and improve theme support 2025-06-01 20:17:22 +08:00
ShirkNeko
ee4c3bb03b manager: Optimize color schemes for themes and module screens
- Remove unnecessary background color settings
2025-06-01 14:04:10 +08:00
ShirkNeko
dd1d17d2cf Optimize the display logic of reboot drop down menu items 2025-06-01 02:27:55 +08:00
WenHao2130
3c353e8f88 manager: Modify the display logic of safe_mode (#125)
Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-06-01 01:30:16 +08:00
116 changed files with 13858 additions and 6559 deletions

View File

@@ -24,23 +24,23 @@ jobs:
matrix:
include:
- version: "android12-5.10"
sub_level: 237
os_patch_level: 2025-06
- version: "android13-5.10"
sub_level: 236
os_patch_level: 2025-05
- version: "android13-5.10"
sub_level: 234
os_patch_level: 2025-03
- version: "android13-5.15"
sub_level: 178
os_patch_level: 2025-03
sub_level: 180
os_patch_level: 2025-05
- version: "android14-5.15"
sub_level: 178
os_patch_level: 2025-03
sub_level: 180
os_patch_level: 2025-05
- version: "android14-6.1"
sub_level: 134
os_patch_level: 2025-05
sub_level: 138
os_patch_level: 2025-06
- version: "android15-6.6"
sub_level: 87
os_patch_level: 2025-05
sub_level: 89
os_patch_level: 2025-06
# uses: ./.github/workflows/gki-kernel-mock.yml when debugging
uses: ./.github/workflows/gki-kernel.yml
with:

View File

@@ -4,35 +4,37 @@ on:
push:
branches: [ main ]
paths:
- 'manager/app/src/main/res/**'
- 'manager/app/src/main/res/values/strings.xml'
- 'manager/app/src/main/res/values-*/strings.xml'
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
jobs:
synchronize-with-crowdin:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Checkout
uses: actions/checkout@v4
- name: crowdin action
uses: crowdin/github-action@master
with:
upload_sources: true
upload_translations: true
download_translations: true
localization_branch_name: "Crowdin"
crowdin_branch_name: "main"
create_pull_request: true
pull_request_title: 'New Crowdin Translations'
pull_request_body: 'New Crowdin translations by [Crowdin GH Action](https://github.com/crowdin/github-action)'
pull_request_base_branch_name: 'main'
skip_untranslated_files: true
env:
# A classic GitHub Personal Access Token with the 'repo' scope selected (the user should have write access to the repository).
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
- name: Crowdin Action
uses: crowdin/github-action@v2
with:
upload_sources: true
upload_translations: true
auto_approve_imported: true
download_translations: true
skip_untranslated_files: false
skip_untranslated_strings: true
# A numeric ID, found at https://crowdin.com/project/<projectName>/tools/api
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
create_pull_request: true
localization_branch_name: "Crowdin"
pull_request_labels: 'enhancement, translation'
pull_request_title: 'opt: sync translation from Crowdin'
# Visit https://crowdin.com/settings#api-key to create this token
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
config: 'crowdin.yml'
crowdin_branch_name: "main"
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_API_TOKEN: ${{ secrets.CROWDIN_API_TOKEN }}

View File

@@ -1,3 +1,6 @@
project_id_env: CROWDIN_PROJECT_ID
api_token_env: CROWDIN_API_TOKEN
preserve_hierarchy: 1
files:
- source: /manager/app/src/main/res/values/strings.xml
translation: /manager/app/src/main/res/values-%two_letters_code%/strings.xml

View File

@@ -13,42 +13,63 @@ Android device root solution based on [KernelSU](https://github.com/tiann/Kernel
## How to add
Using main branching (non-GKI device builds are not supported) (requires manual integration of susfs)
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main
```
Using branches that support non-GKI devices (requires manual integration of susfs)
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s nongki
```
## How to use integrated susfs
1. Use the susfs-dev branch directly without any patching
1. Use susfs-main or other susfs-\* branches directly, no need to integrate susfs again (supports non-GKI device builds)
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-dev
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-main
```
## Hook method
- This method references the hook [method by rsuntk](https://github.com/rsuntk/KernelSU)
1. **KPROBES hook:**
- Also used for Loadable Kernel Module (LKM)
- Default hook method on GKI kernels.
- Need `CONFIG_KPROBES=y`
2. **Manual hook:**
- Standard KernelSU hook: https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#manually-modify-the-kernel-source
- backslashxx's syscall manual hook: https://github.com/backslashxx/KernelSU/issues/5
- Default hook method on Non-GKI kernels.
- Need `CONFIG_KSU_MANUAL_HOOK=y`
## KPM Support
- Based on KernelPatch, we have removed duplicates of KSU and kept only KPM support.
- We will introduce more APatch-compatible functions to ensure the integrity of KPM functionality.
We will introduce more APatch-compatible functions to ensure the completeness of KPM functionality.
Repository address: https://github.com/ShirkNeko/SukiSU_KernelPatch_patch
KPM templates: https://github.com/udochina/KPM-Build-Anywhere
> [!Note]
>
> 1. `CONFIG_KPM=y` needs to be added.
> 2. Non-GKI devices need to add `CONFIG_KALLSYMS=y` and `CONFIG_KALLSYMS_ALL=y` as well.
> 3. Some kernel source code below `4.19` also needs to be backport from `4.19` to the header file `set_memory.h`.
## How to do a system update to retain ROOT
- After OTA, don't reboot first, go to the manager flashing/patching kernel interface, find `GKI/non_GKI install` and select the Anykernel3 kernel zip file that needs to be flashed, select the slot that is opposite to the current running slot of the system for flashing, and then reboot to retain the GKI mode update This method is not supported for all non-GKI devices, so please try it yourself. It is the safest way to use TWRP for non-GKI devices.
- Or use LKM mode to install to the unused slot (after OTA).
## Compatibility Status
- KernelSU (versions prior to v1.0.0) officially supports Android GKI 2.0 devices (kernel 5.10+)
- Older kernels (4.4+) are also compatible, but the kernel must be built manually
@@ -57,29 +78,16 @@ KPM templates: https://github.com/udochina/KPM-Build-Anywhere
- Currently supports `arm64-v8a`, `armeabi-v7a (bare)` and some `X86_64`
## More links
**If you need to submit a translation for the manager go to** https://crowdin.com/project/SukiSU-Ultra
Projects compiled based on Sukisu and susfs
- [GKI](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS)
- [More patched GKI](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS) including ZRAM patches, KPM, susfs...
- [Less patched GKI](https://github.com/MiRinFork/GKI_SukiSU_SUSFS/releases) only susfs
- [OnePlus](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS)
## Hook method
- This method references the hook method from (https://github.com/rsuntk/KernelSU)
1. **KPROBES hook:**
- Also used for Loadable Kernel Module (LKM)
- Default hook method on GKI kernels.
- Need `CONFIG_KPROBES=y`
2. **Manual hook:**
- Standard KernelSU hook: https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#manually-modify-the-kernel-source
- backslashxx's syscall manual hook: https://github.com/backslashxx/KernelSU/issues/5
- Default hook method on Non-GKI kernels.
- Need `CONFIG_KSU_MANUAL_HOOK=y`
## Usage
### Universal GKI
@@ -87,16 +95,17 @@ Projects compiled based on Sukisu and susfs
Please **all** refer to https://kernelsu.org/zh_CN/guide/installation.html
> [!Note]
>
> 1. for devices with GKI 2.0 such as Xiaomi, Redmi, Samsung, etc. (excludes kernel-modified manufacturers such as Meizu, OnePlus, Zenith, and oppo)
> 2. Find the GKI build in [more links](#%E6%9B%B4%E5%A4%9A%E9%93%BE%E6%8E%A5). Find the device kernel version. Then download it and use TWRP or kernel flashing tool to flash the zip file with AnyKernel3 suffix.
> 2. Find the GKI build in [more links](#%E6%9B%B4%E5%A4%9A%E9%93%BE%E6%8E%A5). Find the device kernel version. Then download it and use TWRP or kernel flashing tool to flash the zip file with AnyKernel3 suffix. Pixel user need use _Less patched GKI_.
> 3. The .zip archive without suffix is uncompressed, the gz suffix is the compression used by Tenguet models.
### OnePlus
1. Use the link mentioned in the 'More Links' section to create a customized build with your device information, and then flash the zip file with the AnyKernel3 suffix.
> [!Note]
>
> - You only need to fill in the first two parts of kernel versions, such as 5.10, 5.15, 6.1, or 6.6.
> - Please search for the processor codename by yourself, usually it is all English without numbers.
> - You can find the branch and configuration files from the OnePlus open-source kernel repository.
@@ -110,14 +119,21 @@ Please **all** refer to https://kernelsu.org/zh_CN/guide/installation.html
5. More customization
6. Support for KPM kernel modules
## Troubleshooting
1. Uninstalling the KernelSU Manager device is stuck. → Uninstall the application with package name com.sony.playmemories.mobile.
## License
- The file in the “kernel” directory is under [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) license.
- The images of the files `ic_launcher*` with anime character emoticons are copyrighted by [五十根大虾仁](https://space.bilibili.com/370927), the Brand Intellectual Property in the images is owned by [明风OuO](https://space.bilibili.com/274939213), and the vectorization is done by @MiRinChan. Before using these files, in addition to complying with [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt), you also need to comply with the authorization of the two authors to use these artistic contents.
- The images of the files `ic_launcher(?!.*alt.*).*` with anime character emoticons are copyrighted by [五十根大虾仁](https://space.bilibili.com/370927), the Brand Intellectual Property in the images is owned by [明风 OuO](https://space.bilibili.com/274939213), and the vectorization is done by @MiRinChan. Before using these files, in addition to complying with [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt), you also need to comply with the authorization of the two authors to use these artistic contents.
- Except for the files or directories mentioned above, all other parts are under [GPL-3.0 or later](https://www.gnu.org/licenses/gpl-3.0.html) license.
## Afdian link
- https://afdian.com/a/shirkneko
## Sponsorship list
- [Ktouls](https://github.com/Ktouls) Thanks so much for bringing me support
@@ -125,8 +141,8 @@ Please **all** refer to https://kernelsu.org/zh_CN/guide/installation.html
- [wswzgdg](https://github.com/wswzgdg) Many thanks for supporting this project
- [yspbwx2010](https://github.com/yspbwx2010) Many thanks
- [DARKWWEE](https://github.com/DARKWWEE) Thanks for the 100 USDT Lao
If the above list does not have your name, I will update it as soon as possible, and thanks again for your support!
- [Saksham Singla](https://github.com/TypeFlu) Website provision as well as maintenance
- [OukaroMF](https://github.com/OukaroMF) Donation of website domain name
## Contributions

View File

@@ -25,9 +25,10 @@ curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kern
## 統合された susfs の使い方
1. パッチを当てずに susfs-dev ブランチを直接使用してください。
1. susfs-mainまたは他のsusfs-*ブランチを直接使用し、susfsを再度統合する必要はありません
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-dev
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-main
```
## KPM に対応
@@ -108,10 +109,14 @@ https://kernelsu.org/zh_CN/guide/installation.html をご参照ください。
5. その他のカスタマイズ
6. KPM カーネルモジュールに対応
## トラブルシューティング
1.KernelSU Managerのアンインストールができない。 →パッケージ名com.sony.playmemories.mobile.KernelSU Managerのアプリケーションをアンインストールする。
## ライセンス
- `kernel` ディレクトリ以下のファイルは[GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)です。
- アニメキャラクターの絵文字を含むファイル `ic_launcher*` の画像は[五十根大虾仁](https://space.bilibili.com/370927)が著作権を所有しており、画像内のブランド知的財産権は[明风OuO](https://space.bilibili.com/274939213)が所有しています。ベクトル化は @MiRinChan が行っています。これらのファイルを使用する前に、[Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt)に準拠することに加えて、これらの芸術コンテンツを使用するには、2人の著者の許可にも従う必要があります。
- アニメキャラクターの絵文字を含むファイル `ic_launcher(?!.*alt.*).*` の画像は[五十根大虾仁](https://space.bilibili.com/370927)が著作権を所有しており、画像内のブランド知的財産権は[明风OuO](https://space.bilibili.com/274939213)が所有しています。ベクトル化は @MiRinChan が行っています。これらのファイルを使用する前に、[Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt)に準拠することに加えて、これらの芸術コンテンツを使用するには、2人の著者の許可にも従う必要があります。
- 上記のファイルまたはディレクトリを除き、その他のすべての部分は[GPL-3.0以降](https://www.gnu.org/licenses/gpl-3.0.html)です。
## スポンサーシップの一覧
@@ -121,8 +126,8 @@ https://kernelsu.org/zh_CN/guide/installation.html をご参照ください。
- [wswzgdg](https://github.com/wswzgdg) このプロジェクトを支援していただき、ありがとうございます。
- [yspbwx2010](https://github.com/yspbwx2010) どうもありがとう。
- [DARKWWEE](https://github.com/DARKWWEE) ラオウ100USDTありがとう
上記の一覧にあなたの名前がない場合は、できるだけ早急に更新しますので再度ご支援をお願いします。
- [Saksham Singla](https://github.com/TypeFlu) ウェブサイトの提供およびメンテナンス
- [OukaroMF](https://github.com/OukaroMF) ウェブサイトドメイン名の寄付
## 貢献者

View File

@@ -28,10 +28,10 @@ curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kern
## susfs Nasıl Entegre Edilir
1. Doğrudan susfs-stable veya susfs-dev dalını kullanın, susfs entegrasyonuna gerek yok
1. Doğrudan susfs-main veya susfs-* dalını kullanın, susfs entegrasyonuna gerek yok
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-dev
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-main
```
## Kanca Yöntemleri
@@ -121,7 +121,7 @@ Lütfen **tümünü** https://kernelsu.org/zh_CN/guide/installation.html adresin
## Lisans
- `kernel` dizinindeki dosyalar [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) lisansı altındadır.
- Anime karakter ifadeleri içeren `ic_launcher*` dosyalarının görüntüleri [五十根大虾仁](https://space.bilibili.com/370927) tarafından telif hakkıyla korunmaktadır, görüntülerdeki Marka Fikri Mülkiyeti [明风 OuO](https://space.bilibili.com/274939213)'ye aittir ve vektörleştirme @MiRinChan tarafından yapılmıştır. Bu dosyaları kullanmadan önce, [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt) ile uyumlu olmanın yanı sıra, bu sanatsal içerikleri kullanmak için iki yazarın yetkilendirmesine de uymanız gerekir.
- Anime karakter ifadeleri içeren `ic_launcher(?!.*alt.*).*` dosyalarının görüntüleri [五十根大虾仁](https://space.bilibili.com/370927) tarafından telif hakkıyla korunmaktadır, görüntülerdeki Marka Fikri Mülkiyeti [明风 OuO](https://space.bilibili.com/274939213)'ye aittir ve vektörleştirme @MiRinChan tarafından yapılmıştır. Bu dosyaları kullanmadan önce, [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt) ile uyumlu olmanın yanı sıra, bu sanatsal içerikleri kullanmak için iki yazarın yetkilendirmesine de uymanız gerekir.
- Yukarıda belirtilen dosyalar veya dizinler hariç, diğer tüm parçalar [GPL-3.0 veya üzeri](https://www.gnu.org/licenses/gpl-3.0.html)'dir.
## Afdian Bağlantısı
@@ -136,8 +136,6 @@ Lütfen **tümünü** https://kernelsu.org/zh_CN/guide/installation.html adresin
- [yspbwx2010](https://github.com/yspbwx2010) Çok teşekkür ederim
- [DARKWWEE](https://github.com/DARKWWEE) 100 USDT için teşekkürler
Eğer yukarıdaki listede adınız yoksa, zamanında güncelleyeceğim, herkese tekrar teşekkür ederim
## Katkıda Bulunanlar
- [KernelSU](https://github.com/tiann/KernelSU): Orijinal proje

View File

@@ -28,10 +28,10 @@ curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kern
## 如何集成 susfs
1. 直接使用 susfs-stable 或者 susfs-dev 分支,不需要再集成 susfs
1. 直接使用 susfs-main 或者其他 susfs-\* 分支,不需要再集成 susfs (支持非 GKI 设备构建)
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-dev
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-main
```
## 钩子方法
@@ -86,7 +86,8 @@ KPM 模板地址: https://github.com/udochina/KPM-Build-Anywhere
基于 SukiSU 和 susfs 编译的项目
- [GKI](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS)
- [增强 GKI](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS)(包括 ZRAM 算法等补丁、KPM、susfs 等)
- [GKI](https://github.com/MiRinFork/GKI_SukiSU_SUSFS/releases)(若增强 GKI boot 失败再尝试这份,这份没有 KPM 等修改,只有 susfs
- [一加](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS)
## 使用方法
@@ -98,7 +99,7 @@ KPM 模板地址: https://github.com/udochina/KPM-Build-Anywhere
> [!Note]
>
> 1. 适用于如小米、红米、三星等的 GKI 2.0 的设备 (不包含魔改内核的厂商如魅族、一加、真我和 oppo)
> 2. 找到[更多链接](#%E6%9B%B4%E5%A4%9A%E9%93%BE%E6%8E%A5)里的 GKI 构建的项目。找到设备内核版本。然后下载下来,用 TWRP 或者内核刷写工具刷入带 AnyKernel3 后缀的压缩包即可
> 2. 找到[更多链接](#%E6%9B%B4%E5%A4%9A%E9%93%BE%E6%8E%A5)里的 GKI 构建的项目。找到设备内核版本。然后下载下来,用 TWRP 或者内核刷写工具刷入带 AnyKernel3 后缀的压缩包即可。Pixel 请使用不是增强的 GKI。
> 3. 一般不带后缀的 .zip 压缩包是未压缩的gz 后缀的为天玑机型所使用的压缩方式
### 一加
@@ -120,10 +121,14 @@ KPM 模板地址: https://github.com/udochina/KPM-Build-Anywhere
5. 更多自定义功能
6. 对 KPM 内核模块的支持
## 疑难解答
1. 卸载 KernelSU 管理器设备卡死。→ 卸载包名为 com.sony.playmemories.mobile 的应用。
## 许可证
- `kernel` 目录下的文件是 [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)。
- 有动漫人物图片表情包的这些文件 `ic_launcher*` 的图像版权为[五十根大虾仁](https://space.bilibili.com/370927)所有,图像中的 Brand Intellectual Property 由[明风OuO](https://space.bilibili.com/274939213)所有,矢量化由 @MiRinChan 完成,在使用这些文件之前,除了必须遵守 [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt) 以外,还需要遵守向前两者索要使用这些艺术内容的授权。
- 有动漫人物图片表情包的这些文件 `ic_launcher(?!.*alt.*).*` 的图像版权为[五十根大虾仁](https://space.bilibili.com/370927)所有,图像中的 Brand Intellectual Property 由[明风 OuO](https://space.bilibili.com/274939213)所有,矢量化由 @MiRinChan 完成,在使用这些文件之前,除了必须遵守 [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt) 以外,还需要遵守向前两者索要使用这些艺术内容的授权。
- 除了以上所述的文件或目录外,所有其他部分均为 [GPL-3.0 或更高版本](https://www.gnu.org/licenses/gpl-3.0.html)。
## 爱发电链接
@@ -137,8 +142,8 @@ KPM 模板地址: https://github.com/udochina/KPM-Build-Anywhere
- [wswzgdg](https://github.com/wswzgdg) 非常感谢对此项目的支持
- [yspbwx2010](https://github.com/yspbwx2010) 非常感谢
- [DARKWWEE](https://github.com/DARKWWEE) 感谢老哥的 100 USDT
如果以上名单没有你的名称,我会及时更新,再次感谢大家的支持
- [Saksham Singla](https://github.com/TypeFlu) 网站的提供以及维护
- [OukaroMF](https://github.com/OukaroMF) 网站域名捐赠
## 贡献

View File

@@ -19,19 +19,33 @@ obj-$(CONFIG_KSU) += kernelsu.o
obj-$(CONFIG_KPM) += kpm/
# .git is a text file while the module is imported by 'git submodule add'.
ifeq ($(shell test -e $(srctree)/$(src)/../.git; echo $$?),0)
$(shell cd $(srctree)/$(src); /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin [ -f ../.git/shallow ] && git fetch --unshallow)
KSU_GIT_VERSION := $(shell cd $(srctree)/$(src); /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin git rev-list --count main)
# ksu_version: major * 10000 + git version + 606 for historical reasons
$(eval KSU_VERSION=$(shell expr 10000 + $(KSU_GIT_VERSION) + 606))
$(info -- KernelSU version: $(KSU_VERSION))
ccflags-y += -DKSU_VERSION=$(KSU_VERSION)
else # If there is no .git file, the default version will be passed.
$(warning "KSU_GIT_VERSION not defined! It is better to make KernelSU a git submodule!")
ccflags-y += -DKSU_VERSION=16
REPO_OWNER := SukiSU-Ultra
REPO_NAME := SukiSU-Ultra
REPO_BRANCH := main
GIT_BIN := /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin git
CURL_BIN := /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin curl
KSU_GITHUB_VERSION := $(shell $(CURL_BIN) -sI "https://api.github.com/repos/$(REPO_OWNER)/$(REPO_NAME)/commits?sha=$(REPO_BRANCH)&per_page=1" | grep -i "link:" | sed -n 's/.*page=\([0-9]*\)>; rel="last".*/\1/p')
ifeq ($(KSU_GITHUB_VERSION),)
ifeq ($(shell test -e $(srctree)/$(src)/../.git; echo $$?),0)
$(shell cd $(srctree)/$(src); [ -f ../.git/shallow ] && $(GIT_BIN) fetch --unshallow)
KSU_LOCAL_VERSION := $(shell cd $(srctree)/$(src); $(GIT_BIN) rev-list --count HEAD)
$(eval KSU_VERSION := $(shell expr 10000 + $(KSU_LOCAL_VERSION) + 700))
$(info -- SukiSU-Ultra version (local .git): $(KSU_VERSION))
else
$(eval KSU_VERSION := 13000)
$(warning -- Could not fetch version online or via local .git! Using fallback version: $(KSU_VERSION))
endif
else
$(eval KSU_VERSION := $(shell expr 10000 + $(KSU_GITHUB_VERSION) + 700))
$(info -- SukiSU-Ultra version (GitHub): $(KSU_VERSION))
endif
$(info -- SukiSU-Ultra version: $(KSU_VERSION))
ccflags-y += -DKSU_VERSION=$(KSU_VERSION)
ifndef KSU_EXPECTED_SIZE
KSU_EXPECTED_SIZE := 0x35c
endif

View File

@@ -110,6 +110,7 @@ static void setup_groups(struct root_profile *profile, struct cred *cred)
groups_sort(group_info);
set_groups(cred, group_info);
put_group_info(group_info);
}
static void disable_seccomp()
@@ -134,18 +135,18 @@ void escape_to_root(void)
{
struct cred *cred;
rcu_read_lock();
do {
cred = (struct cred *)__task_cred((current));
BUG_ON(!cred);
} while (!get_cred_rcu(cred));
cred = prepare_creds();
if (!cred) {
pr_warn("prepare_creds failed!\n");
return;
}
if (cred->euid.val == 0) {
pr_warn("Already root, don't escape!\n");
rcu_read_unlock();
abort_creds(cred);
return;
}
struct root_profile *profile = ksu_get_root_profile(cred->uid.val);
cred->uid.val = profile->uid;
@@ -176,7 +177,7 @@ void escape_to_root(void)
setup_groups(profile, cred);
rcu_read_unlock();
commit_creds(cred);
// Refer to kernel/seccomp.c: seccomp_set_mode_strict
// When disabling Seccomp, ensure that current->sighand->siglock is held during the operation.
@@ -243,6 +244,7 @@ static void nuke_ext4_sysfs() {
}
ext4_unregister_sysfs(sb);
path_put(&path);
}
#else
static inline void nuke_ext4_sysfs() { }
@@ -564,11 +566,13 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
if (path.dentry != path.mnt->mnt_root) {
// it is not root mountpoint, maybe umounted by others already.
path_put(&path);
return;
}
// we are only interest in some specific mounts
if (check_mnt && !should_umount(&path)) {
path_put(&path);
return;
}

View File

@@ -60,6 +60,13 @@ uid_t sukisu_get_manager_uid() {
return ksu_manager_uid;
}
static
void sukisu_set_manager_uid(uid_t uid, int force) {
if(force || ksu_manager_uid == -1) {
ksu_manager_uid = uid;
}
}
// ======================================================================
struct CompactAddressSymbol {
@@ -75,7 +82,8 @@ static struct CompactAddressSymbol address_symbol [] = {
{ "get_ap_mod_exclude", &sukisu_get_ap_mod_exclude },
{ "is_uid_should_umount", &sukisu_is_uid_should_umount },
{ "is_current_uid_manager", &sukisu_is_current_uid_manager },
{ "get_manager_uid", &sukisu_get_manager_uid }
{ "get_manager_uid", &sukisu_get_manager_uid },
{ "sukisu_set_manager_uid", &sukisu_set_manager_uid }
};
unsigned long sukisu_compact_find_symbol(const char* name) {

View File

@@ -214,6 +214,7 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
int i, stop = 0;
struct list_head data_path_list;
INIT_LIST_HEAD(&data_path_list);
unsigned long data_app_magic = 0;
// Initialize APK cache list
struct apk_path_hash *pos, *n;
@@ -246,6 +247,24 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
goto skip_iterate;
}
// grab magic on first folder, which is /data/app
if (!data_app_magic) {
if (file->f_inode->i_sb->s_magic) {
data_app_magic = file->f_inode->i_sb->s_magic;
pr_info("%s: dir: %s got magic! 0x%lx\n", __func__, pos->dirpath, data_app_magic);
} else {
filp_close(file, NULL);
goto skip_iterate;
}
}
if (file->f_inode->i_sb->s_magic != data_app_magic) {
pr_info("%s: skip: %s magic: 0x%lx expected: 0x%lx\n", __func__, pos->dirpath,
file->f_inode->i_sb->s_magic, data_app_magic);
filp_close(file, NULL);
goto skip_iterate;
}
iterate_dir(file, &ctx.ctx);
filp_close(file, NULL);
}

View File

@@ -32,6 +32,19 @@
</intent-filter>
</activity>
<activity-alias
android:name=".ui.MainActivityAlias"
android:exported="true"
android:enabled="false"
android:icon="@mipmap/ic_launcher_alt"
android:roundIcon="@mipmap/ic_launcher_alt_round"
android:targetActivity=".ui.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity
android:name=".ui.webui.WebUIActivity"
android:autoRemoveFromRecents="true"

Binary file not shown.

Binary file not shown.

View File

@@ -1,4 +1,3 @@
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
@@ -7,14 +6,11 @@ cmake_minimum_required(VERSION 3.18.1)
project("kernelsu")
find_package(cxx REQUIRED CONFIG)
link_libraries(cxx::cxx)
add_library(zako
SHARED
jni.cc
ksu.cc
)
jni.c
ksu.c
)
find_library(log-lib log)

View File

@@ -0,0 +1,348 @@
#include "prelude.h"
#include "ksu.h"
#include <jni.h>
#include <sys/prctl.h>
#include <android/log.h>
#include <string.h>
NativeBridge(becomeManager, jboolean, jstring pkg) {
const char* cpkg = GetEnvironment()->GetStringUTFChars(env, pkg, JNI_FALSE);
bool result = become_manager(cpkg);
GetEnvironment()->ReleaseStringUTFChars(env, pkg, cpkg);
return result;
}
NativeBridgeNP(getVersion, jint) {
return get_version();
}
NativeBridgeNP(getAllowList, jintArray) {
int uids[1024];
int size = 0;
bool result = get_allow_list(uids, &size);
LogDebug("getAllowList: %d, size: %d", result, size);
if (result) {
jintArray array = GetEnvironment()->NewIntArray(env, size);
GetEnvironment()->SetIntArrayRegion(env, array, 0, size, uids);
return array;
}
return GetEnvironment()->NewIntArray(env, 0);
}
NativeBridgeNP(isSafeMode, jboolean) {
return is_safe_mode();
}
NativeBridgeNP(isLkmMode, jboolean) {
return is_lkm_mode();
}
static void fillIntArray(JNIEnv *env, jobject list, int *data, int count) {
jclass cls = GetEnvironment()->GetObjectClass(env, list);
jmethodID add = GetEnvironment()->GetMethodID(env, cls, "add", "(Ljava/lang/Object;)Z");
jclass integerCls = GetEnvironment()->FindClass(env, "java/lang/Integer");
jmethodID constructor = GetEnvironment()->GetMethodID(env, integerCls, "<init>", "(I)V");
for (int i = 0; i < count; ++i) {
jobject integer = GetEnvironment()->NewObject(env, integerCls, constructor, data[i]);
GetEnvironment()->CallBooleanMethod(env, list, add, integer);
}
}
static void addIntToList(JNIEnv *env, jobject list, int ele) {
jclass cls = GetEnvironment()->GetObjectClass(env, list);
jmethodID add = GetEnvironment()->GetMethodID(env, cls, "add", "(Ljava/lang/Object;)Z");
jclass integerCls = GetEnvironment()->FindClass(env, "java/lang/Integer");
jmethodID constructor = GetEnvironment()->GetMethodID(env, integerCls, "<init>", "(I)V");
jobject integer = GetEnvironment()->NewObject(env, integerCls, constructor, ele);
GetEnvironment()->CallBooleanMethod(env, list, add, integer);
}
static uint64_t capListToBits(JNIEnv *env, jobject list) {
jclass cls = GetEnvironment()->GetObjectClass(env, list);
jmethodID get = GetEnvironment()->GetMethodID(env, cls, "get", "(I)Ljava/lang/Object;");
jmethodID size = GetEnvironment()->GetMethodID(env, cls, "size", "()I");
jint listSize = GetEnvironment()->CallIntMethod(env, list, size);
jclass integerCls = GetEnvironment()->FindClass(env, "java/lang/Integer");
jmethodID intValue = GetEnvironment()->GetMethodID(env, integerCls, "intValue", "()I");
uint64_t result = 0;
for (int i = 0; i < listSize; ++i) {
jobject integer = GetEnvironment()->CallObjectMethod(env, list, get, i);
int data = GetEnvironment()->CallIntMethod(env, integer, intValue);
if (cap_valid(data)) {
result |= (1ULL << data);
}
}
return result;
}
static int getListSize(JNIEnv *env, jobject list) {
jclass cls = GetEnvironment()->GetObjectClass(env, list);
jmethodID size = GetEnvironment()->GetMethodID(env, cls, "size", "()I");
return GetEnvironment()->CallIntMethod(env, list, size);
}
static void fillArrayWithList(JNIEnv *env, jobject list, int *data, int count) {
jclass cls = GetEnvironment()->GetObjectClass(env, list);
jmethodID get = GetEnvironment()->GetMethodID(env, cls, "get", "(I)Ljava/lang/Object;");
jclass integerCls = GetEnvironment()->FindClass(env, "java/lang/Integer");
jmethodID intValue = GetEnvironment()->GetMethodID(env, integerCls, "intValue", "()I");
for (int i = 0; i < count; ++i) {
jobject integer = GetEnvironment()->CallObjectMethod(env, list, get, i);
data[i] = GetEnvironment()->CallIntMethod(env, integer, intValue);
}
}
NativeBridge(getAppProfile, jobject, jstring pkg, jint uid) {
if (GetEnvironment()->GetStringLength(env, pkg) > KSU_MAX_PACKAGE_NAME) {
return NULL;
}
char key[KSU_MAX_PACKAGE_NAME] = { 0 };
const char* cpkg = GetEnvironment()->GetStringUTFChars(env, pkg, nullptr);
strcpy(key, cpkg);
GetEnvironment()->ReleaseStringUTFChars(env, pkg, cpkg);
struct app_profile profile = { 0 };
profile.version = KSU_APP_PROFILE_VER;
strcpy(profile.key, key);
profile.current_uid = uid;
bool useDefaultProfile = !get_app_profile(key, &profile);
jclass cls = GetEnvironment()->FindClass(env, "com/sukisu/ultra/Natives$Profile");
jmethodID constructor = GetEnvironment()->GetMethodID(env, cls, "<init>", "()V");
jobject obj = GetEnvironment()->NewObject(env, cls, constructor);
jfieldID keyField = GetEnvironment()->GetFieldID(env, cls, "name", "Ljava/lang/String;");
jfieldID currentUidField = GetEnvironment()->GetFieldID(env, cls, "currentUid", "I");
jfieldID allowSuField = GetEnvironment()->GetFieldID(env, cls, "allowSu", "Z");
jfieldID rootUseDefaultField = GetEnvironment()->GetFieldID(env, cls, "rootUseDefault", "Z");
jfieldID rootTemplateField = GetEnvironment()->GetFieldID(env, cls, "rootTemplate", "Ljava/lang/String;");
jfieldID uidField = GetEnvironment()->GetFieldID(env, cls, "uid", "I");
jfieldID gidField = GetEnvironment()->GetFieldID(env, cls, "gid", "I");
jfieldID groupsField = GetEnvironment()->GetFieldID(env, cls, "groups", "Ljava/util/List;");
jfieldID capabilitiesField = GetEnvironment()->GetFieldID(env, cls, "capabilities", "Ljava/util/List;");
jfieldID domainField = GetEnvironment()->GetFieldID(env, cls, "context", "Ljava/lang/String;");
jfieldID namespacesField = GetEnvironment()->GetFieldID(env, cls, "namespace", "I");
jfieldID nonRootUseDefaultField = GetEnvironment()->GetFieldID(env, cls, "nonRootUseDefault", "Z");
jfieldID umountModulesField = GetEnvironment()->GetFieldID(env, cls, "umountModules", "Z");
GetEnvironment()->SetObjectField(env, obj, keyField, GetEnvironment()->NewStringUTF(env, profile.key));
GetEnvironment()->SetIntField(env, obj, currentUidField, profile.current_uid);
if (useDefaultProfile) {
// no profile found, so just use default profile:
// don't allow root and use default profile!
LogDebug("use default profile for: %s, %d", key, uid);
// allow_su = false
// non root use default = true
GetEnvironment()->SetBooleanField(env, obj, allowSuField, false);
GetEnvironment()->SetBooleanField(env, obj, nonRootUseDefaultField, true);
return obj;
}
bool allowSu = profile.allow_su;
if (allowSu) {
GetEnvironment()->SetBooleanField(env, obj, rootUseDefaultField, (jboolean) profile.rp_config.use_default);
if (strlen(profile.rp_config.template_name) > 0) {
GetEnvironment()->SetObjectField(env, obj, rootTemplateField,
GetEnvironment()->NewStringUTF(env, profile.rp_config.template_name));
}
GetEnvironment()->SetIntField(env, obj, uidField, profile.rp_config.profile.uid);
GetEnvironment()->SetIntField(env, obj, gidField, profile.rp_config.profile.gid);
jobject groupList = GetEnvironment()->GetObjectField(env, obj, groupsField);
int groupCount = profile.rp_config.profile.groups_count;
if (groupCount > KSU_MAX_GROUPS) {
LogDebug("kernel group count too large: %d???", groupCount);
groupCount = KSU_MAX_GROUPS;
}
fillIntArray(env, groupList, profile.rp_config.profile.groups, groupCount);
jobject capList = GetEnvironment()->GetObjectField(env, obj, capabilitiesField);
for (int i = 0; i <= CAP_LAST_CAP; i++) {
if (profile.rp_config.profile.capabilities.effective & (1ULL << i)) {
addIntToList(env, capList, i);
}
}
GetEnvironment()->SetObjectField(env, obj, domainField,
GetEnvironment()->NewStringUTF(env, profile.rp_config.profile.selinux_domain));
GetEnvironment()->SetIntField(env, obj, namespacesField, profile.rp_config.profile.namespaces);
GetEnvironment()->SetBooleanField(env, obj, allowSuField, profile.allow_su);
} else {
GetEnvironment()->SetBooleanField(env, obj, nonRootUseDefaultField, profile.nrp_config.use_default);
GetEnvironment()->SetBooleanField(env, obj, umountModulesField, profile.nrp_config.profile.umount_modules);
}
return obj;
}
NativeBridge(setAppProfile, jboolean, jobject profile) {
jclass cls = GetEnvironment()->FindClass(env, "com/sukisu/ultra/Natives$Profile");
jfieldID keyField = GetEnvironment()->GetFieldID(env, cls, "name", "Ljava/lang/String;");
jfieldID currentUidField = GetEnvironment()->GetFieldID(env, cls, "currentUid", "I");
jfieldID allowSuField = GetEnvironment()->GetFieldID(env, cls, "allowSu", "Z");
jfieldID rootUseDefaultField = GetEnvironment()->GetFieldID(env, cls, "rootUseDefault", "Z");
jfieldID rootTemplateField = GetEnvironment()->GetFieldID(env, cls, "rootTemplate", "Ljava/lang/String;");
jfieldID uidField = GetEnvironment()->GetFieldID(env, cls, "uid", "I");
jfieldID gidField = GetEnvironment()->GetFieldID(env, cls, "gid", "I");
jfieldID groupsField = GetEnvironment()->GetFieldID(env, cls, "groups", "Ljava/util/List;");
jfieldID capabilitiesField = GetEnvironment()->GetFieldID(env, cls, "capabilities", "Ljava/util/List;");
jfieldID domainField = GetEnvironment()->GetFieldID(env, cls, "context", "Ljava/lang/String;");
jfieldID namespacesField = GetEnvironment()->GetFieldID(env, cls, "namespace", "I");
jfieldID nonRootUseDefaultField = GetEnvironment()->GetFieldID(env, cls, "nonRootUseDefault", "Z");
jfieldID umountModulesField = GetEnvironment()->GetFieldID(env, cls, "umountModules", "Z");
jobject key = GetEnvironment()->GetObjectField(env, profile, keyField);
if (!key) {
return false;
}
if (GetEnvironment()->GetStringLength(env, (jstring) key) > KSU_MAX_PACKAGE_NAME) {
return false;
}
const char* cpkg = GetEnvironment()->GetStringUTFChars(env, (jstring) key, nullptr);
char p_key[KSU_MAX_PACKAGE_NAME] = { 0 };
strcpy(p_key, cpkg);
GetEnvironment()->ReleaseStringUTFChars(env, (jstring) key, cpkg);
jint currentUid = GetEnvironment()->GetIntField(env, profile, currentUidField);
jint uid = GetEnvironment()->GetIntField(env, profile, uidField);
jint gid = GetEnvironment()->GetIntField(env, profile, gidField);
jobject groups = GetEnvironment()->GetObjectField(env, profile, groupsField);
jobject capabilities = GetEnvironment()->GetObjectField(env, profile, capabilitiesField);
jobject domain = GetEnvironment()->GetObjectField(env, profile, domainField);
jboolean allowSu = GetEnvironment()->GetBooleanField(env, profile, allowSuField);
jboolean umountModules = GetEnvironment()->GetBooleanField(env, profile, umountModulesField);
struct app_profile p = { 0 };
p.version = KSU_APP_PROFILE_VER;
strcpy(p.key, p_key);
p.allow_su = allowSu;
p.current_uid = currentUid;
if (allowSu) {
p.rp_config.use_default = GetEnvironment()->GetBooleanField(env, profile, rootUseDefaultField);
jobject templateName = GetEnvironment()->GetObjectField(env, profile, rootTemplateField);
if (templateName) {
const char* ctemplateName = GetEnvironment()->GetStringUTFChars(env, (jstring) templateName, nullptr);
strcpy(p.rp_config.template_name, ctemplateName);
GetEnvironment()->ReleaseStringUTFChars(env, (jstring) templateName, ctemplateName);
}
p.rp_config.profile.uid = uid;
p.rp_config.profile.gid = gid;
int groups_count = getListSize(env, groups);
if (groups_count > KSU_MAX_GROUPS) {
LogDebug("groups count too large: %d", groups_count);
return false;
}
p.rp_config.profile.groups_count = groups_count;
fillArrayWithList(env, groups, p.rp_config.profile.groups, groups_count);
p.rp_config.profile.capabilities.effective = capListToBits(env, capabilities);
const char* cdomain = GetEnvironment()->GetStringUTFChars(env, (jstring) domain, nullptr);
strcpy(p.rp_config.profile.selinux_domain, cdomain);
GetEnvironment()->ReleaseStringUTFChars(env, (jstring) domain, cdomain);
p.rp_config.profile.namespaces = GetEnvironment()->GetIntField(env, profile, namespacesField);
} else {
p.nrp_config.use_default = GetEnvironment()->GetBooleanField(env, profile, nonRootUseDefaultField);
p.nrp_config.profile.umount_modules = umountModules;
}
return set_app_profile(&p);
}
NativeBridge(uidShouldUmount, jboolean, jint uid) {
return uid_should_umount(uid);
}
NativeBridgeNP(isSuEnabled, jboolean) {
return is_su_enabled();
}
NativeBridge(setSuEnabled, jboolean, jboolean enabled) {
return set_su_enabled(enabled);
}
NativeBridgeNP(isKPMEnabled, jboolean) {
return is_KPM_enable();
}
NativeBridgeNP(getHookType, jstring) {
char hook_type[16];
get_hook_type(hook_type, sizeof(hook_type));
return GetEnvironment()->NewStringUTF(env, hook_type);
}
NativeBridgeNP(getSusfsFeatureStatus, jobject) {
struct susfs_feature_status status;
bool result = get_susfs_feature_status(&status);
if (!result) {
return NULL;
}
jclass cls = GetEnvironment()->FindClass(env, "com/sukisu/ultra/Natives$SusfsFeatureStatus");
jmethodID constructor = GetEnvironment()->GetMethodID(env, cls, "<init>", "()V");
jobject obj = GetEnvironment()->NewObject(env, cls, constructor);
// 设置各个字段
jfieldID statusSusPathField = GetEnvironment()->GetFieldID(env, cls, "statusSusPath", "Z");
jfieldID statusSusMountField = GetEnvironment()->GetFieldID(env, cls, "statusSusMount", "Z");
jfieldID statusAutoDefaultMountField = GetEnvironment()->GetFieldID(env, cls, "statusAutoDefaultMount", "Z");
jfieldID statusAutoBindMountField = GetEnvironment()->GetFieldID(env, cls, "statusAutoBindMount", "Z");
jfieldID statusSusKstatField = GetEnvironment()->GetFieldID(env, cls, "statusSusKstat", "Z");
jfieldID statusTryUmountField = GetEnvironment()->GetFieldID(env, cls, "statusTryUmount", "Z");
jfieldID statusAutoTryUmountBindField = GetEnvironment()->GetFieldID(env, cls, "statusAutoTryUmountBind", "Z");
jfieldID statusSpoofUnameField = GetEnvironment()->GetFieldID(env, cls, "statusSpoofUname", "Z");
jfieldID statusEnableLogField = GetEnvironment()->GetFieldID(env, cls, "statusEnableLog", "Z");
jfieldID statusHideSymbolsField = GetEnvironment()->GetFieldID(env, cls, "statusHideSymbols", "Z");
jfieldID statusSpoofCmdlineField = GetEnvironment()->GetFieldID(env, cls, "statusSpoofCmdline", "Z");
jfieldID statusOpenRedirectField = GetEnvironment()->GetFieldID(env, cls, "statusOpenRedirect", "Z");
jfieldID statusMagicMountField = GetEnvironment()->GetFieldID(env, cls, "statusMagicMount", "Z");
jfieldID statusSusSuField = GetEnvironment()->GetFieldID(env, cls, "statusSusSu", "Z");
GetEnvironment()->SetBooleanField(env, obj, statusSusPathField, status.status_sus_path);
GetEnvironment()->SetBooleanField(env, obj, statusSusMountField, status.status_sus_mount);
GetEnvironment()->SetBooleanField(env, obj, statusAutoDefaultMountField, status.status_auto_default_mount);
GetEnvironment()->SetBooleanField(env, obj, statusAutoBindMountField, status.status_auto_bind_mount);
GetEnvironment()->SetBooleanField(env, obj, statusSusKstatField, status.status_sus_kstat);
GetEnvironment()->SetBooleanField(env, obj, statusTryUmountField, status.status_try_umount);
GetEnvironment()->SetBooleanField(env, obj, statusAutoTryUmountBindField, status.status_auto_try_umount_bind);
GetEnvironment()->SetBooleanField(env, obj, statusSpoofUnameField, status.status_spoof_uname);
GetEnvironment()->SetBooleanField(env, obj, statusEnableLogField, status.status_enable_log);
GetEnvironment()->SetBooleanField(env, obj, statusHideSymbolsField, status.status_hide_symbols);
GetEnvironment()->SetBooleanField(env, obj, statusSpoofCmdlineField, status.status_spoof_cmdline);
GetEnvironment()->SetBooleanField(env, obj, statusOpenRedirectField, status.status_open_redirect);
GetEnvironment()->SetBooleanField(env, obj, statusMagicMountField, status.status_magic_mount);
GetEnvironment()->SetBooleanField(env, obj, statusSusSuField, status.status_sus_su);
return obj;
}

View File

@@ -1,313 +0,0 @@
#include <jni.h>
#include <sys/prctl.h>
#include <android/log.h>
#include <cstring>
#include "ksu.h"
#define LOG_TAG "KernelSU"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_sukisu_ultra_Natives_becomeManager(JNIEnv *env, jobject, jstring pkg) {
auto cpkg = env->GetStringUTFChars(pkg, nullptr);
auto result = become_manager(cpkg);
env->ReleaseStringUTFChars(pkg, cpkg);
return result;
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_sukisu_ultra_Natives_getVersion(JNIEnv *env, jobject) {
return get_version();
}
extern "C"
JNIEXPORT jintArray JNICALL
Java_com_sukisu_ultra_Natives_getAllowList(JNIEnv *env, jobject) {
int uids[1024];
int size = 0;
bool result = get_allow_list(uids, &size);
LOGD("getAllowList: %d, size: %d", result, size);
if (result) {
auto array = env->NewIntArray(size);
env->SetIntArrayRegion(array, 0, size, uids);
return array;
}
return env->NewIntArray(0);
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_sukisu_ultra_Natives_isSafeMode(JNIEnv *env, jclass clazz) {
return is_safe_mode();
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_sukisu_ultra_Natives_isLkmMode(JNIEnv *env, jclass clazz) {
return is_lkm_mode();
}
static void fillIntArray(JNIEnv *env, jobject list, int *data, int count) {
auto cls = env->GetObjectClass(list);
auto add = env->GetMethodID(cls, "add", "(Ljava/lang/Object;)Z");
auto integerCls = env->FindClass("java/lang/Integer");
auto constructor = env->GetMethodID(integerCls, "<init>", "(I)V");
for (int i = 0; i < count; ++i) {
auto integer = env->NewObject(integerCls, constructor, data[i]);
env->CallBooleanMethod(list, add, integer);
}
}
static void addIntToList(JNIEnv *env, jobject list, int ele) {
auto cls = env->GetObjectClass(list);
auto add = env->GetMethodID(cls, "add", "(Ljava/lang/Object;)Z");
auto integerCls = env->FindClass("java/lang/Integer");
auto constructor = env->GetMethodID(integerCls, "<init>", "(I)V");
auto integer = env->NewObject(integerCls, constructor, ele);
env->CallBooleanMethod(list, add, integer);
}
static uint64_t capListToBits(JNIEnv *env, jobject list) {
auto cls = env->GetObjectClass(list);
auto get = env->GetMethodID(cls, "get", "(I)Ljava/lang/Object;");
auto size = env->GetMethodID(cls, "size", "()I");
auto listSize = env->CallIntMethod(list, size);
auto integerCls = env->FindClass("java/lang/Integer");
auto intValue = env->GetMethodID(integerCls, "intValue", "()I");
uint64_t result = 0;
for (int i = 0; i < listSize; ++i) {
auto integer = env->CallObjectMethod(list, get, i);
int data = env->CallIntMethod(integer, intValue);
if (cap_valid(data)) {
result |= (1ULL << data);
}
}
return result;
}
static int getListSize(JNIEnv *env, jobject list) {
auto cls = env->GetObjectClass(list);
auto size = env->GetMethodID(cls, "size", "()I");
return env->CallIntMethod(list, size);
}
static void fillArrayWithList(JNIEnv *env, jobject list, int *data, int count) {
auto cls = env->GetObjectClass(list);
auto get = env->GetMethodID(cls, "get", "(I)Ljava/lang/Object;");
auto integerCls = env->FindClass("java/lang/Integer");
auto intValue = env->GetMethodID(integerCls, "intValue", "()I");
for (int i = 0; i < count; ++i) {
auto integer = env->CallObjectMethod(list, get, i);
data[i] = env->CallIntMethod(integer, intValue);
}
}
extern "C"
JNIEXPORT jobject JNICALL
Java_com_sukisu_ultra_Natives_getAppProfile(JNIEnv *env, jobject, jstring pkg, jint uid) {
if (env->GetStringLength(pkg) > KSU_MAX_PACKAGE_NAME) {
return nullptr;
}
p_key_t key = {};
auto cpkg = env->GetStringUTFChars(pkg, nullptr);
strcpy(key, cpkg);
env->ReleaseStringUTFChars(pkg, cpkg);
app_profile profile = {};
profile.version = KSU_APP_PROFILE_VER;
strcpy(profile.key, key);
profile.current_uid = uid;
bool useDefaultProfile = !get_app_profile(key, &profile);
auto cls = env->FindClass("com/sukisu/ultra/Natives$Profile");
auto constructor = env->GetMethodID(cls, "<init>", "()V");
auto obj = env->NewObject(cls, constructor);
auto keyField = env->GetFieldID(cls, "name", "Ljava/lang/String;");
auto currentUidField = env->GetFieldID(cls, "currentUid", "I");
auto allowSuField = env->GetFieldID(cls, "allowSu", "Z");
auto rootUseDefaultField = env->GetFieldID(cls, "rootUseDefault", "Z");
auto rootTemplateField = env->GetFieldID(cls, "rootTemplate", "Ljava/lang/String;");
auto uidField = env->GetFieldID(cls, "uid", "I");
auto gidField = env->GetFieldID(cls, "gid", "I");
auto groupsField = env->GetFieldID(cls, "groups", "Ljava/util/List;");
auto capabilitiesField = env->GetFieldID(cls, "capabilities", "Ljava/util/List;");
auto domainField = env->GetFieldID(cls, "context", "Ljava/lang/String;");
auto namespacesField = env->GetFieldID(cls, "namespace", "I");
auto nonRootUseDefaultField = env->GetFieldID(cls, "nonRootUseDefault", "Z");
auto umountModulesField = env->GetFieldID(cls, "umountModules", "Z");
env->SetObjectField(obj, keyField, env->NewStringUTF(profile.key));
env->SetIntField(obj, currentUidField, profile.current_uid);
if (useDefaultProfile) {
// no profile found, so just use default profile:
// don't allow root and use default profile!
LOGD("use default profile for: %s, %d", key, uid);
// allow_su = false
// non root use default = true
env->SetBooleanField(obj, allowSuField, false);
env->SetBooleanField(obj, nonRootUseDefaultField, true);
return obj;
}
auto allowSu = profile.allow_su;
if (allowSu) {
env->SetBooleanField(obj, rootUseDefaultField, (jboolean) profile.rp_config.use_default);
if (strlen(profile.rp_config.template_name) > 0) {
env->SetObjectField(obj, rootTemplateField,
env->NewStringUTF(profile.rp_config.template_name));
}
env->SetIntField(obj, uidField, profile.rp_config.profile.uid);
env->SetIntField(obj, gidField, profile.rp_config.profile.gid);
jobject groupList = env->GetObjectField(obj, groupsField);
int groupCount = profile.rp_config.profile.groups_count;
if (groupCount > KSU_MAX_GROUPS) {
LOGD("kernel group count too large: %d???", groupCount);
groupCount = KSU_MAX_GROUPS;
}
fillIntArray(env, groupList, profile.rp_config.profile.groups, groupCount);
jobject capList = env->GetObjectField(obj, capabilitiesField);
for (int i = 0; i <= CAP_LAST_CAP; i++) {
if (profile.rp_config.profile.capabilities.effective & (1ULL << i)) {
addIntToList(env, capList, i);
}
}
env->SetObjectField(obj, domainField,
env->NewStringUTF(profile.rp_config.profile.selinux_domain));
env->SetIntField(obj, namespacesField, profile.rp_config.profile.namespaces);
env->SetBooleanField(obj, allowSuField, profile.allow_su);
} else {
env->SetBooleanField(obj, nonRootUseDefaultField,
(jboolean) profile.nrp_config.use_default);
env->SetBooleanField(obj, umountModulesField, profile.nrp_config.profile.umount_modules);
}
return obj;
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_sukisu_ultra_Natives_setAppProfile(JNIEnv *env, jobject clazz, jobject profile) {
auto cls = env->FindClass("com/sukisu/ultra/Natives$Profile");
auto keyField = env->GetFieldID(cls, "name", "Ljava/lang/String;");
auto currentUidField = env->GetFieldID(cls, "currentUid", "I");
auto allowSuField = env->GetFieldID(cls, "allowSu", "Z");
auto rootUseDefaultField = env->GetFieldID(cls, "rootUseDefault", "Z");
auto rootTemplateField = env->GetFieldID(cls, "rootTemplate", "Ljava/lang/String;");
auto uidField = env->GetFieldID(cls, "uid", "I");
auto gidField = env->GetFieldID(cls, "gid", "I");
auto groupsField = env->GetFieldID(cls, "groups", "Ljava/util/List;");
auto capabilitiesField = env->GetFieldID(cls, "capabilities", "Ljava/util/List;");
auto domainField = env->GetFieldID(cls, "context", "Ljava/lang/String;");
auto namespacesField = env->GetFieldID(cls, "namespace", "I");
auto nonRootUseDefaultField = env->GetFieldID(cls, "nonRootUseDefault", "Z");
auto umountModulesField = env->GetFieldID(cls, "umountModules", "Z");
auto key = env->GetObjectField(profile, keyField);
if (!key) {
return false;
}
if (env->GetStringLength((jstring) key) > KSU_MAX_PACKAGE_NAME) {
return false;
}
auto cpkg = env->GetStringUTFChars((jstring) key, nullptr);
p_key_t p_key = {};
strcpy(p_key, cpkg);
env->ReleaseStringUTFChars((jstring) key, cpkg);
auto currentUid = env->GetIntField(profile, currentUidField);
auto uid = env->GetIntField(profile, uidField);
auto gid = env->GetIntField(profile, gidField);
auto groups = env->GetObjectField(profile, groupsField);
auto capabilities = env->GetObjectField(profile, capabilitiesField);
auto domain = env->GetObjectField(profile, domainField);
auto allowSu = env->GetBooleanField(profile, allowSuField);
auto umountModules = env->GetBooleanField(profile, umountModulesField);
app_profile p = {};
p.version = KSU_APP_PROFILE_VER;
strcpy(p.key, p_key);
p.allow_su = allowSu;
p.current_uid = currentUid;
if (allowSu) {
p.rp_config.use_default = env->GetBooleanField(profile, rootUseDefaultField);
auto templateName = env->GetObjectField(profile, rootTemplateField);
if (templateName) {
auto ctemplateName = env->GetStringUTFChars((jstring) templateName, nullptr);
strcpy(p.rp_config.template_name, ctemplateName);
env->ReleaseStringUTFChars((jstring) templateName, ctemplateName);
}
p.rp_config.profile.uid = uid;
p.rp_config.profile.gid = gid;
int groups_count = getListSize(env, groups);
if (groups_count > KSU_MAX_GROUPS) {
LOGD("groups count too large: %d", groups_count);
return false;
}
p.rp_config.profile.groups_count = groups_count;
fillArrayWithList(env, groups, p.rp_config.profile.groups, groups_count);
p.rp_config.profile.capabilities.effective = capListToBits(env, capabilities);
auto cdomain = env->GetStringUTFChars((jstring) domain, nullptr);
strcpy(p.rp_config.profile.selinux_domain, cdomain);
env->ReleaseStringUTFChars((jstring) domain, cdomain);
p.rp_config.profile.namespaces = env->GetIntField(profile, namespacesField);
} else {
p.nrp_config.use_default = env->GetBooleanField(profile, nonRootUseDefaultField);
p.nrp_config.profile.umount_modules = umountModules;
}
return set_app_profile(&p);
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_sukisu_ultra_Natives_uidShouldUmount(JNIEnv *env, jobject thiz, jint uid) {
return uid_should_umount(uid);
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_sukisu_ultra_Natives_isSuEnabled(JNIEnv *env, jobject thiz) {
return is_su_enabled();
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_sukisu_ultra_Natives_setSuEnabled(JNIEnv *env, jobject thiz, jboolean enabled) {
return set_su_enabled(enabled);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_sukisu_ultra_Natives_isKPMEnabled(JNIEnv *env, jobject) {
return is_KPM_enable();
}

View File

@@ -8,6 +8,7 @@
#include <stdio.h>
#include <unistd.h>
#include "prelude.h"
#include "ksu.h"
#define KERNEL_SU_OPTION 0xDEADBEEF
@@ -30,11 +31,14 @@
#define CMD_IS_SU_ENABLED 14
#define CMD_ENABLE_SU 15
#define CMD_ENABLE_KPM 100
#define CMD_HOOK_TYPE 101
#define CMD_GET_SUSFS_FEATURE_STATUS 102
static bool ksuctl(int cmd, void* arg1, void* arg2) {
int32_t result = 0;
prctl(KERNEL_SU_OPTION, cmd, arg1, arg2, &result);
return result == KERNEL_SU_OPTION;
int32_t rtn = prctl(KERNEL_SU_OPTION, cmd, arg1, arg2, &result);
return result == KERNEL_SU_OPTION && rtn == -1;
}
bool become_manager(const char* pkg) {
@@ -47,7 +51,7 @@ bool become_manager(const char* pkg) {
snprintf(param, sizeof(param), "/data/user/%d/%s", userId, pkg);
}
return ksuctl(CMD_BECOME_MANAGER, param, nullptr);
return ksuctl(CMD_BECOME_MANAGER, param, NULL);
}
// cache the result to avoid unnecessary syscall
@@ -67,7 +71,7 @@ bool get_allow_list(int *uids, int *size) {
}
bool is_safe_mode() {
return ksuctl(CMD_CHECK_SAFEMODE, nullptr, nullptr);
return ksuctl(CMD_CHECK_SAFEMODE, NULL, NULL);
}
bool is_lkm_mode() {
@@ -76,30 +80,56 @@ bool is_lkm_mode() {
}
bool uid_should_umount(int uid) {
bool should;
return ksuctl(CMD_IS_UID_SHOULD_UMOUNT, reinterpret_cast<void*>(uid), &should) && should;
int should;
return ksuctl(CMD_IS_UID_SHOULD_UMOUNT, (void*) ((size_t) uid), &should) && should;
}
bool set_app_profile(const app_profile *profile) {
return ksuctl(CMD_SET_APP_PROFILE, (void*) profile, nullptr);
bool set_app_profile(const struct app_profile* profile) {
return ksuctl(CMD_SET_APP_PROFILE, (void*) profile, NULL);
}
bool get_app_profile(p_key_t key, app_profile *profile) {
return ksuctl(CMD_GET_APP_PROFILE, (void*) profile, nullptr);
bool get_app_profile(char* key, struct app_profile* profile) {
return ksuctl(CMD_GET_APP_PROFILE, profile, NULL);
}
bool set_su_enabled(bool enabled) {
return ksuctl(CMD_ENABLE_SU, (void*) enabled, nullptr);
return ksuctl(CMD_ENABLE_SU, (void*) enabled, NULL);
}
bool is_su_enabled() {
bool enabled = true;
int enabled = true;
// if ksuctl failed, we assume su is enabled, and it cannot be disabled.
ksuctl(CMD_IS_SU_ENABLED, &enabled, nullptr);
ksuctl(CMD_IS_SU_ENABLED, &enabled, NULL);
return enabled;
}
bool is_KPM_enable() {
bool enabled = false;
return ksuctl(CMD_ENABLE_KPM, &enabled, nullptr), enabled;
int enabled = false;
ksuctl(CMD_ENABLE_KPM, &enabled, NULL);
return enabled;
}
bool get_hook_type(char* hook_type, size_t size) {
if (hook_type == NULL || size == 0) {
return false;
}
static char cached_hook_type[16] = {0};
if (cached_hook_type[0] == '\0') {
if (!ksuctl(CMD_HOOK_TYPE, cached_hook_type, NULL)) {
strcpy(cached_hook_type, "Unknown");
}
}
strncpy(hook_type, cached_hook_type, size);
hook_type[size - 1] = '\0';
return true;
}
bool get_susfs_feature_status(struct susfs_feature_status* status) {
if (status == NULL) {
return false;
}
return ksuctl(CMD_GET_SUSFS_FEATURE_STATUS, status, NULL);
}

View File

@@ -5,6 +5,7 @@
#ifndef KERNELSU_KSU_H
#define KERNELSU_KSU_H
#include "prelude.h"
#include <linux/capability.h>
bool become_manager(const char *);
@@ -25,7 +26,24 @@ bool is_lkm_mode();
#define KSU_MAX_GROUPS 32
#define KSU_SELINUX_DOMAIN 64
using p_key_t = char[KSU_MAX_PACKAGE_NAME];
// SUSFS Functional State Structures
struct susfs_feature_status {
bool status_sus_path;
bool status_sus_mount;
bool status_auto_default_mount;
bool status_auto_bind_mount;
bool status_sus_kstat;
bool status_try_umount;
bool status_auto_try_umount_bind;
bool status_spoof_uname;
bool status_enable_log;
bool status_hide_symbols;
bool status_spoof_cmdline;
bool status_open_redirect;
bool status_magic_mount;
bool status_overlayfs_auto_kstat;
bool status_sus_su;
};
struct root_profile {
int32_t uid;
@@ -75,9 +93,9 @@ struct app_profile {
};
};
bool set_app_profile(const app_profile *profile);
bool set_app_profile(const struct app_profile* profile);
bool get_app_profile(p_key_t key, app_profile *profile);
bool get_app_profile(char* key, struct app_profile* profile);
bool set_su_enabled(bool enabled);
@@ -85,4 +103,8 @@ bool is_su_enabled();
bool is_KPM_enable();
bool get_hook_type(char* hook_type, size_t size);
bool get_susfs_feature_status(struct susfs_feature_status* status);
#endif //KERNELSU_KSU_H

View File

@@ -0,0 +1,17 @@
#ifndef KERNELSU_PRELUDE_H
#define KERNELSU_PRELUDE_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <jni.h>
#include <android/log.h>
#define GetEnvironment() (*env)
#define NativeBridge(fn, rtn, ...) JNIEXPORT rtn JNICALL Java_com_sukisu_ultra_Natives_##fn(JNIEnv* env, jclass clazz, __VA_ARGS__)
#define NativeBridgeNP(fn, rtn) JNIEXPORT rtn JNICALL Java_com_sukisu_ultra_Natives_##fn(JNIEnv* env, jclass clazz)
#define LogDebug(...) __android_log_print(ANDROID_LOG_DEBUG, "KernelSU", __VA_ARGS__)
#endif

View File

@@ -1,11 +1,14 @@
package com.sukisu.ultra
import android.annotation.SuppressLint
import android.app.Activity
import android.app.ActivityOptions
import android.app.Application
import android.content.Context
import android.content.res.Configuration
import android.content.res.Resources
import android.os.Build
import android.os.Bundle
import coil.Coil
import coil.ImageLoader
import com.dergoogler.mmrl.platform.Platform
@@ -14,9 +17,31 @@ import me.zhanghai.android.appiconloader.coil.AppIconKeyer
import java.io.File
import java.util.Locale
@SuppressLint("StaticFieldLeak")
lateinit var ksuApp: KernelSUApplication
class KernelSUApplication : Application() {
private var currentActivity: Activity? = null
private val activityLifecycleCallbacks = object : ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
currentActivity = activity
}
override fun onActivityStarted(activity: Activity) {
currentActivity = activity
}
override fun onActivityResumed(activity: Activity) {
currentActivity = activity
}
override fun onActivityPaused(activity: Activity) {}
override fun onActivityStopped(activity: Activity) {}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityDestroyed(activity: Activity) {
if (currentActivity == activity) {
currentActivity = null
}
}
}
override fun attachBaseContext(base: Context) {
val prefs = base.getSharedPreferences("settings", MODE_PRIVATE)
@@ -62,6 +87,9 @@ class KernelSUApplication : Application() {
super.onCreate()
ksuApp = this
// 注册Activity生命周期回调
registerActivityLifecycleCallbacks(activityLifecycleCallbacks)
Platform.setHiddenApiExemptions()
val context = this
@@ -107,4 +135,17 @@ class KernelSUApplication : Application() {
}
}
}
// 添加刷新当前Activity的方法
fun refreshCurrentActivity() {
currentActivity?.let { activity ->
val intent = activity.intent
activity.finish()
val options = ActivityOptions.makeCustomAnimation(
activity, android.R.anim.fade_in, android.R.anim.fade_out
)
activity.startActivity(intent, options.toBundle())
}
}
}

View File

@@ -69,6 +69,13 @@ object Natives {
external fun isSuEnabled(): Boolean
external fun setSuEnabled(enabled: Boolean): Boolean
external fun isKPMEnabled(): Boolean
external fun getHookType(): String
/**
* Get SUSFS feature status from kernel
* @return SusfsFeatureStatus object containing all feature states, or null if failed
*/
external fun getSusfsFeatureStatus(): SusfsFeatureStatus?
private const val NON_ROOT_DEFAULT_PROFILE_KEY = "$"
private const val NOBODY_UID = 9999
@@ -94,6 +101,48 @@ object Natives {
return version < MINIMAL_SUPPORTED_KERNEL
}
@Immutable
@Parcelize
@Keep
data class SusfsFeatureStatus(
val statusSusPath: Boolean = false,
val statusSusMount: Boolean = false,
val statusAutoDefaultMount: Boolean = false,
val statusAutoBindMount: Boolean = false,
val statusSusKstat: Boolean = false,
val statusTryUmount: Boolean = false,
val statusAutoTryUmountBind: Boolean = false,
val statusSpoofUname: Boolean = false,
val statusEnableLog: Boolean = false,
val statusHideSymbols: Boolean = false,
val statusSpoofCmdline: Boolean = false,
val statusOpenRedirect: Boolean = false,
val statusMagicMount: Boolean = false,
val statusOverlayfsAutoKstat: Boolean = false,
val statusSusSu: Boolean = false
) : Parcelable {
fun toMap(): Map<String, Boolean> {
return mapOf(
"CONFIG_KSU_SUSFS_SUS_PATH" to statusSusPath,
"CONFIG_KSU_SUSFS_SUS_MOUNT" to statusSusMount,
"CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT" to statusAutoDefaultMount,
"CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT" to statusAutoBindMount,
"CONFIG_KSU_SUSFS_SUS_KSTAT" to statusSusKstat,
"CONFIG_KSU_SUSFS_TRY_UMOUNT" to statusTryUmount,
"CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT" to statusAutoTryUmountBind,
"CONFIG_KSU_SUSFS_SPOOF_UNAME" to statusSpoofUname,
"CONFIG_KSU_SUSFS_ENABLE_LOG" to statusEnableLog,
"CONFIG_KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS" to statusHideSymbols,
"CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG" to statusSpoofCmdline,
"CONFIG_KSU_SUSFS_OPEN_REDIRECT" to statusOpenRedirect,
"CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT" to statusMagicMount,
"CONFIG_KSU_SUSFS_SUS_OVERLAYFS" to statusOverlayfsAutoKstat,
"CONFIG_KSU_SUSFS_SUS_SU" to statusSusSu
)
}
}
@Immutable
@Parcelize
@Keep

View File

@@ -1,243 +1,183 @@
package com.sukisu.ultra.ui
import android.annotation.SuppressLint
import android.content.Context
import android.content.res.Configuration
import android.database.ContentObserver
import android.os.Build
import android.os.Bundle
import android.os.Handler
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.animation.*
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavHostController
import androidx.lifecycle.lifecycleScope
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import com.ramcosta.composedestinations.DestinationsNavHost
import com.ramcosta.composedestinations.animations.NavHostAnimatedDestinationStyle
import com.ramcosta.composedestinations.generated.NavGraphs
import com.ramcosta.composedestinations.generated.destinations.ExecuteModuleActionScreenDestination
import com.ramcosta.composedestinations.spec.NavHostGraphSpec
import com.ramcosta.composedestinations.spec.RouteOrDirection
import com.ramcosta.composedestinations.utils.isRouteOnBackStackAsState
import com.ramcosta.composedestinations.utils.rememberDestinationsNavigator
import io.sukisu.ultra.UltraToolInstall
import com.sukisu.ultra.Natives
import com.sukisu.ultra.ksuApp
import com.sukisu.ultra.ui.screen.BottomBarDestination
import zako.zako.zako.zakoui.activity.util.AppData
import com.sukisu.ultra.ui.theme.*
import com.sukisu.ultra.ui.theme.CardConfig.cardAlpha
import com.sukisu.ultra.ui.util.*
import androidx.core.content.edit
import com.sukisu.ultra.ui.theme.CardConfig.cardElevation
import com.sukisu.ultra.ui.webui.initPlatform
import java.util.Locale
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.lifecycle.lifecycleScope
import zako.zako.zako.zakoui.activity.util.*
import zako.zako.zako.zakoui.activity.component.BottomBar
import com.sukisu.ultra.ui.util.LocalSnackbarHost
import com.sukisu.ultra.ui.util.install
import com.sukisu.ultra.ui.viewmodel.HomeViewModel
import com.sukisu.ultra.ui.viewmodel.SuperUserViewModel
import com.sukisu.ultra.ui.webui.initPlatform
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
private lateinit var superUserViewModel: SuperUserViewModel
private lateinit var homeViewModel: HomeViewModel
internal val settingsStateFlow = MutableStateFlow(SettingsState())
private inner class ThemeChangeContentObserver(
handler: Handler,
private val onThemeChanged: () -> Unit
) : ContentObserver(handler) {
override fun onChange(selfChange: Boolean) {
super.onChange(selfChange)
onThemeChanged()
}
}
data class SettingsState(
val isHideOtherInfo: Boolean = false,
val showKpmInfo: Boolean = false
)
// 应用保存的语言设置
@SuppressLint("ObsoleteSdkInt")
private fun applyLanguageSetting() {
val prefs = getSharedPreferences("settings", MODE_PRIVATE)
val languageCode = prefs.getString("app_language", "") ?: ""
private lateinit var themeChangeObserver: ThemeChangeContentObserver
if (languageCode.isNotEmpty()) {
val locale = Locale.forLanguageTag(languageCode)
Locale.setDefault(locale)
val resources = resources
val config = Configuration(resources.configuration)
config.setLocale(locale)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
createConfigurationContext(config)
} else {
@Suppress("DEPRECATION")
resources.updateConfiguration(config, resources.displayMetrics)
}
}
}
// 添加标记避免重复初始化
private var isInitialized = false
override fun attachBaseContext(newBase: Context) {
val prefs = newBase.getSharedPreferences("settings", MODE_PRIVATE)
val languageCode = prefs.getString("app_language", "") ?: ""
var context = newBase
if (languageCode.isNotEmpty()) {
val locale = Locale.forLanguageTag(languageCode)
Locale.setDefault(locale)
val config = Configuration(newBase.resources.configuration)
config.setLocale(locale)
context = newBase.createConfigurationContext(config)
}
val context = LocaleUtils.applyLocale(newBase)
super.attachBaseContext(context)
}
@SuppressLint("RestrictedApi")
override fun onCreate(savedInstanceState: Bundle?) {
// 确保应用正确的语言设置
applyLanguageSetting()
try {
// 确保应用正确的语言设置
LocaleUtils.applyLanguageSetting(this)
// 应用自定义 DPI
applyCustomDpi()
// 应用自定义 DPI
DisplayUtils.applyCustomDpi(this)
// Enable edge to edge
enableEdgeToEdge()
// Enable edge to edge
enableEdgeToEdge()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
window.isNavigationBarContrastEnforced = false
}
super.onCreate(savedInstanceState)
// 初始化 SuperUserViewModel
superUserViewModel = SuperUserViewModel()
lifecycleScope.launch {
superUserViewModel.fetchAppList()
}
// 初始化 HomeViewModel
homeViewModel = HomeViewModel()
// 预加载数据
lifecycleScope.launch {
homeViewModel.initializeData()
}
val prefs = getSharedPreferences("settings", MODE_PRIVATE)
val isFirstRun = prefs.getBoolean("is_first_run", true)
if (isFirstRun) {
ThemeConfig.preventBackgroundRefresh = false
getSharedPreferences("theme_prefs", MODE_PRIVATE).edit {
putBoolean("prevent_background_refresh", false)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
window.isNavigationBarContrastEnforced = false
}
prefs.edit { putBoolean("is_first_run", false) }
}
// 加载保存的背景设置
loadThemeMode()
loadThemeColors()
loadDynamicColorState()
CardConfig.load(applicationContext)
super.onCreate(savedInstanceState)
val contentObserver = ThemeChangeContentObserver(Handler(mainLooper)) {
runOnUiThread {
if (!ThemeConfig.preventBackgroundRefresh) {
ThemeConfig.backgroundImageLoaded = false
loadCustomBackground()
// 使用标记控制初始化流程
if (!isInitialized) {
initializeViewModels()
initializeData()
isInitialized = true
}
setContent {
KernelSUTheme {
val navController = rememberNavController()
val snackBarHostState = remember { SnackbarHostState() }
val currentDestination = navController.currentBackStackEntryAsState().value?.destination
val showBottomBar = when (currentDestination?.route) {
ExecuteModuleActionScreenDestination.route -> false
else -> true
}
LaunchedEffect(Unit) {
initPlatform()
}
CompositionLocalProvider(
LocalSnackbarHost provides snackBarHostState
) {
Scaffold(
bottomBar = {
AnimatedBottomBar.AnimatedBottomBarWrapper(
showBottomBar = showBottomBar,
content = { BottomBar(navController) }
)
},
contentWindowInsets = WindowInsets(0, 0, 0, 0)
) { innerPadding ->
DestinationsNavHost(
modifier = Modifier.padding(innerPadding),
navGraph = NavGraphs.root as NavHostGraphSpec,
navController = navController,
defaultTransitions = NavigationUtils.defaultTransitions()
)
}
}
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun initializeViewModels() {
superUserViewModel = SuperUserViewModel()
homeViewModel = HomeViewModel()
// 设置主题变化监听器
themeChangeObserver = ThemeUtils.registerThemeChangeObserver(this)
}
private fun initializeData() {
lifecycleScope.launch {
try {
superUserViewModel.fetchAppList()
} catch (e: Exception) {
e.printStackTrace()
}
}
contentResolver.registerContentObserver(
android.provider.Settings.System.getUriFor("ui_night_mode"),
false,
contentObserver
)
val destroyListeners = mutableListOf<() -> Unit>()
destroyListeners.add {
contentResolver.unregisterContentObserver(contentObserver)
lifecycleScope.launch {
try {
homeViewModel.initializeData()
} catch (e: Exception) {
e.printStackTrace()
}
}
val isManager = Natives.becomeManager(ksuApp.packageName)
// 数据刷新协程
DataRefreshUtils.startDataRefreshCoroutine(lifecycleScope)
DataRefreshUtils.startSettingsMonitorCoroutine(lifecycleScope, this, settingsStateFlow)
// 初始化主题相关设置
ThemeUtils.initializeThemeSettings(this, settingsStateFlow)
val isManager = AppData.isManager(ksuApp.packageName)
if (isManager) {
install()
UltraToolInstall.tryToInstall()
}
}
setContent {
KernelSUTheme {
val navController = rememberNavController()
val snackBarHostState = remember { SnackbarHostState() }
val currentDestination = navController.currentBackStackEntryAsState().value?.destination
override fun onResume() {
try {
super.onResume()
LocaleUtils.applyLanguageSetting(this)
ThemeUtils.onActivityResume()
val showBottomBar = when (currentDestination?.route) {
ExecuteModuleActionScreenDestination.route -> false // Hide for ExecuteModuleActionScreen
else -> true
}
// pre-init platform to faster start WebUI X activities
LaunchedEffect(Unit) {
initPlatform()
}
Scaffold(
bottomBar = {
AnimatedVisibility(
visible = showBottomBar,
enter = slideInVertically(initialOffsetY = { it }) + fadeIn(),
exit = slideOutVertically(targetOffsetY = { it }) + fadeOut()
) {
BottomBar(navController)
}
},
contentWindowInsets = WindowInsets(0, 0, 0, 0)
) { innerPadding ->
CompositionLocalProvider(
LocalSnackbarHost provides snackBarHostState
) {
DestinationsNavHost(
modifier = Modifier.padding(innerPadding),
navGraph = NavGraphs.root as NavHostGraphSpec,
navController = navController,
defaultTransitions = object : NavHostAnimatedDestinationStyle() {
override val enterTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition
get() = { fadeIn(animationSpec = tween(340)) }
override val exitTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition
get() = { fadeOut(animationSpec = tween(340)) }
}
)
}
}
// 仅在需要时刷新数据
if (isInitialized) {
refreshData()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
// 应用自定义DPI设置
private fun applyCustomDpi() {
val prefs = getSharedPreferences("settings", MODE_PRIVATE)
val customDpi = prefs.getInt("app_dpi", 0)
if (customDpi > 0) {
private fun refreshData() {
lifecycleScope.launch {
try {
val resources = resources
val metrics = resources.displayMetrics
metrics.density = customDpi / 160f
@Suppress("DEPRECATION")
metrics.scaledDensity = customDpi / 160f
metrics.densityDpi = customDpi
superUserViewModel.fetchAppList()
homeViewModel.initializeData()
DataRefreshUtils.refreshData(lifecycleScope)
} catch (e: Exception) {
e.printStackTrace()
}
@@ -245,125 +185,29 @@ class MainActivity : ComponentActivity() {
}
override fun onPause() {
super.onPause()
CardConfig.save(applicationContext)
getSharedPreferences("theme_prefs", MODE_PRIVATE).edit {
putBoolean("prevent_background_refresh", true)
}
ThemeConfig.preventBackgroundRefresh = true
}
override fun onResume() {
super.onResume()
applyLanguageSetting()
if (!ThemeConfig.backgroundImageLoaded && !ThemeConfig.preventBackgroundRefresh) {
loadCustomBackground()
}
lifecycleScope.launch {
superUserViewModel.fetchAppList()
}
lifecycleScope.launch {
homeViewModel.initializeData()
try {
super.onPause()
ThemeUtils.onActivityPause(this)
} catch (e: Exception) {
e.printStackTrace()
}
}
private val destroyListeners = mutableListOf<() -> Unit>()
override fun onDestroy() {
destroyListeners.forEach { it() }
super.onDestroy()
try {
ThemeUtils.unregisterThemeChangeObserver(this, themeChangeObserver)
super.onDestroy()
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
applyLanguageSetting()
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun BottomBar(navController: NavHostController) {
val navigator = navController.rememberDestinationsNavigator()
val isManager = Natives.becomeManager(ksuApp.packageName)
val fullFeatured = isManager && !Natives.requireNewKernel() && rootAvailable()
val kpmVersion = getKpmVersion()
val cardColor = MaterialTheme.colorScheme.surfaceContainer
// 检查是否显示KPM
val showKpmInfo = LocalContext.current.getSharedPreferences("settings", Context.MODE_PRIVATE)
.getBoolean("show_kpm_info", true)
NavigationBar(
modifier = Modifier.windowInsetsPadding(
WindowInsets.navigationBars.only(WindowInsetsSides.Horizontal)
),
containerColor = TopAppBarDefaults.topAppBarColors(
containerColor = cardColor.copy(alpha = cardAlpha),
scrolledContainerColor = cardColor.copy(alpha = cardAlpha)
).containerColor,
tonalElevation = cardElevation
) {
BottomBarDestination.entries.forEach { destination ->
if (destination == BottomBarDestination.Kpm) {
if (kpmVersion.isNotEmpty() && !kpmVersion.startsWith("Error") && showKpmInfo && Natives.version >= Natives.MINIMAL_SUPPORTED_KPM) {
if (!fullFeatured && destination.rootRequired) return@forEach
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
NavigationBarItem(
selected = isCurrentDestOnBackStack,
onClick = {
if (!isCurrentDestOnBackStack) {
navigator.popBackStack(destination.direction, false)
}
navigator.navigate(destination.direction) {
popUpTo(NavGraphs.root as RouteOrDirection) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
},
icon = {
if (isCurrentDestOnBackStack) {
Icon(destination.iconSelected, stringResource(destination.label))
} else {
Icon(destination.iconNotSelected, stringResource(destination.label))
}
},
label = { Text(stringResource(destination.label),style = MaterialTheme.typography.labelMedium) },
alwaysShowLabel = false
)
}
} else {
if (!fullFeatured && destination.rootRequired) return@forEach
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
NavigationBarItem(
selected = isCurrentDestOnBackStack,
onClick = {
if (isCurrentDestOnBackStack) {
navigator.popBackStack(destination.direction, false)
}
navigator.navigate(destination.direction) {
popUpTo(NavGraphs.root) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
},
icon = {
if (isCurrentDestOnBackStack) {
Icon(destination.iconSelected, stringResource(destination.label))
} else {
Icon(destination.iconNotSelected, stringResource(destination.label))
}
},
label = { Text(stringResource(destination.label),style = MaterialTheme.typography.labelMedium) },
alwaysShowLabel = false
)
}
try {
super.onConfigurationChanged(newConfig)
LocaleUtils.applyLanguageSetting(this)
} catch (e: Exception) {
e.printStackTrace()
}
}
}

View File

@@ -0,0 +1,73 @@
package com.sukisu.ultra.ui.component
import android.annotation.SuppressLint
import androidx.compose.animation.core.*
import androidx.compose.animation.*
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.scale
import androidx.compose.ui.unit.dp
@SuppressLint("AutoboxingStateCreation")
@Composable
fun rememberFabVisibilityState(listState: LazyListState): State<Boolean> {
var previousScrollOffset by remember { mutableStateOf(0) }
var previousIndex by remember { mutableStateOf(0) }
val fabVisible = remember { mutableStateOf(true) }
LaunchedEffect(listState) {
snapshotFlow { listState.firstVisibleItemIndex to listState.firstVisibleItemScrollOffset }
.collect { (index, offset) ->
if (previousIndex == 0 && previousScrollOffset == 0) {
fabVisible.value = true
} else {
val isScrollingDown = when {
index > previousIndex -> false
index < previousIndex -> true
else -> offset < previousScrollOffset
}
fabVisible.value = isScrollingDown
}
previousIndex = index
previousScrollOffset = offset
}
}
return fabVisible
}
@Composable
fun AnimatedFab(
visible: Boolean,
content: @Composable () -> Unit
) {
val scale by animateFloatAsState(
targetValue = if (visible) 1f else 0f,
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessLow
)
)
AnimatedVisibility(
visible = visible,
enter = fadeIn() + scaleIn(),
exit = fadeOut() + scaleOut(targetScale = 0.8f)
) {
Box(
modifier = Modifier
.clip(RoundedCornerShape(16.dp))
.scale(scale)
.alpha(scale)
) {
content()
}
}
}

View File

@@ -20,7 +20,6 @@ import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
@@ -138,7 +137,7 @@ fun ImageEditorDialog(
0f
}
updateTransformation(newScale, newOffsetX, newOffsetY)
} catch (e: Exception) {
} catch (_: Exception) {
updateTransformation(lastScale, lastOffsetX, lastOffsetY)
}
}
@@ -186,7 +185,7 @@ fun ImageEditorDialog(
val transformation = BackgroundTransformation(scale, offsetX, offsetY)
val savedUri = context.saveTransformedBackground(imageUri, transformation)
savedUri?.let { onConfirm(it) }
} catch (e: Exception) {
} catch (_: Exception) {
""
}
}

View File

@@ -63,7 +63,12 @@ fun SearchAppBar(
var onSearch by remember { mutableStateOf(false) }
// 获取卡片颜色和透明度
val cardColor = MaterialTheme.colorScheme.surfaceContainerLow
val colorScheme = MaterialTheme.colorScheme
val cardColor = if (CardConfig.isCustomBackgroundEnabled) {
colorScheme.surfaceContainerLow
} else {
colorScheme.background
}
val cardAlpha = CardConfig.cardAlpha
if (onSearch) {

View File

@@ -6,16 +6,19 @@ import androidx.compose.foundation.selection.toggleable
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.semantics.Role
import com.dergoogler.mmrl.ui.component.LabelItem
import com.dergoogler.mmrl.ui.component.text.TextRow
import com.sukisu.ultra.ui.theme.CardConfig
@Composable
fun SwitchItem(
@@ -25,63 +28,84 @@ fun SwitchItem(
checked: Boolean,
enabled: Boolean = true,
beta: Boolean = false,
onCheckedChange: (Boolean) -> Unit,
onCheckedChange: (Boolean) -> Unit
) {
val interactionSource = remember { MutableInteractionSource() }
val stateAlpha = remember(checked, enabled) { Modifier.alpha(if (enabled) 1f else 0.5f) }
MaterialTheme(
colorScheme = MaterialTheme.colorScheme.copy(
surface = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else MaterialTheme.colorScheme.surfaceContainerHigh
)
) {
ListItem(
modifier = Modifier
.toggleable(
value = checked,
interactionSource = interactionSource,
role = Role.Switch,
enabled = enabled,
indication = LocalIndication.current,
onValueChange = onCheckedChange
),
headlineContent = {
TextRow(
leadingContent = if (beta) {
{
LabelItem(
modifier = Modifier.then(stateAlpha),
text = "Beta"
)
}
} else null
) {
Text(
modifier = Modifier.then(stateAlpha),
text = title,
)
}
},
leadingContent = icon?.let {
{
Icon(
modifier = Modifier.then(stateAlpha),
imageVector = icon,
contentDescription = title
)
}
},
trailingContent = {
Switch(
checked = checked,
enabled = enabled,
onCheckedChange = onCheckedChange,
interactionSource = interactionSource
)
},
supportingContent = {
if (summary != null) {
Text(
modifier = Modifier.then(stateAlpha),
text = summary
)
}
}
)
}
}
@Composable
fun RadioItem(
title: String,
selected: Boolean,
onClick: () -> Unit,
) {
ListItem(
modifier = Modifier
.toggleable(
value = checked,
interactionSource = interactionSource,
role = Role.Switch,
enabled = enabled,
indication = LocalIndication.current,
onValueChange = onCheckedChange
),
headlineContent = {
TextRow(
leadingContent = if (beta) {
{
LabelItem(
modifier = Modifier.then(stateAlpha),
text = "Beta"
)
}
} else null
) {
Text(
modifier = Modifier.then(stateAlpha),
text = title,
)
}
Text(title)
},
leadingContent = icon?.let {
{
Icon(
modifier = Modifier.then(stateAlpha),
imageVector = icon,
contentDescription = title,
tint = MaterialTheme.colorScheme.primary
)
}
},
trailingContent = {
Switch(
checked = checked,
enabled = enabled,
onCheckedChange = onCheckedChange,
interactionSource = interactionSource
)
},
supportingContent = {
if (summary != null) {
Text(
modifier = Modifier.then(stateAlpha),
text = summary
)
}
leadingContent = {
RadioButton(selected = selected, onClick = onClick)
}
)
}

View File

@@ -1,6 +1,5 @@
package com.sukisu.ultra.ui.component
import android.content.Context
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.horizontalScroll
@@ -10,12 +9,10 @@ import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.sukisu.ultra.R
import com.sukisu.ultra.ui.theme.ThemeConfig
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.SdStorage
import androidx.compose.ui.draw.clip
@@ -32,13 +29,19 @@ fun SlotSelectionDialog(
onDismiss: () -> Unit,
onSlotSelected: (String) -> Unit
) {
val context = LocalContext.current
var currentSlot by remember { mutableStateOf<String?>(null) }
var errorMessage by remember { mutableStateOf<String?>(null) }
var selectedSlot by remember { mutableStateOf<String?>(null) }
LaunchedEffect(Unit) {
try {
currentSlot = getCurrentSlot(context)
currentSlot = getCurrentSlot()
// 设置默认选择为当前槽位
selectedSlot = when (currentSlot) {
"a" -> "a"
"b" -> "b"
else -> null
}
errorMessage = null
} catch (e: Exception) {
errorMessage = e.message
@@ -103,12 +106,12 @@ fun SlotSelectionDialog(
val slotOptions = listOf(
ListOption(
titleText = stringResource(id = R.string.slot_a),
subtitleText = if (currentSlot == "a" || currentSlot == "_a") stringResource(id = R.string.currently_selected) else null,
subtitleText = null,
icon = Icons.Filled.SdStorage
),
ListOption(
titleText = stringResource(id = R.string.slot_b),
subtitleText = if (currentSlot == "b" || currentSlot == "_b") stringResource(id = R.string.currently_selected) else null,
subtitleText = null,
icon = Icons.Filled.SdStorage
)
)
@@ -124,19 +127,20 @@ fun SlotSelectionDialog(
.fillMaxWidth()
.clip(MaterialTheme.shapes.medium)
.background(
color = if (option.subtitleText != null) {
color = if (selectedSlot == when(index) {
0 -> "a"
else -> "b"
}) {
MaterialTheme.colorScheme.primary.copy(alpha = 0.9f)
} else {
MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.3f)
}
)
.clickable {
onSlotSelected(
when (index) {
0 -> "a"
else -> "b"
}
)
selectedSlot = when(index) {
0 -> "a"
else -> "b"
}
}
.padding(vertical = 12.dp, horizontal = 16.dp),
verticalAlignment = Alignment.CenterVertically
@@ -144,7 +148,10 @@ fun SlotSelectionDialog(
Icon(
imageVector = option.icon,
contentDescription = null,
tint = if (option.subtitleText != null) {
tint = if (selectedSlot == when(index) {
0 -> "a"
else -> "b"
}) {
MaterialTheme.colorScheme.onPrimary
} else {
MaterialTheme.colorScheme.primary
@@ -159,7 +166,10 @@ fun SlotSelectionDialog(
Text(
text = option.titleText,
style = MaterialTheme.typography.titleMedium,
color = if (option.subtitleText != null) {
color = if (selectedSlot == when(index) {
0 -> "a"
else -> "b"
}) {
MaterialTheme.colorScheme.onPrimary
} else {
MaterialTheme.colorScheme.primary
@@ -169,7 +179,10 @@ fun SlotSelectionDialog(
Text(
text = it,
style = MaterialTheme.typography.bodyMedium,
color = if (true) {
color = if (selectedSlot == when(index) {
0 -> "a"
else -> "b"
}) {
MaterialTheme.colorScheme.onPrimary.copy(alpha = 0.8f)
} else {
MaterialTheme.colorScheme.onSurfaceVariant
@@ -186,9 +199,10 @@ fun SlotSelectionDialog(
confirmButton = {
TextButton(
onClick = {
currentSlot?.let { onSlotSelected(it) }
selectedSlot?.let { onSlotSelected(it) }
onDismiss()
}
},
enabled = selectedSlot != null
) {
Text(
text = stringResource(android.R.string.ok),
@@ -221,7 +235,7 @@ data class ListOption(
)
// Utility function to get current slot
private fun getCurrentSlot(context: Context): String? {
private fun getCurrentSlot(): String? {
return runCommandGetOutput(true, "getprop ro.boot.slot_suffix")?.let {
if (it.startsWith("_")) it.substring(1) else it
}

View File

@@ -0,0 +1,517 @@
package com.sukisu.ultra.ui.component
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MenuAnchorType
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.sukisu.ultra.R
/**
* 添加路径对话框
*/
@Composable
fun AddPathDialog(
showDialog: Boolean,
onDismiss: () -> Unit,
onConfirm: (String) -> Unit,
isLoading: Boolean,
titleRes: Int,
labelRes: Int,
placeholderRes: Int
) {
var newPath by remember { mutableStateOf("") }
if (showDialog) {
AlertDialog(
onDismissRequest = onDismiss,
title = {
Text(
stringResource(titleRes),
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold
)
},
text = {
OutlinedTextField(
value = newPath,
onValueChange = { newPath = it },
label = { Text(stringResource(labelRes)) },
placeholder = { Text(stringResource(placeholderRes)) },
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(8.dp)
)
},
confirmButton = {
Button(
onClick = {
if (newPath.isNotBlank()) {
onConfirm(newPath.trim())
newPath = ""
}
},
enabled = newPath.isNotBlank() && !isLoading,
shape = RoundedCornerShape(8.dp)
) {
Text(stringResource(R.string.susfs_add))
}
},
dismissButton = {
TextButton(
onClick = {
onDismiss()
newPath = ""
},
shape = RoundedCornerShape(8.dp)
) {
Text(stringResource(R.string.cancel))
}
},
shape = RoundedCornerShape(12.dp)
)
}
}
/**
* 添加尝试卸载对话框
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AddTryUmountDialog(
showDialog: Boolean,
onDismiss: () -> Unit,
onConfirm: (String, Int) -> Unit,
isLoading: Boolean
) {
var newUmountPath by remember { mutableStateOf("") }
var newUmountMode by remember { mutableIntStateOf(0) }
var umountModeExpanded by remember { mutableStateOf(false) }
if (showDialog) {
AlertDialog(
onDismissRequest = onDismiss,
title = {
Text(
stringResource(R.string.susfs_add_try_umount),
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold
)
},
text = {
Column(
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
OutlinedTextField(
value = newUmountPath,
onValueChange = { newUmountPath = it },
label = { Text(stringResource(R.string.susfs_path_label)) },
placeholder = { Text(stringResource(R.string.susfs_path_placeholder)) },
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(8.dp)
)
ExposedDropdownMenuBox(
expanded = umountModeExpanded,
onExpandedChange = { umountModeExpanded = !umountModeExpanded }
) {
OutlinedTextField(
value = if (newUmountMode == 0)
stringResource(R.string.susfs_umount_mode_normal)
else
stringResource(R.string.susfs_umount_mode_detach),
onValueChange = { },
readOnly = true,
label = { Text(stringResource(R.string.susfs_umount_mode_label)) },
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = umountModeExpanded) },
modifier = Modifier
.fillMaxWidth()
.menuAnchor(MenuAnchorType.PrimaryEditable, true),
shape = RoundedCornerShape(8.dp)
)
ExposedDropdownMenu(
expanded = umountModeExpanded,
onDismissRequest = { umountModeExpanded = false }
) {
DropdownMenuItem(
text = { Text(stringResource(R.string.susfs_umount_mode_normal)) },
onClick = {
newUmountMode = 0
umountModeExpanded = false
}
)
DropdownMenuItem(
text = { Text(stringResource(R.string.susfs_umount_mode_detach)) },
onClick = {
newUmountMode = 1
umountModeExpanded = false
}
)
}
}
}
},
confirmButton = {
Button(
onClick = {
if (newUmountPath.isNotBlank()) {
onConfirm(newUmountPath.trim(), newUmountMode)
newUmountPath = ""
newUmountMode = 0
}
},
enabled = newUmountPath.isNotBlank() && !isLoading,
shape = RoundedCornerShape(8.dp)
) {
Text(stringResource(R.string.susfs_add))
}
},
dismissButton = {
TextButton(
onClick = {
onDismiss()
newUmountPath = ""
newUmountMode = 0
},
shape = RoundedCornerShape(8.dp)
) {
Text(stringResource(R.string.cancel))
}
},
shape = RoundedCornerShape(12.dp)
)
}
}
/**
* 添加Kstat静态配置对话框
*/
@Composable
fun AddKstatStaticallyDialog(
showDialog: Boolean,
onDismiss: () -> Unit,
onConfirm: (String, String, String, String, String, String, String, String, String, String, String, String, String) -> Unit,
isLoading: Boolean
) {
var newKstatPath by remember { mutableStateOf("") }
var newKstatIno by remember { mutableStateOf("") }
var newKstatDev by remember { mutableStateOf("") }
var newKstatNlink by remember { mutableStateOf("") }
var newKstatSize by remember { mutableStateOf("") }
var newKstatAtime by remember { mutableStateOf("") }
var newKstatAtimeNsec by remember { mutableStateOf("") }
var newKstatMtime by remember { mutableStateOf("") }
var newKstatMtimeNsec by remember { mutableStateOf("") }
var newKstatCtime by remember { mutableStateOf("") }
var newKstatCtimeNsec by remember { mutableStateOf("") }
var newKstatBlocks by remember { mutableStateOf("") }
var newKstatBlksize by remember { mutableStateOf("") }
if (showDialog) {
AlertDialog(
onDismissRequest = onDismiss,
title = {
Text(
stringResource(R.string.add_kstat_statically_title),
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold
)
},
text = {
Column(
modifier = Modifier.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
OutlinedTextField(
value = newKstatPath,
onValueChange = { newKstatPath = it },
label = { Text(stringResource(R.string.file_or_directory_path_label)) },
placeholder = { Text("/path/to/file_or_directory") },
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(8.dp)
)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
OutlinedTextField(
value = newKstatIno,
onValueChange = { newKstatIno = it },
label = { Text("ino") },
placeholder = { Text("1234") },
modifier = Modifier.weight(1f),
shape = RoundedCornerShape(8.dp)
)
OutlinedTextField(
value = newKstatDev,
onValueChange = { newKstatDev = it },
label = { Text("dev") },
placeholder = { Text("1234") },
modifier = Modifier.weight(1f),
shape = RoundedCornerShape(8.dp)
)
}
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
OutlinedTextField(
value = newKstatNlink,
onValueChange = { newKstatNlink = it },
label = { Text("nlink") },
placeholder = { Text("2") },
modifier = Modifier.weight(1f),
shape = RoundedCornerShape(8.dp)
)
OutlinedTextField(
value = newKstatSize,
onValueChange = { newKstatSize = it },
label = { Text("size") },
placeholder = { Text("223344") },
modifier = Modifier.weight(1f),
shape = RoundedCornerShape(8.dp)
)
}
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
OutlinedTextField(
value = newKstatAtime,
onValueChange = { newKstatAtime = it },
label = { Text("atime") },
placeholder = { Text("1712592355") },
modifier = Modifier.weight(1f),
shape = RoundedCornerShape(8.dp)
)
OutlinedTextField(
value = newKstatAtimeNsec,
onValueChange = { newKstatAtimeNsec = it },
label = { Text("atime_nsec") },
placeholder = { Text("0") },
modifier = Modifier.weight(1f),
shape = RoundedCornerShape(8.dp)
)
}
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
OutlinedTextField(
value = newKstatMtime,
onValueChange = { newKstatMtime = it },
label = { Text("mtime") },
placeholder = { Text("1712592355") },
modifier = Modifier.weight(1f),
shape = RoundedCornerShape(8.dp)
)
OutlinedTextField(
value = newKstatMtimeNsec,
onValueChange = { newKstatMtimeNsec = it },
label = { Text("mtime_nsec") },
placeholder = { Text("0") },
modifier = Modifier.weight(1f),
shape = RoundedCornerShape(8.dp)
)
}
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
OutlinedTextField(
value = newKstatCtime,
onValueChange = { newKstatCtime = it },
label = { Text("ctime") },
placeholder = { Text("1712592355") },
modifier = Modifier.weight(1f),
shape = RoundedCornerShape(8.dp)
)
OutlinedTextField(
value = newKstatCtimeNsec,
onValueChange = { newKstatCtimeNsec = it },
label = { Text("ctime_nsec") },
placeholder = { Text("0") },
modifier = Modifier.weight(1f),
shape = RoundedCornerShape(8.dp)
)
}
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
OutlinedTextField(
value = newKstatBlocks,
onValueChange = { newKstatBlocks = it },
label = { Text("blocks") },
placeholder = { Text("16") },
modifier = Modifier.weight(1f),
shape = RoundedCornerShape(8.dp)
)
OutlinedTextField(
value = newKstatBlksize,
onValueChange = { newKstatBlksize = it },
label = { Text("blksize") },
placeholder = { Text("512") },
modifier = Modifier.weight(1f),
shape = RoundedCornerShape(8.dp)
)
}
Text(
text = stringResource(R.string.hint_use_default_value),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
},
confirmButton = {
Button(
onClick = {
if (newKstatPath.isNotBlank()) {
onConfirm(
newKstatPath.trim(),
newKstatIno.trim().ifBlank { "default" },
newKstatDev.trim().ifBlank { "default" },
newKstatNlink.trim().ifBlank { "default" },
newKstatSize.trim().ifBlank { "default" },
newKstatAtime.trim().ifBlank { "default" },
newKstatAtimeNsec.trim().ifBlank { "default" },
newKstatMtime.trim().ifBlank { "default" },
newKstatMtimeNsec.trim().ifBlank { "default" },
newKstatCtime.trim().ifBlank { "default" },
newKstatCtimeNsec.trim().ifBlank { "default" },
newKstatBlocks.trim().ifBlank { "default" },
newKstatBlksize.trim().ifBlank { "default" }
)
// 清空所有字段
newKstatPath = ""
newKstatIno = ""
newKstatDev = ""
newKstatNlink = ""
newKstatSize = ""
newKstatAtime = ""
newKstatAtimeNsec = ""
newKstatMtime = ""
newKstatMtimeNsec = ""
newKstatCtime = ""
newKstatCtimeNsec = ""
newKstatBlocks = ""
newKstatBlksize = ""
}
},
enabled = newKstatPath.isNotBlank() && !isLoading,
shape = RoundedCornerShape(8.dp)
) {
Text("添加")
}
},
dismissButton = {
TextButton(
onClick = {
onDismiss()
// 清空所有字段
newKstatPath = ""
newKstatIno = ""
newKstatDev = ""
newKstatNlink = ""
newKstatSize = ""
newKstatAtime = ""
newKstatAtimeNsec = ""
newKstatMtime = ""
newKstatMtimeNsec = ""
newKstatCtime = ""
newKstatCtimeNsec = ""
newKstatBlocks = ""
newKstatBlksize = ""
},
shape = RoundedCornerShape(8.dp)
) {
Text(stringResource(R.string.cancel))
}
},
shape = RoundedCornerShape(12.dp)
)
}
}
/**
* 确认对话框
*/
@Composable
fun ConfirmDialog(
showDialog: Boolean,
onDismiss: () -> Unit,
onConfirm: () -> Unit,
titleRes: Int,
messageRes: Int,
isLoading: Boolean = false,
isDestructive: Boolean = false
) {
if (showDialog) {
AlertDialog(
onDismissRequest = onDismiss,
title = {
Text(
text = stringResource(titleRes),
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold
)
},
text = { Text(stringResource(messageRes)) },
confirmButton = {
Button(
onClick = onConfirm,
enabled = !isLoading,
colors = if (isDestructive) {
ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.error
)
} else {
ButtonDefaults.buttonColors()
},
shape = RoundedCornerShape(8.dp)
) {
Text(stringResource(R.string.confirm))
}
},
dismissButton = {
TextButton(
onClick = onDismiss,
shape = RoundedCornerShape(8.dp)
) {
Text(stringResource(R.string.cancel))
}
},
shape = RoundedCornerShape(12.dp)
)
}
}

View File

@@ -0,0 +1,579 @@
package com.sukisu.ultra.ui.component
import android.annotation.SuppressLint
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Folder
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.filled.Storage
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.sukisu.ultra.R
import com.sukisu.ultra.ui.screen.extensions.AddKstatPathItemCard
import com.sukisu.ultra.ui.screen.extensions.EmptyStateCard
import com.sukisu.ultra.ui.screen.extensions.FeatureStatusCard
import com.sukisu.ultra.ui.screen.extensions.KstatConfigItemCard
import com.sukisu.ultra.ui.screen.extensions.PathItemCard
import com.sukisu.ultra.ui.screen.extensions.SusMountHidingControlCard
import com.sukisu.ultra.ui.util.SuSFSManager
/**
* SUS路径内容组件
*/
@Composable
fun SusPathsContent(
susPaths: Set<String>,
isLoading: Boolean,
onAddPath: () -> Unit,
onRemovePath: (String) -> Unit
) {
Box(modifier = Modifier.fillMaxSize()) {
LazyColumn(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
if (susPaths.isEmpty()) {
item {
EmptyStateCard(
message = stringResource(R.string.susfs_no_paths_configured)
)
}
} else {
items(susPaths.toList()) { path ->
PathItemCard(
path = path,
icon = Icons.Default.Folder,
onDelete = { onRemovePath(path) },
isLoading = isLoading
)
}
}
// 添加普通长按钮
item {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Button(
onClick = onAddPath,
modifier = Modifier
.weight(1f)
.height(48.dp),
shape = RoundedCornerShape(8.dp)
) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = null,
modifier = Modifier.size(24.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(R.string.susfs_add))
}
}
}
}
}
}
/**
* SUS挂载内容组件
*/
@Composable
fun SusMountsContent(
susMounts: Set<String>,
hideSusMountsForAllProcs: Boolean,
isSusVersion_1_5_8: Boolean,
isLoading: Boolean,
onAddMount: () -> Unit,
onRemoveMount: (String) -> Unit,
onToggleHideSusMountsForAllProcs: (Boolean) -> Unit
) {
Box(modifier = Modifier.fillMaxSize()) {
LazyColumn(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
if (isSusVersion_1_5_8) {
item {
SusMountHidingControlCard(
hideSusMountsForAllProcs = hideSusMountsForAllProcs,
isLoading = isLoading,
onToggleHiding = onToggleHideSusMountsForAllProcs
)
}
}
if (susMounts.isEmpty()) {
item {
EmptyStateCard(
message = stringResource(R.string.susfs_no_mounts_configured)
)
}
} else {
items(susMounts.toList()) { mount ->
PathItemCard(
path = mount,
icon = Icons.Default.Storage,
onDelete = { onRemoveMount(mount) },
isLoading = isLoading
)
}
}
// 添加普通长按钮
item {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Button(
onClick = onAddMount,
modifier = Modifier
.weight(1f)
.height(48.dp),
shape = RoundedCornerShape(8.dp)
) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = null,
modifier = Modifier.size(24.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(R.string.susfs_add))
}
}
}
}
}
}
/**
* 尝试卸载内容组件
*/
@Composable
fun TryUmountContent(
tryUmounts: Set<String>,
isLoading: Boolean,
onAddUmount: () -> Unit,
onRunUmount: () -> Unit,
onRemoveUmount: (String) -> Unit
) {
Box(modifier = Modifier.fillMaxSize()) {
LazyColumn(
modifier = Modifier
.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
if (tryUmounts.isEmpty()) {
item {
EmptyStateCard(
message = stringResource(R.string.susfs_no_umounts_configured)
)
}
} else {
items(tryUmounts.toList()) { umountEntry ->
val parts = umountEntry.split("|")
val path = if (parts.isNotEmpty()) parts[0] else umountEntry
val mode = if (parts.size > 1) parts[1] else "0"
val modeText = if (mode == "0")
stringResource(R.string.susfs_umount_mode_normal_short)
else
stringResource(R.string.susfs_umount_mode_detach_short)
PathItemCard(
path = path,
icon = Icons.Default.Storage,
additionalInfo = stringResource(R.string.susfs_umount_mode_display, modeText, mode),
onDelete = { onRemoveUmount(umountEntry) },
isLoading = isLoading
)
}
}
// 添加普通长按钮
item {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Button(
onClick = onAddUmount,
modifier = Modifier
.weight(1f)
.height(48.dp),
shape = RoundedCornerShape(8.dp)
) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = null,
modifier = Modifier.size(24.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(R.string.susfs_add))
}
if (tryUmounts.isNotEmpty()) {
Button(
onClick = onRunUmount,
modifier = Modifier
.weight(1f)
.height(48.dp),
shape = RoundedCornerShape(8.dp)
) {
Icon(
imageVector = Icons.Default.PlayArrow,
contentDescription = null,
modifier = Modifier.size(24.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(R.string.susfs_run))
}
}
}
}
}
}
}
/**
* Kstat配置内容组件
*/
@Composable
fun KstatConfigContent(
kstatConfigs: Set<String>,
addKstatPaths: Set<String>,
isLoading: Boolean,
onAddKstatStatically: () -> Unit,
onAddKstat: () -> Unit,
onRemoveKstatConfig: (String) -> Unit,
onRemoveAddKstat: (String) -> Unit,
onUpdateKstat: (String) -> Unit,
onUpdateKstatFullClone: (String) -> Unit
) {
Box(modifier = Modifier.fillMaxSize()) {
LazyColumn(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
// 说明卡片
item {
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f)
),
shape = RoundedCornerShape(12.dp)
) {
Column(
modifier = Modifier.padding(12.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Text(
text = stringResource(R.string.kstat_config_description_title),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.primary
)
Text(
text = stringResource(R.string.kstat_config_description_add_statically),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = stringResource(R.string.kstat_config_description_add),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = stringResource(R.string.kstat_config_description_update),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = stringResource(R.string.kstat_config_description_update_full_clone),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
}
// 静态Kstat配置列表
if (kstatConfigs.isNotEmpty()) {
item {
Text(
text = stringResource(R.string.static_kstat_config),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold
)
}
items(kstatConfigs.toList()) { config ->
KstatConfigItemCard(
config = config,
onDelete = { onRemoveKstatConfig(config) },
isLoading = isLoading
)
}
}
// Add Kstat路径列表
if (addKstatPaths.isNotEmpty()) {
item {
Text(
text = stringResource(R.string.kstat_path_management),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold
)
}
items(addKstatPaths.toList()) { path ->
AddKstatPathItemCard(
path = path,
onDelete = { onRemoveAddKstat(path) },
onUpdate = { onUpdateKstat(path) },
onUpdateFullClone = { onUpdateKstatFullClone(path) },
isLoading = isLoading
)
}
}
// 空状态显示
if (kstatConfigs.isEmpty() && addKstatPaths.isEmpty()) {
item {
EmptyStateCard(
message = stringResource(R.string.no_kstat_config_message)
)
}
}
// 添加普通长按钮
item {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Button(
onClick = onAddKstat,
modifier = Modifier
.weight(1f)
.height(48.dp),
shape = RoundedCornerShape(8.dp)
) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = null,
modifier = Modifier.size(24.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(R.string.susfs_add))
}
Button(
onClick = onAddKstatStatically,
modifier = Modifier
.weight(1f)
.height(48.dp),
shape = RoundedCornerShape(8.dp)
) {
Icon(
imageVector = Icons.Default.Settings,
contentDescription = null,
modifier = Modifier.size(24.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(R.string.susfs_add))
}
}
}
}
}
}
/**
* 路径设置内容组件
*/
@SuppressLint("SdCardPath")
@Composable
fun PathSettingsContent(
androidDataPath: String,
onAndroidDataPathChange: (String) -> Unit,
sdcardPath: String,
onSdcardPathChange: (String) -> Unit,
isLoading: Boolean,
onSetAndroidDataPath: () -> Unit,
onSetSdcardPath: () -> Unit
) {
LazyColumn(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
// Android Data路径设置
item {
Card(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(12.dp)
) {
Column(
modifier = Modifier.padding(12.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
OutlinedTextField(
value = androidDataPath,
onValueChange = onAndroidDataPathChange,
label = { Text(stringResource(R.string.susfs_android_data_path_label)) },
placeholder = { Text("/sdcard/Android/data") },
modifier = Modifier.fillMaxWidth(),
enabled = !isLoading,
singleLine = true,
shape = RoundedCornerShape(8.dp)
)
Button(
onClick = onSetAndroidDataPath,
enabled = !isLoading && androidDataPath.isNotBlank(),
modifier = Modifier
.fillMaxWidth()
.height(40.dp),
shape = RoundedCornerShape(8.dp)
) {
Text(stringResource(R.string.susfs_set_android_data_path))
}
}
}
}
// SD卡路径设置
item {
Card(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(12.dp)
) {
Column(
modifier = Modifier.padding(12.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
OutlinedTextField(
value = sdcardPath,
onValueChange = onSdcardPathChange,
label = { Text(stringResource(R.string.susfs_sdcard_path_label)) },
placeholder = { Text("/sdcard") },
modifier = Modifier.fillMaxWidth(),
enabled = !isLoading,
singleLine = true,
shape = RoundedCornerShape(8.dp)
)
Button(
onClick = onSetSdcardPath,
enabled = !isLoading && sdcardPath.isNotBlank(),
modifier = Modifier
.fillMaxWidth()
.height(40.dp),
shape = RoundedCornerShape(8.dp)
) {
Text(stringResource(R.string.susfs_set_sdcard_path))
}
}
}
}
}
}
/**
* 启用功能状态内容组件
*/
@Composable
fun EnabledFeaturesContent(
enabledFeatures: List<SuSFSManager.EnabledFeature>,
onRefresh: () -> Unit
) {
LazyColumn(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
// 说明卡片
item {
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f)
),
shape = RoundedCornerShape(12.dp)
) {
Column(
modifier = Modifier.padding(12.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = Icons.Default.Settings,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(18.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = stringResource(R.string.susfs_enabled_features_description),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
}
}
if (enabledFeatures.isEmpty()) {
item {
EmptyStateCard(
message = stringResource(R.string.susfs_no_features_found)
)
}
} else {
items(enabledFeatures) { feature ->
FeatureStatusCard(
feature = feature,
onRefresh = onRefresh
)
}
}
}
}

View File

@@ -1,101 +0,0 @@
package com.sukisu.ultra.ui.component
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Switch
import androidx.compose.material3.SwitchDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
@Composable
fun SwitchItem(
icon: ImageVector,
title: String,
summary: String? = null,
checked: Boolean,
enabled: Boolean = true,
onCheckedChange: (Boolean) -> Unit
) {
// 颜色动画
val iconTint by animateColorAsState(
targetValue = if (checked) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f),
animationSpec = tween(300),
label = "iconTint"
)
// 开关颜色
val switchColors = SwitchDefaults.colors(
checkedThumbColor = MaterialTheme.colorScheme.primary,
checkedTrackColor = MaterialTheme.colorScheme.primaryContainer,
checkedBorderColor = MaterialTheme.colorScheme.primary,
checkedIconColor = MaterialTheme.colorScheme.onPrimary,
uncheckedThumbColor = MaterialTheme.colorScheme.outline,
uncheckedTrackColor = MaterialTheme.colorScheme.surfaceVariant,
uncheckedBorderColor = MaterialTheme.colorScheme.outline,
uncheckedIconColor = MaterialTheme.colorScheme.surfaceVariant,
disabledCheckedThumbColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f),
disabledCheckedTrackColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f),
disabledCheckedBorderColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f),
disabledCheckedIconColor = MaterialTheme.colorScheme.surfaceVariant,
disabledUncheckedThumbColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f),
disabledUncheckedTrackColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f),
disabledUncheckedBorderColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f),
disabledUncheckedIconColor = MaterialTheme.colorScheme.surfaceVariant
)
ListItem(
headlineContent = {
Text(
text = title,
style = MaterialTheme.typography.titleMedium,
maxLines = Int.MAX_VALUE,
overflow = TextOverflow.Ellipsis
)
},
supportingContent = summary?.let {
{
Text(
text = it,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = Int.MAX_VALUE,
overflow = TextOverflow.Ellipsis
)
}
},
leadingContent = {
Icon(
imageVector = icon,
contentDescription = null,
modifier = Modifier.size(24.dp),
tint = iconTint
)
},
trailingContent = {
Switch(
checked = checked,
onCheckedChange = null,
enabled = enabled,
colors = switchColors
)
},
modifier = Modifier
.fillMaxWidth()
.clickable(enabled = enabled) {
onCheckedChange(!checked)
}
.padding(vertical = 4.dp)
)
}

View File

@@ -0,0 +1,277 @@
package com.sukisu.ultra.ui.component
import androidx.compose.animation.*
import androidx.compose.animation.core.*
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.Dp
import com.sukisu.ultra.R
// 菜单项数据类
data class FabMenuItem(
val icon: ImageVector,
val labelRes: Int,
val color: Color = Color.Unspecified,
val onClick: () -> Unit
)
// 动画配置
object FabAnimationConfig {
const val ANIMATION_DURATION = 300
const val STAGGER_DELAY = 50
val BUTTON_SPACING = 72.dp
val BUTTON_SIZE = 56.dp
val SMALL_BUTTON_SIZE = 48.dp
}
@Composable
fun VerticalExpandableFab(
menuItems: List<FabMenuItem>,
modifier: Modifier = Modifier,
buttonSize: Dp = FabAnimationConfig.BUTTON_SIZE,
smallButtonSize: Dp = FabAnimationConfig.SMALL_BUTTON_SIZE,
buttonSpacing: Dp = FabAnimationConfig.BUTTON_SPACING,
animationDurationMs: Int = FabAnimationConfig.ANIMATION_DURATION,
staggerDelayMs: Int = FabAnimationConfig.STAGGER_DELAY,
mainButtonIcon: ImageVector = Icons.Filled.Add,
mainButtonExpandedIcon: ImageVector = Icons.Filled.Close,
onMainButtonClick: (() -> Unit)? = null,
) {
var isExpanded by remember { mutableStateOf(false) }
// 主按钮旋转动画
val rotationAngle by animateFloatAsState(
targetValue = if (isExpanded) 45f else 0f,
animationSpec = tween(
durationMillis = animationDurationMs,
easing = FastOutSlowInEasing
),
label = "mainButtonRotation"
)
// 主按钮缩放动画
val mainButtonScale by animateFloatAsState(
targetValue = if (isExpanded) 1.1f else 1f,
animationSpec = tween(
durationMillis = animationDurationMs,
easing = FastOutSlowInEasing
),
label = "mainButtonScale"
)
Box(
modifier = modifier.wrapContentSize(),
contentAlignment = Alignment.BottomEnd
) {
// 子菜单按钮
menuItems.forEachIndexed { index, menuItem ->
val animatedOffsetY by animateFloatAsState(
targetValue = if (isExpanded) {
-(buttonSpacing.value * (index + 1))
} else {
0f
},
animationSpec = tween(
durationMillis = animationDurationMs,
delayMillis = if (isExpanded) {
index * staggerDelayMs
} else {
(menuItems.size - index - 1) * staggerDelayMs
},
easing = FastOutSlowInEasing
),
label = "fabOffset$index"
)
val animatedScale by animateFloatAsState(
targetValue = if (isExpanded) 1f else 0f,
animationSpec = tween(
durationMillis = animationDurationMs,
delayMillis = if (isExpanded) {
index * staggerDelayMs + 100
} else {
(menuItems.size - index - 1) * staggerDelayMs
},
easing = FastOutSlowInEasing
),
label = "fabScale$index"
)
val animatedAlpha by animateFloatAsState(
targetValue = if (isExpanded) 1f else 0f,
animationSpec = tween(
durationMillis = animationDurationMs,
delayMillis = if (isExpanded) {
index * staggerDelayMs + 150
} else {
(menuItems.size - index - 1) * staggerDelayMs
},
easing = FastOutSlowInEasing
),
label = "fabAlpha$index"
)
// 子按钮容器(包含标签)
Row(
modifier = Modifier
.offset(y = animatedOffsetY.dp)
.scale(animatedScale)
.alpha(animatedAlpha),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.End
) {
// 标签
AnimatedVisibility(
visible = isExpanded && animatedScale > 0.5f,
enter = slideInHorizontally(
initialOffsetX = { it / 2 },
animationSpec = tween(200)
) + fadeIn(animationSpec = tween(200)),
exit = slideOutHorizontally(
targetOffsetX = { it / 2 },
animationSpec = tween(150)
) + fadeOut(animationSpec = tween(150))
) {
Surface(
modifier = Modifier.padding(end = 16.dp),
shape = MaterialTheme.shapes.small,
color = MaterialTheme.colorScheme.inverseSurface,
tonalElevation = 6.dp
) {
Text(
text = stringResource(menuItem.labelRes),
modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.inverseOnSurface
)
}
}
// 子按钮
SmallFloatingActionButton(
onClick = {
menuItem.onClick()
isExpanded = false
},
modifier = Modifier.size(smallButtonSize),
containerColor = if (menuItem.color != Color.Unspecified) {
menuItem.color
} else {
MaterialTheme.colorScheme.secondary
},
contentColor = if (menuItem.color != Color.Unspecified) {
if (menuItem.color == Color.Gray) Color.White
else MaterialTheme.colorScheme.onSecondary
} else {
MaterialTheme.colorScheme.onSecondary
},
elevation = FloatingActionButtonDefaults.elevation(
defaultElevation = 4.dp,
pressedElevation = 6.dp
)
) {
Icon(
imageVector = menuItem.icon,
contentDescription = stringResource(menuItem.labelRes),
modifier = Modifier.size(20.dp)
)
}
}
}
// 主按钮
FloatingActionButton(
onClick = {
onMainButtonClick?.invoke()
isExpanded = !isExpanded
},
modifier = Modifier
.size(buttonSize)
.scale(mainButtonScale),
elevation = FloatingActionButtonDefaults.elevation(
defaultElevation = 6.dp,
pressedElevation = 8.dp,
hoveredElevation = 8.dp
)
) {
Icon(
imageVector = if (isExpanded) mainButtonExpandedIcon else mainButtonIcon,
contentDescription = stringResource(
if (isExpanded) R.string.collapse_menu else R.string.expand_menu
),
modifier = Modifier
.size(24.dp)
.rotate(if (mainButtonIcon == Icons.Filled.Add) rotationAngle else 0f)
)
}
}
}
// 预设菜单项
object FabMenuPresets {
fun getScrollMenuItems(
onScrollToTop: () -> Unit,
onScrollToBottom: () -> Unit
) = listOf(
FabMenuItem(
icon = Icons.Filled.KeyboardArrowDown,
labelRes = R.string.scroll_to_bottom,
onClick = onScrollToBottom
),
FabMenuItem(
icon = Icons.Filled.KeyboardArrowUp,
labelRes = R.string.scroll_to_top,
onClick = onScrollToTop
)
)
@Composable
fun getBatchActionMenuItems(
onCancel: () -> Unit,
onDeny: () -> Unit,
onAllow: () -> Unit,
onUnmountModules: () -> Unit,
onDisableUnmount: () -> Unit
) = listOf(
FabMenuItem(
icon = Icons.Filled.Close,
labelRes = R.string.cancel,
color = Color.Gray,
onClick = onCancel
),
FabMenuItem(
icon = Icons.Filled.Block,
labelRes = R.string.deny_authorization,
color = MaterialTheme.colorScheme.error,
onClick = onDeny
),
FabMenuItem(
icon = Icons.Filled.Check,
labelRes = R.string.grant_authorization,
color = MaterialTheme.colorScheme.primary,
onClick = onAllow
),
FabMenuItem(
icon = Icons.Filled.FolderOff,
labelRes = R.string.unmount_modules,
onClick = onUnmountModules
),
FabMenuItem(
icon = Icons.Filled.Folder,
labelRes = R.string.disable_unmount,
onClick = onDisableUnmount
)
)
}

View File

@@ -31,7 +31,6 @@ fun AppProfileConfig(
onValueChange = { onProfileChange(profile.copy(name = it)) }
)
}
SwitchItem(
title = stringResource(R.string.profile_umount_modules),
summary = stringResource(R.string.profile_umount_modules_summary),

View File

@@ -24,6 +24,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
@@ -47,6 +48,8 @@ import com.sukisu.ultra.R
import com.sukisu.ultra.profile.Capabilities
import com.sukisu.ultra.profile.Groups
import com.sukisu.ultra.ui.component.rememberCustomDialog
import com.sukisu.ultra.ui.theme.CardConfig
import com.sukisu.ultra.ui.theme.CardConfig.cardAlpha
import com.sukisu.ultra.ui.util.isSepolicyValid
@OptIn(ExperimentalMaterial3Api::class)
@@ -206,11 +209,10 @@ fun GroupsPanel(selected: List<Groups>, closeSelection: (selection: Set<Groups>)
}
val selection = HashSet(selected)
val backgroundColor = MaterialTheme.colorScheme.surfaceContainerHighest
MaterialTheme(
colorScheme = MaterialTheme.colorScheme.copy(
surface = backgroundColor
surface = MaterialTheme.colorScheme.surfaceContainerHigh
)
) {
ListDialog(
@@ -286,11 +288,10 @@ fun CapsPanel(
}
val selection = HashSet(selected)
val backgroundColor = MaterialTheme.colorScheme.surfaceContainerHighest
MaterialTheme(
colorScheme = MaterialTheme.colorScheme.copy(
surface = backgroundColor
surface = MaterialTheme.colorScheme.surfaceContainerHigh
)
) {
ListDialog(
@@ -441,11 +442,10 @@ private fun SELinuxPanel(
)
)
val backgroundColor = MaterialTheme.colorScheme.surfaceContainerHighest
MaterialTheme(
colorScheme = MaterialTheme.colorScheme.copy(
surface = backgroundColor
surface = MaterialTheme.colorScheme.surfaceContainerHigh
)
) {
InputDialog(

View File

@@ -37,7 +37,6 @@ import androidx.compose.material3.FilterChip
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
@@ -60,6 +59,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext
@@ -84,6 +84,9 @@ import com.sukisu.ultra.ui.component.profile.AppProfileConfig
import com.sukisu.ultra.ui.component.profile.RootProfileConfig
import com.sukisu.ultra.ui.component.profile.TemplateConfig
import com.sukisu.ultra.ui.theme.CardConfig
import com.sukisu.ultra.ui.theme.CardConfig.cardAlpha
import com.sukisu.ultra.ui.theme.getCardColors
import com.sukisu.ultra.ui.theme.getCardElevation
import com.sukisu.ultra.ui.util.LocalSnackbarHost
import com.sukisu.ultra.ui.util.forceStopApp
import com.sukisu.ultra.ui.util.getSepolicy
@@ -122,7 +125,12 @@ fun AppProfileScreen(
mutableStateOf(initialProfile)
}
val cardColor = MaterialTheme.colorScheme.surfaceContainerLow
val colorScheme = MaterialTheme.colorScheme
val cardColor = if (CardConfig.isCustomBackgroundEnabled) {
colorScheme.surfaceContainerLow
} else {
colorScheme.background
}
val cardAlpha = CardConfig.cardAlpha
Scaffold(
@@ -203,149 +211,173 @@ private fun AppProfileInner(
onProfileChange: (Natives.Profile) -> Unit,
) {
val isRootGranted = profile.allowSu
val cardColors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh)
Column(modifier = modifier) {
ElevatedCard(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium
) {
AppMenuBox(packageName) {
ListItem(
headlineContent = {
Text(
text = appLabel,
style = MaterialTheme.typography.titleMedium
)
},
supportingContent = {
Text(
text = packageName,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
},
leadingContent = appIcon,
MaterialTheme(
colorScheme = MaterialTheme.colorScheme.copy(
surface = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else MaterialTheme.colorScheme.surfaceContainerHigh
)
) {
Column(modifier = modifier) {
ElevatedCard(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium,
colors = cardColors,
elevation = getCardElevation(),
) {
AppMenuBox(packageName) {
ListItem(
headlineContent = {
Text(
text = appLabel,
style = MaterialTheme.typography.titleMedium
)
},
supportingContent = {
Text(
text = packageName,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
},
leadingContent = appIcon,
)
}
}
ElevatedCard(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium,
colors = cardColors,
elevation = getCardElevation(),
) {
SwitchItem(
icon = Icons.Filled.Security,
title = stringResource(id = R.string.superuser),
checked = isRootGranted,
onCheckedChange = { onProfileChange(profile.copy(allowSu = it)) },
)
}
}
ElevatedCard(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium
) {
SwitchItem(
icon = Icons.Filled.Security,
title = stringResource(id = R.string.superuser),
checked = isRootGranted,
onCheckedChange = { onProfileChange(profile.copy(allowSu = it)) },
)
}
Crossfade(
targetState = isRootGranted,
label = "RootAccess"
) { current ->
Column(
modifier = Modifier.padding(bottom = 6.dp + 48.dp + 6.dp /* SnackBar height */)
) {
if (current) {
val initialMode = if (profile.rootUseDefault) {
Mode.Default
} else if (profile.rootTemplate != null) {
Mode.Template
} else {
Mode.Custom
}
var mode by rememberSaveable {
mutableStateOf(initialMode)
}
ElevatedCard(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium
) {
ProfileBox(mode, true) {
// template mode shouldn't change profile here!
if (it == Mode.Default || it == Mode.Custom) {
onProfileChange(profile.copy(rootUseDefault = it == Mode.Default))
}
mode = it
Crossfade(
targetState = isRootGranted,
label = "RootAccess"
) { current ->
Column(
modifier = Modifier.padding(bottom = 6.dp + 48.dp + 6.dp /* SnackBar height */)
) {
if (current) {
val initialMode = if (profile.rootUseDefault) {
Mode.Default
} else if (profile.rootTemplate != null) {
Mode.Template
} else {
Mode.Custom
}
var mode by rememberSaveable {
mutableStateOf(initialMode)
}
}
AnimatedVisibility(
visible = mode != Mode.Default,
enter = fadeIn() + expandVertically(),
exit = fadeOut() + shrinkVertically()
) {
ElevatedCard(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium
shape = MaterialTheme.shapes.medium,
colors = cardColors,
elevation = getCardElevation(),
) {
Column(modifier = Modifier.padding(vertical = 8.dp)) {
Crossfade(targetState = mode, label = "ProfileMode") { currentMode ->
when (currentMode) {
Mode.Template -> {
TemplateConfig(
profile = profile,
onViewTemplate = onViewTemplate,
onManageTemplate = onManageTemplate,
onProfileChange = onProfileChange
)
ProfileBox(mode, true) {
// template mode shouldn't change profile here!
if (it == Mode.Default || it == Mode.Custom) {
onProfileChange(profile.copy(rootUseDefault = it == Mode.Default))
}
mode = it
}
}
AnimatedVisibility(
visible = mode != Mode.Default,
enter = fadeIn() + expandVertically(),
exit = fadeOut() + shrinkVertically()
) {
ElevatedCard(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium,
colors = cardColors,
elevation = getCardElevation(),
) {
Column(modifier = Modifier.padding(vertical = 8.dp)) {
Crossfade(
targetState = mode,
label = "ProfileMode"
) { currentMode ->
when (currentMode) {
Mode.Template -> {
TemplateConfig(
profile = profile,
onViewTemplate = onViewTemplate,
onManageTemplate = onManageTemplate,
onProfileChange = onProfileChange
)
}
Mode.Custom -> {
RootProfileConfig(
fixedName = true,
profile = profile,
onProfileChange = onProfileChange
)
}
else -> {}
}
Mode.Custom -> {
RootProfileConfig(
fixedName = true,
profile = profile,
onProfileChange = onProfileChange
)
}
else -> {}
}
}
}
}
}
} else {
val mode = if (profile.nonRootUseDefault) Mode.Default else Mode.Custom
} else {
val mode = if (profile.nonRootUseDefault) Mode.Default else Mode.Custom
ElevatedCard(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium
) {
ProfileBox(mode, false) {
onProfileChange(profile.copy(nonRootUseDefault = (it == Mode.Default)))
}
}
AnimatedVisibility(
visible = mode == Mode.Custom,
enter = fadeIn() + expandVertically(),
exit = fadeOut() + shrinkVertically()
) {
ElevatedCard(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium
shape = MaterialTheme.shapes.medium,
colors = cardColors,
elevation = getCardElevation(),
) {
Column(modifier = Modifier.padding(vertical = 8.dp)) {
AppProfileConfig(
fixedName = true,
profile = profile,
enabled = mode == Mode.Custom,
onProfileChange = onProfileChange
)
ProfileBox(mode, false) {
onProfileChange(profile.copy(nonRootUseDefault = (it == Mode.Default)))
}
}
AnimatedVisibility(
visible = mode == Mode.Custom,
enter = fadeIn() + expandVertically(),
exit = fadeOut() + shrinkVertically()
) {
ElevatedCard(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
shape = MaterialTheme.shapes.medium,
colors = cardColors,
elevation = getCardElevation(),
) {
Column(modifier = Modifier.padding(vertical = 8.dp)) {
AppProfileConfig(
fixedName = true,
profile = profile,
enabled = mode == Mode.Custom,
onProfileChange = onProfileChange
)
}
}
}
}
@@ -377,12 +409,10 @@ private fun TopBar(
Text(
text = title,
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurface
)
Text(
text = packageName,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.alpha(0.8f)
)
}
@@ -391,9 +421,6 @@ private fun TopBar(
navigationIcon = {
IconButton(
onClick = onBack,
colors = IconButtonDefaults.iconButtonColors(
contentColor = MaterialTheme.colorScheme.onSurface
)
) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
@@ -408,7 +435,6 @@ private fun TopBar(
modifier = Modifier.shadow(
elevation = if ((scrollBehavior?.state?.overlappedFraction ?: 0f) > 0.01f)
4.dp else 0.dp,
spotColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.1f)
)
)
}
@@ -431,7 +457,6 @@ private fun ProfileBox(
Text(
text = mode.text,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
},
leadingContent = {
@@ -444,7 +469,6 @@ private fun ProfileBox(
HorizontalDivider(
thickness = Dp.Hairline,
color = MaterialTheme.colorScheme.outlineVariant
)
ListItem(
@@ -574,20 +598,26 @@ private fun AppMenuOption(text: String, onClick: () -> Unit) {
@Composable
private fun AppProfilePreview() {
var profile by remember { mutableStateOf(Natives.Profile("")) }
Surface {
AppProfileInner(
packageName = "icu.nullptr.test",
appLabel = "Test",
appIcon = {
Icon(
imageVector = Icons.Filled.Android,
contentDescription = null,
)
},
profile = profile,
onProfileChange = {
profile = it
},
MaterialTheme(
colorScheme = MaterialTheme.colorScheme.copy(
surface = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else MaterialTheme.colorScheme.surfaceContainerHigh
)
) {
Surface {
AppProfileInner(
packageName = "icu.nullptr.test",
appLabel = "Test",
appIcon = {
Icon(
imageVector = Icons.Filled.Android,
contentDescription = null,
)
},
profile = profile,
onProfileChange = {
profile = it
},
)
}
}
}

View File

@@ -110,6 +110,8 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
var tempText: String
val logContent = rememberSaveable { StringBuilder() }
var showFloatAction by rememberSaveable { mutableStateOf(false) }
// 添加状态跟踪是否已经完成刷写
var hasFlashCompleted by rememberSaveable { mutableStateOf(false) }
val snackBarHost = LocalSnackbarHost.current
val scope = rememberCoroutineScope()
@@ -132,13 +134,19 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
totalModules = flashIt.uris.size,
currentModule = 1
)
hasFlashCompleted = false
} else if (flashIt !is FlashIt.FlashModules) {
hasFlashCompleted = false
}
}
LaunchedEffect(Unit) {
if (text.isNotEmpty()) {
// 只有在未完成刷写时才执行刷写操作
LaunchedEffect(flashIt, hasFlashCompleted) {
// 如果已经完成刷写或者已有文本内容,则不再执行
if (hasFlashCompleted || text.isNotEmpty()) {
return@LaunchedEffect
}
withContext(Dispatchers.IO) {
setFlashingStatus(FlashingStatus.FLASHING)
@@ -157,7 +165,7 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
}
}
flashIt(context, flashIt, onFinish = { showReboot, code ->
flashIt(flashIt, onFinish = { showReboot, code ->
if (code != 0) {
text += "$errorCodeString $code.\n$checkLogString\n"
setFlashingStatus(FlashingStatus.FAILED)
@@ -176,6 +184,8 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
showFloatAction = true
}
hasFlashCompleted = true
if (flashIt is FlashIt.FlashModules && flashIt.currentIndex < flashIt.uris.size - 1) {
val nextFlashIt = flashIt.copy(
currentIndex = flashIt.currentIndex + 1
@@ -187,7 +197,7 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
}
}, onStdout = {
tempText = "$it\n"
if (tempText.startsWith("[H[J")) { // clear command
if (tempText.startsWith("")) { // clear command
text = tempText.substring(6)
} else {
text += tempText
@@ -201,13 +211,14 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
val onBack: () -> Unit = {
if (currentFlashingStatus.value != FlashingStatus.FLASHING) {
if (flashIt is FlashIt.FlashBoot) {
navigator.popBackStack()
if (flashIt is FlashIt.FlashModules) {
viewModel.markNeedRefresh()
viewModel.fetchModuleList()
navigator.navigate(ModuleScreenDestination)
} else {
viewModel.markNeedRefresh()
viewModel.fetchModuleList()
navigator.navigate(ModuleScreenDestination) {
}
navigator.popBackStack()
}
}
}
@@ -221,8 +232,6 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
TopBar(
currentFlashingStatus.value,
currentStatus,
navigator = navigator,
flashIt = flashIt,
onBack = onBack,
onSave = {
scope.launch {
@@ -433,13 +442,16 @@ fun ModuleInstallProgressBar(
private fun TopBar(
status: FlashingStatus,
moduleStatus: ModuleInstallStatus = ModuleInstallStatus(),
navigator: DestinationsNavigator,
flashIt: FlashIt,
onBack: () -> Unit,
onSave: () -> Unit = {},
scrollBehavior: TopAppBarScrollBehavior? = null
) {
val cardColor = MaterialTheme.colorScheme.surfaceContainerLow
val colorScheme = MaterialTheme.colorScheme
val cardColor = if (CardConfig.isCustomBackgroundEnabled) {
colorScheme.surfaceContainerLow
} else {
colorScheme.background
}
val cardAlpha = CardConfig.cardAlpha
val statusColor = when(status) {
@@ -525,7 +537,6 @@ sealed class FlashIt : Parcelable {
}
fun flashIt(
context: android.content.Context,
flashIt: FlashIt,
onFinish: (Boolean, Int) -> Unit,
onStdout: (String) -> Unit,

View File

@@ -29,21 +29,12 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Android
import androidx.compose.material.icons.filled.Archive
import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.Memory
import androidx.compose.material.icons.filled.PhoneAndroid
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material.icons.filled.Security
import androidx.compose.material.icons.filled.SettingsSuggest
import androidx.compose.material.icons.filled.Storage
import androidx.compose.material.icons.filled.*
import androidx.compose.material.icons.outlined.Block
import androidx.compose.material.icons.outlined.TaskAlt
import androidx.compose.material.icons.outlined.Warning
@@ -63,7 +54,6 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@@ -75,12 +65,8 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource
@@ -91,6 +77,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.generated.destinations.InstallScreenDestination
import com.ramcosta.composedestinations.generated.destinations.SuSFSConfigScreenDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.sukisu.ultra.KernelVersion
import com.sukisu.ultra.Natives
@@ -98,15 +85,15 @@ import com.sukisu.ultra.R
import com.sukisu.ultra.ui.component.KsuIsValid
import com.sukisu.ultra.ui.component.rememberConfirmDialog
import com.sukisu.ultra.ui.theme.CardConfig
import com.sukisu.ultra.ui.theme.CardConfig.cardAlpha
import com.sukisu.ultra.ui.theme.CardConfig.cardElevation
import com.sukisu.ultra.ui.theme.getCardColors
import com.sukisu.ultra.ui.theme.getCardElevation
import com.sukisu.ultra.ui.util.checkNewVersion
import com.sukisu.ultra.ui.util.getKpmModuleCount
import com.sukisu.ultra.ui.util.getKpmVersion
import com.sukisu.ultra.ui.util.getModuleCount
import com.sukisu.ultra.ui.util.getSuperuserCount
import com.sukisu.ultra.ui.util.module.LatestVersionInfo
import com.sukisu.ultra.ui.util.reboot
import com.sukisu.ultra.ui.util.getSuSFS
import com.sukisu.ultra.ui.util.SuSFSManager
import com.sukisu.ultra.ui.viewmodel.HomeViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -143,9 +130,8 @@ fun HomeScreen(navigator: DestinationsNavigator) {
Scaffold(
topBar = {
TopBar(
kernelVersion = viewModel.systemStatus.kernelVersion,
onInstallClick = { navigator.navigate(InstallScreenDestination) },
scrollBehavior = scrollBehavior
scrollBehavior = scrollBehavior,
navigator = navigator
)
},
contentWindowInsets = WindowInsets.safeDrawing.only(
@@ -205,8 +191,6 @@ fun HomeScreen(navigator: DestinationsNavigator) {
InfoCard(
systemInfo = viewModel.systemInfo,
isSimpleMode = viewModel.isSimpleMode,
isHideVersion = viewModel.isHideVersion,
isHideOtherInfo = viewModel.isHideOtherInfo,
isHideSusfsStatus = viewModel.isHideSusfsStatus,
showKpmInfo = viewModel.showKpmInfo,
lkmMode = viewModel.systemStatus.lkmMode,
@@ -257,7 +241,7 @@ fun UpdateCard() {
val updateDialog = rememberConfirmDialog(onConfirm = { uriHandler.openUri(newVersionUrl) })
WarningCard(
message = stringResource(id = R.string.new_version_available).format(newVersionCode),
color = MaterialTheme.colorScheme.surfaceVariant,
color = MaterialTheme.colorScheme.outlineVariant,
onClick = {
if (changelog.isEmpty()) {
uriHandler.openUri(newVersionUrl)
@@ -277,26 +261,23 @@ fun UpdateCard() {
@Composable
fun RebootDropdownItem(@StringRes id: Int, reason: String = "") {
DropdownMenuItem(
text = { Text(stringResource(id)) },
onClick = { reboot(reason) },
leadingIcon = {
Icon(
imageVector = Icons.Filled.Refresh,
contentDescription = null,
)
}
)
text = {Text(stringResource(id))},
onClick = {reboot(reason)})
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun TopBar(
kernelVersion: KernelVersion,
onInstallClick: () -> Unit,
scrollBehavior: TopAppBarScrollBehavior? = null
scrollBehavior: TopAppBarScrollBehavior? = null,
navigator: DestinationsNavigator
) {
val cardColor = MaterialTheme.colorScheme.surfaceContainerLow
val cardAlpha = CardConfig.cardAlpha
val context = LocalContext.current
val colorScheme = MaterialTheme.colorScheme
val cardColor = if (CardConfig.isCustomBackgroundEnabled) {
colorScheme.surfaceContainerLow
} else {
colorScheme.background
}
TopAppBar(
title = {
@@ -310,13 +291,26 @@ private fun TopBar(
scrolledContainerColor = cardColor.copy(alpha = cardAlpha)
),
actions = {
// SuSFS 配置按钮
if (getSuSFS() == "Supported" && SuSFSManager.isBinaryAvailable(context)) {
IconButton(onClick = {
navigator.navigate(SuSFSConfigScreenDestination)
}) {
Icon(
imageVector = Icons.Filled.Tune,
contentDescription = stringResource(R.string.susfs_config_setting_title)
)
}
}
// 重启按钮
var showDropdown by remember { mutableStateOf(false) }
KsuIsValid {
IconButton(onClick = {
showDropdown = true
}) {
Icon(
imageVector = Icons.Filled.Refresh,
imageVector = Icons.Filled.PowerSettingsNew,
contentDescription = stringResource(id = R.string.reboot)
)
@@ -349,16 +343,9 @@ private fun StatusCard(
onClickInstall: () -> Unit = {}
) {
ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.secondaryContainer),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation),
modifier = Modifier
.fillMaxWidth()
.clip(MaterialTheme.shapes.large)
.shadow(
elevation = cardElevation,
shape = MaterialTheme.shapes.large,
spotColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.1f)
)
colors = getCardColors( if (systemStatus.ksuVersion != null)MaterialTheme.colorScheme.secondaryContainer
else MaterialTheme.colorScheme.errorContainer),
elevation = getCardElevation(),
) {
Row(
modifier = Modifier
@@ -375,9 +362,14 @@ private fun StatusCard(
systemStatus.ksuVersion != null -> {
val workingModeText = when {
Natives.isSafeMode == true -> stringResource(id = R.string.safe_mode)
else -> stringResource(id = R.string.home_working)
}
val workingModeSurfaceText = when {
systemStatus.lkmMode == true -> "LKM"
systemStatus.lkmMode == null && systemStatus.kernelVersion.isGKI1() -> "GKI-1.0"
systemStatus.lkmMode == false || systemStatus.kernelVersion.isGKI() -> "GKI-2.0"
systemStatus.lkmMode == null && systemStatus.kernelVersion.isGKI1() -> "GKI 1.0"
systemStatus.lkmMode == false || systemStatus.kernelVersion.isGKI() -> "GKI 2.0"
else -> "N-GKI"
}
@@ -385,7 +377,11 @@ private fun StatusCard(
Icons.Outlined.TaskAlt,
contentDescription = stringResource(R.string.home_working),
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(24.dp)
modifier = Modifier
.size(28.dp)
.padding(
horizontal = 4.dp
),
)
Column(Modifier.padding(start = 20.dp)) {
@@ -394,9 +390,9 @@ private fun StatusCard(
modifier = Modifier.fillMaxWidth()
) {
Text(
text = stringResource(id = R.string.home_working),
text = workingModeText,
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurface
color = MaterialTheme.colorScheme.primary,
)
Spacer(Modifier.width(8.dp))
@@ -408,79 +404,46 @@ private fun StatusCard(
modifier = Modifier
) {
Text(
text = workingModeText,
text = workingModeSurfaceText,
style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.onSecondary,
modifier = Modifier.padding(horizontal = 6.dp, vertical = 2.dp)
modifier = Modifier.padding(horizontal = 6.dp, vertical = 2.dp),
color = MaterialTheme.colorScheme.onPrimary
)
}
Spacer(Modifier.width(6.dp))
// 机器架构标签或者安全模式标签
val labelText = if (Natives.isSafeMode) {
stringResource(id = R.string.safe_mode)
} else {
Os.uname().machine
}
Surface(
shape = RoundedCornerShape(4.dp),
color = MaterialTheme.colorScheme.primary,
modifier = Modifier
) {
Text(
text = labelText,
style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.onSecondary,
modifier = Modifier.padding(horizontal = 6.dp, vertical = 2.dp)
)
// 架构标签
if (Os.uname().machine != "aarch64") {
Surface(
shape = RoundedCornerShape(4.dp),
color = MaterialTheme.colorScheme.primary,
modifier = Modifier
) {
Text(
text = Os.uname().machine,
style = MaterialTheme.typography.labelMedium,
modifier = Modifier.padding(
horizontal = 6.dp,
vertical = 2.dp
),
color = MaterialTheme.colorScheme.onPrimary
)
}
}
}
val isHideVersion = LocalContext.current.getSharedPreferences("settings", Context.MODE_PRIVATE)
.getBoolean("is_hide_version", false)
val isHideOtherInfo = LocalContext.current.getSharedPreferences("settings", Context.MODE_PRIVATE)
.getBoolean("is_hide_other_info", false)
val showKpmInfo = LocalContext.current.getSharedPreferences("settings", Context.MODE_PRIVATE)
.getBoolean("show_kpm_info", true)
if (!isHideVersion) {
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_working_version, systemStatus.ksuVersion),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
color = MaterialTheme.colorScheme.secondary,
)
}
if (!isHideOtherInfo) {
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_superuser_count, getSuperuserCount()),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_module_count, getModuleCount()),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
val kpmVersion = getKpmVersion()
if (kpmVersion.isNotEmpty() && !kpmVersion.startsWith("Error") && showKpmInfo && Natives.version >= Natives.MINIMAL_SUPPORTED_KPM) {
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_kpm_module, getKpmModuleCount()),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
}
}
@@ -489,7 +452,11 @@ private fun StatusCard(
Icons.Outlined.Warning,
contentDescription = stringResource(R.string.home_not_installed),
tint = MaterialTheme.colorScheme.error,
modifier = Modifier.size(24.dp)
modifier = Modifier
.size(28.dp)
.padding(
horizontal = 4.dp
),
)
Column(Modifier.padding(start = 20.dp)) {
@@ -503,7 +470,7 @@ private fun StatusCard(
Text(
text = stringResource(R.string.home_click_to_install),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
color = MaterialTheme.colorScheme.onErrorContainer
)
}
}
@@ -513,7 +480,11 @@ private fun StatusCard(
Icons.Outlined.Block,
contentDescription = stringResource(R.string.home_unsupported),
tint = MaterialTheme.colorScheme.error,
modifier = Modifier.size(24.dp)
modifier = Modifier
.size(28.dp)
.padding(
horizontal = 4.dp
),
)
Column(Modifier.padding(start = 20.dp)) {
@@ -527,7 +498,7 @@ private fun StatusCard(
Text(
text = stringResource(R.string.home_unsupported_reason),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
color = MaterialTheme.colorScheme.onErrorContainer
)
}
}
@@ -544,14 +515,7 @@ fun WarningCard(
) {
ElevatedCard(
colors = getCardColors(color),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation),
modifier = Modifier
.fillMaxWidth()
.clip(MaterialTheme.shapes.large)
.shadow(
elevation = cardElevation,
shape = MaterialTheme.shapes.large,
)
elevation = getCardElevation(),
) {
Row(
modifier = Modifier
@@ -563,7 +527,6 @@ fun WarningCard(
Text(
text = message,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onErrorContainer
)
}
}
@@ -576,16 +539,7 @@ fun ContributionCard() {
ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainer),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation),
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.clip(MaterialTheme.shapes.large)
.shadow(
elevation = cardElevation,
shape = MaterialTheme.shapes.large,
spotColor = MaterialTheme.colorScheme.tertiary.copy(alpha = 0.1f)
)
elevation = getCardElevation(),
) {
Row(
modifier = Modifier
@@ -601,14 +555,12 @@ fun ContributionCard() {
Text(
text = stringResource(R.string.home_ContributionCard_kernelsu),
style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_click_to_ContributionCard_kernelsu),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.8f)
)
}
}
@@ -622,15 +574,7 @@ fun LearnMoreCard() {
ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainer),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation),
modifier = Modifier
.fillMaxWidth()
.clip(MaterialTheme.shapes.large)
.shadow(
elevation = cardElevation,
shape = MaterialTheme.shapes.large,
spotColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.1f)
)
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation)
) {
Row(
modifier = Modifier
@@ -645,14 +589,12 @@ fun LearnMoreCard() {
Text(
text = stringResource(R.string.home_learn_kernelsu),
style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_click_to_learn_kernelsu),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.8f)
)
}
}
@@ -665,15 +607,7 @@ fun DonateCard() {
ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainer),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation),
modifier = Modifier
.fillMaxWidth()
.clip(MaterialTheme.shapes.large)
.shadow(
elevation = cardElevation,
shape = MaterialTheme.shapes.large,
spotColor = MaterialTheme.colorScheme.secondary.copy(alpha = 0.1f)
)
elevation = getCardElevation(),
) {
Row(
modifier = Modifier
@@ -688,14 +622,12 @@ fun DonateCard() {
Text(
text = stringResource(R.string.home_support_title),
style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_support_content),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.8f)
)
}
}
@@ -706,23 +638,13 @@ fun DonateCard() {
private fun InfoCard(
systemInfo: HomeViewModel.SystemInfo,
isSimpleMode: Boolean,
isHideVersion: Boolean,
isHideOtherInfo: Boolean,
isHideSusfsStatus: Boolean,
showKpmInfo: Boolean,
lkmMode: Boolean?
) {
ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainer),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation),
modifier = Modifier
.fillMaxWidth()
.clip(MaterialTheme.shapes.large)
.shadow(
elevation = cardElevation,
shape = MaterialTheme.shapes.large,
spotColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.05f)
)
elevation = getCardElevation(),
) {
Column(
modifier = Modifier
@@ -733,20 +655,23 @@ private fun InfoCard(
fun InfoCardItem(
label: String,
content: String,
icon: ImageVector = Icons.Default.Info
icon: ImageVector? = null,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
verticalAlignment = Alignment.Top,
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp)
) {
Icon(
imageVector = icon,
contentDescription = label,
modifier = Modifier.size(24.dp),
tint = MaterialTheme.colorScheme.primary.copy(alpha = 0.7f),
)
if (icon != null) {
Icon(
imageVector = icon,
contentDescription = label,
modifier = Modifier
.size(28.dp)
.padding(vertical = 4.dp),
)
}
Spacer(modifier = Modifier.width(16.dp))
Column(
modifier = Modifier
@@ -756,12 +681,10 @@ private fun InfoCard(
Text(
text = label,
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = content,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurface,
softWrap = true
)
}
@@ -801,55 +724,67 @@ private fun InfoCard(
)
if (!isSimpleMode) {
if (lkmMode != true) {
// 根据showKpmInfo决定是否显示KPM信息
if (showKpmInfo && Natives.version >= Natives.MINIMAL_SUPPORTED_KPM) {
val displayVersion = if (systemInfo.kpmVersion.isEmpty() || systemInfo.kpmVersion.startsWith("Error")) {
val statusText = if (Natives.isKPMEnabled()) {
stringResource(R.string.kernel_patched)
} else {
stringResource(R.string.kernel_not_enabled)
}
"${stringResource(R.string.not_supported)} ($statusText)"
// 根据showKpmInfo决定是否显示KPM信息
if (lkmMode != true && !showKpmInfo && Natives.version >= Natives.MINIMAL_SUPPORTED_KPM) {
val displayVersion = if (systemInfo.kpmVersion.isEmpty() || systemInfo.kpmVersion.startsWith("Error")) {
val statusText = if (Natives.isKPMEnabled()) {
stringResource(R.string.kernel_patched)
} else {
"${stringResource(R.string.supported)} (${systemInfo.kpmVersion})"
stringResource(R.string.kernel_not_enabled)
}
InfoCardItem(
stringResource(R.string.home_kpm_version),
displayVersion,
icon = Icons.Default.Archive
)
"${stringResource(R.string.not_supported)} ($statusText)"
} else {
"${stringResource(R.string.supported)} (${systemInfo.kpmVersion})"
}
InfoCardItem(
stringResource(R.string.home_kpm_version),
displayVersion,
icon = Icons.Default.Archive
)
}
}
if ((!isSimpleMode) && (!isHideSusfsStatus)) {
if (systemInfo.suSFSStatus == "Supported") {
if (systemInfo.suSFSVersion.isNotEmpty()) {
val isSUS_SU = systemInfo.suSFSFeatures == "CONFIG_KSU_SUSFS_SUS_SU"
val infoText = buildString {
append(systemInfo.suSFSVersion)
append(if (isSUS_SU) " (${systemInfo.suSFSVariant})" else " (${stringResource(R.string.manual_hook)})")
if (isSUS_SU) {
if (systemInfo.susSUMode.isNotEmpty()) {
append(" ${stringResource(R.string.sus_su_mode)} ${systemInfo.susSUMode}")
}
}
}
if (!isSimpleMode && !isHideSusfsStatus &&
systemInfo.suSFSStatus == "Supported" &&
systemInfo.suSFSVersion.isNotEmpty()) {
InfoCardItem(
stringResource(R.string.home_susfs_version),
infoText,
icon = Icons.Default.Storage
)
}
}
val infoText = SuSFSInfoText(systemInfo)
InfoCardItem(
stringResource(R.string.home_susfs_version),
infoText,
icon = Icons.Default.Storage
)
}
}
}
}
@SuppressLint("ComposableNaming")
@Composable
private fun SuSFSInfoText(systemInfo: HomeViewModel.SystemInfo): String = buildString {
append(systemInfo.suSFSVersion)
val isSUS_SU = systemInfo.suSFSFeatures == "CONFIG_KSU_SUSFS_SUS_SU"
val isKprobesHook = Natives.getHookType() == "Kprobes"
when {
isSUS_SU && isKprobesHook -> {
append(" (${systemInfo.suSFSVariant})")
if (systemInfo.susSUMode.isNotEmpty()) {
append(" ${stringResource(R.string.sus_su_mode)} ${systemInfo.susSUMode}")
}
}
Natives.getHookType() == "Manual" -> {
append(" (${stringResource(R.string.manual_hook)})")
}
else -> {
append(" (${Natives.getHookType()})")
}
}
}
fun getManagerVersion(context: Context): Pair<String, Long> {
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)!!
val versionCode = PackageInfoCompat.getLongVersionCode(packageInfo)
@@ -913,12 +848,3 @@ private fun WarningCardPreview() {
onClick = {})
}
}
@SuppressLint("UnnecessaryComposedModifier")
fun Modifier.disableOverscroll(): Modifier = composed {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
this
} else {
this
}
}

View File

@@ -33,7 +33,6 @@ import androidx.compose.material.icons.filled.FileUpload
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
@@ -60,6 +59,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
@@ -92,6 +92,8 @@ import com.sukisu.ultra.ui.util.isAbDevice
import com.sukisu.ultra.ui.util.isInitBoot
import com.sukisu.ultra.ui.util.rootAvailable
import com.sukisu.ultra.getKernelVersion
import com.sukisu.ultra.ui.theme.CardConfig
import com.sukisu.ultra.ui.theme.getCardElevation
/**
* @author ShirkNeko
@@ -191,21 +193,6 @@ fun InstallScreen(navigator: DestinationsNavigator) {
}
}
val selectLkmLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) {
if (it.resultCode == Activity.RESULT_OK) {
it.data?.data?.let { uri ->
lkmSelection = LkmSelection.LkmUri(uri)
}
}
}
val onLkmUpload = {
selectLkmLauncher.launch(Intent(Intent.ACTION_GET_CONTENT).apply {
type = "application/octet-stream"
})
}
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
@@ -213,7 +200,6 @@ fun InstallScreen(navigator: DestinationsNavigator) {
topBar = {
TopBar(
onBack = { navigator.popBackStack() },
onLkmUpload = onLkmUpload,
scrollBehavior = scrollBehavior
)
},
@@ -230,7 +216,6 @@ fun InstallScreen(navigator: DestinationsNavigator) {
) {
SelectInstallMethod(
isGKI = isGKI,
isAbDevice = isAbDevice,
onSelected = { method ->
if (method is InstallMethod.HorizonKernel && method.uri != null) {
if (isAbDevice) {
@@ -253,7 +238,7 @@ fun InstallScreen(navigator: DestinationsNavigator) {
(lkmSelection as? LkmSelection.LkmUri)?.let {
ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.surfaceVariant),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation),
elevation = getCardElevation(),
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 12.dp)
@@ -279,7 +264,7 @@ fun InstallScreen(navigator: DestinationsNavigator) {
if (method.slot != null) {
ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.surfaceVariant),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation),
elevation = getCardElevation(),
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 12.dp)
@@ -381,7 +366,6 @@ sealed class InstallMethod {
@Composable
private fun SelectInstallMethod(
isGKI: Boolean = false,
isAbDevice: Boolean = false,
onSelected: (InstallMethod) -> Unit = {}
) {
val rootAvailable = rootAvailable()
@@ -468,8 +452,8 @@ private fun SelectInstallMethod(
}
}
var LKMExpanded by remember { mutableStateOf(false) }
var GKIExpanded by remember { mutableStateOf(false) }
var lkmExpanded by remember { mutableStateOf(false) }
var gkiExpanded by remember { mutableStateOf(false) }
Column(
modifier = Modifier.padding(horizontal = 16.dp)
@@ -478,38 +462,39 @@ private fun SelectInstallMethod(
if (isGKI) {
ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.surfaceVariant),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation),
elevation = getCardElevation(),
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 12.dp)
.padding(bottom = 16.dp)
.clip(MaterialTheme.shapes.large)
.shadow(
elevation = cardElevation,
shape = MaterialTheme.shapes.large,
spotColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.1f)
)
) {
ListItem(
leadingContent = {
Icon(
Icons.Filled.AutoFixHigh,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary
)
},
headlineContent = {
Text(
stringResource(R.string.Lkm_install_methods),
style = MaterialTheme.typography.titleMedium
)
},
modifier = Modifier.clickable {
LKMExpanded = !LKMExpanded
}
)
MaterialTheme(
colorScheme = MaterialTheme.colorScheme.copy(
surface = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else MaterialTheme.colorScheme.surfaceVariant
)
) {
ListItem(
leadingContent = {
Icon(
Icons.Filled.AutoFixHigh,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary
)
},
headlineContent = {
Text(
stringResource(R.string.Lkm_install_methods),
style = MaterialTheme.typography.titleMedium
)
},
modifier = Modifier.clickable {
lkmExpanded = !lkmExpanded
}
)
}
AnimatedVisibility(
visible = LKMExpanded,
visible = lkmExpanded,
enter = fadeIn() + expandVertically(),
exit = shrinkVertically() + fadeOut()
) {
@@ -584,38 +569,39 @@ private fun SelectInstallMethod(
if (rootAvailable) {
ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.surfaceVariant),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation),
elevation = getCardElevation(),
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 12.dp)
.clip(MaterialTheme.shapes.large)
.shadow(
elevation = cardElevation,
shape = MaterialTheme.shapes.large,
spotColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.1f)
)
) {
ListItem(
leadingContent = {
Icon(
Icons.Filled.FileUpload,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary
)
},
headlineContent = {
Text(
stringResource(R.string.GKI_install_methods),
style = MaterialTheme.typography.titleMedium
)
},
modifier = Modifier.clickable {
GKIExpanded = !GKIExpanded
}
)
MaterialTheme(
colorScheme = MaterialTheme.colorScheme.copy(
surface = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else MaterialTheme.colorScheme.surfaceVariant
)
) {
ListItem(
leadingContent = {
Icon(
Icons.Filled.FileUpload,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary
)
},
headlineContent = {
Text(
stringResource(R.string.GKI_install_methods),
style = MaterialTheme.typography.titleMedium
)
},
modifier = Modifier.clickable {
gkiExpanded = !gkiExpanded
}
)
}
AnimatedVisibility(
visible = GKIExpanded,
visible = gkiExpanded,
enter = fadeIn() + expandVertically(),
exit = shrinkVertically() + fadeOut()
) {
@@ -702,11 +688,10 @@ fun rememberSelectKmiDialog(onSelected: (String?) -> Unit): DialogHandle {
}
var selection by remember { mutableStateOf<String?>(null) }
val backgroundColor = MaterialTheme.colorScheme.surfaceContainerHighest
MaterialTheme(
colorScheme = MaterialTheme.colorScheme.copy(
surface = backgroundColor
surface = MaterialTheme.colorScheme.surfaceContainerHigh
)
) {
ListDialog(state = rememberUseCaseState(visible = true, onFinishedRequest = {
@@ -729,10 +714,14 @@ fun rememberSelectKmiDialog(onSelected: (String?) -> Unit): DialogHandle {
@Composable
private fun TopBar(
onBack: () -> Unit = {},
onLkmUpload: () -> Unit = {},
scrollBehavior: TopAppBarScrollBehavior? = null
) {
val cardColor = MaterialTheme.colorScheme.surfaceContainerLow
val colorScheme = MaterialTheme.colorScheme
val cardColor = if (CardConfig.isCustomBackgroundEnabled) {
colorScheme.surfaceContainerLow
} else {
colorScheme.background
}
val cardAlpha = cardAlpha
TopAppBar(

View File

@@ -5,9 +5,13 @@ import android.content.Intent
import android.util.Log
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.*
import androidx.compose.animation.core.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.material3.*
@@ -38,6 +42,7 @@ import java.io.FileInputStream
import java.io.InputStreamReader
import java.net.*
import android.app.Activity
import androidx.compose.ui.res.painterResource
import com.sukisu.ultra.ui.theme.CardConfig.cardElevation
/**
@@ -57,6 +62,9 @@ fun KpmScreen(
val snackBarHost = remember { SnackbarHostState() }
val confirmDialog = rememberConfirmDialog()
val listState = rememberLazyListState()
val fabVisible by rememberFabVisibilityState(listState)
val moduleConfirmContentMap = viewModel.moduleList.associate { module ->
val moduleFileName = module.id
module.id to stringResource(R.string.confirm_uninstall_content, moduleFileName)
@@ -112,7 +120,6 @@ fun KpmScreen(
Text(
text = kpmInstallMode,
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.onSurface
)
},
text = {
@@ -121,7 +128,6 @@ fun KpmScreen(
Text(
text = stringResource(R.string.kpm_install_mode_description, it),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Spacer(modifier = Modifier.height(16.dp))
@@ -146,9 +152,6 @@ fun KpmScreen(
}
},
modifier = Modifier.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.primary
)
) {
Icon(
imageVector = Icons.Filled.Download,
@@ -176,9 +179,6 @@ fun KpmScreen(
}
},
modifier = Modifier.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.secondary
)
) {
Icon(
imageVector = Icons.Filled.Inventory,
@@ -209,7 +209,6 @@ fun KpmScreen(
}
}
},
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
shape = MaterialTheme.shapes.extraLarge
)
}
@@ -292,38 +291,34 @@ fun KpmScreen(
)
},
floatingActionButton = {
ExtendedFloatingActionButton(
onClick = {
selectPatchLauncher.launch(
Intent(Intent.ACTION_GET_CONTENT).apply {
type = "application/octet-stream"
}
)
},
icon = {
Icon(
imageVector = Icons.Filled.Add,
contentDescription = stringResource(R.string.kpm_install),
)
},
text = {
Text(
text = stringResource(R.string.kpm_install),
color = MaterialTheme.colorScheme.onPrimaryContainer
)
},
contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
expanded = true,
)
AnimatedFab(visible = fabVisible) {
FloatingActionButton(
contentColor = MaterialTheme.colorScheme.onPrimary,
containerColor = MaterialTheme.colorScheme.primary,
onClick = {
selectPatchLauncher.launch(
Intent(Intent.ACTION_GET_CONTENT).apply {
type = "application/octet-stream"
}
)
},
content = {
Icon(
painter = painterResource(id = R.drawable.package_import),
contentDescription = null
)
}
)
}
},
contentWindowInsets = WindowInsets.safeDrawing.only(
WindowInsetsSides.Top + WindowInsetsSides.Horizontal
),
snackbarHost = { SnackbarHost(snackBarHost) }
) { padding ->
Column(modifier = Modifier.padding(padding)) {
if (!isNoticeClosed) {
Card(
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.secondaryContainer
),
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
@@ -348,7 +343,6 @@ fun KpmScreen(
text = stringResource(R.string.kernel_module_notice),
modifier = Modifier.weight(1f),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSecondaryContainer
)
IconButton(
@@ -357,9 +351,6 @@ fun KpmScreen(
sharedPreferences.edit { putBoolean("is_notice_closed", true) }
},
modifier = Modifier.size(24.dp),
colors = IconButtonDefaults.iconButtonColors(
contentColor = MaterialTheme.colorScheme.onSecondaryContainer
)
) {
Icon(
imageVector = Icons.Filled.Close,
@@ -391,12 +382,12 @@ fun KpmScreen(
stringResource(R.string.kpm_empty),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
} else {
LazyColumn(
state = listState,
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(horizontal = 16.dp, vertical = 16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
@@ -585,7 +576,6 @@ private fun KpmModuleItem(
Text(
text = stringResource(R.string.kpm_control),
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.onSurface
)
},
text = {
@@ -595,20 +585,14 @@ private fun KpmModuleItem(
label = {
Text(
text = stringResource(R.string.kpm_args),
color = MaterialTheme.colorScheme.primary
)
},
placeholder = {
Text(
text = module.args,
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f)
)
},
modifier = Modifier.fillMaxWidth(),
colors = OutlinedTextFieldDefaults.colors(
focusedBorderColor = MaterialTheme.colorScheme.primary,
unfocusedBorderColor = MaterialTheme.colorScheme.outline
)
)
},
confirmButton = {
@@ -627,7 +611,6 @@ private fun KpmModuleItem(
) {
Text(
text = stringResource(R.string.confirm),
color = MaterialTheme.colorScheme.primary
)
}
},
@@ -635,26 +618,16 @@ private fun KpmModuleItem(
TextButton(onClick = { viewModel.hideInputDialog() }) {
Text(
text = stringResource(R.string.cancel),
color = MaterialTheme.colorScheme.primary
)
}
},
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
shape = MaterialTheme.shapes.extraLarge
)
}
Card(
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation),
modifier = Modifier
.fillMaxWidth()
.clip(MaterialTheme.shapes.large)
.shadow(
elevation = cardElevation,
shape = MaterialTheme.shapes.large,
spotColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.1f)
)
elevation = getCardElevation()
) {
Column(
modifier = Modifier.padding(20.dp)
@@ -668,7 +641,6 @@ private fun KpmModuleItem(
Text(
text = module.name,
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onSurface
)
Spacer(modifier = Modifier.height(4.dp))
@@ -676,19 +648,16 @@ private fun KpmModuleItem(
Text(
text = "${stringResource(R.string.kpm_version)}: ${module.version}",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = "${stringResource(R.string.kpm_author)}: ${module.author}",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = "${stringResource(R.string.kpm_args)}: ${module.args}",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
@@ -698,7 +667,6 @@ private fun KpmModuleItem(
Text(
text = module.description,
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Spacer(modifier = Modifier.height(20.dp))
@@ -711,10 +679,6 @@ private fun KpmModuleItem(
onClick = { viewModel.showInputDialog(module.id) },
enabled = module.hasAction,
modifier = Modifier.weight(1f),
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.primary,
disabledContainerColor = MaterialTheme.colorScheme.surfaceVariant
)
) {
Icon(
imageVector = Icons.Filled.Settings,

View File

@@ -1,6 +1,9 @@
package com.sukisu.ultra.ui.screen
import android.annotation.SuppressLint
import android.app.Activity.*
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.net.Uri
@@ -8,12 +11,22 @@ import android.util.Log
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.*
import androidx.compose.animation.core.*
import androidx.compose.foundation.*
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsPressedAsState
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.selection.toggleable
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.*
import androidx.compose.material.icons.filled.*
@@ -23,11 +36,13 @@ import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.*
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.font.FontWeight
@@ -68,17 +83,27 @@ import com.sukisu.ultra.ui.viewmodel.ModuleViewModel
import java.util.concurrent.TimeUnit
import androidx.core.content.edit
import com.sukisu.ultra.R
import com.sukisu.ultra.ui.theme.CardConfig.cardElevation
import com.sukisu.ultra.ui.webui.WebUIXActivity
import com.dergoogler.mmrl.platform.Platform
import androidx.core.net.toUri
import com.dergoogler.mmrl.platform.model.ModuleConfig
import com.dergoogler.mmrl.platform.model.ModuleConfig.Companion.asModuleConfig
import com.sukisu.ultra.ui.component.AnimatedFab
import com.sukisu.ultra.ui.component.rememberFabVisibilityState
import com.sukisu.ultra.ui.theme.getCardElevation
// 菜单项数据类
data class ModuleBottomSheetMenuItem(
val icon: ImageVector,
val titleRes: Int,
val onClick: () -> Unit
)
/**
* @author ShirkNeko
* @date 2025/5/31.
*/
@SuppressLint("ResourceType", "AutoboxingStateCreation")
@OptIn(ExperimentalMaterial3Api::class)
@Destination<RootGraph>
@Composable
@@ -90,6 +115,19 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
val confirmDialog = rememberConfirmDialog()
var lastClickTime by remember { mutableStateOf(0L) }
// 初始化缓存系统
LaunchedEffect(Unit) {
viewModel.initializeCache(context)
}
// BottomSheet状态
val bottomSheetState = rememberModalBottomSheetState(
skipPartiallyExpanded = true
)
var showBottomSheet by remember { mutableStateOf(false) }
val listState = rememberLazyListState()
val fabVisible by rememberFabVisibilityState(listState)
val selectZipLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) {
@@ -202,6 +240,34 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
contract = ActivityResultContracts.StartActivityForResult()
) { viewModel.fetchModuleList() }
// BottomSheet菜单项
val bottomSheetMenuItems = remember {
listOf(
ModuleBottomSheetMenuItem(
icon = Icons.Outlined.Save,
titleRes = R.string.backup_modules,
onClick = {
backupLauncher.launch(ModuleModify.createBackupIntent())
scope.launch {
bottomSheetState.hide()
showBottomSheet = false
}
}
),
ModuleBottomSheetMenuItem(
icon = Icons.Outlined.RestoreFromTrash,
titleRes = R.string.restore_modules,
onClick = {
restoreLauncher.launch(ModuleModify.createRestoreIntent())
scope.launch {
bottomSheetState.hide()
showBottomSheet = false
}
}
)
)
}
Scaffold(
topBar = {
SearchAppBar(
@@ -210,104 +276,23 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
onSearchTextChange = { viewModel.search = it },
onClearClick = { viewModel.search = "" },
dropdownContent = {
var showDropdown by remember { mutableStateOf(false) }
IconButton(
onClick = { showDropdown = true },
onClick = { showBottomSheet = true },
) {
Icon(
imageVector = Icons.Filled.MoreVert,
contentDescription = stringResource(id = R.string.settings),
)
DropdownMenu(
expanded = showDropdown,
onDismissRequest = { showDropdown = false }
) {
DropdownMenuItem(
text = { Text(stringResource(R.string.module_sort_action_first)) },
trailingIcon = {
Checkbox(
checked = viewModel.sortActionFirst,
onCheckedChange = null,
colors = CheckboxDefaults.colors(
checkedColor = MaterialTheme.colorScheme.primary,
uncheckedColor = MaterialTheme.colorScheme.outline
)
)
},
onClick = {
viewModel.sortActionFirst = !viewModel.sortActionFirst
prefs.edit {
putBoolean(
"module_sort_action_first",
viewModel.sortActionFirst
)
}
scope.launch {
viewModel.fetchModuleList()
}
}
)
DropdownMenuItem(
text = { Text(stringResource(R.string.module_sort_enabled_first)) },
trailingIcon = {
Checkbox(
checked = viewModel.sortEnabledFirst,
onCheckedChange = null,
colors = CheckboxDefaults.colors(
checkedColor = MaterialTheme.colorScheme.primary,
uncheckedColor = MaterialTheme.colorScheme.outline
)
)
},
onClick = {
viewModel.sortEnabledFirst = !viewModel.sortEnabledFirst
prefs.edit {
putBoolean("module_sort_enabled_first", viewModel.sortEnabledFirst)
}
scope.launch {
viewModel.fetchModuleList()
}
}
)
HorizontalDivider(thickness = Dp.Hairline, modifier = Modifier.padding(vertical = 4.dp))
DropdownMenuItem(
text = { Text(stringResource(R.string.backup_modules)) },
leadingIcon = {
Icon(
imageVector = Icons.Outlined.Download,
contentDescription = stringResource(R.string.backup),
)
},
onClick = {
showDropdown = false
backupLauncher.launch(ModuleModify.createBackupIntent())
}
)
DropdownMenuItem(
text = { Text(stringResource(R.string.restore_modules)) },
leadingIcon = {
Icon(
imageVector = Icons.Outlined.Refresh,
contentDescription = stringResource(R.string.restore),
)
},
onClick = {
showDropdown = false
restoreLauncher.launch(ModuleModify.createRestoreIntent())
}
)
}
}
},
scrollBehavior = scrollBehavior,
)
},
floatingActionButton = {
if (!hideInstallButton) {
val moduleInstall = stringResource(id = R.string.module_install)
ExtendedFloatingActionButton(
AnimatedFab(visible = !hideInstallButton && fabVisible) {
FloatingActionButton(
contentColor = MaterialTheme.colorScheme.onPrimary,
containerColor = MaterialTheme.colorScheme.primary,
onClick = {
selectZipLauncher.launch(
Intent(Intent.ACTION_GET_CONTENT).apply {
@@ -316,20 +301,12 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
}
)
},
icon = {
content = {
Icon(
imageVector = Icons.Filled.Add,
contentDescription = moduleInstall,
painter = painterResource(id = R.drawable.package_import),
contentDescription = null
)
},
text = {
Text(
text = moduleInstall,
color = MaterialTheme.colorScheme.onPrimaryContainer
)
},
contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
expanded = true,
}
)
}
},
@@ -353,7 +330,6 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
Icon(
imageVector = Icons.Outlined.Warning,
contentDescription = null,
tint = MaterialTheme.colorScheme.error,
modifier = Modifier
.size(64.dp)
.padding(bottom = 16.dp)
@@ -362,7 +338,6 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
stringResource(R.string.module_magisk_conflict),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
@@ -371,6 +346,7 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
ModuleList(
navigator = navigator,
viewModel = viewModel,
listState = listState,
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
boxModifier = Modifier.padding(innerPadding),
onInstallModule = {
@@ -438,6 +414,202 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
)
}
}
// BottomSheet
if (showBottomSheet) {
ModalBottomSheet(
onDismissRequest = {
showBottomSheet = false
},
sheetState = bottomSheetState,
dragHandle = {
Surface(
modifier = Modifier.padding(vertical = 11.dp),
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.4f),
shape = RoundedCornerShape(16.dp)
) {
Box(
Modifier.size(
width = 32.dp,
height = 4.dp
)
)
}
}
) {
ModuleBottomSheetContent(
menuItems = bottomSheetMenuItems,
viewModel = viewModel,
prefs = prefs,
scope = scope,
bottomSheetState = bottomSheetState,
onDismiss = { showBottomSheet = false }
)
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun ModuleBottomSheetContent(
menuItems: List<ModuleBottomSheetMenuItem>,
viewModel: ModuleViewModel,
prefs: android.content.SharedPreferences,
scope: kotlinx.coroutines.CoroutineScope,
bottomSheetState: SheetState,
onDismiss: () -> Unit
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 24.dp)
) {
// 标题
Text(
text = stringResource(R.string.menu_options),
style = MaterialTheme.typography.headlineSmall,
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp)
)
// 菜单选项网格
LazyVerticalGrid(
columns = GridCells.Fixed(4),
modifier = Modifier.fillMaxWidth(),
contentPadding = PaddingValues(horizontal = 16.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
items(menuItems) { menuItem ->
ModuleBottomSheetMenuItemView(
menuItem = menuItem
)
}
}
// 排序选项
Spacer(modifier = Modifier.height(24.dp))
HorizontalDivider(modifier = Modifier.padding(horizontal = 24.dp))
Text(
text = stringResource(R.string.sort_options),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp)
)
// 排序选项
Column(
modifier = Modifier.padding(horizontal = 24.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
// 优先显示有操作的模块
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = stringResource(R.string.module_sort_action_first),
style = MaterialTheme.typography.bodyMedium
)
Switch(
checked = viewModel.sortActionFirst,
onCheckedChange = { checked ->
viewModel.sortActionFirst = checked
prefs.edit {
putBoolean("module_sort_action_first", checked)
}
scope.launch {
viewModel.fetchModuleList()
bottomSheetState.hide()
onDismiss()
}
}
)
}
// 优先显示已启用的模块
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = stringResource(R.string.module_sort_enabled_first),
style = MaterialTheme.typography.bodyMedium
)
Switch(
checked = viewModel.sortEnabledFirst,
onCheckedChange = { checked ->
viewModel.sortEnabledFirst = checked
prefs.edit {
putBoolean("module_sort_enabled_first", checked)
}
scope.launch {
viewModel.fetchModuleList()
bottomSheetState.hide()
onDismiss()
}
}
)
}
}
}
}
@Composable
private fun ModuleBottomSheetMenuItemView(menuItem: ModuleBottomSheetMenuItem) {
// 添加交互状态
val interactionSource = remember { MutableInteractionSource() }
val isPressed by interactionSource.collectIsPressedAsState()
val scale by animateFloatAsState(
targetValue = if (isPressed) 0.95f else 1.0f,
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessHigh
),
label = "menuItemScale"
)
Column(
modifier = Modifier
.fillMaxWidth()
.scale(scale)
.clickable(
interactionSource = interactionSource,
indication = null
) { menuItem.onClick() }
.padding(8.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Surface(
modifier = Modifier.size(48.dp),
shape = CircleShape,
color = MaterialTheme.colorScheme.primaryContainer,
contentColor = MaterialTheme.colorScheme.onPrimaryContainer
) {
Box(
contentAlignment = Alignment.Center
) {
Icon(
imageVector = menuItem.icon,
contentDescription = stringResource(menuItem.titleRes),
modifier = Modifier.size(24.dp)
)
}
}
Spacer(modifier = Modifier.height(8.dp))
Text(
text = stringResource(menuItem.titleRes),
style = MaterialTheme.typography.labelSmall,
textAlign = TextAlign.Center,
maxLines = 2
)
}
}
@@ -446,6 +618,7 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
private fun ModuleList(
navigator: DestinationsNavigator,
viewModel: ModuleViewModel,
listState: LazyListState,
modifier: Modifier = Modifier,
boxModifier: Modifier = Modifier,
onInstallModule: (Uri) -> Unit,
@@ -577,6 +750,7 @@ private fun ModuleList(
if (success) {
viewModel.fetchModuleList()
viewModel.markNeedRefresh()
}
if (!isUninstall) return
val message = if (success) {
@@ -606,6 +780,7 @@ private fun ModuleList(
isRefreshing = viewModel.isRefreshing
) {
LazyColumn(
state = listState,
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(16.dp),
contentPadding = remember {
@@ -640,7 +815,6 @@ private fun ModuleList(
text = stringResource(R.string.module_empty),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
@@ -724,23 +898,30 @@ fun ModuleItem(
onUpdate: (ModuleViewModel.ModuleInfo) -> Unit,
onClick: (ModuleViewModel.ModuleInfo) -> Unit
) {
val context = LocalContext.current
val prefs = context.getSharedPreferences("settings", MODE_PRIVATE)
val isHideTagRow = prefs.getBoolean("is_hide_tag_row", false)
// 获取显示更多模块信息的设置
val showMoreModuleInfo = prefs.getBoolean("show_more_module_info", false)
// 剪贴板管理器和触觉反馈
val clipboardManager = context.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
val hapticFeedback = LocalHapticFeedback.current
ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerHigh),
elevation = CardDefaults.cardElevation(defaultElevation = cardElevation),
modifier = Modifier
.fillMaxWidth()
.clip(MaterialTheme.shapes.large)
.shadow(
elevation = cardElevation,
shape = MaterialTheme.shapes.large,
spotColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.1f)
)
elevation = getCardElevation(),
) {
val textDecoration = if (!module.remove) null else TextDecoration.LineThrough
val interactionSource = remember { MutableInteractionSource() }
val indication = LocalIndication.current
val viewModel = viewModel<ModuleViewModel>()
// 使用缓存系统获取模块大小
val sizeStr = remember(module.dirId) {
viewModel.getModuleSize(module.dirId)
}
Column(
modifier = Modifier
.run {
@@ -777,7 +958,6 @@ fun ModuleItem(
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.titleMedium.fontFamily,
textDecoration = textDecoration,
color = MaterialTheme.colorScheme.onSurface
)
Text(
@@ -786,7 +966,6 @@ fun ModuleItem(
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
textDecoration = textDecoration,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
@@ -795,8 +974,44 @@ fun ModuleItem(
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
textDecoration = textDecoration,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
// 显示更多模块信息时添加updateJson
if (showMoreModuleInfo && module.updateJson.isNotEmpty()) {
val updateJsonLabel = stringResource(R.string.module_update_json)
Text(
text = "$updateJsonLabel: ${module.updateJson}",
fontSize = MaterialTheme.typography.bodySmall.fontSize,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
textDecoration = textDecoration,
color = MaterialTheme.colorScheme.primary,
maxLines = 5,
overflow = TextOverflow.Ellipsis,
modifier = Modifier
.fillMaxWidth()
.combinedClickable(
onClick = {
},
onLongClick = {
// 长按复制updateJson地址
val clipData = ClipData.newPlainText(
"Update JSON URL",
module.updateJson
)
clipboardManager.setPrimaryClip(clipData)
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
// 显示复制成功的提示
Toast.makeText(
context,
context.getString(R.string.module_update_json_copied),
Toast.LENGTH_SHORT
).show()
}
),
)
}
}
Spacer(modifier = Modifier.weight(1f))
@@ -810,14 +1025,6 @@ fun ModuleItem(
checked = module.enabled,
onCheckedChange = onCheckChanged,
interactionSource = if (!module.hasWebUi) interactionSource else null,
colors = SwitchDefaults.colors(
checkedThumbColor = MaterialTheme.colorScheme.onPrimary,
checkedTrackColor = MaterialTheme.colorScheme.primary,
checkedIconColor = MaterialTheme.colorScheme.primary,
uncheckedThumbColor = MaterialTheme.colorScheme.outline,
uncheckedTrackColor = MaterialTheme.colorScheme.surfaceVariant,
uncheckedIconColor = MaterialTheme.colorScheme.surfaceVariant
)
)
}
}
@@ -833,8 +1040,45 @@ fun ModuleItem(
overflow = TextOverflow.Ellipsis,
maxLines = 4,
textDecoration = textDecoration,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
if (!isHideTagRow) {
Spacer(modifier = Modifier.height(12.dp))
// 文件夹名称和大小标签
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.fillMaxWidth()
) {
Surface(
shape = RoundedCornerShape(4.dp),
color = MaterialTheme.colorScheme.primary,
modifier = Modifier
) {
Text(
text = module.dirId,
style = MaterialTheme.typography.labelSmall,
modifier = Modifier.padding(horizontal = 4.dp, vertical = 1.dp),
color = MaterialTheme.colorScheme.onPrimary,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
Surface(
shape = RoundedCornerShape(4.dp),
color = MaterialTheme.colorScheme.secondaryContainer,
modifier = Modifier
) {
Text(
text = sizeStr,
style = MaterialTheme.typography.labelSmall,
modifier = Modifier.padding(horizontal = 4.dp, vertical = 1.dp),
color = MaterialTheme.colorScheme.onSecondaryContainer,
maxLines = 1
)
}
}
}
Spacer(modifier = Modifier.height(16.dp))
@@ -855,7 +1099,6 @@ fun ModuleItem(
viewModel.markNeedRefresh()
},
contentPadding = ButtonDefaults.TextButtonContentPadding,
colors = ButtonDefaults.filledTonalButtonColors()
) {
Icon(
modifier = Modifier.size(20.dp),
@@ -872,9 +1115,8 @@ fun ModuleItem(
onClick = { onClick(module) },
interactionSource = interactionSource,
contentPadding = ButtonDefaults.TextButtonContentPadding,
colors = ButtonDefaults.filledTonalButtonColors()
) {
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.AutoMirrored.Outlined.Wysiwyg,
@@ -892,7 +1134,6 @@ fun ModuleItem(
onClick = { onUpdate(module) },
shape = ButtonDefaults.textShape,
contentPadding = ButtonDefaults.TextButtonContentPadding,
colors = ButtonDefaults.filledTonalButtonColors()
) {
Icon(
modifier = Modifier.size(20.dp),
@@ -906,8 +1147,6 @@ fun ModuleItem(
modifier = Modifier.defaultMinSize(minWidth = 52.dp, minHeight = 32.dp),
onClick = { onUninstallClicked(module) },
contentPadding = ButtonDefaults.TextButtonContentPadding,
colors = ButtonDefaults.filledTonalButtonColors(
containerColor = if (!module.remove) MaterialTheme.colorScheme.secondaryContainer else MaterialTheme.colorScheme.errorContainer)
) {
if (!module.remove) {
Icon(

View File

@@ -12,9 +12,7 @@ import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
@@ -55,7 +53,6 @@ import kotlinx.coroutines.withContext
import com.sukisu.ultra.BuildConfig
import com.sukisu.ultra.Natives
import com.sukisu.ultra.R
import com.sukisu.ultra.*
import com.sukisu.ultra.ui.component.*
import com.sukisu.ultra.ui.theme.*
import com.sukisu.ultra.ui.theme.CardConfig.cardAlpha
@@ -69,6 +66,10 @@ import com.sukisu.ultra.ui.component.KsuIsValid
* @author ShirkNeko
* @date 2025/5/31.
*/
private val SPACING_SMALL = 3.dp
private val SPACING_MEDIUM = 8.dp
private val SPACING_LARGE = 16.dp
@OptIn(ExperimentalMaterial3Api::class)
@Destination<RootGraph>
@Composable
@@ -84,10 +85,9 @@ fun SettingScreen(navigator: DestinationsNavigator) {
}
Scaffold(
// containerColor = MaterialTheme.colorScheme.surfaceBright,
topBar = {
TopBar(
scrollBehavior = scrollBehavior
)
TopBar(scrollBehavior = scrollBehavior)
},
snackbarHost = { SnackbarHost(snackBarHost) },
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
@@ -121,31 +121,16 @@ fun SettingScreen(navigator: DestinationsNavigator) {
}
}
// 配置
Card(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh.copy(alpha = cardAlpha)
),
elevation = CardDefaults.cardElevation(defaultElevation = 0.dp)
) {
Column(modifier = Modifier.padding(vertical = 8.dp)) {
Text(
text = stringResource(R.string.configuration),
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
)
// 配置卡片
SettingsGroupCard(
title = stringResource(R.string.configuration),
content = {
// 配置文件模板入口
val profileTemplate = stringResource(id = R.string.settings_profile_template)
KsuIsValid {
SettingItem(
icon = Icons.Filled.Fence,
title = profileTemplate,
summary = stringResource(id = R.string.settings_profile_template_summary),
title = stringResource(R.string.settings_profile_template),
summary = stringResource(R.string.settings_profile_template_summary),
onClick = {
navigator.navigate(AppProfileTemplateScreenDestination)
}
@@ -160,17 +145,18 @@ fun SettingScreen(navigator: DestinationsNavigator) {
KsuIsValid {
SwitchItem(
icon = Icons.Filled.FolderDelete,
title = stringResource(id = R.string.settings_umount_modules_default),
summary = stringResource(id = R.string.settings_umount_modules_default_summary),
checked = umountChecked
) { enabled ->
if (Natives.setDefaultUmountModules(enabled)) {
umountChecked = enabled
title = stringResource(R.string.settings_umount_modules_default),
summary = stringResource(R.string.settings_umount_modules_default_summary),
checked = umountChecked,
onCheckedChange = { enabled ->
if (Natives.setDefaultUmountModules(enabled)) {
umountChecked = enabled
}
}
}
)
}
// SU 禁用开关(仅在兼容版本显示)
// SU 禁用开关
KsuIsValid {
if (Natives.version >= Natives.MINIMAL_SUPPORTED_SU_COMPAT) {
var isSuDisabled by rememberSaveable {
@@ -178,138 +164,70 @@ fun SettingScreen(navigator: DestinationsNavigator) {
}
SwitchItem(
icon = Icons.Filled.RemoveModerator,
title = stringResource(id = R.string.settings_disable_su),
summary = stringResource(id = R.string.settings_disable_su_summary),
checked = isSuDisabled
) { enabled ->
val shouldEnable = !enabled
if (Natives.setSuEnabled(shouldEnable)) {
isSuDisabled = enabled
}
}
}
}
}
}
// 应用设置
Card(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh.copy(alpha = cardAlpha)
),
elevation = CardDefaults.cardElevation(defaultElevation = 0.dp)
) {
Column(modifier = Modifier.padding(vertical = 8.dp)) {
Text(
text = stringResource(R.string.app_settings),
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
)
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
// 更新检查开关
var checkUpdate by rememberSaveable {
mutableStateOf(
prefs.getBoolean("check_update", true)
)
}
SwitchItem(
icon = Icons.Filled.Update,
title = stringResource(id = R.string.settings_check_update),
summary = stringResource(id = R.string.settings_check_update_summary),
checked = checkUpdate
) { enabled ->
prefs.edit { putBoolean("check_update", enabled) }
checkUpdate = enabled
}
// WebUI引擎选择
KsuIsValid {
val engineOptions = listOf(
"default" to stringResource(id = R.string.engine_auto_select),
"wx" to stringResource(id = R.string.engine_force_webuix),
"ksu" to stringResource(id = R.string.engine_force_ksu)
)
var showEngineDialog by remember { mutableStateOf(false) }
SettingItem(
icon = Icons.Filled.WebAsset,
title = stringResource(id = R.string.use_webuix),
summary = engineOptions.find { it.first == selectedEngine }?.second
?: stringResource(id = R.string.engine_auto_select),
onClick = {
showEngineDialog = true
}
)
if (showEngineDialog) {
AlertDialog(
onDismissRequest = { showEngineDialog = false },
title = { Text(stringResource(id = R.string.use_webuix)) },
text = {
Column {
engineOptions.forEach { (value, label) ->
Row(
modifier = Modifier
.fillMaxWidth()
.clickable {
selectedEngine = value
prefs.edit {
putString("webui_engine", value)
}
showEngineDialog = false
}
.padding(vertical = 12.dp),
verticalAlignment = Alignment.CenterVertically
) {
RadioButton(
selected = selectedEngine == value,
onClick = null
)
Spacer(modifier = Modifier.width(8.dp))
Text(text = label)
}
}
}
},
confirmButton = {
TextButton(
onClick = { showEngineDialog = false }
) {
Text(stringResource(id = R.string.cancel))
title = stringResource(R.string.settings_disable_su),
summary = stringResource(R.string.settings_disable_su_summary),
checked = isSuDisabled,
onCheckedChange = { enabled ->
val shouldEnable = !enabled
if (Natives.setSuEnabled(shouldEnable)) {
isSuDisabled = enabled
}
}
)
}
}
}
)
// 应用设置卡片
SettingsGroupCard(
title = stringResource(R.string.app_settings),
content = {
// 更新检查开关
var checkUpdate by rememberSaveable {
mutableStateOf(prefs.getBoolean("check_update", true))
}
SwitchItem(
icon = Icons.Filled.Update,
title = stringResource(R.string.settings_check_update),
summary = stringResource(R.string.settings_check_update_summary),
checked = checkUpdate,
onCheckedChange = { enabled ->
prefs.edit { putBoolean("check_update", enabled) }
checkUpdate = enabled
}
)
// WebUI引擎选择
KsuIsValid {
WebUIEngineSelector(
selectedEngine = selectedEngine,
onEngineSelected = { engine ->
selectedEngine = engine
prefs.edit { putString("webui_engine", engine) }
}
)
}
// Web调试和Web X Eruda 开关
var enableWebDebugging by rememberSaveable {
mutableStateOf(
prefs.getBoolean("enable_web_debugging", false)
)
mutableStateOf(prefs.getBoolean("enable_web_debugging", false))
}
var useWebUIXEruda by rememberSaveable {
mutableStateOf(
prefs.getBoolean("use_webuix_eruda", false)
)
mutableStateOf(prefs.getBoolean("use_webuix_eruda", false))
}
KsuIsValid {
SwitchItem(
icon = Icons.Filled.DeveloperMode,
title = stringResource(id = R.string.enable_web_debugging),
summary = stringResource(id = R.string.enable_web_debugging_summary),
checked = enableWebDebugging
) { enabled ->
prefs.edit { putBoolean("enable_web_debugging", enabled) }
enableWebDebugging = enabled
}
title = stringResource(R.string.enable_web_debugging),
summary = stringResource(R.string.enable_web_debugging_summary),
checked = enableWebDebugging,
onCheckedChange = { enabled ->
prefs.edit { putBoolean("enable_web_debugging", enabled) }
enableWebDebugging = enabled
}
)
AnimatedVisibility(
visible = enableWebDebugging && selectedEngine == "wx",
@@ -318,116 +236,83 @@ fun SettingScreen(navigator: DestinationsNavigator) {
) {
SwitchItem(
icon = Icons.Filled.FormatListNumbered,
title = stringResource(id = R.string.use_webuix_eruda),
summary = stringResource(id = R.string.use_webuix_eruda_summary),
checked = useWebUIXEruda
) { enabled ->
prefs.edit { putBoolean("use_webuix_eruda", enabled) }
useWebUIXEruda = enabled
}
title = stringResource(R.string.use_webuix_eruda),
summary = stringResource(R.string.use_webuix_eruda_summary),
checked = useWebUIXEruda,
onCheckedChange = { enabled ->
prefs.edit { putBoolean("use_webuix_eruda", enabled) }
useWebUIXEruda = enabled
}
)
}
}
// 更多设置
SettingItem(
icon = Icons.Filled.Settings,
title = stringResource(id = R.string.more_settings),
summary = stringResource(id = R.string.more_settings),
title = stringResource(R.string.more_settings),
summary = stringResource(R.string.more_settings),
onClick = {
navigator.navigate(MoreSettingsScreenDestination)
}
)
}
}
// 工具
Card(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh.copy(alpha = cardAlpha)
),
elevation = CardDefaults.cardElevation(defaultElevation = 0.dp)
) {
Column(modifier = Modifier.padding(vertical = 8.dp)) {
Text(
text = stringResource(R.string.tools),
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
)
)
// 工具卡片
SettingsGroupCard(
title = stringResource(R.string.tools),
content = {
var showBottomsheet by remember { mutableStateOf(false) }
SettingItem(
icon = Icons.Filled.BugReport,
title = stringResource(id = R.string.send_log),
title = stringResource(R.string.send_log),
onClick = {
showBottomsheet = true
}
)
if (showBottomsheet) {
ModalBottomSheet(
onDismissRequest = { showBottomsheet = false },
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
horizontalArrangement = Arrangement.SpaceEvenly
) {
LogActionButton(
icon = Icons.Filled.Save,
text = stringResource(R.string.save_log),
onClick = {
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH_mm")
val current = LocalDateTime.now().format(formatter)
exportBugreportLauncher.launch("KernelSU_bugreport_${current}.tar.gz")
showBottomsheet = false
}
)
LogActionButton(
icon = Icons.Filled.Share,
text = stringResource(R.string.send_log),
onClick = {
scope.launch {
val bugreport = loadingDialog.withLoading {
withContext(Dispatchers.IO) {
getBugreportFile(context)
}
}
val uri: Uri =
FileProvider.getUriForFile(
context,
"${BuildConfig.APPLICATION_ID}.fileprovider",
bugreport
)
val shareIntent = Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_STREAM, uri)
setDataAndType(uri, "application/gzip")
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
context.startActivity(
Intent.createChooser(
shareIntent,
context.getString(R.string.send_log)
)
)
showBottomsheet = false
LogBottomSheet(
onDismiss = { showBottomsheet = false },
onSaveLog = {
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH_mm")
val current = LocalDateTime.now().format(formatter)
exportBugreportLauncher.launch("KernelSU_bugreport_${current}.tar.gz")
showBottomsheet = false
},
onShareLog = {
scope.launch {
val bugreport = loadingDialog.withLoading {
withContext(Dispatchers.IO) {
getBugreportFile(context)
}
}
)
val uri = FileProvider.getUriForFile(
context,
"${BuildConfig.APPLICATION_ID}.fileprovider",
bugreport
)
val shareIntent = Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_STREAM, uri)
setDataAndType(uri, "application/gzip")
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
context.startActivity(
Intent.createChooser(
shareIntent,
context.getString(R.string.send_log)
)
)
showBottomsheet = false
}
}
Spacer(modifier = Modifier.height(16.dp))
}
)
}
val lkmMode = Natives.version >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && Natives.isLkmMode
@@ -437,26 +322,12 @@ fun SettingScreen(navigator: DestinationsNavigator) {
}
}
}
}
// 关于
Card(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh.copy(alpha = cardAlpha)
),
elevation = CardDefaults.cardElevation(defaultElevation = 0.dp)
) {
Column(modifier = Modifier.padding(vertical = 8.dp)) {
Text(
text = stringResource(R.string.about),
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
)
)
// 关于卡片
SettingsGroupCard(
title = stringResource(R.string.about),
content = {
SettingItem(
icon = Icons.Filled.Info,
title = stringResource(R.string.about),
@@ -465,13 +336,128 @@ fun SettingScreen(navigator: DestinationsNavigator) {
}
)
}
}
)
Spacer(modifier = Modifier.height(16.dp))
Spacer(modifier = Modifier.height(SPACING_LARGE))
}
}
}
@Composable
private fun SettingsGroupCard(
title: String,
content: @Composable ColumnScope.() -> Unit
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = SPACING_LARGE, vertical = SPACING_MEDIUM),
colors = getCardColors(MaterialTheme.colorScheme.surfaceContainerLow),
elevation = getCardElevation()
) {
Column(
modifier = Modifier.padding(vertical = SPACING_MEDIUM)
) {
Text(
text = title,
style = MaterialTheme.typography.titleMedium,
modifier = Modifier.padding(horizontal = SPACING_LARGE, vertical = SPACING_MEDIUM),
color = MaterialTheme.colorScheme.primary
)
content()
}
}
}
@Composable
private fun WebUIEngineSelector(
selectedEngine: String,
onEngineSelected: (String) -> Unit
) {
var showDialog by remember { mutableStateOf(false) }
val engineOptions = listOf(
"default" to stringResource(R.string.engine_auto_select),
"wx" to stringResource(R.string.engine_force_webuix),
"ksu" to stringResource(R.string.engine_force_ksu)
)
SettingItem(
icon = Icons.Filled.WebAsset,
title = stringResource(R.string.use_webuix),
summary = engineOptions.find { it.first == selectedEngine }?.second
?: stringResource(R.string.engine_auto_select),
onClick = { showDialog = true }
)
if (showDialog) {
AlertDialog(
onDismissRequest = { showDialog = false },
title = { Text(stringResource(R.string.use_webuix)) },
text = {
Column {
engineOptions.forEach { (value, label) ->
Row(
modifier = Modifier
.fillMaxWidth()
.clickable {
onEngineSelected(value)
showDialog = false
}
.padding(vertical = 12.dp),
verticalAlignment = Alignment.CenterVertically
) {
RadioButton(
selected = selectedEngine == value,
onClick = null
)
Spacer(modifier = Modifier.width(SPACING_MEDIUM))
Text(text = label)
}
}
}
},
confirmButton = {
TextButton(onClick = { showDialog = false }) {
Text(stringResource(R.string.cancel))
}
}
)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun LogBottomSheet(
onDismiss: () -> Unit,
onSaveLog: () -> Unit,
onShareLog: () -> Unit
) {
ModalBottomSheet(
onDismissRequest = onDismiss,
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(SPACING_LARGE),
horizontalArrangement = Arrangement.SpaceEvenly
) {
LogActionButton(
icon = Icons.Filled.Save,
text = stringResource(R.string.save_log),
onClick = onSaveLog
)
LogActionButton(
icon = Icons.Filled.Share,
text = stringResource(R.string.send_log),
onClick = onShareLog
)
}
Spacer(modifier = Modifier.height(SPACING_LARGE))
}
}
@Composable
fun LogActionButton(
icon: ImageVector,
@@ -482,7 +468,7 @@ fun LogActionButton(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.clickable(onClick = onClick)
.padding(8.dp)
.padding(SPACING_MEDIUM)
) {
Box(
contentAlignment = Alignment.Center,
@@ -498,11 +484,10 @@ fun LogActionButton(
modifier = Modifier.size(24.dp)
)
}
Spacer(modifier = Modifier.height(8.dp))
Spacer(modifier = Modifier.height(SPACING_MEDIUM))
Text(
text = text,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurface
style = MaterialTheme.typography.bodyMedium
)
}
}
@@ -518,29 +503,28 @@ fun SettingItem(
modifier = Modifier
.fillMaxWidth()
.clickable(onClick = onClick)
.padding(horizontal = 16.dp, vertical = 12.dp),
verticalAlignment = Alignment.CenterVertically
.padding(horizontal = SPACING_LARGE, vertical = 12.dp),
verticalAlignment = Alignment.Top
) {
Icon(
imageVector = icon,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier
.padding(end = 16.dp)
.padding(end = SPACING_LARGE)
.size(24.dp)
)
Column(modifier = Modifier.weight(1f)) {
Text(
text = title,
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurface
style = MaterialTheme.typography.titleMedium
)
if (summary != null) {
Spacer(modifier = Modifier.height(SPACING_SMALL))
Text(
text = summary,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
style = MaterialTheme.typography.bodyMedium
)
}
}
@@ -553,6 +537,50 @@ fun SettingItem(
}
}
@Composable
fun SwitchItem(
icon: ImageVector,
title: String,
summary: String? = null,
checked: Boolean,
onCheckedChange: (Boolean) -> Unit
) {
Row(
modifier = Modifier
.fillMaxWidth()
.clickable { onCheckedChange(!checked) }
.padding(horizontal = SPACING_LARGE, vertical = 12.dp),
verticalAlignment = Alignment.Top
) {
Icon(
imageVector = icon,
contentDescription = null,
tint = if (checked) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier
.padding(end = SPACING_LARGE)
.size(24.dp)
)
Column(modifier = Modifier.weight(1f)) {
Text(
text = title,
style = MaterialTheme.typography.titleMedium
)
if (summary != null) {
Spacer(modifier = Modifier.height(SPACING_SMALL))
Text(
text = summary,
style = MaterialTheme.typography.bodyMedium
)
}
}
Switch(
checked = checked,
onCheckedChange = onCheckedChange
)
}
}
@Composable
fun UninstallItem(
navigator: DestinationsNavigator,
@@ -634,137 +662,121 @@ fun rememberUninstallDialog(onSelected: (UninstallType) -> Unit): DialogHandle {
var selectedOption by remember { mutableStateOf<UninstallType?>(null) }
AlertDialog(
onDismissRequest = {
dismiss()
},
title = {
Text(
text = stringResource(R.string.settings_uninstall),
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.onSurface
)
},
text = {
Column(
modifier = Modifier.padding(vertical = 8.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
options.forEachIndexed { index, option ->
val isSelected = selectedOption == option
val backgroundColor = if (isSelected)
MaterialTheme.colorScheme.primaryContainer
else
Color.Transparent
val borderColor = if (isSelected)
MaterialTheme.colorScheme.primary
else
Color.Transparent
val contentColor = if (isSelected)
MaterialTheme.colorScheme.onPrimaryContainer
else
MaterialTheme.colorScheme.onSurface
MaterialTheme(
colorScheme = MaterialTheme.colorScheme.copy(
surface = MaterialTheme.colorScheme.surfaceContainerHigh
)
) {
AlertDialog(
onDismissRequest = {
dismiss()
},
title = {
Text(
text = stringResource(R.string.settings_uninstall),
style = MaterialTheme.typography.headlineSmall,
)
},
text = {
Column(
modifier = Modifier.padding(vertical = 8.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
options.forEachIndexed { index, option ->
val isSelected = selectedOption == option
val backgroundColor = if (isSelected)
MaterialTheme.colorScheme.primaryContainer
else
Color.Transparent
val contentColor = if (isSelected)
MaterialTheme.colorScheme.onPrimaryContainer
else
MaterialTheme.colorScheme.onSurface
Row(
modifier = Modifier
.fillMaxWidth()
.clip(MaterialTheme.shapes.medium)
.background(backgroundColor)
.border(
width = 1.dp,
color = borderColor,
shape = MaterialTheme.shapes.medium
)
.clickable {
selectedOption = option
}
.padding(vertical = 12.dp, horizontal = 8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = option.icon,
contentDescription = null,
tint = if (isSelected)
MaterialTheme.colorScheme.primary
else
MaterialTheme.colorScheme.primary,
Row(
modifier = Modifier
.padding(end = 16.dp)
.size(24.dp)
)
Column(
modifier = Modifier.weight(1f)
.fillMaxWidth()
.clip(MaterialTheme.shapes.medium)
.background(backgroundColor)
.clickable {
selectedOption = option
}
.padding(vertical = 12.dp, horizontal = 8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = listOptions[index].titleText,
style = MaterialTheme.typography.titleMedium,
color = contentColor
Icon(
imageVector = option.icon,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier
.padding(end = 16.dp)
.size(24.dp)
)
listOptions[index].subtitleText?.let {
Column(
modifier = Modifier.weight(1f)
) {
Text(
text = it,
style = MaterialTheme.typography.bodyMedium,
color = if (isSelected)
contentColor.copy(alpha = 0.8f)
else
MaterialTheme.colorScheme.onSurfaceVariant
text = listOptions[index].titleText,
style = MaterialTheme.typography.titleMedium,
)
listOptions[index].subtitleText?.let {
Text(
text = it,
style = MaterialTheme.typography.bodyMedium,
color = if (isSelected)
contentColor.copy(alpha = 0.8f)
else
MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
if (isSelected) {
Icon(
imageVector = Icons.Default.RadioButtonChecked,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(24.dp)
)
} else {
Icon(
imageVector = Icons.Default.RadioButtonUnchecked,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.size(24.dp)
)
}
}
if (isSelected) {
Icon(
imageVector = Icons.Default.RadioButtonChecked,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(24.dp)
)
} else {
Icon(
imageVector = Icons.Default.RadioButtonUnchecked,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.size(24.dp)
)
}
}
}
}
},
confirmButton = {
Button(
onClick = {
selectedOption?.let { onSelected(it) }
dismiss()
},
enabled = selectedOption != null,
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.primary,
contentColor = MaterialTheme.colorScheme.onPrimary,
disabledContainerColor = MaterialTheme.colorScheme.surfaceVariant,
disabledContentColor = MaterialTheme.colorScheme.onSurfaceVariant
)
) {
Text(
text = stringResource(android.R.string.ok)
)
}
},
dismissButton = {
TextButton(
onClick = {
dismiss()
},
confirmButton = {
Button(
onClick = {
selectedOption?.let { onSelected(it) }
dismiss()
},
enabled = selectedOption != null,
) {
Text(
text = stringResource(android.R.string.ok)
)
}
) {
Text(
text = stringResource(android.R.string.cancel),
color = MaterialTheme.colorScheme.primary
)
}
},
containerColor = MaterialTheme.colorScheme.secondaryContainer,
shape = MaterialTheme.shapes.extraLarge,
tonalElevation = 4.dp
)
},
dismissButton = {
TextButton(
onClick = {
dismiss()
}
) {
Text(
text = stringResource(android.R.string.cancel),
)
}
},
shape = MaterialTheme.shapes.extraLarge,
tonalElevation = 4.dp
)
}
}
}
@@ -773,14 +785,12 @@ fun rememberUninstallDialog(onSelected: (UninstallType) -> Unit): DialogHandle {
private fun TopBar(
scrollBehavior: TopAppBarScrollBehavior? = null
) {
val systemIsDark = isSystemInDarkTheme()
val cardColor = MaterialTheme.colorScheme.surfaceContainerLow
val cardAlpha = if (ThemeConfig.customBackgroundUri != null) {
cardAlpha
val colorScheme = MaterialTheme.colorScheme
val cardColor = if (CardConfig.isCustomBackgroundEnabled) {
colorScheme.surfaceContainerLow
} else {
if (systemIsDark) 0.8f else 1f
colorScheme.background
}
TopAppBar(
title = {
Text(

File diff suppressed because it is too large Load Diff

View File

@@ -207,13 +207,13 @@ private fun TemplateItem(
)
Text(template.description)
FlowRow {
LabelText(label = "UID: ${template.uid}", backgroundColor = MaterialTheme.colorScheme.surface)
LabelText(label = "GID: ${template.gid}", backgroundColor = MaterialTheme.colorScheme.surface)
LabelText(label = template.context, backgroundColor = MaterialTheme.colorScheme.surface)
LabelText(label = "UID: ${template.uid}")
LabelText(label = "GID: ${template.gid}")
LabelText(label = template.context,)
if (template.local) {
LabelText(label = "local", backgroundColor = MaterialTheme.colorScheme.surface)
LabelText(label = "local")
} else {
LabelText(label = "remote", backgroundColor = MaterialTheme.colorScheme.surface)
LabelText(label = "remote")
}
}
}
@@ -231,7 +231,12 @@ private fun TopBar(
colors: TopAppBarColors,
scrollBehavior: TopAppBarScrollBehavior? = null
) {
val cardColor = MaterialTheme.colorScheme.surfaceContainerLow
val colorScheme = MaterialTheme.colorScheme
val cardColor = if (CardConfig.isCustomBackgroundEnabled) {
colorScheme.surfaceContainerLow
} else {
colorScheme.background
}
val cardAlpha = CardConfig.cardAlpha
TopAppBar(

View File

@@ -0,0 +1,581 @@
package com.sukisu.ultra.ui.screen.extensions
import android.annotation.SuppressLint
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Folder
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material.icons.filled.Update
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.filled.Visibility
import androidx.compose.material.icons.filled.VisibilityOff
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.sukisu.ultra.R
import com.sukisu.ultra.ui.util.SuSFSManager
import kotlinx.coroutines.launch
/**
* 空状态显示组件
*/
@Composable
fun EmptyStateCard(
message: String,
modifier: Modifier = Modifier
) {
Card(
modifier = modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.2f)
),
shape = RoundedCornerShape(12.dp)
) {
Box(
modifier = Modifier
.fillMaxWidth()
.padding(24.dp),
contentAlignment = Alignment.Center
) {
Text(
text = message,
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant,
textAlign = TextAlign.Center
)
}
}
}
/**
* 路径项目卡片组件
*/
@Composable
fun PathItemCard(
path: String,
icon: ImageVector,
onDelete: () -> Unit,
isLoading: Boolean = false,
additionalInfo: String? = null
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 1.dp),
shape = RoundedCornerShape(8.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 1.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.weight(1f)
) {
Icon(
imageVector = icon,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(18.dp)
)
Spacer(modifier = Modifier.width(12.dp))
Column {
Text(
text = path,
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium
)
if (additionalInfo != null) {
Text(
text = additionalInfo,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
}
IconButton(
onClick = onDelete,
enabled = !isLoading,
modifier = Modifier.size(32.dp)
) {
Icon(
imageVector = Icons.Default.Delete,
contentDescription = null,
tint = MaterialTheme.colorScheme.error,
modifier = Modifier.size(16.dp)
)
}
}
}
}
/**
* Kstat配置项目卡片组件
*/
@Composable
fun KstatConfigItemCard(
config: String,
onDelete: () -> Unit,
isLoading: Boolean = false
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 1.dp),
shape = RoundedCornerShape(8.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 1.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.weight(1f)
) {
Icon(
imageVector = Icons.Default.Settings,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(18.dp)
)
Spacer(modifier = Modifier.width(12.dp))
Column {
val parts = config.split("|")
if (parts.isNotEmpty()) {
Text(
text = parts[0], // 路径
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium
)
if (parts.size > 1) {
Text(
text = "${parts.drop(1).joinToString(" ")}",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
} else {
Text(
text = config,
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium
)
}
}
}
IconButton(
onClick = onDelete,
enabled = !isLoading,
modifier = Modifier.size(32.dp)
) {
Icon(
imageVector = Icons.Default.Delete,
contentDescription = null,
tint = MaterialTheme.colorScheme.error,
modifier = Modifier.size(16.dp)
)
}
}
}
}
/**
* Add Kstat路径项目卡片组件
*/
@Composable
fun AddKstatPathItemCard(
path: String,
onDelete: () -> Unit,
onUpdate: () -> Unit,
onUpdateFullClone: () -> Unit,
isLoading: Boolean = false
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 1.dp),
shape = RoundedCornerShape(8.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 1.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.weight(1f)
) {
Icon(
imageVector = Icons.Default.Folder,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(18.dp)
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = path,
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium
)
}
Row(
horizontalArrangement = Arrangement.spacedBy(4.dp)
) {
IconButton(
onClick = onUpdate,
enabled = !isLoading,
modifier = Modifier.size(32.dp)
) {
Icon(
imageVector = Icons.Default.Update,
contentDescription = null,
tint = MaterialTheme.colorScheme.secondary,
modifier = Modifier.size(16.dp)
)
}
IconButton(
onClick = onUpdateFullClone,
enabled = !isLoading,
modifier = Modifier.size(32.dp)
) {
Icon(
imageVector = Icons.Default.PlayArrow,
contentDescription = null,
tint = MaterialTheme.colorScheme.tertiary,
modifier = Modifier.size(16.dp)
)
}
IconButton(
onClick = onDelete,
enabled = !isLoading,
modifier = Modifier.size(32.dp)
) {
Icon(
imageVector = Icons.Default.Delete,
contentDescription = null,
tint = MaterialTheme.colorScheme.error,
modifier = Modifier.size(16.dp)
)
}
}
}
}
}
/**
* 启用功能状态卡片组件
*/
@Composable
fun FeatureStatusCard(
feature: SuSFSManager.EnabledFeature,
onRefresh: (() -> Unit)? = null,
@SuppressLint("ModifierParameter") modifier: Modifier = Modifier
) {
val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
// 日志配置对话框状态
var showLogConfigDialog by remember { mutableStateOf(false) }
var logEnabled by remember { mutableStateOf(SuSFSManager.getEnableLogState(context)) }
// 日志配置对话框
if (showLogConfigDialog) {
AlertDialog(
onDismissRequest = { showLogConfigDialog = false },
title = {
Text(
text = stringResource(R.string.susfs_log_config_title),
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold
)
},
text = {
Column(
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
Text(
text = stringResource(R.string.susfs_log_config_description),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = stringResource(R.string.susfs_enable_log_label),
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium
)
Switch(
checked = logEnabled,
onCheckedChange = { logEnabled = it }
)
}
}
},
confirmButton = {
Button(
onClick = {
coroutineScope.launch {
if (SuSFSManager.setEnableLog(context, logEnabled)) {
onRefresh?.invoke()
}
showLogConfigDialog = false
}
},
shape = RoundedCornerShape(8.dp)
) {
Text(stringResource(R.string.susfs_apply))
}
},
dismissButton = {
TextButton(
onClick = {
// 恢复原始状态
logEnabled = SuSFSManager.getEnableLogState(context)
showLogConfigDialog = false
},
shape = RoundedCornerShape(8.dp)
) {
Text(stringResource(R.string.cancel))
}
},
shape = RoundedCornerShape(12.dp)
)
}
Card(
modifier = modifier
.fillMaxWidth()
.padding(vertical = 1.dp)
.then(
if (feature.canConfigure) {
Modifier.clickable {
// 更新当前状态
logEnabled = SuSFSManager.getEnableLogState(context)
showLogConfigDialog = true
}
} else {
Modifier
}
),
shape = RoundedCornerShape(8.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 1.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column(
modifier = Modifier.weight(1f)
) {
Text(
text = feature.name,
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium
)
if (feature.canConfigure) {
Text(
text = stringResource(R.string.susfs_feature_configurable),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
// 状态标签
Surface(
shape = RoundedCornerShape(6.dp),
color = when {
feature.isEnabled -> MaterialTheme.colorScheme.primary
else -> Color.Gray
}
) {
Text(
text = feature.statusText,
style = MaterialTheme.typography.labelLarge,
color = when {
feature.isEnabled -> MaterialTheme.colorScheme.onPrimary
else -> Color.White
},
modifier = Modifier.padding(horizontal = 8.dp, vertical = 3.dp)
)
}
}
}
}
}
/**
* SUS挂载隐藏控制卡片组件
*/
@Composable
fun SusMountHidingControlCard(
hideSusMountsForAllProcs: Boolean,
isLoading: Boolean,
onToggleHiding: (Boolean) -> Unit
) {
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surface
),
shape = RoundedCornerShape(12.dp)
) {
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
// 标题行
Row(
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = if (hideSusMountsForAllProcs) Icons.Default.VisibilityOff else Icons.Default.Visibility,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(20.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = stringResource(R.string.susfs_hide_mounts_control_title),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.onSurface
)
}
// 描述文本
Text(
text = stringResource(R.string.susfs_hide_mounts_control_description),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
lineHeight = 16.sp
)
// 控制开关行
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column(
modifier = Modifier.weight(1f)
) {
Text(
text = stringResource(R.string.susfs_hide_mounts_for_all_procs_label),
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.onSurface
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = if (hideSusMountsForAllProcs) {
stringResource(R.string.susfs_hide_mounts_for_all_procs_enabled_description)
} else {
stringResource(R.string.susfs_hide_mounts_for_all_procs_disabled_description)
},
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
lineHeight = 14.sp
)
}
Switch(
checked = hideSusMountsForAllProcs,
onCheckedChange = onToggleHiding,
enabled = !isLoading
)
}
// 当前设置显示
Text(
text = stringResource(
R.string.susfs_hide_mounts_current_setting,
if (hideSusMountsForAllProcs) {
stringResource(R.string.susfs_hide_mounts_setting_all)
} else {
stringResource(R.string.susfs_hide_mounts_setting_non_ksu)
}
),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.primary,
fontWeight = FontWeight.Medium
)
// 建议文本
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f)
),
shape = RoundedCornerShape(8.dp)
) {
Text(
text = stringResource(R.string.susfs_hide_mounts_recommendation),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
lineHeight = 14.sp,
modifier = Modifier.padding(12.dp)
)
}
}
}
}

View File

@@ -10,19 +10,15 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.luminance
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
object CardConfig {
val settingElevation: Dp = 4.dp
val customBackgroundElevation: Dp = 0.dp
// 卡片透明度
var cardAlpha by mutableFloatStateOf(1f)
// 卡片亮度
var cardDim by mutableFloatStateOf(0f)
// 卡片阴影
var cardElevation by mutableStateOf(settingElevation)
var cardElevation by mutableStateOf(0.dp)
var isShadowEnabled by mutableStateOf(true)
var isCustomAlphaSet by mutableStateOf(false)
var isCustomDimSet by mutableStateOf(false)
@@ -69,37 +65,18 @@ object CardConfig {
*/
fun updateShadowEnabled(enabled: Boolean) {
isShadowEnabled = enabled
cardElevation = if (isCustomBackgroundEnabled && cardAlpha != 1f) {
customBackgroundElevation
} else if (enabled) {
settingElevation
} else {
customBackgroundElevation
}
cardElevation = 0.dp
}
/**
* 设置深色模式默认值
* 设置主题模式默认值
*/
fun setDarkModeDefaults() {
fun setThemeDefaults(isDarkMode: Boolean) {
if (!isCustomAlphaSet) {
cardAlpha = 1f
}
if (!isCustomDimSet) {
cardDim = 0.5f
}
updateShadowEnabled(isShadowEnabled)
}
/**
* 设置浅色模式默认值
*/
fun setLightModeDefaults() {
if (!isCustomAlphaSet) {
cardAlpha = 1f
}
if (!isCustomDimSet) {
cardDim = 0f
cardDim = if (isDarkMode) 0.5f else 0f
}
updateShadowEnabled(isShadowEnabled)
}
@@ -114,6 +91,19 @@ fun getCardColors(originalColor: Color) = CardDefaults.cardColors(
contentColor = determineContentColor(originalColor)
)
/**
* 获取卡片阴影配置
*/
@Composable
fun getCardElevation() = CardDefaults.cardElevation(
defaultElevation = CardConfig.cardElevation,
pressedElevation = CardConfig.cardElevation,
focusedElevation = CardConfig.cardElevation,
hoveredElevation = CardConfig.cardElevation,
draggedElevation = CardConfig.cardElevation,
disabledElevation = CardConfig.cardElevation
)
/**
* 根据背景颜色、主题模式和用户设置确定内容颜色
*/

View File

@@ -47,6 +47,7 @@ import com.sukisu.ultra.ui.util.saveTransformedBackground
import androidx.activity.SystemBarStyle
import androidx.activity.ComponentActivity
import androidx.activity.enableEdgeToEdge
import androidx.compose.material3.ColorScheme
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.graphics.toArgb
@@ -150,9 +151,9 @@ fun KernelSUTheme(
// 根据暗色模式和自定义背景调整卡片配置
val isDarkModeWithCustomBackground = darkTheme && ThemeConfig.customBackgroundUri != null
if (darkTheme && !dynamicColor) {
CardConfig.setDarkModeDefaults()
CardConfig.setThemeDefaults(true)
} else if (!darkTheme && !dynamicColor) {
CardConfig.setLightModeDefaults()
CardConfig.setThemeDefaults(false)
}
CardConfig.updateShadowEnabled(!isDarkModeWithCustomBackground)
@@ -216,7 +217,8 @@ fun KernelSUTheme(
modifier = Modifier
.fillMaxSize()
.zIndex(-2f)
.background(if (darkTheme) MaterialTheme.colorScheme.surfaceContainerLow else MaterialTheme.colorScheme.surfaceContainerLow)
.background(if (darkTheme) if (CardConfig.isCustomBackgroundEnabled) { colorScheme.surfaceContainerLow } else { colorScheme.background }
else if (CardConfig.isCustomBackgroundEnabled) { colorScheme.surfaceContainerLow } else { colorScheme.background })
)
// 自定义背景层
@@ -287,24 +289,32 @@ fun KernelSUTheme(
*/
@RequiresApi(Build.VERSION_CODES.S)
@Composable
private fun createDynamicDarkColorScheme(context: Context) =
dynamicDarkColorScheme(context).copy(
background = Color.Transparent,
surface = Color.Transparent,
onBackground = Color.White,
onSurface = Color.White
private fun createDynamicDarkColorScheme(context: Context): ColorScheme {
val scheme = dynamicDarkColorScheme(context)
return scheme.copy(
background = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else scheme.background,
surface = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else scheme.surface,
onBackground = scheme.onBackground,
onSurface = scheme.onSurface
)
}
/**
* 创建动态浅色颜色方案
*/
@RequiresApi(Build.VERSION_CODES.S)
@Composable
private fun createDynamicLightColorScheme(context: Context) =
dynamicLightColorScheme(context).copy(
background = Color.Transparent,
surface = Color.Transparent
private fun createDynamicLightColorScheme(context: Context): ColorScheme {
val scheme = dynamicLightColorScheme(context)
return scheme.copy(
background = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else scheme.background,
surface = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else scheme.surface,
onBackground = scheme.onBackground,
onSurface = scheme.onSurface
)
}
/**
* 创建深色颜色方案
@@ -327,9 +337,9 @@ private fun createDarkColorScheme() = darkColorScheme(
onError = ThemeConfig.currentTheme.onErrorDark,
errorContainer = ThemeConfig.currentTheme.errorContainerDark,
onErrorContainer = ThemeConfig.currentTheme.onErrorContainerDark,
background = Color.Transparent,
background = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else ThemeConfig.currentTheme.backgroundDark,
onBackground = ThemeConfig.currentTheme.onBackgroundDark,
surface = Color.Transparent,
surface = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else ThemeConfig.currentTheme.surfaceDark,
onSurface = ThemeConfig.currentTheme.onSurfaceDark,
surfaceVariant = ThemeConfig.currentTheme.surfaceVariantDark,
onSurfaceVariant = ThemeConfig.currentTheme.onSurfaceVariantDark,
@@ -369,9 +379,9 @@ private fun createLightColorScheme() = lightColorScheme(
onError = ThemeConfig.currentTheme.onErrorLight,
errorContainer = ThemeConfig.currentTheme.errorContainerLight,
onErrorContainer = ThemeConfig.currentTheme.onErrorContainerLight,
background = Color.Transparent,
background = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else ThemeConfig.currentTheme.backgroundLight,
onBackground = ThemeConfig.currentTheme.onBackgroundLight,
surface = Color.Transparent,
surface = if (CardConfig.isCustomBackgroundEnabled) Color.Transparent else ThemeConfig.currentTheme.surfaceLight,
onSurface = ThemeConfig.currentTheme.onSurfaceLight,
surfaceVariant = ThemeConfig.currentTheme.surfaceVariantLight,
onSurfaceVariant = ThemeConfig.currentTheme.onSurfaceVariantLight,
@@ -390,6 +400,7 @@ private fun createLightColorScheme() = lightColorScheme(
surfaceContainerHighest = ThemeConfig.currentTheme.surfaceContainerHighestLight,
)
/**
* 复制图片到应用内部存储并提升持久性
*/

View File

@@ -1,17 +1,14 @@
package com.sukisu.ultra.ui.util
import android.app.AlertDialog
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.util.Log
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarResult
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.platform.LocalContext
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -25,18 +22,78 @@ import java.util.Date
import java.util.Locale
object ModuleModify {
suspend fun showRestoreConfirmation(context: Context): Boolean {
val result = CompletableDeferred<Boolean>()
withContext(Dispatchers.Main) {
AlertDialog.Builder(context)
.setTitle(context.getString(R.string.restore_confirm_title))
.setMessage(context.getString(R.string.restore_confirm_message))
.setPositiveButton(context.getString(R.string.confirm)) { _, _ -> result.complete(true) }
.setNegativeButton(context.getString(R.string.cancel)) { _, _ -> result.complete(false) }
.setOnCancelListener { result.complete(false) }
.show()
@Composable
fun RestoreConfirmationDialog(
showDialog: Boolean,
onConfirm: () -> Unit,
onDismiss: () -> Unit
) {
val context = LocalContext.current
if (showDialog) {
AlertDialog(
onDismissRequest = onDismiss,
title = {
Text(
text = context.getString(R.string.restore_confirm_title),
style = MaterialTheme.typography.headlineSmall
)
},
text = {
Text(
text = context.getString(R.string.restore_confirm_message),
style = MaterialTheme.typography.bodyMedium
)
},
confirmButton = {
TextButton(onClick = onConfirm) {
Text(context.getString(R.string.confirm))
}
},
dismissButton = {
TextButton(onClick = onDismiss) {
Text(context.getString(R.string.cancel))
}
}
)
}
}
@Composable
fun AllowlistRestoreConfirmationDialog(
showDialog: Boolean,
onConfirm: () -> Unit,
onDismiss: () -> Unit
) {
val context = LocalContext.current
if (showDialog) {
AlertDialog(
onDismissRequest = onDismiss,
title = {
Text(
text = context.getString(R.string.allowlist_restore_confirm_title),
style = MaterialTheme.typography.headlineSmall
)
},
text = {
Text(
text = context.getString(R.string.allowlist_restore_confirm_message),
style = MaterialTheme.typography.bodyMedium
)
},
confirmButton = {
TextButton(onClick = onConfirm) {
Text(context.getString(R.string.confirm))
}
},
dismissButton = {
TextButton(onClick = onDismiss) {
Text(context.getString(R.string.cancel))
}
}
)
}
return result.await()
}
suspend fun backupModules(context: Context, snackBarHost: SnackbarHostState, uri: Uri) {
@@ -82,8 +139,19 @@ object ModuleModify {
}
}
suspend fun restoreModules(context: Context, snackBarHost: SnackbarHostState, uri: Uri) {
val userConfirmed = showRestoreConfirmation(context)
suspend fun restoreModules(
context: Context,
snackBarHost: SnackbarHostState,
uri: Uri,
showConfirmDialog: (Boolean) -> Unit,
confirmResult: CompletableDeferred<Boolean>
) {
// 显示确认对话框
withContext(Dispatchers.Main) {
showConfirmDialog(true)
}
val userConfirmed = confirmResult.await()
if (!userConfirmed) return
withContext(Dispatchers.IO) {
@@ -132,20 +200,6 @@ object ModuleModify {
}
}
suspend fun showAllowlistRestoreConfirmation(context: Context): Boolean {
val result = CompletableDeferred<Boolean>()
withContext(Dispatchers.Main) {
AlertDialog.Builder(context)
.setTitle(context.getString(R.string.allowlist_restore_confirm_title))
.setMessage(context.getString(R.string.allowlist_restore_confirm_message))
.setPositiveButton(context.getString(R.string.confirm)) { _, _ -> result.complete(true) }
.setNegativeButton(context.getString(R.string.cancel)) { _, _ -> result.complete(false) }
.setOnCancelListener { result.complete(false) }
.show()
}
return result.await()
}
suspend fun backupAllowlist(context: Context, snackBarHost: SnackbarHostState, uri: Uri) {
withContext(Dispatchers.IO) {
try {
@@ -182,8 +236,19 @@ object ModuleModify {
}
}
suspend fun restoreAllowlist(context: Context, snackBarHost: SnackbarHostState, uri: Uri) {
val userConfirmed = showAllowlistRestoreConfirmation(context)
suspend fun restoreAllowlist(
context: Context,
snackBarHost: SnackbarHostState,
uri: Uri,
showConfirmDialog: (Boolean) -> Unit,
confirmResult: CompletableDeferred<Boolean>
) {
// 显示确认对话框
withContext(Dispatchers.Main) {
showConfirmDialog(true)
}
val userConfirmed = confirmResult.await()
if (!userConfirmed) return
withContext(Dispatchers.IO) {
@@ -246,13 +311,42 @@ object ModuleModify {
context: Context,
snackBarHost: SnackbarHostState,
scope: kotlinx.coroutines.CoroutineScope = rememberCoroutineScope()
) = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == android.app.Activity.RESULT_OK) {
result.data?.data?.let { uri ->
scope.launch {
restoreModules(context, snackBarHost, uri)
): androidx.activity.result.ActivityResultLauncher<Intent> {
var showRestoreDialog by remember { mutableStateOf(false) }
var restoreConfirmResult by remember { mutableStateOf<CompletableDeferred<Boolean>?>(null) }
var pendingUri by remember { mutableStateOf<Uri?>(null) }
// 显示恢复确认对话框
RestoreConfirmationDialog(
showDialog = showRestoreDialog,
onConfirm = {
showRestoreDialog = false
restoreConfirmResult?.complete(true)
},
onDismiss = {
showRestoreDialog = false
restoreConfirmResult?.complete(false)
}
)
return rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == android.app.Activity.RESULT_OK) {
result.data?.data?.let { uri ->
pendingUri = uri
scope.launch {
val confirmResult = CompletableDeferred<Boolean>()
restoreConfirmResult = confirmResult
restoreModules(
context = context,
snackBarHost = snackBarHost,
uri = uri,
showConfirmDialog = { show -> showRestoreDialog = show },
confirmResult = confirmResult
)
}
}
}
}
@@ -280,13 +374,42 @@ object ModuleModify {
context: Context,
snackBarHost: SnackbarHostState,
scope: kotlinx.coroutines.CoroutineScope = rememberCoroutineScope()
) = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == android.app.Activity.RESULT_OK) {
result.data?.data?.let { uri ->
scope.launch {
restoreAllowlist(context, snackBarHost, uri)
): androidx.activity.result.ActivityResultLauncher<Intent> {
var showAllowlistRestoreDialog by remember { mutableStateOf(false) }
var allowlistRestoreConfirmResult by remember { mutableStateOf<CompletableDeferred<Boolean>?>(null) }
var pendingUri by remember { mutableStateOf<Uri?>(null) }
// 显示允许列表恢复确认对话框
AllowlistRestoreConfirmationDialog(
showDialog = showAllowlistRestoreDialog,
onConfirm = {
showAllowlistRestoreDialog = false
allowlistRestoreConfirmResult?.complete(true)
},
onDismiss = {
showAllowlistRestoreDialog = false
allowlistRestoreConfirmResult?.complete(false)
}
)
return rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == android.app.Activity.RESULT_OK) {
result.data?.data?.let { uri ->
pendingUri = uri
scope.launch {
val confirmResult = CompletableDeferred<Boolean>()
allowlistRestoreConfirmResult = confirmResult
restoreAllowlist(
context = context,
snackBarHost = snackBarHost,
uri = uri,
showConfirmDialog = { show -> showAllowlistRestoreDialog = show },
confirmResult = confirmResult
)
}
}
}
}

View File

@@ -0,0 +1,44 @@
package com.sukisu.ultra.ui.util
import android.app.Activity
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import com.sukisu.ultra.ui.MainActivity
/**
* 重启应用程序
**/
fun Context.restartApp(
activityClass: Class<out Activity>,
finishCurrent: Boolean = true,
clearTask: Boolean = true,
newTask: Boolean = true
) {
val intent = Intent(this, activityClass)
if (clearTask) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
if (newTask) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
if (finishCurrent && this is Activity) {
finish()
}
}
/**
* 刷新启动器图标
*/
fun toggleLauncherIcon(context: Context, useAlt: Boolean) {
val pm = context.packageManager
val main = ComponentName(context, MainActivity::class.java.name)
val alt = ComponentName(context, "${MainActivity::class.java.name}Alias")
if (useAlt) {
pm.setComponentEnabledSetting(main, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP)
pm.setComponentEnabledSetting(alt, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP)
} else {
pm.setComponentEnabledSetting(alt, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP)
pm.setComponentEnabledSetting(main, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP)
}
}

View File

@@ -0,0 +1,674 @@
package com.sukisu.ultra.ui.util
import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import android.widget.Toast
import com.dergoogler.mmrl.platform.Platform.Companion.context
import com.sukisu.ultra.Natives
import com.sukisu.ultra.R
import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import androidx.core.content.edit
/**
* SuSFS 配置管理器
* 用于管理SuSFS相关的配置和命令执行
*/
object SuSFSManager {
private const val PREFS_NAME = "susfs_config"
private const val KEY_UNAME_VALUE = "uname_value"
private const val KEY_BUILD_TIME_VALUE = "build_time_value"
private const val KEY_AUTO_START_ENABLED = "auto_start_enabled"
private const val KEY_SUS_PATHS = "sus_paths"
private const val KEY_SUS_MOUNTS = "sus_mounts"
private const val KEY_TRY_UMOUNTS = "try_umounts"
private const val KEY_ANDROID_DATA_PATH = "android_data_path"
private const val KEY_SDCARD_PATH = "sdcard_path"
private const val KEY_ENABLE_LOG = "enable_log"
private const val KEY_EXECUTE_IN_POST_FS_DATA = "execute_in_post_fs_data"
private const val KEY_KSTAT_CONFIGS = "kstat_configs"
private const val KEY_ADD_KSTAT_PATHS = "add_kstat_paths"
private const val KEY_HIDE_SUS_MOUNTS_FOR_ALL_PROCS = "hide_sus_mounts_for_all_procs"
// 常量
private const val SUSFS_BINARY_BASE_NAME = "ksu_susfs"
private const val DEFAULT_UNAME = "default"
private const val DEFAULT_BUILD_TIME = "default"
private const val MODULE_ID = "susfs_manager"
private const val MODULE_PATH = "/data/adb/modules/$MODULE_ID"
data class SlotInfo(val slotName: String, val uname: String, val buildTime: String)
data class CommandResult(val isSuccess: Boolean, val output: String, val errorOutput: String = "")
data class EnabledFeature(
val name: String,
val isEnabled: Boolean,
val statusText: String = if (isEnabled) context.getString(R.string.susfs_feature_enabled) else context.getString(R.string.susfs_feature_disabled),
val canConfigure: Boolean = false
)
// 命令执行
private fun getPrefs(context: Context): SharedPreferences =
context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
private fun getSuSFSVersionUse(): String = try {
getSuSFSVersion()
} catch (_: Exception) { "1.5.8" }
private fun getSuSFSBinaryName(): String = "${SUSFS_BINARY_BASE_NAME}_${getSuSFSVersionUse().removePrefix("v")}"
private fun getSuSFSTargetPath(): String = "/data/adb/ksu/bin/${getSuSFSBinaryName()}"
private fun runCmd(shell: Shell, cmd: String): String {
return shell.newJob()
.add(cmd)
.to(mutableListOf<String>(), null)
.exec().out
.joinToString("\n")
}
private fun runCmdWithResult(cmd: String): CommandResult {
val result = Shell.getShell().newJob().add(cmd).exec()
return CommandResult(result.isSuccess, result.out.joinToString("\n"), result.err.joinToString("\n"))
}
// 版本比较
private fun compareVersions(version1: String, version2: String): Int {
val v1Parts = version1.removePrefix("v").split(".").map { it.toIntOrNull() ?: 0 }
val v2Parts = version2.removePrefix("v").split(".").map { it.toIntOrNull() ?: 0 }
val maxLength = maxOf(v1Parts.size, v2Parts.size)
for (i in 0 until maxLength) {
val v1Part = v1Parts.getOrNull(i) ?: 0
val v2Part = v2Parts.getOrNull(i) ?: 0
when {
v1Part > v2Part -> return 1
v1Part < v2Part -> return -1
}
}
return 0
}
// 检查当前SuSFS版本是否支持SUS挂载隐藏控制功能
fun isSusVersion_1_5_8(): Boolean {
return try {
val currentVersion = getSuSFSVersion()
compareVersions(currentVersion, "1.5.8") >= 0
} catch (_: Exception) {
true
}
}
// 配置存取方法
fun saveUnameValue(context: Context, value: String) =
getPrefs(context).edit { putString(KEY_UNAME_VALUE, value) }
fun getUnameValue(context: Context): String =
getPrefs(context).getString(KEY_UNAME_VALUE, DEFAULT_UNAME) ?: DEFAULT_UNAME
fun saveBuildTimeValue(context: Context, value: String) =
getPrefs(context).edit { putString(KEY_BUILD_TIME_VALUE, value)}
fun getBuildTimeValue(context: Context): String =
getPrefs(context).getString(KEY_BUILD_TIME_VALUE, DEFAULT_BUILD_TIME) ?: DEFAULT_BUILD_TIME
fun getLastAppliedValue(context: Context): String = getUnameValue(context)
fun getLastAppliedBuildTime(context: Context): String = getBuildTimeValue(context)
fun setAutoStartEnabled(context: Context, enabled: Boolean) =
getPrefs(context).edit { putBoolean(KEY_AUTO_START_ENABLED, enabled) }
fun isAutoStartEnabled(context: Context): Boolean =
getPrefs(context).getBoolean(KEY_AUTO_START_ENABLED, false)
fun saveEnableLogState(context: Context, enabled: Boolean) =
getPrefs(context).edit { putBoolean(KEY_ENABLE_LOG, enabled) }
fun getEnableLogState(context: Context): Boolean =
getPrefs(context).getBoolean(KEY_ENABLE_LOG, false)
fun getExecuteInPostFsData(context: Context): Boolean =
getPrefs(context).getBoolean(KEY_EXECUTE_IN_POST_FS_DATA, false)
fun saveExecuteInPostFsData(context: Context, executeInPostFsData: Boolean) {
getPrefs(context).edit { putBoolean(KEY_EXECUTE_IN_POST_FS_DATA, executeInPostFsData) }
if (isAutoStartEnabled(context)) {
kotlinx.coroutines.CoroutineScope(Dispatchers.Default).launch {
removeMagiskModule()
createMagiskModule(context)
}
}
}
// SUS挂载隐藏控制
fun saveHideSusMountsForAllProcs(context: Context, hideForAll: Boolean) =
getPrefs(context).edit { putBoolean(KEY_HIDE_SUS_MOUNTS_FOR_ALL_PROCS, hideForAll) }
fun getHideSusMountsForAllProcs(context: Context): Boolean =
getPrefs(context).getBoolean(KEY_HIDE_SUS_MOUNTS_FOR_ALL_PROCS, true)
// 路径和配置管理
fun saveSusPaths(context: Context, paths: Set<String>) =
getPrefs(context).edit { putStringSet(KEY_SUS_PATHS, paths) }
fun getSusPaths(context: Context): Set<String> =
getPrefs(context).getStringSet(KEY_SUS_PATHS, emptySet()) ?: emptySet()
fun saveSusMounts(context: Context, mounts: Set<String>) =
getPrefs(context).edit { putStringSet(KEY_SUS_MOUNTS, mounts) }
fun getSusMounts(context: Context): Set<String> =
getPrefs(context).getStringSet(KEY_SUS_MOUNTS, emptySet()) ?: emptySet()
fun saveTryUmounts(context: Context, umounts: Set<String>) =
getPrefs(context).edit { putStringSet(KEY_TRY_UMOUNTS, umounts) }
fun getTryUmounts(context: Context): Set<String> =
getPrefs(context).getStringSet(KEY_TRY_UMOUNTS, emptySet()) ?: emptySet()
fun saveKstatConfigs(context: Context, configs: Set<String>) =
getPrefs(context).edit { putStringSet(KEY_KSTAT_CONFIGS, configs) }
fun getKstatConfigs(context: Context): Set<String> =
getPrefs(context).getStringSet(KEY_KSTAT_CONFIGS, emptySet()) ?: emptySet()
fun saveAddKstatPaths(context: Context, paths: Set<String>) =
getPrefs(context).edit { putStringSet(KEY_ADD_KSTAT_PATHS, paths) }
fun getAddKstatPaths(context: Context): Set<String> =
getPrefs(context).getStringSet(KEY_ADD_KSTAT_PATHS, emptySet()) ?: emptySet()
@SuppressLint("SdCardPath")
fun saveAndroidDataPath(context: Context, path: String) =
getPrefs(context).edit { putString(KEY_ANDROID_DATA_PATH, path) }
@SuppressLint("SdCardPath")
fun getAndroidDataPath(context: Context): String =
getPrefs(context).getString(KEY_ANDROID_DATA_PATH, "/sdcard/Android/data") ?: "/sdcard/Android/data"
@SuppressLint("SdCardPath")
fun saveSdcardPath(context: Context, path: String) =
getPrefs(context).edit { putString(KEY_SDCARD_PATH, path) }
@SuppressLint("SdCardPath")
fun getSdcardPath(context: Context): String =
getPrefs(context).getString(KEY_SDCARD_PATH, "/sdcard") ?: "/sdcard"
// 槽位信息获取
suspend fun getCurrentSlotInfo(): List<SlotInfo> = withContext(Dispatchers.IO) {
try {
val slotInfoList = mutableListOf<SlotInfo>()
val shell = Shell.getShell()
listOf("boot_a", "boot_b").forEach { slot ->
val unameCmd =
"strings -n 20 /dev/block/by-name/$slot | awk '/Linux version/ && ++c==2 {print $3; exit}'"
val buildTimeCmd = "strings -n 20 /dev/block/by-name/$slot | sed -n '/Linux version.*#/{s/.*#/#/p;q}'"
val uname = runCmd(shell, unameCmd).trim()
val buildTime = runCmd(shell, buildTimeCmd).trim()
if (uname.isNotEmpty() && buildTime.isNotEmpty()) {
slotInfoList.add(SlotInfo(slot, uname.ifEmpty { "unknown" }, buildTime.ifEmpty { "unknown" }))
}
}
slotInfoList
} catch (e: Exception) {
e.printStackTrace()
emptyList()
}
}
suspend fun getCurrentActiveSlot(): String = withContext(Dispatchers.IO) {
try {
val shell = Shell.getShell()
val suffix = runCmd(shell, "getprop ro.boot.slot_suffix").trim()
when (suffix) {
"_a" -> "boot_a"
"_b" -> "boot_b"
else -> "unknown"
}
} catch (_: Exception) {
"unknown"
}
}
// 二进制文件管理
private suspend fun copyBinaryFromAssets(context: Context): String? = withContext(Dispatchers.IO) {
try {
val binaryName = getSuSFSBinaryName()
val targetPath = getSuSFSTargetPath()
val tempFile = File(context.cacheDir, binaryName)
context.assets.open(binaryName).use { input ->
FileOutputStream(tempFile).use { output ->
input.copyTo(output)
}
}
val success = runCmdWithResult("cp '${tempFile.absolutePath}' '$targetPath' && chmod 755 '$targetPath'").isSuccess
tempFile.delete()
if (success && runCmdWithResult("test -f '$targetPath'").isSuccess) targetPath else null
} catch (e: IOException) {
e.printStackTrace()
null
}
}
fun isBinaryAvailable(context: Context): Boolean = try {
context.assets.open(getSuSFSBinaryName()).use { true }
} catch (_: IOException) { false }
// 命令执行
private suspend fun executeSusfsCommand(context: Context, command: String): Boolean = withContext(Dispatchers.IO) {
try {
val binaryPath = copyBinaryFromAssets(context) ?: run {
showToast(context, context.getString(R.string.susfs_binary_not_found))
return@withContext false
}
val result = runCmdWithResult("$binaryPath $command")
if (!result.isSuccess) {
showToast(context, "${context.getString(R.string.susfs_command_failed)}\n${result.output}\n${result.errorOutput}")
}
result.isSuccess
} catch (e: Exception) {
e.printStackTrace()
showToast(context, context.getString(R.string.susfs_command_error, e.message ?: "Unknown error"))
false
}
}
private suspend fun executeSusfsCommandWithOutput(context: Context, command: String): CommandResult = withContext(Dispatchers.IO) {
try {
val binaryPath = copyBinaryFromAssets(context) ?: return@withContext CommandResult(
false, "", context.getString(R.string.susfs_binary_not_found)
)
runCmdWithResult("$binaryPath $command")
} catch (e: Exception) {
e.printStackTrace()
CommandResult(false, "", e.message ?: "Unknown error")
}
}
private suspend fun showToast(context: Context, message: String) = withContext(Dispatchers.Main) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
}
private inline fun <reified T> Map<String, Any?>.getSetSafe(key: String): Set<T> {
return when (val value = this[key]) {
is Set<*> -> value.filterIsInstance<T>().toSet()
else -> emptySet()
}
}
// 模块管理
private suspend fun createMagiskModule(context: Context): Boolean = withContext(Dispatchers.IO) {
try {
val targetPath = getSuSFSTargetPath()
// 创建模块目录
if (!runCmdWithResult("mkdir -p $MODULE_PATH").isSuccess) return@withContext false
// 创建module.prop
val moduleProp = ScriptGenerator.generateModuleProp(MODULE_ID)
if (!runCmdWithResult("cat > $MODULE_PATH/module.prop << 'EOF'\n$moduleProp\nEOF").isSuccess) return@withContext false
// 获取配置
val config = mapOf(
"unameValue" to getUnameValue(context),
"buildTimeValue" to getBuildTimeValue(context),
"executeInPostFsData" to getExecuteInPostFsData(context),
"susPaths" to getSusPaths(context),
"susMounts" to getSusMounts(context),
"tryUmounts" to getTryUmounts(context),
"androidDataPath" to getAndroidDataPath(context),
"sdcardPath" to getSdcardPath(context),
"enableLog" to getEnableLogState(context),
"kstatConfigs" to getKstatConfigs(context),
"addKstatPaths" to getAddKstatPaths(context),
"hideSusMountsForAllProcs" to getHideSusMountsForAllProcs(context)
)
// 生成脚本
val scripts = mapOf(
"service.sh" to ScriptGenerator.generateServiceScript(
targetPath, config["unameValue"] as String, config["buildTimeValue"] as String,
config.getSetSafe<String>("susPaths"), config["androidDataPath"] as String,
config["sdcardPath"] as String, config["enableLog"] as Boolean,
config["executeInPostFsData"] as Boolean, config.getSetSafe<String>("kstatConfigs"),
config.getSetSafe<String>("addKstatPaths")
),
"post-fs-data.sh" to ScriptGenerator.generatePostFsDataScript(
targetPath, config["unameValue"] as String, config["buildTimeValue"] as String,
config["executeInPostFsData"] as Boolean
),
"post-mount.sh" to ScriptGenerator.generatePostMountScript(
targetPath, config.getSetSafe<String>("susMounts"), config.getSetSafe<String>("tryUmounts")
),
"boot-completed.sh" to ScriptGenerator.generateBootCompletedScript(
targetPath, config["hideSusMountsForAllProcs"] as Boolean
)
)
// 创建脚本文件
scripts.all { (filename, content) ->
runCmdWithResult("cat > $MODULE_PATH/$filename << 'EOF'\n$content\nEOF").isSuccess &&
runCmdWithResult("chmod 755 $MODULE_PATH/$filename").isSuccess
}
} catch (e: Exception) {
e.printStackTrace()
false
}
}
private suspend fun removeMagiskModule(): Boolean = withContext(Dispatchers.IO) {
try {
runCmdWithResult("rm -rf $MODULE_PATH").isSuccess
} catch (e: Exception) {
e.printStackTrace()
false
}
}
// 功能状态获取
suspend fun getEnabledFeatures(context: Context): List<EnabledFeature> = withContext(Dispatchers.IO) {
try {
Natives.getSusfsFeatureStatus()?.let { status ->
parseEnabledFeaturesFromStatus(context, status)
} ?: emptyList()
} catch (e: Exception) {
e.printStackTrace()
emptyList()
}
}
private fun parseEnabledFeaturesFromStatus(context: Context, status: Natives.SusfsFeatureStatus): List<EnabledFeature> {
val featureList = listOf(
Triple("status_sus_path", context.getString(R.string.sus_path_feature_label), status.statusSusPath),
Triple("status_sus_mount", context.getString(R.string.sus_mount_feature_label), status.statusSusMount),
Triple("status_try_umount", context.getString(R.string.try_umount_feature_label), status.statusTryUmount),
Triple("status_spoof_uname", context.getString(R.string.spoof_uname_feature_label), status.statusSpoofUname),
Triple("status_spoof_cmdline", context.getString(R.string.spoof_cmdline_feature_label), status.statusSpoofCmdline),
Triple("status_open_redirect", context.getString(R.string.open_redirect_feature_label), status.statusOpenRedirect),
Triple("status_enable_log", context.getString(R.string.enable_log_feature_label), status.statusEnableLog),
Triple("status_auto_default_mount", context.getString(R.string.auto_default_mount_feature_label), status.statusAutoDefaultMount),
Triple("status_auto_bind_mount", context.getString(R.string.auto_bind_mount_feature_label), status.statusAutoBindMount),
Triple("status_auto_try_umount_bind", context.getString(R.string.auto_try_umount_bind_feature_label), status.statusAutoTryUmountBind),
Triple("status_hide_symbols", context.getString(R.string.hide_symbols_feature_label), status.statusHideSymbols),
Triple("status_sus_kstat", context.getString(R.string.sus_kstat_feature_label), status.statusSusKstat),
Triple("status_magic_mount", context.getString(R.string.magic_mount_feature_label), status.statusMagicMount),
Triple("status_sus_su", context.getString(R.string.sus_su_feature_label), status.statusSusSu)
)
return featureList.map { (id, displayName, isEnabled) ->
val statusText = if (isEnabled) context.getString(R.string.susfs_feature_enabled) else context.getString(R.string.susfs_feature_disabled)
val canConfigure = id == "status_enable_log"
EnabledFeature(displayName, isEnabled, statusText, canConfigure)
}.sortedBy { it.name }
}
// sus日志开关
suspend fun setEnableLog(context: Context, enabled: Boolean): Boolean {
val success = executeSusfsCommand(context, "enable_log ${if (enabled) 1 else 0}")
if (success) {
saveEnableLogState(context, enabled)
if (isAutoStartEnabled(context)) createMagiskModule(context)
showToast(context, if (enabled) context.getString(R.string.susfs_log_enabled) else context.getString(R.string.susfs_log_disabled))
}
return success
}
// SUS挂载隐藏控制
suspend fun setHideSusMountsForAllProcs(context: Context, hideForAll: Boolean): Boolean {
if (!isSusVersion_1_5_8()) {
return false
}
val success = executeSusfsCommand(context, "hide_sus_mnts_for_all_procs ${if (hideForAll) 1 else 0}")
if (success) {
saveHideSusMountsForAllProcs(context, hideForAll)
if (isAutoStartEnabled(context)) createMagiskModule(context)
showToast(context, if (hideForAll)
context.getString(R.string.susfs_hide_mounts_all_enabled)
else
context.getString(R.string.susfs_hide_mounts_all_disabled)
)
}
return success
}
// uname和构建时间
@SuppressLint("StringFormatMatches")
suspend fun setUname(context: Context, unameValue: String, buildTimeValue: String): Boolean {
val success = executeSusfsCommand(context, "set_uname '$unameValue' '$buildTimeValue'")
if (success) {
saveUnameValue(context, unameValue)
saveBuildTimeValue(context, buildTimeValue)
if (isAutoStartEnabled(context)) createMagiskModule(context)
showToast(context, context.getString(R.string.susfs_uname_set_success, unameValue, buildTimeValue))
}
return success
}
// 添加SUS路径
@SuppressLint("StringFormatInvalid")
suspend fun addSusPath(context: Context, path: String): Boolean {
val result = executeSusfsCommandWithOutput(context, "add_sus_path '$path'")
val isActuallySuccessful = result.isSuccess && !result.output.contains("not found, skip adding")
if (isActuallySuccessful) {
saveSusPaths(context, getSusPaths(context) + path)
if (isAutoStartEnabled(context)) createMagiskModule(context)
showToast(context, context.getString(R.string.susfs_sus_path_added_success, path))
} else {
val errorMessage = if (result.output.contains("not found, skip adding")) {
context.getString(R.string.susfs_path_not_found_error, path)
} else {
"${context.getString(R.string.susfs_command_failed)}\n${result.output}\n${result.errorOutput}"
}
showToast(context, errorMessage)
}
return isActuallySuccessful
}
suspend fun removeSusPath(context: Context, path: String): Boolean {
saveSusPaths(context, getSusPaths(context) - path)
if (isAutoStartEnabled(context)) createMagiskModule(context)
showToast(context, "SUS path removed: $path")
return true
}
// 添加SUS挂载
suspend fun addSusMount(context: Context, mount: String): Boolean {
val success = executeSusfsCommand(context, "add_sus_mount '$mount'")
if (success) {
saveSusMounts(context, getSusMounts(context) + mount)
if (isAutoStartEnabled(context)) createMagiskModule(context)
}
return success
}
suspend fun removeSusMount(context: Context, mount: String): Boolean {
saveSusMounts(context, getSusMounts(context) - mount)
if (isAutoStartEnabled(context)) createMagiskModule(context)
showToast(context, "Removed SUS mount: $mount")
return true
}
// 添加尝试卸载
suspend fun addTryUmount(context: Context, path: String, mode: Int): Boolean {
val commandSuccess = executeSusfsCommand(context, "add_try_umount '$path' $mode")
saveTryUmounts(context, getTryUmounts(context) + "$path|$mode")
if (isAutoStartEnabled(context)) createMagiskModule(context)
showToast(context, if (commandSuccess) {
context.getString(R.string.susfs_try_umount_added_success, path)
} else {
context.getString(R.string.susfs_try_umount_added_saved, path)
})
return true
}
suspend fun removeTryUmount(context: Context, umountEntry: String): Boolean {
saveTryUmounts(context, getTryUmounts(context) - umountEntry)
if (isAutoStartEnabled(context)) createMagiskModule(context)
val path = umountEntry.split("|").firstOrNull() ?: umountEntry
showToast(context, "Removed Try to uninstall: $path")
return true
}
suspend fun runTryUmount(context: Context): Boolean = executeSusfsCommand(context, "run_try_umount")
// 添加kstat配置
suspend fun addKstatStatically(context: Context, path: String, ino: String, dev: String, nlink: String,
size: String, atime: String, atimeNsec: String, mtime: String, mtimeNsec: String,
ctime: String, ctimeNsec: String, blocks: String, blksize: String): Boolean {
val command = "add_sus_kstat_statically '$path' '$ino' '$dev' '$nlink' '$size' '$atime' '$atimeNsec' '$mtime' '$mtimeNsec' '$ctime' '$ctimeNsec' '$blocks' '$blksize'"
val success = executeSusfsCommand(context, command)
if (success) {
val configEntry = "$path|$ino|$dev|$nlink|$size|$atime|$atimeNsec|$mtime|$mtimeNsec|$ctime|$ctimeNsec|$blocks|$blksize"
saveKstatConfigs(context, getKstatConfigs(context) + configEntry)
if (isAutoStartEnabled(context)) createMagiskModule(context)
showToast(context, context.getString(R.string.kstat_static_config_added, path))
}
return success
}
suspend fun removeKstatConfig(context: Context, config: String): Boolean {
saveKstatConfigs(context, getKstatConfigs(context) - config)
if (isAutoStartEnabled(context)) createMagiskModule(context)
val path = config.split("|").firstOrNull() ?: config
showToast(context, context.getString(R.string.kstat_config_removed, path))
return true
}
// 添加kstat路径
suspend fun addKstat(context: Context, path: String): Boolean {
val success = executeSusfsCommand(context, "add_sus_kstat '$path'")
if (success) {
saveAddKstatPaths(context, getAddKstatPaths(context) + path)
if (isAutoStartEnabled(context)) createMagiskModule(context)
showToast(context, context.getString(R.string.kstat_path_added, path))
}
return success
}
suspend fun removeAddKstat(context: Context, path: String): Boolean {
saveAddKstatPaths(context, getAddKstatPaths(context) - path)
if (isAutoStartEnabled(context)) createMagiskModule(context)
showToast(context, context.getString(R.string.kstat_path_removed, path))
return true
}
// 更新kstat
suspend fun updateKstat(context: Context, path: String): Boolean {
val success = executeSusfsCommand(context, "update_sus_kstat '$path'")
if (success) showToast(context, context.getString(R.string.kstat_updated, path))
return success
}
// 更新kstat全克隆
suspend fun updateKstatFullClone(context: Context, path: String): Boolean {
val success = executeSusfsCommand(context, "update_sus_kstat_full_clone '$path'")
if (success) showToast(context, context.getString(R.string.kstat_full_clone_updated, path))
return success
}
// 设置Android数据路径和SD卡路径
suspend fun setAndroidDataPath(context: Context, path: String): Boolean {
val success = executeSusfsCommand(context, "set_android_data_root_path '$path'")
if (success) {
saveAndroidDataPath(context, path)
if (isAutoStartEnabled(context)) createMagiskModule(context)
}
return success
}
// 设置SD卡路径
suspend fun setSdcardPath(context: Context, path: String): Boolean {
val success = executeSusfsCommand(context, "set_sdcard_root_path '$path'")
if (success) {
saveSdcardPath(context, path)
if (isAutoStartEnabled(context)) createMagiskModule(context)
}
return success
}
fun hasConfigurationForAutoStart(context: Context): Boolean {
val enabledFeatures = runBlocking { getEnabledFeatures(context) }
return getUnameValue(context) != DEFAULT_UNAME ||
getBuildTimeValue(context) != DEFAULT_BUILD_TIME ||
getSusPaths(context).isNotEmpty() ||
getSusMounts(context).isNotEmpty() ||
getTryUmounts(context).isNotEmpty() ||
getKstatConfigs(context).isNotEmpty() ||
getAddKstatPaths(context).isNotEmpty() ||
enabledFeatures.any { it.isEnabled }
}
suspend fun configureAutoStart(context: Context, enabled: Boolean): Boolean = withContext(Dispatchers.IO) {
try {
if (enabled) {
if (!hasConfigurationForAutoStart(context)) {
showToast(context, context.getString(R.string.susfs_no_config_to_autostart))
return@withContext false
}
val targetPath = getSuSFSTargetPath()
if (!runCmdWithResult("test -f '$targetPath'").isSuccess) {
copyBinaryFromAssets(context) ?: run {
showToast(context, context.getString(R.string.susfs_binary_not_found))
return@withContext false
}
}
val success = createMagiskModule(context)
if (success) {
setAutoStartEnabled(context, true)
showToast(context, context.getString(R.string.susfs_autostart_enabled_success, MODULE_PATH))
} else {
showToast(context, context.getString(R.string.susfs_autostart_enable_failed))
}
success
} else {
val success = removeMagiskModule()
if (success) {
setAutoStartEnabled(context, false)
showToast(context, context.getString(R.string.susfs_autostart_disabled_success))
} else {
showToast(context, context.getString(R.string.susfs_autostart_disable_failed))
}
success
}
} catch (e: Exception) {
e.printStackTrace()
showToast(context, context.getString(R.string.susfs_autostart_error, e.message ?: "Unknown error"))
false
}
}
suspend fun resetToDefault(context: Context): Boolean {
val success = setUname(context, DEFAULT_UNAME, DEFAULT_BUILD_TIME)
if (success && isAutoStartEnabled(context)) {
configureAutoStart(context, false)
}
return success
}
}

View File

@@ -0,0 +1,411 @@
package com.sukisu.ultra.ui.util
import android.annotation.SuppressLint
/**
* Magisk模块脚本生成器
* 用于生成各种启动脚本的内容
*/
object ScriptGenerator {
// 常量定义
@SuppressLint("SdCardPath")
private const val DEFAULT_ANDROID_DATA_PATH = "/sdcard/Android/data"
@SuppressLint("SdCardPath")
private const val DEFAULT_SDCARD_PATH = "/sdcard"
private const val DEFAULT_UNAME = "default"
private const val DEFAULT_BUILD_TIME = "default"
private const val LOG_DIR = "/data/adb/ksu/log"
// 日志相关的通用脚本片段
private fun generateLogSetup(logFileName: String): String = """
# 日志目录
LOG_DIR="$LOG_DIR"
LOG_FILE="${'$'}LOG_DIR/$logFileName"
# 创建日志目录
mkdir -p "${'$'}LOG_DIR"
# 获取当前时间
get_current_time() {
date '+%Y-%m-%d %H:%M:%S'
}
""".trimIndent()
// 二进制文件检查的通用脚本片段
private fun generateBinaryCheck(targetPath: String): String = """
# 检查SuSFS二进制文件
SUSFS_BIN="$targetPath"
if [ ! -f "${'$'}SUSFS_BIN" ]; then
echo "$(get_current_time): SuSFS二进制文件未找到: ${'$'}SUSFS_BIN" >> "${'$'}LOG_FILE"
exit 1
fi
""".trimIndent()
/**
* 生成service.sh脚本内容
*/
@SuppressLint("SdCardPath")
fun generateServiceScript(
targetPath: String,
unameValue: String,
buildTimeValue: String,
susPaths: Set<String>,
androidDataPath: String,
sdcardPath: String,
enableLog: Boolean,
executeInPostFsData: Boolean = false,
kstatConfigs: Set<String> = emptySet(),
addKstatPaths: Set<String> = emptySet()
): String {
return buildString {
appendLine("#!/system/bin/sh")
appendLine("# SuSFS Service Script")
appendLine("# 在系统服务启动后执行")
appendLine()
appendLine(generateLogSetup("susfs_service.log"))
appendLine()
appendLine(generateBinaryCheck(targetPath))
appendLine()
// 设置日志启用状态
generateLogSettingSection(enableLog)
// 设置路径
generatePathSettingSection(androidDataPath, sdcardPath)
// 添加SUS路径
generateSusPathsSection(susPaths)
// 添加Kstat配置
generateKstatSection(kstatConfigs, addKstatPaths)
// 设置uname和构建时间
generateUnameSection(unameValue, buildTimeValue, executeInPostFsData)
// 隐藏BL相关配置
generateHideBlSection()
appendLine("echo \"$(get_current_time): Service脚本执行完成\" >> \"${'$'}LOG_FILE\"")
}
}
private fun StringBuilder.generateLogSettingSection(enableLog: Boolean) {
appendLine("# 设置日志启用状态")
val logValue = if (enableLog) 1 else 0
appendLine("\"${'$'}SUSFS_BIN\" enable_log $logValue")
appendLine("echo \"$(get_current_time): 日志功能设置为: ${if (enableLog) "启用" else "禁用"}\" >> \"${'$'}LOG_FILE\"")
appendLine()
}
private fun StringBuilder.generatePathSettingSection(
androidDataPath: String,
sdcardPath: String
) {
// 设置Android Data路径
if (androidDataPath != DEFAULT_ANDROID_DATA_PATH) {
appendLine("# 设置Android Data路径")
appendLine("\"${'$'}SUSFS_BIN\" set_android_data_root_path '$androidDataPath'")
appendLine("echo \"$(get_current_time): Android Data路径设置为: $androidDataPath\" >> \"${'$'}LOG_FILE\"")
appendLine()
}
// 设置SD卡路径
if (sdcardPath != DEFAULT_SDCARD_PATH) {
appendLine("# 设置SD卡路径")
appendLine("\"${'$'}SUSFS_BIN\" set_sdcard_root_path '$sdcardPath'")
appendLine("echo \"$(get_current_time): SD卡路径设置为: $sdcardPath\" >> \"${'$'}LOG_FILE\"")
appendLine()
}
}
private fun StringBuilder.generateSusPathsSection(susPaths: Set<String>) {
if (susPaths.isNotEmpty()) {
appendLine("# 添加SUS路径")
susPaths.forEach { path ->
appendLine("\"${'$'}SUSFS_BIN\" add_sus_path '$path'")
appendLine("echo \"$(get_current_time): 添加SUS路径: $path\" >> \"${'$'}LOG_FILE\"")
}
appendLine()
}
}
private fun StringBuilder.generateKstatSection(
kstatConfigs: Set<String>,
addKstatPaths: Set<String>
) {
// 添加Kstat路径
if (addKstatPaths.isNotEmpty()) {
appendLine("# 添加Kstat路径")
addKstatPaths.forEach { path ->
appendLine("\"${'$'}SUSFS_BIN\" add_sus_kstat '$path'")
appendLine("echo \"$(get_current_time): 添加Kstat路径: $path\" >> \"${'$'}LOG_FILE\"")
}
appendLine()
}
// 添加Kstat静态配置
if (kstatConfigs.isNotEmpty()) {
appendLine("# 添加Kstat静态配置")
kstatConfigs.forEach { config ->
val parts = config.split("|")
if (parts.size >= 13) {
val path = parts[0]
val params = parts.drop(1).joinToString("' '", "'", "'")
appendLine("\"${'$'}SUSFS_BIN\" add_sus_kstat_statically '$path' $params")
appendLine("echo \"$(get_current_time): 添加Kstat静态配置: $path\" >> \"${'$'}LOG_FILE\"")
appendLine("\"${'$'}SUSFS_BIN\" update_sus_kstat '$path'")
appendLine("echo \"$(get_current_time): 更新Kstat配置: $path\" >> \"${'$'}LOG_FILE\"")
}
}
appendLine()
}
}
private fun StringBuilder.generateUnameSection(
unameValue: String,
buildTimeValue: String,
executeInPostFsData: Boolean
) {
if (!executeInPostFsData && (unameValue != DEFAULT_UNAME || buildTimeValue != DEFAULT_BUILD_TIME)) {
appendLine("# 设置uname和构建时间")
appendLine("\"${'$'}SUSFS_BIN\" set_uname '$unameValue' '$buildTimeValue'")
appendLine("echo \"$(get_current_time): 设置uname为: $unameValue, 构建时间为: $buildTimeValue\" >> \"${'$'}LOG_FILE\"")
appendLine()
}
}
private fun StringBuilder.generateHideBlSection() {
appendLine("# 隐藏BL 来自 Shamiko 脚本")
appendLine(
"""
check_reset_prop() {
local NAME=$1
local EXPECTED=$2
local VALUE=$(resetprop ${'$'}NAME)
[ -z ${'$'}VALUE ] || [ ${'$'}VALUE = ${'$'}EXPECTED ] || resetprop ${'$'}NAME ${'$'}EXPECTED
}
check_missing_prop() {
local NAME=$1
local EXPECTED=$2
local VALUE=$(resetprop ${'$'}NAME)
[ -z ${'$'}VALUE ] && resetprop ${'$'}NAME ${'$'}EXPECTED
}
check_missing_match_prop() {
local NAME=$1
local EXPECTED=$2
local VALUE=$(resetprop ${'$'}NAME)
[ -z ${'$'}VALUE ] || [ ${'$'}VALUE = ${'$'}EXPECTED ] || resetprop ${'$'}NAME ${'$'}EXPECTED
[ -z ${'$'}VALUE ] && resetprop ${'$'}NAME ${'$'}EXPECTED
}
contains_reset_prop() {
local NAME=$1
local CONTAINS=$2
local NEWVAL=$3
[[ "$(resetprop ${'$'}NAME)" = *"${'$'}CONTAINS"* ]] && resetprop ${'$'}NAME ${'$'}NEWVAL
}
""".trimIndent())
appendLine()
appendLine("resetprop -w sys.boot_completed 0")
appendLine()
// 添加所有系统属性重置
val systemProps = listOf(
"ro.boot.vbmeta.invalidate_on_error" to "yes",
"ro.boot.vbmeta.avb_version" to "1.2",
"ro.boot.vbmeta.hash_alg" to "sha256",
"ro.boot.vbmeta.device_state" to "locked",
"ro.boot.verifiedbootstate" to "green",
"ro.boot.flash.locked" to "1",
"ro.boot.veritymode" to "enforcing",
"ro.boot.warranty_bit" to "0",
"ro.warranty_bit" to "0",
"ro.debuggable" to "0",
"ro.force.debuggable" to "0",
"ro.secure" to "1",
"ro.adb.secure" to "1",
"ro.build.type" to "user",
"ro.build.tags" to "release-keys",
"ro.vendor.boot.warranty_bit" to "0",
"ro.vendor.warranty_bit" to "0",
"vendor.boot.vbmeta.device_state" to "locked",
"vendor.boot.verifiedbootstate" to "green",
"sys.oem_unlock_allowed" to "0",
"ro.secureboot.lockstate" to "locked",
"ro.boot.realmebootstate" to "green",
"ro.boot.realme.lockstate" to "1",
"ro.crypto.state" to "encrypted"
)
systemProps.forEach { (prop, value) ->
when {
prop.startsWith("ro.boot.vbmeta") && prop.endsWith("_on_error") ->
appendLine("check_missing_prop \"$prop\" \"$value\"")
prop.contains("device_state") || prop.contains("verifiedbootstate") ->
appendLine("check_missing_match_prop \"$prop\" \"$value\"")
else ->
appendLine("check_reset_prop \"$prop\" \"$value\"")
}
}
appendLine()
appendLine("# Hide adb debugging traces")
appendLine("resetprop \"sys.usb.adb.disabled\" \" \"")
appendLine()
appendLine("# Hide recovery boot mode")
appendLine("contains_reset_prop \"ro.bootmode\" \"recovery\" \"unknown\"")
appendLine("contains_reset_prop \"ro.boot.bootmode\" \"recovery\" \"unknown\"")
appendLine("contains_reset_prop \"vendor.boot.bootmode\" \"recovery\" \"unknown\"")
appendLine()
appendLine("# Hide cloudphone detection")
appendLine("[ -n \"$(resetprop ro.kernel.qemu)\" ] && resetprop ro.kernel.qemu \"\"")
appendLine()
}
/**
* 生成post-fs-data.sh脚本内容
*/
fun generatePostFsDataScript(
targetPath: String,
unameValue: String,
buildTimeValue: String,
executeInPostFsData: Boolean = false
): String {
return buildString {
appendLine("#!/system/bin/sh")
appendLine("# SuSFS Post-FS-Data Script")
appendLine("# 在文件系统挂载后但在系统完全启动前执行")
appendLine()
appendLine(generateLogSetup("susfs_post_fs_data.log"))
appendLine()
appendLine(generateBinaryCheck(targetPath))
appendLine()
appendLine("echo \"$(get_current_time): Post-FS-Data脚本开始执行\" >> \"${'$'}LOG_FILE\"")
appendLine()
// 设置uname和构建时间 - 只有在选择在post-fs-data中执行时才执行
if (executeInPostFsData && (unameValue != DEFAULT_UNAME || buildTimeValue != DEFAULT_BUILD_TIME)) {
appendLine("# 设置uname和构建时间")
appendLine("\"${'$'}SUSFS_BIN\" set_uname '$unameValue' '$buildTimeValue'")
appendLine("echo \"$(get_current_time): 设置uname为: $unameValue, 构建时间为: $buildTimeValue\" >> \"${'$'}LOG_FILE\"")
appendLine()
}
appendLine("echo \"$(get_current_time): Post-FS-Data脚本执行完成\" >> \"${'$'}LOG_FILE\"")
}
}
/**
* 生成post-mount.sh脚本内容
*/
fun generatePostMountScript(
targetPath: String,
susMounts: Set<String>,
tryUmounts: Set<String>
): String {
return buildString {
appendLine("#!/system/bin/sh")
appendLine("# SuSFS Post-Mount Script")
appendLine("# 在所有分区挂载完成后执行")
appendLine()
appendLine(generateLogSetup("susfs_post_mount.log"))
appendLine()
appendLine("echo \"$(get_current_time): Post-Mount脚本开始执行\" >> \"${'$'}LOG_FILE\"")
appendLine()
appendLine(generateBinaryCheck(targetPath))
appendLine()
// 添加SUS挂载
if (susMounts.isNotEmpty()) {
appendLine("# 添加SUS挂载")
susMounts.forEach { mount ->
appendLine("\"${'$'}SUSFS_BIN\" add_sus_mount '$mount'")
appendLine("echo \"$(get_current_time): 添加SUS挂载: $mount\" >> \"${'$'}LOG_FILE\"")
}
appendLine()
}
// 添加尝试卸载
if (tryUmounts.isNotEmpty()) {
appendLine("# 添加尝试卸载")
tryUmounts.forEach { umount ->
val parts = umount.split("|")
if (parts.size == 2) {
val path = parts[0]
val mode = parts[1]
appendLine("\"${'$'}SUSFS_BIN\" add_try_umount '$path' $mode")
appendLine("echo \"$(get_current_time): 添加尝试卸载: $path (模式: $mode)\" >> \"${'$'}LOG_FILE\"")
}
}
appendLine()
}
appendLine("echo \"$(get_current_time): Post-Mount脚本执行完成\" >> \"${'$'}LOG_FILE\"")
}
}
/**
* 生成boot-completed.sh脚本内容
*/
fun generateBootCompletedScript(
targetPath: String,
hideSusMountsForAllProcs: Boolean = true
): String {
return buildString {
appendLine("#!/system/bin/sh")
appendLine("# SuSFS Boot-Completed Script")
appendLine("# 在系统完全启动后执行")
appendLine()
appendLine(generateLogSetup("susfs_boot_completed.log"))
appendLine()
appendLine("echo \"$(get_current_time): Boot-Completed脚本开始执行\" >> \"${'$'}LOG_FILE\"")
appendLine()
appendLine(generateBinaryCheck(targetPath))
appendLine()
// SUS挂载隐藏控制仅限1.5.8及以上版本
appendLine("# 设置SUS挂载隐藏控制仅限1.5.8及以上版本)")
appendLine("SUSFS_VERSION=$(${'$'}SUSFS_BIN show version 2>/dev/null | grep -o 'v[0-9]\\+\\.[0-9]\\+\\.[0-9]\\+' | head -1)")
appendLine("if [ -n \"${'$'}SUSFS_VERSION\" ]; then")
appendLine(" VERSION_NUM=$(echo \"${'$'}SUSFS_VERSION\" | sed 's/v//' | awk -F. '{printf \"%d%02d%02d\", $1, $2, $3}')")
appendLine(" if [ \"${'$'}VERSION_NUM\" -ge 10508 ]; then")
val hideValue = if (hideSusMountsForAllProcs) 1 else 0
appendLine(" \"${'$'}SUSFS_BIN\" hide_sus_mnts_for_all_procs $hideValue")
appendLine(" echo \"$(get_current_time): SUS挂载隐藏控制设置为: ${if (hideSusMountsForAllProcs) "对所有进程隐藏" else "仅对非KSU进程隐藏"}\" >> \"${'$'}LOG_FILE\"")
appendLine(" else")
appendLine(" echo \"$(get_current_time): 当前版本 ${'$'}SUSFS_VERSION 不支持SUS挂载隐藏控制功能需要1.5.8及以上版本\" >> \"${'$'}LOG_FILE\"")
appendLine(" fi")
appendLine("else")
appendLine(" echo \"$(get_current_time): 无法获取SuSFS版本信息跳过SUS挂载隐藏控制设置\" >> \"${'$'}LOG_FILE\"")
appendLine("fi")
appendLine()
appendLine("echo \"$(get_current_time): Boot-Completed脚本执行完成\" >> \"${'$'}LOG_FILE\"")
}
}
/**
* 生成module.prop文件内容
*/
fun generateModuleProp(moduleId: String): String {
val moduleVersion = "v1.0.0"
val moduleVersionCode = "1000"
return """
id=$moduleId
name=SuSFS Manager
version=$moduleVersion
versionCode=$moduleVersionCode
author=ShirkNeko
description=SuSFS Manager Auto Configuration Module (自动生成请不要手动卸载或删除该模块! / Automatically generated Please do not manually uninstall or delete the module!)
updateJson=
""".trimIndent()
}
}

View File

@@ -3,7 +3,6 @@ package com.sukisu.ultra.ui.viewmodel
import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
import android.os.SystemClock
import android.system.Os
import android.util.Log
import androidx.compose.runtime.getValue
@@ -27,7 +26,6 @@ import androidx.core.content.edit
class HomeViewModel : ViewModel() {
companion object {
private const val TAG = "HomeViewModel"
private const val CACHE_DURATION = 5 * 60 * 1000L
private const val PREFS_NAME = "home_cache"
private const val KEY_SYSTEM_STATUS = "system_status"
private const val KEY_SYSTEM_INFO = "system_info"
@@ -86,7 +84,7 @@ class HomeViewModel : ViewModel() {
private set
var isHideLinkCard by mutableStateOf(false)
private set
var showKpmInfo by mutableStateOf(true)
var showKpmInfo by mutableStateOf(false)
private set
fun loadUserSettings(context: Context) {
@@ -97,21 +95,13 @@ class HomeViewModel : ViewModel() {
isHideOtherInfo = prefs.getBoolean("is_hide_other_info", false)
isHideSusfsStatus = prefs.getBoolean("is_hide_susfs_status", false)
isHideLinkCard = prefs.getBoolean("is_hide_link_card", false)
showKpmInfo = prefs.getBoolean("show_kpm_info", true)
showKpmInfo = prefs.getBoolean("show_kpm_info", false)
}
}
fun initializeData() {
viewModelScope.launch {
val currentTime = System.currentTimeMillis()
val lastUpdateTime = prefs.getLong(KEY_LAST_UPDATE, 0)
val shouldRefresh = currentTime - lastUpdateTime > CACHE_DURATION
if (!shouldRefresh) {
loadCachedData()
} else {
fetchAndSaveData()
}
loadCachedData()
}
}
@@ -147,16 +137,11 @@ class HomeViewModel : ViewModel() {
.getBoolean("check_update", true)
if (checkUpdate) {
val currentTime = System.currentTimeMillis()
val lastUpdateTime = prefs.getLong(KEY_LAST_UPDATE, 0)
val shouldRefresh = currentTime - lastUpdateTime > CACHE_DURATION
if (shouldRefresh) {
val start = SystemClock.elapsedRealtime()
val newVersionInfo = checkNewVersion()
latestVersionInfo = newVersionInfo
prefs.edit { putString(KEY_VERSION_INFO, gson.toJson(newVersionInfo)) }
Log.i(TAG, "Update check completed in ${SystemClock.elapsedRealtime() - start}ms")
val newVersionInfo = checkNewVersion()
latestVersionInfo = newVersionInfo
prefs.edit {
putString(KEY_VERSION_INFO, gson.toJson(newVersionInfo))
putLong(KEY_LAST_UPDATE, System.currentTimeMillis())
}
}
} catch (e: Exception) {
@@ -251,6 +236,16 @@ class HomeViewModel : ViewModel() {
}
}
private fun getDeviceInfo(): String {
var manufacturer =
Build.MANUFACTURER[0].uppercaseChar().toString() + Build.MANUFACTURER.substring(1)
if (!Build.BRAND.equals(Build.MANUFACTURER, ignoreCase = true)) {
manufacturer += " " + Build.BRAND[0].uppercaseChar() + Build.BRAND.substring(1)
}
manufacturer += " " + Build.MODEL + " "
return manufacturer
}
@SuppressLint("PrivateApi")
private fun getDeviceModel(): String {
return try {
@@ -262,7 +257,7 @@ class HomeViewModel : ViewModel() {
"ro.vivo.market.name", // Vivo
"ro.config.marketing_name" // Huawei
)
var result = Build.DEVICE
var result = getDeviceInfo()
for (key in marketNameKeys) {
val marketName = getMethod.invoke(null, key, "") as String
if (marketName.isNotEmpty()) {
@@ -273,7 +268,7 @@ class HomeViewModel : ViewModel() {
result
} catch (e: Exception) {
Log.e(TAG, "Error getting device model", e)
Build.DEVICE
getDeviceInfo()
}
}

View File

@@ -1,5 +1,6 @@
package com.sukisu.ultra.ui.viewmodel
import android.content.Context
import android.os.SystemClock
import android.util.Log
import androidx.compose.runtime.derivedStateOf
@@ -17,9 +18,15 @@ import com.sukisu.ultra.ui.util.listModules
import kotlinx.coroutines.withContext
import org.json.JSONArray
import org.json.JSONObject
import java.io.BufferedReader
import java.io.InputStreamReader
import java.text.Collator
import java.text.DecimalFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
import kotlin.math.log10
import kotlin.math.pow
import androidx.core.content.edit
/**
* @author ShirkNeko
@@ -33,6 +40,38 @@ class ModuleViewModel : ViewModel() {
private const val CUSTOM_USER_AGENT = "SukiSU-Ultra/2.0"
}
// 模块大小缓存管理器
private lateinit var moduleSizeCache: ModuleSizeCache
fun initializeCache(context: Context) {
if (!::moduleSizeCache.isInitialized) {
moduleSizeCache = ModuleSizeCache(context)
}
}
fun getModuleSize(dirId: String): String {
if (!::moduleSizeCache.isInitialized) {
return "0 KB"
}
val size = moduleSizeCache.getModuleSize(dirId)
return formatFileSize(size)
}
/**
* 刷新所有模块的大小缓存
* 只在安装、卸载、更新模块后调用
*/
fun refreshModuleSizeCache() {
if (!::moduleSizeCache.isInitialized) return
viewModelScope.launch(Dispatchers.IO) {
Log.d(TAG, "开始刷新模块大小缓存")
val currentModules = modules.map { it.dirId }
moduleSizeCache.refreshCache(currentModules)
Log.d(TAG, "模块大小缓存刷新完成")
}
}
class ModuleInfo(
val id: String,
val name: String,
@@ -75,6 +114,8 @@ class ModuleViewModel : ViewModel() {
fun markNeedRefresh() {
isNeedRefresh = true
// 标记需要刷新时,同时刷新大小缓存
refreshModuleSizeCache()
}
fun fetchModuleList() {
@@ -144,6 +185,13 @@ class ModuleViewModel : ViewModel() {
}
}
}
// 首次加载模块列表时,初始化缓存
if (::moduleSizeCache.isInitialized) {
val currentModules = modules.map { it.dirId }
moduleSizeCache.initializeCacheIfNeeded(currentModules)
}
isNeedRefresh = false
}.onFailure { e ->
Log.e(TAG, "fetchModuleList: ", e)
@@ -221,3 +269,171 @@ class ModuleViewModel : ViewModel() {
return Triple(zipUrl, version, changelog)
}
}
/**
* 模块大小缓存管理器
*/
class ModuleSizeCache(context: Context) {
companion object {
private const val TAG = "ModuleSizeCache"
private const val CACHE_PREFS_NAME = "module_size_cache"
private const val CACHE_VERSION_KEY = "cache_version"
private const val CACHE_INITIALIZED_KEY = "cache_initialized"
private const val CURRENT_CACHE_VERSION = 1
}
private val cachePrefs = context.getSharedPreferences(CACHE_PREFS_NAME, Context.MODE_PRIVATE)
private val sizeCache = mutableMapOf<String, Long>()
init {
loadCacheFromPrefs()
}
/**
* 从SharedPreferences加载缓存
*/
private fun loadCacheFromPrefs() {
try {
val cacheVersion = cachePrefs.getInt(CACHE_VERSION_KEY, 0)
if (cacheVersion != CURRENT_CACHE_VERSION) {
Log.d(TAG, "缓存版本不匹配,清空缓存")
clearCache()
return
}
val allEntries = cachePrefs.all
for ((key, value) in allEntries) {
if (key != CACHE_VERSION_KEY && key != CACHE_INITIALIZED_KEY && value is Long) {
sizeCache[key] = value
}
}
Log.d(TAG, "从缓存加载了 ${sizeCache.size} 个模块大小数据")
} catch (e: Exception) {
Log.e(TAG, "加载缓存失败", e)
clearCache()
}
}
/**
* 保存缓存到SharedPreferences
*/
private fun saveCacheToPrefs() {
try {
cachePrefs.edit {
putInt(CACHE_VERSION_KEY, CURRENT_CACHE_VERSION)
putBoolean(CACHE_INITIALIZED_KEY, true)
for ((dirId, size) in sizeCache) {
putLong(dirId, size)
}
}
Log.d(TAG, "保存了 ${sizeCache.size} 个模块大小到缓存")
} catch (e: Exception) {
Log.e(TAG, "保存缓存失败", e)
}
}
/**
* 获取模块大小(从缓存)
*/
fun getModuleSize(dirId: String): Long {
return sizeCache[dirId] ?: 0L
}
/**
* 检查缓存是否已初始化,如果没有则初始化
*/
fun initializeCacheIfNeeded(currentModules: List<String>) {
val isInitialized = cachePrefs.getBoolean(CACHE_INITIALIZED_KEY, false)
if (!isInitialized || sizeCache.isEmpty()) {
Log.d(TAG, "首次初始化缓存,计算所有模块大小")
refreshCache(currentModules)
} else {
// 检查是否有新模块需要计算大小
val newModules = currentModules.filter { !sizeCache.containsKey(it) }
if (newModules.isNotEmpty()) {
Log.d(TAG, "发现 ${newModules.size} 个新模块,计算大小: $newModules")
for (dirId in newModules) {
val size = calculateModuleFolderSize(dirId)
sizeCache[dirId] = size
Log.d(TAG, "新模块 $dirId 大小: ${formatFileSize(size)}")
}
saveCacheToPrefs()
}
}
}
/**
* 刷新所有模块的大小缓存
*/
fun refreshCache(currentModules: List<String>) {
try {
// 清理不存在的模块缓存
val toRemove = sizeCache.keys.filter { it !in currentModules }
toRemove.forEach { sizeCache.remove(it) }
if (toRemove.isNotEmpty()) {
Log.d(TAG, "清理了 ${toRemove.size} 个不存在的模块缓存: $toRemove")
}
// 计算所有当前模块的大小
for (dirId in currentModules) {
val size = calculateModuleFolderSize(dirId)
sizeCache[dirId] = size
Log.d(TAG, "更新模块 $dirId 大小: ${formatFileSize(size)}")
}
// 保存到持久化存储
saveCacheToPrefs()
} catch (e: Exception) {
Log.e(TAG, "刷新缓存失败", e)
}
}
/**
* 清空所有缓存
*/
private fun clearCache() {
sizeCache.clear()
cachePrefs.edit { clear() }
Log.d(TAG, "清空所有缓存")
}
/**
* 实际计算模块文件夹大小
*/
private fun calculateModuleFolderSize(dirId: String): Long {
return try {
val process = Runtime.getRuntime().exec(arrayOf("su", "-c", "du -sb /data/adb/modules/$dirId"))
val reader = BufferedReader(InputStreamReader(process.inputStream))
val output = reader.readLine()
process.waitFor()
reader.close()
if (output != null) {
val sizeStr = output.split("\t").firstOrNull()
sizeStr?.toLongOrNull() ?: 0L
} else {
0L
}
} catch (e: Exception) {
Log.e(TAG, "计算模块大小失败 $dirId: ${e.message}")
0L
}
}
}
/**
* 格式化文件大小的工具函数
*/
fun formatFileSize(bytes: Long): String {
if (bytes <= 0) return "0 KB"
val units = arrayOf("B", "KB", "MB", "GB", "TB")
val digitGroups = (log10(bytes.toDouble()) / log10(1024.0)).toInt()
return DecimalFormat("#,##0.#").format(
bytes / 1024.0.pow(digitGroups.toDouble())
) + " " + units[digitGroups]
}

View File

@@ -1,30 +1,72 @@
package com.sukisu.ultra.ui.viewmodel
import android.content.Context
import android.content.SharedPreferences
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.os.Parcelable
import android.os.SystemClock
import android.util.Log
import android.widget.Toast
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.parcelize.Parcelize
import com.sukisu.ultra.Natives
import com.sukisu.ultra.ksuApp
import com.sukisu.ultra.ui.util.HanziToPinyin
import java.text.Collator
import java.util.*
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit
import java.util.concurrent.LinkedBlockingQueue
import com.dergoogler.mmrl.platform.Platform
import com.dergoogler.mmrl.platform.TIMEOUT_MILLIS
import com.sukisu.ultra.ui.webui.getInstalledPackagesAll
import kotlinx.coroutines.delay
import kotlinx.coroutines.withTimeoutOrNull
import androidx.core.content.edit
import kotlinx.coroutines.asCoroutineDispatcher
// 应用分类
enum class AppCategory(val displayNameRes: Int, val persistKey: String) {
ALL(com.sukisu.ultra.R.string.category_all_apps, "ALL"),
ROOT(com.sukisu.ultra.R.string.category_root_apps, "ROOT"),
CUSTOM(com.sukisu.ultra.R.string.category_custom_apps, "CUSTOM"),
DEFAULT(com.sukisu.ultra.R.string.category_default_apps, "DEFAULT");
companion object {
fun fromPersistKey(key: String): AppCategory {
return entries.find { it.persistKey == key } ?: ALL
}
}
}
// 排序方式
enum class SortType(val displayNameRes: Int, val persistKey: String) {
NAME_ASC(com.sukisu.ultra.R.string.sort_name_asc, "NAME_ASC"),
NAME_DESC(com.sukisu.ultra.R.string.sort_name_desc, "NAME_DESC"),
INSTALL_TIME_NEW(com.sukisu.ultra.R.string.sort_install_time_new, "INSTALL_TIME_NEW"),
INSTALL_TIME_OLD(com.sukisu.ultra.R.string.sort_install_time_old, "INSTALL_TIME_OLD"),
SIZE_DESC(com.sukisu.ultra.R.string.sort_size_desc, "SIZE_DESC"),
SIZE_ASC(com.sukisu.ultra.R.string.sort_size_asc, "SIZE_ASC"),
USAGE_FREQ(com.sukisu.ultra.R.string.sort_usage_freq, "USAGE_FREQ");
companion object {
fun fromPersistKey(key: String): SortType {
return entries.find { it.persistKey == key } ?: NAME_ASC
}
}
}
/**
* @author ShirkNeko
@@ -32,9 +74,18 @@ import kotlinx.coroutines.withTimeoutOrNull
*/
class SuperUserViewModel : ViewModel() {
val isPlatformAlive get() = Platform.isAlive
companion object {
private const val TAG = "SuperUserViewModel"
var apps by mutableStateOf<List<AppInfo>>(emptyList())
private const val PREFS_NAME = "settings"
private const val KEY_SHOW_SYSTEM_APPS = "show_system_apps"
private const val KEY_SELECTED_CATEGORY = "selected_category"
private const val KEY_CURRENT_SORT_TYPE = "current_sort_type"
private const val CORE_POOL_SIZE = 4
private const val MAX_POOL_SIZE = 8
private const val KEEP_ALIVE_TIME = 60L
private const val BATCH_SIZE = 20
}
@Parcelize
@@ -63,8 +114,35 @@ class SuperUserViewModel : ViewModel() {
}
}
private val appProcessingThreadPool = ThreadPoolExecutor(
CORE_POOL_SIZE,
MAX_POOL_SIZE,
KEEP_ALIVE_TIME,
TimeUnit.SECONDS,
LinkedBlockingQueue()
) { runnable ->
Thread(runnable, "AppProcessing-${System.currentTimeMillis()}").apply {
isDaemon = true
priority = Thread.NORM_PRIORITY
}
}.asCoroutineDispatcher()
private val appListMutex = Mutex()
private val configChangeListeners = mutableSetOf<(String) -> Unit>()
private val prefs: SharedPreferences = ksuApp.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
var search by mutableStateOf("")
var showSystemApps by mutableStateOf(false)
var showSystemApps by mutableStateOf(loadShowSystemApps())
private set
var selectedCategory by mutableStateOf(loadSelectedCategory())
private set
var currentSortType by mutableStateOf(loadCurrentSortType())
private set
var isRefreshing by mutableStateOf(false)
private set
@@ -74,6 +152,89 @@ class SuperUserViewModel : ViewModel() {
var selectedApps by mutableStateOf<Set<String>>(emptySet())
internal set
// 加载进度状态
var loadingProgress by mutableFloatStateOf(0f)
private set
var loadingMessage by mutableStateOf("")
private set
/**
* 从SharedPreferences加载显示系统应用设置
*/
private fun loadShowSystemApps(): Boolean {
return prefs.getBoolean(KEY_SHOW_SYSTEM_APPS, false)
}
/**
* 从SharedPreferences加载选择的应用分类
*/
private fun loadSelectedCategory(): AppCategory {
val categoryKey = prefs.getString(KEY_SELECTED_CATEGORY, AppCategory.ALL.persistKey) ?: AppCategory.ALL.persistKey
return AppCategory.fromPersistKey(categoryKey)
}
/**
* 从SharedPreferences加载当前排序方式
*/
private fun loadCurrentSortType(): SortType {
val sortKey = prefs.getString(KEY_CURRENT_SORT_TYPE, SortType.NAME_ASC.persistKey) ?: SortType.NAME_ASC.persistKey
return SortType.fromPersistKey(sortKey)
}
/**
* 更新显示系统应用设置并保存到SharedPreferences
*/
fun updateShowSystemApps(newValue: Boolean) {
showSystemApps = newValue
saveShowSystemApps(newValue)
}
/**
* 更新选择的应用分类并保存到SharedPreferences
*/
fun updateSelectedCategory(newCategory: AppCategory) {
selectedCategory = newCategory
saveSelectedCategory(newCategory)
}
/**
* 更新当前排序方式并保存到SharedPreferences
*/
fun updateCurrentSortType(newSortType: SortType) {
currentSortType = newSortType
saveCurrentSortType(newSortType)
}
/**
* 保存显示系统应用设置到SharedPreferences
*/
private fun saveShowSystemApps(value: Boolean) {
prefs.edit {
putBoolean(KEY_SHOW_SYSTEM_APPS, value)
}
Log.d(TAG, "Saved show system apps: $value")
}
/**
* 保存选择的应用分类到SharedPreferences
*/
private fun saveSelectedCategory(category: AppCategory) {
prefs.edit {
putString(KEY_SELECTED_CATEGORY, category.persistKey)
}
Log.d(TAG, "Saved selected category: ${category.persistKey}")
}
/**
* 保存当前排序方式到SharedPreferences
*/
private fun saveCurrentSortType(sortType: SortType) {
prefs.edit {
putString(KEY_CURRENT_SORT_TYPE, sortType.persistKey)
}
Log.d(TAG, "Saved current sort type: ${sortType.persistKey}")
}
private val sortedList by derivedStateOf {
val comparator = compareBy<AppInfo> {
when {
@@ -129,19 +290,14 @@ class SuperUserViewModel : ViewModel() {
val profile = Natives.getAppProfile(packageName, it.uid)
val updatedProfile = profile.copy(allowSu = allowSu)
if (Natives.setAppProfile(updatedProfile)) {
apps = apps.map { app ->
if (app.packageName == packageName) {
app.copy(profile = updatedProfile)
} else {
app
}
}
updateAppProfileLocally(packageName, updatedProfile)
notifyConfigChange(packageName)
}
}
}
clearSelection()
showBatchActions = false // 批量操作完成后退出批量模式
fetchAppList() // 刷新列表以显示最新状态
showBatchActions = false
refreshAppConfigurations()
}
// 批量更新权限和umount模块设置
@@ -156,6 +312,21 @@ class SuperUserViewModel : ViewModel() {
nonRootUseDefault = false
)
if (Natives.setAppProfile(updatedProfile)) {
updateAppProfileLocally(packageName, updatedProfile)
notifyConfigChange(packageName)
}
}
}
clearSelection()
showBatchActions = false
refreshAppConfigurations()
}
// 更新本地应用配置
fun updateAppProfileLocally(packageName: String, updatedProfile: Natives.Profile) {
appListMutex.tryLock().let { locked ->
if (locked) {
try {
apps = apps.map { app ->
if (app.packageName == packageName) {
app.copy(profile = updatedProfile)
@@ -163,27 +334,67 @@ class SuperUserViewModel : ViewModel() {
app
}
}
} finally {
appListMutex.unlock()
}
}
}
clearSelection()
showBatchActions = false // 批量操作完成后退出批量模式
fetchAppList() // 刷新列表以显示最新状态
}
// 更新本地应用配置
fun updateAppProfileLocally(packageName: String, updatedProfile: Natives.Profile) {
apps = apps.map { app ->
if (app.packageName == packageName) {
app.copy(profile = updatedProfile)
} else {
app
private fun notifyConfigChange(packageName: String) {
configChangeListeners.forEach { listener ->
try {
listener(packageName)
} catch (e: Exception) {
Log.e(TAG, "Error notifying config change for $packageName", e)
}
}
}
/**
* 刷新应用配置状态
*/
suspend fun refreshAppConfigurations() {
withContext(appProcessingThreadPool) {
supervisorScope {
val currentApps = apps.toList()
val batches = currentApps.chunked(BATCH_SIZE)
loadingProgress = 0f
val updatedApps = batches.mapIndexed { batchIndex, batch ->
async {
val batchResult = batch.map { app ->
try {
val updatedProfile = Natives.getAppProfile(app.packageName, app.uid)
app.copy(profile = updatedProfile)
} catch (e: Exception) {
Log.e(TAG, "Error refreshing profile for ${app.packageName}", e)
app
}
}
val progress = (batchIndex + 1).toFloat() / batches.size
loadingProgress = progress
batchResult
}
}.awaitAll().flatten()
appListMutex.withLock {
apps = updatedApps
}
loadingProgress = 1f
Log.i(TAG, "Refreshed configurations for ${updatedApps.size} apps")
}
}
}
suspend fun fetchAppList() {
isRefreshing = true
loadingProgress = 0f
withContext(Dispatchers.IO) {
withTimeoutOrNull(TIMEOUT_MILLIS) {
@@ -194,21 +405,87 @@ class SuperUserViewModel : ViewModel() {
val pm = ksuApp.packageManager
val start = SystemClock.elapsedRealtime()
val packages = Platform.getInstalledPackagesAll {
Log.e(TAG, "getInstalledPackagesAll:", it)
Toast.makeText(ksuApp, "Something went wrong, check logs", Toast.LENGTH_SHORT).show()
try {
val packages = Platform.getInstalledPackagesAll {
Log.e(TAG, "getInstalledPackagesAll:", it)
}
loadingProgress = 0.3f
val filteredPackages = packages.filter { it.packageName != ksuApp.packageName }
withContext(appProcessingThreadPool) {
supervisorScope {
val batches = filteredPackages.chunked(BATCH_SIZE)
val processedApps = batches.mapIndexed { batchIndex, batch ->
async {
val batchResult = batch.mapNotNull { packageInfo ->
try {
val appInfo = packageInfo.applicationInfo!!
val uid = appInfo.uid
val labelDeferred = async {
appInfo.loadLabel(pm).toString()
}
val profileDeferred = async {
Natives.getAppProfile(packageInfo.packageName, uid)
}
val label = labelDeferred.await()
val profile = profileDeferred.await()
AppInfo(
label = label,
packageInfo = packageInfo,
profile = profile,
)
} catch (e: Exception) {
Log.e(
TAG,
"Error processing app ${packageInfo.packageName}",
e
)
null
}
}
val progress = 0.3f + (batchIndex + 1).toFloat() / batches.size * 0.6f
loadingProgress = progress
batchResult
}
}.awaitAll().flatten()
appListMutex.withLock {
apps = processedApps
}
loadingProgress = 1f
val elapsed = SystemClock.elapsedRealtime() - start
Log.i(TAG, "Loaded ${processedApps.size} apps in ${elapsed}ms using concurrent processing")
}
}
} catch (e: Exception) {
Log.e(TAG, "Error fetching app list", e)
} finally {
isRefreshing = false
loadingProgress = 0f
loadingMessage = ""
}
apps = packages.map {
val appInfo = it.applicationInfo
val uid = appInfo!!.uid
val profile = Natives.getAppProfile(it.packageName, uid)
AppInfo(
label = appInfo.loadLabel(pm).toString(),
packageInfo = it,
profile = profile,
)
}.filter { it.packageName != ksuApp.packageName }
Log.i(TAG, "load cost: ${SystemClock.elapsedRealtime() - start}")
}
}
/**
* 清理资源
*/
override fun onCleared() {
super.onCleared()
try {
appProcessingThreadPool.close()
configChangeListeners.clear()
} catch (e: Exception) {
Log.e(TAG, "Error cleaning up resources", e)
}
}
}

View File

@@ -0,0 +1,222 @@
package zako.zako.zako.zakoui.activity.component
import android.annotation.SuppressLint
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavHostController
import com.ramcosta.composedestinations.utils.isRouteOnBackStackAsState
import com.ramcosta.composedestinations.utils.rememberDestinationsNavigator
import com.ramcosta.composedestinations.spec.RouteOrDirection
import com.ramcosta.composedestinations.generated.NavGraphs
import com.sukisu.ultra.Natives
import com.sukisu.ultra.ksuApp
import com.sukisu.ultra.ui.MainActivity
import zako.zako.zako.zakoui.activity.util.AppData
import zako.zako.zako.zakoui.activity.util.AppData.getKpmVersionUse
import com.sukisu.ultra.ui.screen.BottomBarDestination
import com.sukisu.ultra.ui.theme.CardConfig.cardAlpha
import com.sukisu.ultra.ui.theme.CardConfig.cardElevation
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.navigationBars
import zako.zako.zako.zakoui.activity.util.AppData.DataRefreshManager
@SuppressLint("ContextCastToActivity")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BottomBar(navController: NavHostController) {
val navigator = navController.rememberDestinationsNavigator()
val isFullFeatured = AppData.isFullFeatured(ksuApp.packageName)
val kpmVersion = getKpmVersionUse()
val cardColor = MaterialTheme.colorScheme.surfaceContainer
val activity = LocalContext.current as MainActivity
val settings by activity.settingsStateFlow.collectAsState()
// 检查是否隐藏红点
val isHideOtherInfo = settings.isHideOtherInfo
val showKpmInfo = settings.showKpmInfo
// 收集计数数据
val superuserCount by DataRefreshManager.superuserCount.collectAsState()
val moduleCount by DataRefreshManager.moduleCount.collectAsState()
val kpmModuleCount by DataRefreshManager.kpmModuleCount.collectAsState()
NavigationBar(
modifier = Modifier.windowInsetsPadding(
WindowInsets.navigationBars.only(WindowInsetsSides.Horizontal)
),
containerColor = TopAppBarDefaults.topAppBarColors(
containerColor = cardColor.copy(alpha = cardAlpha),
scrolledContainerColor = cardColor.copy(alpha = cardAlpha)
).containerColor,
tonalElevation = cardElevation
) {
BottomBarDestination.entries.forEach { destination ->
if (destination == BottomBarDestination.Kpm) {
if (kpmVersion.isNotEmpty() && !kpmVersion.startsWith("Error") && !showKpmInfo && Natives.version >= Natives.MINIMAL_SUPPORTED_KPM) {
if (!isFullFeatured && destination.rootRequired) return@forEach
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
NavigationBarItem(
selected = isCurrentDestOnBackStack,
onClick = {
if (!isCurrentDestOnBackStack) {
navigator.popBackStack(destination.direction, false)
}
navigator.navigate(destination.direction) {
popUpTo(NavGraphs.root as RouteOrDirection) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
},
icon = {
BadgedBox(
badge = {
if (kpmModuleCount > 0 && !isHideOtherInfo) {
Badge(
containerColor = MaterialTheme.colorScheme.secondary
) {
Text(
text = kpmModuleCount.toString(),
style = MaterialTheme.typography.labelSmall
)
}
}
}
) {
if (isCurrentDestOnBackStack) {
Icon(destination.iconSelected, stringResource(destination.label))
} else {
Icon(destination.iconNotSelected, stringResource(destination.label))
}
}
},
label = { Text(stringResource(destination.label),style = MaterialTheme.typography.labelMedium) },
alwaysShowLabel = false
)
}
} else if (destination == BottomBarDestination.SuperUser) {
if (!isFullFeatured && destination.rootRequired) return@forEach
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
NavigationBarItem(
selected = isCurrentDestOnBackStack,
onClick = {
if (isCurrentDestOnBackStack) {
navigator.popBackStack(destination.direction, false)
}
navigator.navigate(destination.direction) {
popUpTo(NavGraphs.root) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
},
icon = {
BadgedBox(
badge = {
if (superuserCount > 0 && !isHideOtherInfo) {
Badge(
containerColor = MaterialTheme.colorScheme.secondary
) {
Text(
text = superuserCount.toString(),
style = MaterialTheme.typography.labelSmall
)
}
}
}
) {
if (isCurrentDestOnBackStack) {
Icon(destination.iconSelected, stringResource(destination.label))
} else {
Icon(destination.iconNotSelected, stringResource(destination.label))
}
}
},
label = { Text(stringResource(destination.label),style = MaterialTheme.typography.labelMedium) },
alwaysShowLabel = false
)
} else if (destination == BottomBarDestination.Module) {
if (!isFullFeatured && destination.rootRequired) return@forEach
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
NavigationBarItem(
selected = isCurrentDestOnBackStack,
onClick = {
if (isCurrentDestOnBackStack) {
navigator.popBackStack(destination.direction, false)
}
navigator.navigate(destination.direction) {
popUpTo(NavGraphs.root) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
},
icon = {
BadgedBox(
badge = {
if (moduleCount > 0 && !isHideOtherInfo) {
Badge(
containerColor = MaterialTheme.colorScheme.secondary)
{
Text(
text = moduleCount.toString(),
style = MaterialTheme.typography.labelSmall
)
}
}
}
) {
if (isCurrentDestOnBackStack) {
Icon(destination.iconSelected, stringResource(destination.label))
} else {
Icon(destination.iconNotSelected, stringResource(destination.label))
}
}
},
label = { Text(stringResource(destination.label),style = MaterialTheme.typography.labelMedium) },
alwaysShowLabel = false
)
} else {
if (!isFullFeatured && destination.rootRequired) return@forEach
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
NavigationBarItem(
selected = isCurrentDestOnBackStack,
onClick = {
if (isCurrentDestOnBackStack) {
navigator.popBackStack(destination.direction, false)
}
navigator.navigate(destination.direction) {
popUpTo(NavGraphs.root) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
},
icon = {
if (isCurrentDestOnBackStack) {
Icon(destination.iconSelected, stringResource(destination.label))
} else {
Icon(destination.iconNotSelected, stringResource(destination.label))
}
},
label = { Text(stringResource(destination.label),style = MaterialTheme.typography.labelMedium) },
alwaysShowLabel = false
)
}
}
}
}

View File

@@ -0,0 +1,24 @@
package zako.zako.zako.zakoui.activity.util
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.runtime.Composable
object AnimatedBottomBar {
@Composable
fun AnimatedBottomBarWrapper(
showBottomBar: Boolean,
content: @Composable () -> Unit
) {
AnimatedVisibility(
visible = showBottomBar,
enter = slideInVertically(initialOffsetY = { it }) + fadeIn(),
exit = slideOutVertically(targetOffsetY = { it }) + fadeOut()
) {
content()
}
}
}

View File

@@ -0,0 +1,109 @@
package zako.zako.zako.zakoui.activity.util
import com.sukisu.ultra.Natives
import com.sukisu.ultra.ui.util.getKpmModuleCount
import com.sukisu.ultra.ui.util.getKpmVersion
import com.sukisu.ultra.ui.util.getModuleCount
import com.sukisu.ultra.ui.util.getSuperuserCount
import com.sukisu.ultra.ui.util.rootAvailable
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.withContext
object AppData {
object DataRefreshManager {
// 私有状态流
private val _superuserCount = MutableStateFlow(0)
private val _moduleCount = MutableStateFlow(0)
private val _kpmModuleCount = MutableStateFlow(0)
// 公开的只读状态流
val superuserCount: StateFlow<Int> = _superuserCount.asStateFlow()
val moduleCount: StateFlow<Int> = _moduleCount.asStateFlow()
val kpmModuleCount: StateFlow<Int> = _kpmModuleCount.asStateFlow()
/**
* 刷新所有数据计数
*/
fun refreshData() {
_superuserCount.value = getSuperuserCountUse()
_moduleCount.value = getModuleCountUse()
_kpmModuleCount.value = getKpmModuleCountUse()
}
/**
* 异步刷新所有数据
*/
suspend fun refreshDataAsync() = withContext(Dispatchers.IO) {
refreshData()
}
}
/**
* 获取超级用户应用计数
*/
fun getSuperuserCountUse(): Int {
return try {
if (!rootAvailable()) return 0
getSuperuserCount()
} catch (_: Exception) {
0
}
}
/**
* 获取模块计数
*/
fun getModuleCountUse(): Int {
return try {
if (!rootAvailable()) return 0
getModuleCount()
} catch (_: Exception) {
0
}
}
/**
* 获取KPM模块计数
*/
fun getKpmModuleCountUse(): Int {
return try {
if (!rootAvailable()) return 0
val kpmVersion = getKpmVersionUse()
if (kpmVersion.isEmpty() || kpmVersion.startsWith("Error")) return 0
getKpmModuleCount()
} catch (_: Exception) {
0
}
}
/**
* 获取KPM版本
*/
fun getKpmVersionUse(): String {
return try {
if (!rootAvailable()) return ""
val version = getKpmVersion()
if (version.isEmpty()) "" else version
} catch (e: Exception) {
"Error: ${e.message}"
}
}
/**
* 检查是否具有管理员权限
*/
fun isManager(packageName: String): Boolean {
return Natives.becomeManager(packageName)
}
/**
* 检查是否是完整功能模式
*/
fun isFullFeatured(packageName: String): Boolean {
val isManager = Natives.becomeManager(packageName)
return isManager && !Natives.requireNewKernel() && rootAvailable()
}
}

View File

@@ -0,0 +1,46 @@
package zako.zako.zako.zakoui.activity.util
import android.content.Context
import androidx.lifecycle.LifecycleCoroutineScope
import com.sukisu.ultra.ui.MainActivity
import zako.zako.zako.zakoui.activity.util.AppData.DataRefreshManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
object DataRefreshUtils {
fun startDataRefreshCoroutine(scope: LifecycleCoroutineScope) {
scope.launch(Dispatchers.IO) {
while (isActive) {
DataRefreshManager.refreshData()
delay(5000)
}
}
}
fun startSettingsMonitorCoroutine(
scope: LifecycleCoroutineScope,
activity: MainActivity,
settingsStateFlow: MutableStateFlow<MainActivity.SettingsState>
) {
scope.launch(Dispatchers.IO) {
while (isActive) {
val prefs = activity.getSharedPreferences("settings", Context.MODE_PRIVATE)
settingsStateFlow.value = MainActivity.SettingsState(
isHideOtherInfo = prefs.getBoolean("is_hide_other_info", false),
showKpmInfo = prefs.getBoolean("show_kpm_info", false)
)
delay(1000)
}
}
}
fun refreshData(scope: LifecycleCoroutineScope) {
scope.launch {
DataRefreshManager.refreshData()
}
}
}

View File

@@ -0,0 +1,24 @@
package zako.zako.zako.zakoui.activity.util
import android.content.Context
object DisplayUtils {
fun applyCustomDpi(context: Context) {
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
val customDpi = prefs.getInt("app_dpi", 0)
if (customDpi > 0) {
try {
val resources = context.resources
val metrics = resources.displayMetrics
metrics.density = customDpi / 160f
@Suppress("DEPRECATION")
metrics.scaledDensity = customDpi / 160f
metrics.densityDpi = customDpi
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}

View File

@@ -0,0 +1,48 @@
package zako.zako.zako.zakoui.activity.util
import android.annotation.SuppressLint
import android.content.Context
import android.content.res.Configuration
import android.os.Build
import java.util.Locale
object LocaleUtils {
@SuppressLint("ObsoleteSdkInt")
fun applyLanguageSetting(context: Context) {
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
val languageCode = prefs.getString("app_language", "") ?: ""
if (languageCode.isNotEmpty()) {
val locale = Locale.forLanguageTag(languageCode)
Locale.setDefault(locale)
val resources = context.resources
val config = Configuration(resources.configuration)
config.setLocale(locale)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
context.createConfigurationContext(config)
} else {
@Suppress("DEPRECATION")
resources.updateConfiguration(config, resources.displayMetrics)
}
}
}
fun applyLocale(context: Context): Context {
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
val languageCode = prefs.getString("app_language", "") ?: ""
var newContext = context
if (languageCode.isNotEmpty()) {
val locale = Locale.forLanguageTag(languageCode)
Locale.setDefault(locale)
val config = Configuration(context.resources.configuration)
config.setLocale(locale)
newContext = context.createConfigurationContext(config)
}
return newContext
}
}

View File

@@ -0,0 +1,19 @@
package zako.zako.zako.zakoui.activity.util
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.navigation.NavBackStackEntry
import com.ramcosta.composedestinations.animations.NavHostAnimatedDestinationStyle
object NavigationUtils {
fun defaultTransitions() = object : NavHostAnimatedDestinationStyle() {
override val enterTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition
get() = { fadeIn(animationSpec = tween(340)) }
override val exitTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition
get() = { fadeOut(animationSpec = tween(340)) }
}
}

View File

@@ -0,0 +1,96 @@
package zako.zako.zako.zakoui.activity.util
import android.content.Context
import android.database.ContentObserver
import android.os.Handler
import androidx.core.content.edit
import com.sukisu.ultra.ui.MainActivity
import com.sukisu.ultra.ui.theme.CardConfig
import com.sukisu.ultra.ui.theme.ThemeConfig
import kotlinx.coroutines.flow.MutableStateFlow
class ThemeChangeContentObserver(
handler: Handler,
private val onThemeChanged: () -> Unit
) : ContentObserver(handler) {
override fun onChange(selfChange: Boolean) {
super.onChange(selfChange)
onThemeChanged()
}
}
object ThemeUtils {
fun initializeThemeSettings(activity: MainActivity, settingsStateFlow: MutableStateFlow<MainActivity.SettingsState>) {
val prefs = activity.getSharedPreferences("settings", Context.MODE_PRIVATE)
val isFirstRun = prefs.getBoolean("is_first_run", true)
settingsStateFlow.value = MainActivity.SettingsState(
isHideOtherInfo = prefs.getBoolean("is_hide_other_info", false),
showKpmInfo = prefs.getBoolean("show_kpm_info", false)
)
if (isFirstRun) {
ThemeConfig.preventBackgroundRefresh = false
activity.getSharedPreferences("theme_prefs", Context.MODE_PRIVATE).edit {
putBoolean("prevent_background_refresh", false)
}
prefs.edit { putBoolean("is_first_run", false) }
}
// 加载保存的背景设置
loadThemeMode()
loadThemeColors()
loadDynamicColorState()
CardConfig.load(activity.applicationContext)
}
fun registerThemeChangeObserver(activity: MainActivity): ThemeChangeContentObserver {
val contentObserver = ThemeChangeContentObserver(Handler(activity.mainLooper)) {
activity.runOnUiThread {
if (!ThemeConfig.preventBackgroundRefresh) {
ThemeConfig.backgroundImageLoaded = false
loadCustomBackground()
}
}
}
activity.contentResolver.registerContentObserver(
android.provider.Settings.System.getUriFor("ui_night_mode"),
false,
contentObserver
)
return contentObserver
}
fun unregisterThemeChangeObserver(activity: MainActivity, observer: ThemeChangeContentObserver) {
activity.contentResolver.unregisterContentObserver(observer)
}
fun onActivityPause(activity: MainActivity) {
CardConfig.save(activity.applicationContext)
activity.getSharedPreferences("theme_prefs", Context.MODE_PRIVATE).edit {
putBoolean("prevent_background_refresh", true)
}
ThemeConfig.preventBackgroundRefresh = true
}
fun onActivityResume() {
if (!ThemeConfig.backgroundImageLoaded && !ThemeConfig.preventBackgroundRefresh) {
loadCustomBackground()
}
}
private fun loadThemeMode() {
}
private fun loadThemeColors() {
}
private fun loadDynamicColorState() {
}
private fun loadCustomBackground() {
}
}

View File

@@ -1,4 +1,4 @@
package com.sukisu.ultra.flash
package zako.zako.zako.zakoui.flash
import android.app.Activity
import android.content.Context

View File

@@ -1,4 +1,4 @@
package com.sukisu.ultra.ui.screen
package zako.zako.zako.zakoui.screen
import android.net.Uri
import android.os.Environment
@@ -29,8 +29,8 @@ import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.sukisu.ultra.R
import com.sukisu.ultra.flash.HorizonKernelState
import com.sukisu.ultra.flash.HorizonKernelWorker
import zako.zako.zako.zakoui.flash.HorizonKernelState
import zako.zako.zako.zakoui.flash.HorizonKernelWorker
import com.sukisu.ultra.ui.component.KeyEventBlocker
import com.sukisu.ultra.ui.util.*
import kotlinx.coroutines.Dispatchers
@@ -42,6 +42,8 @@ import java.util.*
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.key
import com.sukisu.ultra.ui.theme.CardConfig
import zako.zako.zako.zakoui.flash.FlashState
import kotlinx.coroutines.delay
/**
* @author ShirkNeko
@@ -117,7 +119,7 @@ fun KernelFlashScreen(
logContent.clear()
logContent.append(logText)
}
kotlinx.coroutines.delay(100)
delay(100)
}
if (flashState.error.isNotEmpty()) {
@@ -239,7 +241,7 @@ fun KernelFlashScreen(
}
@Composable
private fun FlashProgressIndicator(flashState: com.sukisu.ultra.flash.FlashState) {
private fun FlashProgressIndicator(flashState: FlashState) {
val progressColor = when {
flashState.error.isNotEmpty() -> MaterialTheme.colorScheme.error
flashState.isCompleted -> MaterialTheme.colorScheme.tertiary
@@ -355,7 +357,7 @@ private fun FlashProgressIndicator(flashState: com.sukisu.ultra.flash.FlashState
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun TopBar(
flashState: com.sukisu.ultra.flash.FlashState,
flashState: FlashState,
onBack: () -> Unit,
onSave: () -> Unit = {},
scrollBehavior: TopAppBarScrollBehavior? = null
@@ -366,7 +368,12 @@ private fun TopBar(
else -> MaterialTheme.colorScheme.primary
}
val cardColor = MaterialTheme.colorScheme.surfaceContainerLow
val colorScheme = MaterialTheme.colorScheme
val cardColor = if (CardConfig.isCustomBackgroundEnabled) {
colorScheme.surfaceContainerLow
} else {
colorScheme.background
}
val cardAlpha = CardConfig.cardAlpha
TopAppBar(

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group
android:scaleX="0.135"
android:scaleY="0.135">
<path
android:pathData="M 259 259 H 541 V 541 H 259 V 259 Z"
android:strokeWidth="18"
android:strokeColor="#1e110d" />
<path
android:fillColor="#1e110d"
android:pathData="M 257 257 H 407 V 407 H 257 V 257 Z" />
<path
android:fillColor="#1e110d"
android:pathData="M 393 393 H 543 V 543 H 393 V 393 Z" />
</group>
</vector>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group
android:scaleX="0.135"
android:scaleY="0.135">
<path
android:pathData="M 259 259 H 541 V 541 H 259 V 259 Z"
android:strokeWidth="18"
android:strokeColor="#000000" />
<path
android:fillColor="#000000"
android:pathData="M 257 257 H 407 V 407 H 257 V 257 Z" />
<path
android:fillColor="#000000"
android:pathData="M 393 393 H 543 V 543 H 393 V 393 Z" />
</group>
</vector>

View File

@@ -0,0 +1,42 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12,21l-8,-4.5v-9l8,-4.5l8,4.5v4.5"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:strokeColor="#ffff"
android:strokeLineCap="round"/>
<path
android:pathData="M12,12l8,-4.5"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:strokeColor="#ffff"
android:strokeLineCap="round"/>
<path
android:pathData="M12,12v9"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:strokeColor="#ffff"
android:strokeLineCap="round"/>
<path
android:pathData="M12,12l-8,-4.5"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:strokeColor="#ffff"
android:strokeLineCap="round"/>
<path
android:pathData="M22,18h-7"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:strokeColor="#ffff"
android:strokeLineCap="round"/>
<path
android:pathData="M18,15l-3,3l3,3"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:strokeColor="#ffff"
android:strokeLineCap="round"/>
</vector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground_alt"/>
<monochrome android:drawable="@drawable/ic_launcher_monochrome_alt" />
</adaptive-icon>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground_alt"/>
<monochrome android:drawable="@drawable/ic_launcher_monochrome_alt" />
</adaptive-icon>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">إضغط للتثبيت</string>
<string name="home_working">يعمل</string>
<string name="home_working_version">الإصدار: %d</string>
<string name="home_superuser_count">مستخدمين الجذر: %d</string>
<string name="home_module_count">الإضافات: %d</string>
<string name="home_unsupported">غير مدعوم</string>
<string name="home_unsupported_reason">KernelSU يدعم GKI kernels فقط</string>
<string name="home_kernel">إصدار النواة</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">إصدار SuSFS</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">إصدار المدير</string>
<string name="home_fingerprint">البصمة</string>
<string name="home_selinux_status">وضع SELinux</string>
<string name="selinux_status_disabled">معطل</string>
<string name="selinux_status_enforcing">مفروض</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">فرز (الإجراء أولاً)</string>
<string name="module_sort_enabled_first">فرز (الممكن أولاً)</string>
<string name="uninstall">إلغاء التثبيت</string>
<string name="restore">إسترجاع</string>
<string name="module_install">تثبيت الوحدة</string>
<string name="install">تثبيت</string>
<string name="reboot">إعادة تشغيل</string>
@@ -61,10 +55,6 @@
<string name="profile_template">نموذج</string>
<string name="profile_custom">مُخصّص</string>
<string name="profile_name">اسم الملف الشخصي</string>
<string name="profile_namespace">تركيب مساحة الاسم</string>
<string name="profile_namespace_inherited">موروث</string>
<string name="profile_namespace_global">عالمي</string>
<string name="profile_namespace_individual">فردي</string>
<string name="profile_groups">مجموعات</string>
<string name="profile_capabilities">القدرات</string>
<string name="profile_selinux_context">سياق SELinux</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">التحقق تلقائيًا من وجود تحديثات عند فتح التطبيق</string>
<string name="grant_root_failed">فشل في منح صلاحية الجذر!</string>
<string name="action">إجراء</string>
<string name="open">فتح</string>
<string name="close">إغلاق</string>
<string name="enable_web_debugging">تمكين تصحيح أخطاء WebView</string>
<string name="enable_web_debugging_summary">يمكن استخدامه لتصحيح أخطاء WebUI، يرجى تمكينه فقط عند الحاجة.</string>
@@ -138,9 +127,6 @@
<string name="selected_lkm">LKM المحددة: %s</string>
<string name="save_log">حفظ السجلات</string>
<string name="log_saved">السجلات محفوظة</string>
<string name="status_supported">إدعمنا</string>
<string name="status_not_supported">غير مدعوم</string>
<string name="status_unknown">غير معروف</string>
<string name="sus_su_mode">وضع SuS SU</string>
<!-- Module related -->
<string name="module_install_confirm">تأكيد وحدة التثبيت %1$s؟</string>
@@ -174,14 +160,11 @@
<string name="settings_custom_background">خلفية التطبيق المخصصة</string>
<string name="settings_custom_background_summary">حدد صورة كخلفية</string>
<string name="settings_card_alpha">شفافية شريط التنقل</string>
<string name="settings_restore_default">استعادة الإعدادات الافتراضية</string>
<string name="home_android_version">‏إصدار Android</string>
<string name="home_device_model">نوع الجهاز</string>
<string name="su_not_allowed">لا يسمح بمنح المستخدم المتميز ل %s</string>
<string name="settings_disable_su">تعطيل توافق su</string>
<string name="settings_disable_su_summary">تعطيل أي تطبيقات مؤقتًا من الحصول على امتيازات الجذر عن طريق الأمر &lt;unk&gt; su (لن تتأثر عمليات الجذر الحالية).</string>
<string name="using_mksu_manager">أنت تستخدم مدير Beta SukiSU</string>
<string name="module_install_multiple_confirm">هل أنت متأكد من أنك تريد تثبيت وحدات %d المحددة؟</string>
<string name="module_install_multiple_confirm_with_names">هل أنت متأكد من أنك تريد تثبيت وحدات %1$d التالية؟ \n\n%2$s</string>
<string name="more_settings">المزيد من الإعدادات</string>
<string name="selinux">SELinux</string>
@@ -212,20 +195,14 @@
<string name="color_pink">وردي</string>
<string name="color_gray">رمادي</string>
<string name="color_yellow">الأصفر</string>
<string name="flash_option">خيارات الفرشاة</string>
<string name="flash_option_tip">حدد الملف المراد إلفاؤه</string>
<string name="horizon_kernel">Anykernel3 yükle</string>
<string name="horizon_kernel_summary">فلاش AnyKernel3 ملف kernel</string>
<string name="root_required">يتطلب امتيازات الجذر</string>
<string name="copy_failed">فشل نسخ الملف</string>
<string name="reboot_complete_title">اكتمل التشويش</string>
<string name="reboot_complete_msg">هل تريد إعادة التشغيل فوراً؟</string>
<string name="yes">نعم</string>
<string name="no">لايوجد</string>
<string name="failed_reboot">فشل إعادة التشغيل</string>
<string name="batch_authorization">التمكين</string>
<string name="batch_cancel_authorization">السحب</string>
<string name="backup">النسخ الاحتياطية</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">لا توجد وحدات نواة مثبتة في هذا الوقت</string>
<string name="kpm_version">الإصدار</string>
@@ -233,7 +210,6 @@
<string name="kpm_uninstall">إلغاء التثبيت</string>
<string name="kpm_uninstall_success">تم إلغاء التثبيت بنجاح</string>
<string name="kpm_uninstall_failed">فشل في إلغاء التثبيت</string>
<string name="kpm_install">تثبيت</string>
<string name="kpm_install_success">تم تحميل وحدة كيلو جزء بنجاح</string>
<string name="kpm_install_failed">فشل تحميل وحدة كيلو بايم</string>
<string name="kpm_args">العوامل المتغيرة</string>
@@ -247,8 +223,6 @@
<string name="home_click_to_ContributionCard_kernelsu">وستشكل سوكيسو أولترا في المستقبل فرعا مستقلا نسبيا من فروع الوحدة، ولكننا لا نزال نقدر كيرنيل سو وموكسو الرسميين وما إلى ذلك. لإسهاماتهم!</string>
<string name="not_supported">غير مدعوم</string>
<string name="supported">إدعمنا</string>
<string name="home_kpm_module">"عدد وحدات KPM: %d "</string>
<string name="kpm_invalid_file">ملف KPM غير صحيح</string>
<string name="kernel_patched">النواة غير مصحوبة</string>
<string name="kernel_not_enabled">لم يتم تكوين النواة</string>
<string name="custom_settings">الإعدادات المُخصصة</string>
@@ -256,19 +230,13 @@
<string name="kpm_install_mode_load">التحميل</string>
<string name="kpm_install_mode_embed">فسيفساء</string>
<string name="kpm_install_mode_description">الرجاء التحديد: %1\$s وضع تثبيت الوحدة \n\nالتحميل: قم بتحميل الوحدة \nمؤقتا: تثبيت دائم في النظام</string>
<string name="log_failed_to_check_module_file">فشل التحقق من وجود ملف الوحدة</string>
<string name="snackbar_failed_to_check_module_file">غير قادر على التحقق من وجود ملف الوحدة</string>
<string name="confirm_uninstall_title">تأكيد إلغاء التثبيت</string>
<string name="confirm_uninstall_confirm">إلغاء التثبيت</string>
<string name="confirm_uninstall_dismiss">إلغاء</string>
<string name="theme_color">ألوان المظهر</string>
<string name="invalid_file_type">نوع الملف غير صحيح! الرجاء تحديد ملف .kpm.</string>
<string name="confirm_uninstall_title_with_filename">إلغاء التثبيت</string>
<string name="confirm_uninstall_content">سيتم إلغاء تثبيت KPM التالية: %s</string>
<string name="settings_susfs_toggle_summary">تعطيل روابط kprobe التي أنشأتها KernelSU، باستخدام الروابط الواردة بدلاً من ذلك، والتي تشبه طريقة الربط غير GKI غير GKI.</string>
<string name="image_editor_title">ضبط صورة الخلفية</string>
<string name="image_editor_hint">استخدم إصبعين لتكبير الصورة، وأصبع واحد لسحبها لضبط الموضع</string>
<string name="background_image_error">تعذر تحميل الصورة</string>
<string name="reprovision">إعادة</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">ضرب النواة</string>
@@ -291,25 +259,20 @@
<string name="horizon_getting_original_slot">الحصول على الفتحة الأصلية</string>
<string name="horizon_setting_target_slot">تعيين الفتحة المحددة</string>
<string name="horizon_restoring_original_slot">استعادة الخانة الافتراضية</string>
<string name="current_slot">خانة حالية:%1$s </string>
<string name="current_slot">فتحة النظام الحالية الافتراضية:%1$s </string>
<!-- Error Messages -->
<string name="horizon_copy_failed">فشل النسخ</string>
<string name="horizon_unknown_error">خطأ غير معروف</string>
<string name="flash_failed_message">فشل التركيب</string>
<!-- lkm/gki install -->
<string name="Lkm_install_methods">إصلاح/تثبيت LKM</string>
<string name="GKI_install_methods">Flashing AnyKernel3</string>
<string name="GKI_install_methods">نواة رمادية</string>
<string name="kernel_version_log">إصدار النواة:%1$s</string>
<string name="tool_version_log">استخدام أداة التصحيح:%1$s</string>
<string name="configuration">تعيين</string>
<string name="app_settings">إعدادات التطبيق </string>
<string name="tools">ادوات</string>
<string name="currently_selected">حالياً</string>
<!-- String resources used in SuperUser -->
<string name="clear">إزالة</string>
<string name="apps_with_root">التطبيقات مع امتيازات الجذر</string>
<string name="apps_with_custom_profile">التطبيقات مع الإعدادات المخصصة</string>
<string name="other_apps">التطبيقات ذات الإعدادات الافتراضية بدون تغيير</string>
<string name="no_apps_found">التطبيق غير موجود</string>
<string name="selinux_enabled_toast">تم تمكين SELinux</string>
<string name="selinux_disabled_toast">تم تعطيل SELinux</string>
@@ -317,25 +280,24 @@
<string name="advanced_settings">إعدادات متقدمة</string>
<string name="appearance_settings">تخصيص شريط الأدوات</string>
<string name="back">عد مرة أخرى</string>
<string name="expand">كن في طريقه كامل</string>
<string name="collapse">وضع بعيدا</string>
<string name="susfs_enabled">تم تمكين SuSFS</string>
<string name="susfs_disabled">تم تعطيل SuSFS</string>
<string name="background_set_success">تم تعيين الخلفية بنجاح</string>
<string name="background_removed">إزالة خلفيات مخصصة</string>
<string name="root_require_for_install">يتطلب امتيازات الجذر</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">عرض وظيفة KPM</string>
<string name="show_kpm_info_summary">عرض معلومات KPM ووظيفتها في الشريط المنزلي والأسفل (تحتاج إلى إعادة فتح التطبيق)</string>
<string name="show_kpm_info_summary">إخفاء معلومات KPM ووظيفتها في الشريط المنزلي والأسفل</string>
<!-- Webui X settings -->
<string name="use_webuix">Select the WebUI engine to use</string>
<string name="engine_auto_select">Automatic Selection</string>
<string name="use_webuix">حدد محرك WebUI لاستخدامه</string>
<string name="engine_auto_select">اختيار تلقائي</string>
<string name="engine_force_webuix">Force the use of WebUI X</string>
<string name="engine_force_ksu">Mandatory use of KSU WebUI</string>
<string name="use_webuix_eruda">حقن Eruda في WebUI X</string>
<string name="use_webuix_eruda_summary">حقن وحدة التصحيح في WebUI X لجعل تصحيح الأخطاء أسهل. يتطلب تصحيح أخطاء الويب لتكون قيد التشغيل.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">إعداد DPI</string>
<string name="app_dpi_title">تم تطبيق DPI</string>
<string name="app_dpi_summary">ضبط كثافة عرض الشاشة للتطبيق الحالي فقط</string>
<string name="dpi_size_small">صغير </string>
@@ -353,21 +315,58 @@
<string name="language_follow_system">اتبع النظام</string>
<string name="language_changed">تم تغيير اللغة، إعادة التشغيل لتطبيق التغييرات</string>
<string name="settings_card_dim">تعديل ظلام البطاقة</string>
<!-- Super User Related -->
<string name="scroll_to_top">في الأعلى</string>
<string name="scroll_to_bottom">أسفل</string>
<string name="scroll_to_top_description">التمرير لأعلى</string>
<string name="scroll_to_bottom_description">التمرير إلى الأسفل</string>
<string name="authorized">مصرح</string>
<string name="unauthorized">غير مصرح</string>
<string name="selected">محدد</string>
<string name="select">خيار</string>
<string name="profile_umount_modules_disable">تعطيل وحدة إلغاء التثبيت المخصصة</string>
<!-- Flash related -->
<string name="error_code">رمز الخطأ</string>
<string name="check_log">يرجى التحقق من السجل</string>
<string name="installing_module">تم تثبيت الوحدة %1$d/%2$d</string>
<string name="module_failed_count">أخفق %d في تثبيت وحدة جديدة</string>
<string name="module_download_error">فشل تحميل الوحدة</string>
<string name="kernel_flashing">Kernel Flashing</string>
<string name="kernel_flashing">ضرب النواة</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">في الأعلى</string>
<string name="scroll_to_bottom">أسفل</string>
<string name="selected">محدد</string>
<string name="select">خيار</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">Yükləmək üçün toxunun</string>
<string name="home_working">İşləyir</string>
<string name="home_working_version">Versiya: %d</string>
<string name="home_superuser_count">Super istifadəçilər: %d</string>
<string name="home_module_count">Modullar: %d</string>
<string name="home_unsupported">Dəstəklənmir</string>
<string name="home_unsupported_reason">Hal-hazırda KernelSU yalnız GKI nüvələrini dəstəkləyir</string>
<string name="home_kernel">Nüvə</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS Version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">Menecer versiyası</string>
<string name="home_fingerprint">Barmaq izi</string>
<string name="home_selinux_status">SELinux vəziyyəti</string>
<string name="selinux_status_disabled">Qeyri-aktiv</string>
<string name="selinux_status_enforcing">Məcburi</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="uninstall">Sil</string>
<string name="restore">Restore</string>
<string name="module_install">Yüklə</string>
<string name="install">Yüklə</string>
<string name="reboot">Yenidən başlat</string>
@@ -61,10 +55,6 @@
<string name="profile_template">Şablon</string>
<string name="profile_custom">Özəl</string>
<string name="profile_name">Profil adı</string>
<string name="profile_namespace">Bölmənin ad sahəsi</string>
<string name="profile_namespace_inherited">Miras qalmış</string>
<string name="profile_namespace_global">Qlobal</string>
<string name="profile_namespace_individual">Fərdi</string>
<string name="profile_groups">Qruplar</string>
<string name="profile_capabilities">Bacarıqlar</string>
<string name="profile_selinux_context">SELinux konteksi</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Automatically check for updates when opening the app</string>
<string name="grant_root_failed">Failed to grant root!</string>
<string name="action">Action</string>
<string name="open">Open</string>
<string name="close">Close</string>
<string name="enable_web_debugging">Enable WebView debugging</string>
<string name="enable_web_debugging_summary">Can be used to debug WebUI. Please enable only when needed.</string>
@@ -136,9 +125,6 @@
<string name="selected_lkm">Selected LKM: %s</string>
<string name="save_log">Girişləri Saxla</string>
<string name="log_saved">Logs saved</string>
<string name="status_supported">Supported</string>
<string name="status_not_supported">Not Supported</string>
<string name="status_unknown">Unknown</string>
<string name="sus_su_mode">SuS SU mode:</string>
<!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string>
@@ -172,14 +158,11 @@
<string name="settings_custom_background">Custom App Background</string>
<string name="settings_custom_background_summary">Select an image as background</string>
<string name="settings_card_alpha">Navigation bar transparency</string>
<string name="settings_restore_default">Restore default</string>
<string name="home_android_version">Android version</string>
<string name="home_device_model">Device model</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string>
<string name="using_mksu_manager">You are using the SukiSU Beta manager</string>
<string name="module_install_multiple_confirm">Are you sure you want to install the selected %d modules?</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -210,20 +193,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Gray</string>
<string name="color_yellow">Yellow</string>
<string name="flash_option">Brush Options</string>
<string name="flash_option_tip">Select the file to be flashed</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string>
<string name="root_required">Requires root privileges</string>
<string name="copy_failed">File Copy Failure</string>
<string name="reboot_complete_title">Scrubbing complete</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="failed_reboot">Reboot Failed</string>
<string name="batch_authorization">empower</string>
<string name="batch_cancel_authorization">withdraw</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string>
<string name="kpm_version">Version</string>
@@ -231,7 +208,6 @@
<string name="kpm_uninstall">Uninstall</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string>
<string name="kpm_install">Install</string>
<string name="kpm_install_success">Load of kpm module successful</string>
<string name="kpm_install_failed">Load of kpm module failed</string>
<string name="kpm_args">Parameters</string>
@@ -245,8 +221,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string>
<string name="not_supported">Unsupported</string>
<string name="supported">Supported</string>
<string name="home_kpm_module">"Number of KPM modules: %d "</string>
<string name="kpm_invalid_file">Invalid KPM file</string>
<string name="kernel_patched">Kernel not patched</string>
<string name="kernel_not_enabled">Kernel not configured</string>
<string name="custom_settings">Custom settings</string>
@@ -254,19 +228,13 @@
<string name="kpm_install_mode_load">Load</string>
<string name="kpm_install_mode_embed">Embed</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string>
<string name="log_failed_to_check_module_file">Failed to check module file existence</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string>
<string name="confirm_uninstall_title">Confirm uninstallation</string>
<string name="confirm_uninstall_confirm">Uninstall</string>
<string name="confirm_uninstall_dismiss">Cancel</string>
<string name="theme_color">Theme Color</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string>
<string name="image_editor_title">Adjust background image</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string>
<string name="background_image_error">Could not load image</string>
<string name="reprovision">Reprovision</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -302,12 +270,7 @@
<string name="configuration">Configure</string>
<string name="app_settings">Application Settings</string>
<string name="tools">Tools</string>
<string name="currently_selected">Currently</string>
<!-- String resources used in SuperUser -->
<string name="clear">Removals</string>
<string name="apps_with_root">Applications with root privileges</string>
<string name="apps_with_custom_profile">Applications with customized configurations</string>
<string name="other_apps">Applications with unchanged defaults</string>
<string name="no_apps_found">Application not found</string>
<string name="selinux_enabled_toast">SELinux Enabled</string>
<string name="selinux_disabled_toast">SELinux Disabled</string>
@@ -315,13 +278,13 @@
<string name="advanced_settings">Advanced Settings</string>
<string name="appearance_settings">Customize the toolbar</string>
<string name="back">Comeback</string>
<string name="expand">Be in full swing</string>
<string name="collapse">put away</string>
<string name="susfs_enabled">SuSFS enabled</string>
<string name="susfs_disabled">SuSFS disabled</string>
<string name="background_set_success">Background set successfully</string>
<string name="background_removed">Removed custom backgrounds</string>
<string name="root_require_for_install">Requires root privileges</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string>
@@ -333,7 +296,6 @@
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI setting</string>
<string name="app_dpi_title">Applied DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
<string name="dpi_size_small">Small </string>
@@ -351,16 +313,6 @@
<string name="language_follow_system">Follow System</string>
<string name="language_changed">Language changed, restarting to apply changes</string>
<string name="settings_card_dim">Card Darkness Adjustment</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="scroll_to_top_description">Scroll to top</string>
<string name="scroll_to_bottom_description">Scroll to the bottom</string>
<string name="authorized">authorized</string>
<string name="unauthorized">unauthorized</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Disable custom uninstallation module</string>
<!-- Flash related -->
<string name="error_code">error code</string>
<string name="check_log">Please check the log</string>
@@ -368,4 +320,51 @@
<string name="module_failed_count">%d Failed to install a new module</string>
<string name="module_download_error">Module download failed</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -6,11 +6,9 @@
<string name="module_failed_to_enable">মোডিউল ইনেবল করা যায়নি: %s</string>
<string name="home_click_to_install">ইন্সটল করটে চাপুন</string>
<string name="home_working">কাজ করছে</string>
<string name="home_module_count">মোডিউল: %d</string>
<string name="home_unsupported">অমূলক</string>
<string name="home_kernel">কর্নেল</string>
<string name="home_manager_version">ম্যানেজার ভারসন</string>
<string name="home_fingerprint">ফিঙ্গারপ্রিন্ট</string>
<string name="selinux_status_disabled">ডিসেবল</string>
<string name="selinux_status_enforcing">এনফোর্সিং</string>
<string name="superuser">সুপার ইউজার</string>
@@ -21,7 +19,6 @@
<string name="reboot">রিবুট</string>
<string name="settings">সেটিংস</string>
<string name="reboot_userspace">সফট রিবুট</string>
<string name="profile_namespace_global">গ্লোবাল</string>
<string name="profile_groups">গ্রুপস</string>
<string name="profile_selinux_context">এসইলিনাক্স কন্টেক্সট</string>
<string name="failed_to_update_app_profile">%s এর জন্য অ্যাপ প্রফাইল আপডেট করা যায়নি</string>
@@ -32,10 +29,6 @@
<string name="module_failed_to_disable">মোডিউল ডিসেবল করা যায়নি: %s</string>
<string name="module_empty">কোনো মোডিউল ইন্সটল করা নেই</string>
<string name="home_working_version">সংস্করণ: %d</string>
<string name="home_superuser_count">সুপার ইউজার: %d</string>
<string name="profile_namespace">নেইম স্পেস মাউন্ট</string>
<string name="profile_namespace_inherited">ইনহেরিটেড</string>
<string name="profile_namespace_individual">ইন্ডিভিজুয়াল</string>
<string name="profile_capabilities">ক্যাপাবিলিটিস</string>
<string name="profile_umount_modules">আনমাউন্ট মোডিউলস</string>
<string name="reboot_recovery">রিকভারিতে বুট</string>

View File

@@ -5,13 +5,10 @@
<string name="home_click_to_install">ইনস্টল করার জন্য ক্লিক করুন</string>
<string name="home_working"> ওয়ার্কিং</string>
<string name="home_working_version">ওয়ার্কিং সংস্করণ: %d</string>
<string name="home_superuser_count">সুপার ইউজার: %d</string>
<string name="home_module_count">মডিউল: %d</string>
<string name="home_unsupported">অসমর্থিত</string>
<string name="home_unsupported_reason">KernelSU শুধুমাত্র GKI কার্নেল সমর্থন করে</string>
<string name="home_kernel">কার্নেল</string>
<string name="home_manager_version">ম্যানেজার সংস্করণ</string>
<string name="home_fingerprint">ফিঙ্গারপ্রিন্ট</string>
<string name="home_selinux_status">SELinux স্টেটাস</string>
<string name="selinux_status_disabled">ডিজেবল</string>
<string name="selinux_status_enforcing">কার্যকর</string>
@@ -51,15 +48,12 @@
<string name="home_support_title">সাপোর্ট টাইটেল</string>
<string name="home_support_content">কার্নেলএসইউ বিনামূল্যে এবং ওপেন সোর্স, এবং সবসময় থাকবে। আপনি সবসময় একটি অনুদান দিয়ে আপনার কৃতজ্ঞতা প্রদর্শন করতে পারেন.</string>
<string name="profile_name">প্রফাইলের নাম</string>
<string name="profile_namespace">নেমস্পেস মাউন্ট</string>
<string name="profile_groups">গ্রুপস</string>
<string name="profile_capabilities">যোগ্যতা</string>
<string name="profile_selinux_context">এসই লিনাক্স কনটেক্সট</string>
<string name="profile_default">ডিফল্ট</string>
<string name="profile_template">টেমপ্লেট</string>
<string name="profile_custom">কাস্টম</string>
<string name="profile_namespace_global">গ্লোবাল</string>
<string name="profile_namespace_individual">আলাদাভাবে</string>
<string name="profile_umount_modules">আনমাউন্ট মোডিউল</string>
<string name="save_log">লগ সংরক্ষণ করুন</string>
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">Kliknite da instalirate</string>
<string name="home_working">Radi</string>
<string name="home_working_version">Verzija: %d</string>
<string name="home_superuser_count">Superkorisnici: %d</string>
<string name="home_module_count">Module: %d</string>
<string name="home_unsupported">Nepodržano</string>
<string name="home_unsupported_reason">KernelSU samo podržava GKI kernele sad</string>
<string name="home_kernel">Kernel</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS Version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">Verzija Upravitelja</string>
<string name="home_fingerprint">Otisak prsta</string>
<string name="home_selinux_status">SELinux stanje</string>
<string name="selinux_status_disabled">Isključeno</string>
<string name="selinux_status_enforcing">U Provođenju</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="uninstall">Deinstalirajte</string>
<string name="restore">Restore</string>
<string name="module_install">Instalirajte</string>
<string name="install">Instalirajte</string>
<string name="reboot">Ponovo pokrenite</string>
@@ -61,10 +55,6 @@
<string name="profile_template">Šablon</string>
<string name="profile_custom">Prilagođeno</string>
<string name="profile_name">Naziv profila</string>
<string name="profile_namespace">Imenski prostor nosača</string>
<string name="profile_namespace_inherited">Naslijeđen</string>
<string name="profile_namespace_global">Globalan</string>
<string name="profile_namespace_individual">Pojedinačan</string>
<string name="profile_groups">Grupe</string>
<string name="profile_capabilities">Sposobnosti</string>
<string name="profile_selinux_context">SELinux kontekst</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Automatically check for updates when opening the app</string>
<string name="grant_root_failed">Failed to grant root!</string>
<string name="action">Action</string>
<string name="open">Open</string>
<string name="close">Close</string>
<string name="enable_web_debugging">Enable WebView debugging</string>
<string name="enable_web_debugging_summary">Can be used to debug WebUI. Please enable only when needed.</string>
@@ -136,9 +125,6 @@
<string name="selected_lkm">Selected LKM: %s</string>
<string name="save_log">Sačuvaj Dnevnike</string>
<string name="log_saved">Logs saved</string>
<string name="status_supported">Supported</string>
<string name="status_not_supported">Not Supported</string>
<string name="status_unknown">Unknown</string>
<string name="sus_su_mode">SuS SU mode:</string>
<!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string>
@@ -172,14 +158,11 @@
<string name="settings_custom_background">Custom App Background</string>
<string name="settings_custom_background_summary">Select an image as background</string>
<string name="settings_card_alpha">Navigation bar transparency</string>
<string name="settings_restore_default">Restore default</string>
<string name="home_android_version">Android version</string>
<string name="home_device_model">Device model</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string>
<string name="using_mksu_manager">You are using the SukiSU Beta manager</string>
<string name="module_install_multiple_confirm">Are you sure you want to install the selected %d modules?</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -210,20 +193,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Gray</string>
<string name="color_yellow">Yellow</string>
<string name="flash_option">Brush Options</string>
<string name="flash_option_tip">Select the file to be flashed</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string>
<string name="root_required">Requires root privileges</string>
<string name="copy_failed">File Copy Failure</string>
<string name="reboot_complete_title">Scrubbing complete</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="failed_reboot">Reboot Failed</string>
<string name="batch_authorization">empower</string>
<string name="batch_cancel_authorization">withdraw</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string>
<string name="kpm_version">Version</string>
@@ -231,7 +208,6 @@
<string name="kpm_uninstall">Uninstall</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string>
<string name="kpm_install">Install</string>
<string name="kpm_install_success">Load of kpm module successful</string>
<string name="kpm_install_failed">Load of kpm module failed</string>
<string name="kpm_args">Parameters</string>
@@ -245,8 +221,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string>
<string name="not_supported">Unsupported</string>
<string name="supported">Supported</string>
<string name="home_kpm_module">"Number of KPM modules: %d "</string>
<string name="kpm_invalid_file">Invalid KPM file</string>
<string name="kernel_patched">Kernel not patched</string>
<string name="kernel_not_enabled">Kernel not configured</string>
<string name="custom_settings">Custom settings</string>
@@ -254,19 +228,13 @@
<string name="kpm_install_mode_load">Load</string>
<string name="kpm_install_mode_embed">Embed</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string>
<string name="log_failed_to_check_module_file">Failed to check module file existence</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string>
<string name="confirm_uninstall_title">Confirm uninstallation</string>
<string name="confirm_uninstall_confirm">Uninstall</string>
<string name="confirm_uninstall_dismiss">Cancel</string>
<string name="theme_color">Theme Color</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string>
<string name="image_editor_title">Adjust background image</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string>
<string name="background_image_error">Could not load image</string>
<string name="reprovision">Reprovision</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -302,12 +270,7 @@
<string name="configuration">Configure</string>
<string name="app_settings">Application Settings</string>
<string name="tools">Tools</string>
<string name="currently_selected">Currently</string>
<!-- String resources used in SuperUser -->
<string name="clear">Removals</string>
<string name="apps_with_root">Applications with root privileges</string>
<string name="apps_with_custom_profile">Applications with customized configurations</string>
<string name="other_apps">Applications with unchanged defaults</string>
<string name="no_apps_found">Application not found</string>
<string name="selinux_enabled_toast">SELinux Enabled</string>
<string name="selinux_disabled_toast">SELinux Disabled</string>
@@ -315,13 +278,13 @@
<string name="advanced_settings">Advanced Settings</string>
<string name="appearance_settings">Customize the toolbar</string>
<string name="back">Comeback</string>
<string name="expand">Be in full swing</string>
<string name="collapse">put away</string>
<string name="susfs_enabled">SuSFS enabled</string>
<string name="susfs_disabled">SuSFS disabled</string>
<string name="background_set_success">Background set successfully</string>
<string name="background_removed">Removed custom backgrounds</string>
<string name="root_require_for_install">Requires root privileges</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string>
@@ -333,7 +296,6 @@
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI setting</string>
<string name="app_dpi_title">Applied DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
<string name="dpi_size_small">Small </string>
@@ -351,16 +313,6 @@
<string name="language_follow_system">Follow System</string>
<string name="language_changed">Language changed, restarting to apply changes</string>
<string name="settings_card_dim">Card Darkness Adjustment</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="scroll_to_top_description">Scroll to top</string>
<string name="scroll_to_bottom_description">Scroll to the bottom</string>
<string name="authorized">authorized</string>
<string name="unauthorized">unauthorized</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Disable custom uninstallation module</string>
<!-- Flash related -->
<string name="error_code">error code</string>
<string name="check_log">Please check the log</string>
@@ -368,4 +320,51 @@
<string name="module_failed_count">%d Failed to install a new module</string>
<string name="module_download_error">Module download failed</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">Klik for at installere</string>
<string name="home_working">Arbejder</string>
<string name="home_working_version">Version: %d</string>
<string name="home_superuser_count">Superbrugere: %d</string>
<string name="home_module_count">Moduler: %d</string>
<string name="home_unsupported">Ikke understøttet</string>
<string name="home_unsupported_reason">KernelSU understøtter kun GKI kernels</string>
<string name="home_kernel">Kernel</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS Version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">Manager Version</string>
<string name="home_fingerprint">Fingeraftryk</string>
<string name="home_selinux_status">SELinux-status</string>
<string name="selinux_status_disabled">Deaktiveret</string>
<string name="selinux_status_enforcing">Håndhævende</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="uninstall">Afinstaller</string>
<string name="restore">Restore</string>
<string name="module_install">Installer</string>
<string name="install">Installer</string>
<string name="reboot">Genstart</string>
@@ -61,10 +55,6 @@
<string name="profile_template">Skabelon</string>
<string name="profile_custom">Brugerdefineret</string>
<string name="profile_name">Profilnavn</string>
<string name="profile_namespace">Monter navnerum</string>
<string name="profile_namespace_inherited">Arvet</string>
<string name="profile_namespace_global">Global</string>
<string name="profile_namespace_individual">Individuel</string>
<string name="profile_groups">Grupper</string>
<string name="profile_capabilities">Evner</string>
<string name="profile_selinux_context">SELinux-kontext</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Automatically check for updates when opening the app</string>
<string name="grant_root_failed">Failed to grant root!</string>
<string name="action">Action</string>
<string name="open">Open</string>
<string name="close">Close</string>
<string name="enable_web_debugging">Enable WebView debugging</string>
<string name="enable_web_debugging_summary">Can be used to debug WebUI. Please enable only when needed.</string>
@@ -136,9 +125,6 @@
<string name="selected_lkm">Selected LKM: %s</string>
<string name="save_log">Gem Logfiler</string>
<string name="log_saved">Logs saved</string>
<string name="status_supported">Supported</string>
<string name="status_not_supported">Not Supported</string>
<string name="status_unknown">Unknown</string>
<string name="sus_su_mode">SuS SU mode:</string>
<!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string>
@@ -172,14 +158,11 @@
<string name="settings_custom_background">Custom App Background</string>
<string name="settings_custom_background_summary">Select an image as background</string>
<string name="settings_card_alpha">Navigation bar transparency</string>
<string name="settings_restore_default">Restore default</string>
<string name="home_android_version">Android version</string>
<string name="home_device_model">Device model</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string>
<string name="using_mksu_manager">You are using the SukiSU Beta manager</string>
<string name="module_install_multiple_confirm">Are you sure you want to install the selected %d modules?</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -210,20 +193,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Gray</string>
<string name="color_yellow">Yellow</string>
<string name="flash_option">Brush Options</string>
<string name="flash_option_tip">Select the file to be flashed</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string>
<string name="root_required">Requires root privileges</string>
<string name="copy_failed">File Copy Failure</string>
<string name="reboot_complete_title">Scrubbing complete</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="failed_reboot">Reboot Failed</string>
<string name="batch_authorization">empower</string>
<string name="batch_cancel_authorization">withdraw</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string>
<string name="kpm_version">Version</string>
@@ -231,7 +208,6 @@
<string name="kpm_uninstall">Uninstall</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string>
<string name="kpm_install">Install</string>
<string name="kpm_install_success">Load of kpm module successful</string>
<string name="kpm_install_failed">Load of kpm module failed</string>
<string name="kpm_args">Parameters</string>
@@ -245,8 +221,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string>
<string name="not_supported">Unsupported</string>
<string name="supported">Supported</string>
<string name="home_kpm_module">"Number of KPM modules: %d "</string>
<string name="kpm_invalid_file">Invalid KPM file</string>
<string name="kernel_patched">Kernel not patched</string>
<string name="kernel_not_enabled">Kernel not configured</string>
<string name="custom_settings">Custom settings</string>
@@ -254,19 +228,13 @@
<string name="kpm_install_mode_load">Load</string>
<string name="kpm_install_mode_embed">Embed</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string>
<string name="log_failed_to_check_module_file">Failed to check module file existence</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string>
<string name="confirm_uninstall_title">Confirm uninstallation</string>
<string name="confirm_uninstall_confirm">Uninstall</string>
<string name="confirm_uninstall_dismiss">Cancel</string>
<string name="theme_color">Theme Color</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string>
<string name="image_editor_title">Adjust background image</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string>
<string name="background_image_error">Could not load image</string>
<string name="reprovision">Reprovision</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -302,12 +270,7 @@
<string name="configuration">Configure</string>
<string name="app_settings">Application Settings</string>
<string name="tools">Tools</string>
<string name="currently_selected">Currently</string>
<!-- String resources used in SuperUser -->
<string name="clear">Removals</string>
<string name="apps_with_root">Applications with root privileges</string>
<string name="apps_with_custom_profile">Applications with customized configurations</string>
<string name="other_apps">Applications with unchanged defaults</string>
<string name="no_apps_found">Application not found</string>
<string name="selinux_enabled_toast">SELinux Enabled</string>
<string name="selinux_disabled_toast">SELinux Disabled</string>
@@ -315,13 +278,13 @@
<string name="advanced_settings">Advanced Settings</string>
<string name="appearance_settings">Customize the toolbar</string>
<string name="back">Comeback</string>
<string name="expand">Be in full swing</string>
<string name="collapse">put away</string>
<string name="susfs_enabled">SuSFS enabled</string>
<string name="susfs_disabled">SuSFS disabled</string>
<string name="background_set_success">Background set successfully</string>
<string name="background_removed">Removed custom backgrounds</string>
<string name="root_require_for_install">Requires root privileges</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string>
@@ -333,7 +296,6 @@
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI setting</string>
<string name="app_dpi_title">Applied DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
<string name="dpi_size_small">Small </string>
@@ -351,16 +313,6 @@
<string name="language_follow_system">Follow System</string>
<string name="language_changed">Language changed, restarting to apply changes</string>
<string name="settings_card_dim">Card Darkness Adjustment</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="scroll_to_top_description">Scroll to top</string>
<string name="scroll_to_bottom_description">Scroll to the bottom</string>
<string name="authorized">authorized</string>
<string name="unauthorized">unauthorized</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Disable custom uninstallation module</string>
<!-- Flash related -->
<string name="error_code">error code</string>
<string name="check_log">Please check the log</string>
@@ -368,4 +320,51 @@
<string name="module_failed_count">%d Failed to install a new module</string>
<string name="module_download_error">Module download failed</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">Tippe zum Installieren</string>
<string name="home_working">Funktioniert</string>
<string name="home_working_version">Version: %d</string>
<string name="home_superuser_count">Superuser: %d</string>
<string name="home_module_count">Module: %d</string>
<string name="home_unsupported">Nicht unterstützt</string>
<string name="home_unsupported_reason">KernelSU unterstützt derzeit nur GKI-Kernel</string>
<string name="home_kernel">Kernel</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">Manager-Version</string>
<string name="home_fingerprint">Fingerabdruck</string>
<string name="home_selinux_status">SELinux Status</string>
<string name="selinux_status_disabled">Deaktiviert</string>
<string name="selinux_status_enforcing">Erzwingen</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Sortiere zuerst (Aktion)</string>
<string name="module_sort_enabled_first">Sortieren (zuerst aktiviert)</string>
<string name="uninstall">Deinstallieren</string>
<string name="restore">Wiederherstellen</string>
<string name="module_install">Installieren</string>
<string name="install">Installieren</string>
<string name="reboot">Neustarten</string>
@@ -61,10 +55,6 @@
<string name="profile_template">Vorlage</string>
<string name="profile_custom">Benutzerdefiniert</string>
<string name="profile_name">Profilname</string>
<string name="profile_namespace">Namespace einhängen</string>
<string name="profile_namespace_inherited">Geerbt</string>
<string name="profile_namespace_global">Global</string>
<string name="profile_namespace_individual">Individuell</string>
<string name="profile_groups">Gruppen</string>
<string name="profile_capabilities">Fähigkeiten</string>
<string name="profile_selinux_context">SELinux-Kontext</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Prüfe automatisch auf Aktualisierungen, wenn die App geöffnet wird</string>
<string name="grant_root_failed">Root-Zugriff konnte nicht gewährt werden!</string>
<string name="action">Aktion</string>
<string name="open">Öffnen</string>
<string name="close">Schließen</string>
<string name="enable_web_debugging">WebView-Debugging aktivieren</string>
<string name="enable_web_debugging_summary">Kann zum Fehlerbeheben der WebUI verwendet werden, bitte nur im Notfall aktivieren.</string>
@@ -138,9 +127,6 @@
<string name="selected_lkm">Wähle LKM: %s</string>
<string name="save_log">Protokolle Speichern</string>
<string name="log_saved">Protokolle gespeichert</string>
<string name="status_supported">Unterstützt:</string>
<string name="status_not_supported">Nicht unterstützt</string>
<string name="status_unknown">Unbekannt</string>
<string name="sus_su_mode">SuS SU-Modus:</string>
<!-- Module related -->
<string name="module_install_confirm">das Installationsmodul %1$s bestätigen ?</string>
@@ -174,14 +160,11 @@
<string name="settings_custom_background">Eigener App-Hintergrund</string>
<string name="settings_custom_background_summary">Wählen Sie ein Bild als Hintergrund</string>
<string name="settings_card_alpha">Transparenz der Navigationsleiste</string>
<string name="settings_restore_default">Standard wiederherstellen</string>
<string name="home_android_version">Androidversion</string>
<string name="home_device_model">Geräteausführung</string>
<string name="su_not_allowed">Superuser %s zu erlauben ist nicht erlaubt</string>
<string name="settings_disable_su">Su Kompatibilität deaktivieren</string>
<string name="settings_disable_su_summary">Deaktivieren Sie temporär alle Anwendungen, die root-Privilegien über den Befehl &lt;unk&gt; su zu erhalten (bestehende root-Prozesse werden nicht beeinflusst).</string>
<string name="using_mksu_manager">Sie verwenden den SukiSU Beta-Manager</string>
<string name="module_install_multiple_confirm">Sind Sie sicher, dass Sie die ausgewählten %d -Module installieren möchten?</string>
<string name="module_install_multiple_confirm_with_names">Möchten Sie die folgenden %1$d Module installieren? \n\n\n%2$s</string>
<string name="more_settings">Weitere Einstellungen</string>
<string name="selinux">SELinux</string>
@@ -212,20 +195,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Grau</string>
<string name="color_yellow">Gelb</string>
<string name="flash_option">Pinseloptionen</string>
<string name="flash_option_tip">Wählen Sie die zu flashende Datei</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 Kernel-Datei</string>
<string name="root_required">Erfordert Root-Rechte</string>
<string name="copy_failed">Datei-Kopierfehler</string>
<string name="reboot_complete_title">Scrubbing abgeschlossen</string>
<string name="reboot_complete_msg">Ob sofort neu gestartet werden soll?</string>
<string name="yes">Ja</string>
<string name="no">Nein</string>
<string name="failed_reboot">Neustart fehlgeschlagen</string>
<string name="batch_authorization">empowern</string>
<string name="batch_cancel_authorization">abheben</string>
<string name="backup">Sicherung</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">Keine installierten Kernelmodule</string>
<string name="kpm_version">Version</string>
@@ -233,7 +210,6 @@
<string name="kpm_uninstall">Deinstallieren</string>
<string name="kpm_uninstall_success">Erfolgreich deinstalliert</string>
<string name="kpm_uninstall_failed">Deinstallation fehlgeschlagen</string>
<string name="kpm_install">Installieren</string>
<string name="kpm_install_success">Laden des kpm Moduls erfolgreich</string>
<string name="kpm_install_failed">Laden des kpm-Moduls fehlgeschlagen</string>
<string name="kpm_args">Parameter</string>
@@ -247,8 +223,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra wird in Zukunft ein relativ unabhängiger Zweig der KSU sein, aber wir schätzen immer noch die offiziellen KernelSU und MKSU usw. für ihre Beiträge!</string>
<string name="not_supported">Nicht unterstützt</string>
<string name="supported">Unterstützt:</string>
<string name="home_kpm_module">"Anzahl der KPM-Module: %d "</string>
<string name="kpm_invalid_file">Ungültige KPM-Datei</string>
<string name="kernel_patched">Kernel nicht gepatcht</string>
<string name="kernel_not_enabled">Kernel nicht konfiguriert</string>
<string name="custom_settings">Eigene Einstellungen</string>
@@ -256,19 +230,13 @@
<string name="kpm_install_mode_load">Laden</string>
<string name="kpm_install_mode_embed">Einbetten</string>
<string name="kpm_install_mode_description">Bitte wählen: %1\$s Modul-Installationsmodus \n\nLaden: Das Modul \ntemporär laden: Dauerhaft in das System installieren</string>
<string name="log_failed_to_check_module_file">Fehler beim Prüfen der Moduldatei-Existenz</string>
<string name="snackbar_failed_to_check_module_file">Kann nicht überprüfen, ob die Moduldatei existiert</string>
<string name="confirm_uninstall_title">Deinstallation bestätigen.</string>
<string name="confirm_uninstall_confirm">Deinstallieren</string>
<string name="confirm_uninstall_dismiss">Abbrechen</string>
<string name="theme_color">Themenfarbe</string>
<string name="invalid_file_type">Falscher Dateityp! Bitte wählen Sie eine .kpm Datei.</string>
<string name="confirm_uninstall_title_with_filename">Deinstallieren</string>
<string name="confirm_uninstall_content">Folgende KPM wird deinstalliert: %s</string>
<string name="settings_susfs_toggle_summary">Deaktiviere kprobe Hooks die von KernelSU erstellt wurden und stattdessen inline Hooks verwenden, was der Nicht-GKI-Kernel-Hooking Methode ähnlich ist.</string>
<string name="image_editor_title">Hintergrundbild anpassen</string>
<string name="image_editor_hint">Verwende zwei Finger um das Bild zu vergrößern und einen Finger um die Position anzupassen</string>
<string name="background_image_error">Bild konnte nicht geladen werden</string>
<string name="reprovision">Rückzahlung</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel-Flashen</string>
@@ -291,25 +259,20 @@
<string name="horizon_getting_original_slot">Den ursprünglichen Slot erhalten</string>
<string name="horizon_setting_target_slot">Setze den angegebenen Slot</string>
<string name="horizon_restoring_original_slot">Standard wiederherstellen</string>
<string name="current_slot">Aktueller Slot%1$s </string>
<string name="current_slot">Aktueller Standard-Slot des Systems%1$s </string>
<!-- Error Messages -->
<string name="horizon_copy_failed">Kopieren fehlgeschlagen</string>
<string name="horizon_unknown_error">Ein unbekannter Fehler ist aufgetreten</string>
<string name="flash_failed_message">Schreiben fehlgeschlagen</string>
<!-- lkm/gki install -->
<string name="Lkm_install_methods">LKM Reparatur/Installation</string>
<string name="GKI_install_methods">Flashing AnyKernel3</string>
<string name="GKI_install_methods">Flashen des Kernels…</string>
<string name="kernel_version_log">Kernel</string>
<string name="tool_version_log">Benutze das Patchwerkzeug%1$s</string>
<string name="configuration">Konfigurieren</string>
<string name="app_settings">Anwendungs-Einstellungen</string>
<string name="tools">Tools</string>
<string name="currently_selected">Derzeit</string>
<!-- String resources used in SuperUser -->
<string name="clear">Entfernen</string>
<string name="apps_with_root">Anwendungen mit Root-Rechten</string>
<string name="apps_with_custom_profile">Anwendungen mit angepassten Konfigurationen</string>
<string name="other_apps">Anwendungen mit unveränderten Standardeinstellungen</string>
<string name="no_apps_found">Anwendung nicht gefunden</string>
<string name="selinux_enabled_toast">SELinux aktiviert</string>
<string name="selinux_disabled_toast">SELinux deaktiviert</string>
@@ -317,25 +280,24 @@
<string name="advanced_settings">Erweiterte Einstellungen</string>
<string name="appearance_settings">Passt die Symbolleiste an.</string>
<string name="back">Comeback</string>
<string name="expand">Seien Sie in vollem Gange</string>
<string name="collapse">wegziehen</string>
<string name="susfs_enabled">SuSFS aktiviert</string>
<string name="susfs_disabled">SuSFS deaktiviert</string>
<string name="background_set_success">Hintergrund erfolgreich gesetzt</string>
<string name="background_removed">Eigene Hintergründe entfernt</string>
<string name="root_require_for_install">Erfordert Root-Rechte</string>
<string name="icon_switch_title">Alternatives Symbol</string>
<string name="icon_switch_summary">Ändere das Launcher-Symbol auf das KernelSU Icon.</string>
<string name="icon_switched">Icon gewechselt</string>
<!-- KPM display settings -->
<string name="show_kpm_info">KPM-Funktion anzeigen</string>
<string name="show_kpm_info_summary">KPM-Informationen und Funktion in der Home- und unteren Leiste anzeigen (muss die App erneut öffnen)</string>
<string name="show_kpm_info_summary">Versteckt KPM-Informationen und Funktion in der Home- und Unterleiste</string>
<!-- Webui X settings -->
<string name="use_webuix">Select the WebUI engine to use</string>
<string name="engine_auto_select">Automatic Selection</string>
<string name="engine_force_webuix">Force the use of WebUI X</string>
<string name="engine_force_ksu">Mandatory use of KSU WebUI</string>
<string name="use_webuix">Wähle die zu verwendende WebUI-Engine</string>
<string name="engine_auto_select">Automatisch auswählen</string>
<string name="engine_force_webuix">Nutzung von WebUI X erzwingen</string>
<string name="engine_force_ksu">Pflichtanwendung von KSU WebUI</string>
<string name="use_webuix_eruda">Eruda in WebUI X injizieren</string>
<string name="use_webuix_eruda_summary">Fügen Sie eine Debug-Konsole in WebUI X ein, um das Debuggen zu vereinfachen. Benötigt Debugging im WebUI X.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI-Einstellung</string>
<string name="app_dpi_title">Angewendeter DPI</string>
<string name="app_dpi_summary">Bildschirmanzahl nur für die aktuelle Anwendung anpassen</string>
<string name="dpi_size_small">Klein </string>
@@ -353,21 +315,58 @@
<string name="language_follow_system">Folge Systemeinstellung</string>
<string name="language_changed">Sprache geändert, Neustart um Änderungen zu übernehmen</string>
<string name="settings_card_dim">Kartenfinsternis Anpassung</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Unten</string>
<string name="scroll_to_top_description">Bildlauf nach oben scrollen</string>
<string name="scroll_to_bottom_description">Scrolle zum Ende</string>
<string name="authorized">Autorisiert</string>
<string name="unauthorized">Unberechtigt</string>
<string name="selected">Ausgewählt</string>
<string name="select">variieren</string>
<string name="profile_umount_modules_disable">Eigenes Deinstallationsmodul deaktivieren</string>
<!-- Flash related -->
<string name="error_code">fehlercode</string>
<string name="check_log">Bitte überprüfen Sie das Log</string>
<string name="installing_module">Modul wird installiert %1$d/%2$d</string>
<string name="module_failed_count">%d Fehler bei der Installation eines neuen Moduls</string>
<string name="module_download_error">Modul-Download fehlgeschlagen</string>
<string name="kernel_flashing">Kernel Flashing</string>
<string name="kernel_flashing">Kernel-Flashen</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Unten</string>
<string name="selected">Ausgewählt</string>
<string name="select">variieren</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">Haz clic para instalar</string>
<string name="home_working">Funcionando</string>
<string name="home_working_version">Versión: %d</string>
<string name="home_superuser_count">Superusuarios: %d</string>
<string name="home_module_count">Módulos: %d</string>
<string name="home_unsupported">Sin soporte</string>
<string name="home_unsupported_reason">KernelSU solo admite kernels GKI por ahora</string>
<string name="home_kernel">Versión del kernel</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">Versión SuSFS</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">Versión del gestor</string>
<string name="home_fingerprint">Huella del dispositivo</string>
<string name="home_selinux_status">Estado de SELinux</string>
<string name="selinux_status_disabled">Desactivado</string>
<string name="selinux_status_enforcing">Estricto</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Ordenar (Acción primero)</string>
<string name="module_sort_enabled_first">Ordenar (Activado primero)</string>
<string name="uninstall">Desinstalar</string>
<string name="restore">Restaurar</string>
<string name="module_install">Instalar</string>
<string name="install">Instalar</string>
<string name="reboot">Reiniciar</string>
@@ -61,10 +55,6 @@
<string name="profile_template">Plantilla</string>
<string name="profile_custom">Personalizado</string>
<string name="profile_name">Nombre de perfil</string>
<string name="profile_namespace">Montaje del espacio de nombres</string>
<string name="profile_namespace_inherited">Heredado</string>
<string name="profile_namespace_global">Global</string>
<string name="profile_namespace_individual">Individual</string>
<string name="profile_groups">Grupos</string>
<string name="profile_capabilities">Capacidades</string>
<string name="profile_selinux_context">Contexto SELinux</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Comprobación automática de actualizaciones al abrir la aplicación</string>
<string name="grant_root_failed">¡No se ha podido conceder el acceso root!</string>
<string name="action">Aktion</string>
<string name="open">Abrir</string>
<string name="close">Cancelar</string>
<string name="enable_web_debugging">Activar la depuración de WebView</string>
<string name="enable_web_debugging_summary">Puede ser usado para depurar WebUI, por favor habilítalo sólo cuando sea necesario.</string>
@@ -136,9 +125,6 @@
<string name="selected_lkm">LKM seleccionado: %s</string>
<string name="save_log">Guardar registros</string>
<string name="log_saved">Registro guardado</string>
<string name="status_supported">Apóyanos</string>
<string name="status_not_supported">No soportado</string>
<string name="status_unknown">Desconocido</string>
<string name="sus_su_mode">Modo SuS SU:</string>
<!-- Module related -->
<string name="module_install_confirm">¿confirmar la instalación del módulo %1$s?</string>
@@ -172,14 +158,11 @@
<string name="settings_custom_background">Fondo de aplicación personalizado</string>
<string name="settings_custom_background_summary">Seleccionar una imagen como fondo</string>
<string name="settings_card_alpha">Transparencia de la barra de navegación</string>
<string name="settings_restore_default">Restaurar</string>
<string name="home_android_version">Versión de Android</string>
<string name="home_device_model">Modelo del dispositivo</string>
<string name="su_not_allowed">No se permite conceder superusuario a %s</string>
<string name="settings_disable_su">Desactivar compatibilidad su</string>
<string name="settings_disable_su_summary">Deshabilita temporalmente cualquier aplicación para obtener privilegios de root a través del comando de \"it\" (los procesos de root existentes no se verán afectados).</string>
<string name="using_mksu_manager">Estás usando el administrador de la Beta de SukiSU</string>
<string name="module_install_multiple_confirm">¿Está seguro que desea instalar los módulos %d seleccionados?</string>
<string name="module_install_multiple_confirm_with_names">¿Seguro que quieres instalar los siguientes módulos %1$d ? \n\n%2$s</string>
<string name="more_settings">Opciones avanzadas</string>
<string name="selinux">SELinux</string>
@@ -210,20 +193,14 @@
<string name="color_pink">Rosa</string>
<string name="color_gray">Gris</string>
<string name="color_yellow">Amarillo</string>
<string name="flash_option">Opciones de flash</string>
<string name="flash_option_tip">Seleccione el archivo a flashear</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash archivo del kernel AnyKernel3</string>
<string name="root_required">Requiere privilegios de root</string>
<string name="copy_failed">Fallo al copiar archivo</string>
<string name="reboot_complete_title">Desguace completo</string>
<string name="reboot_complete_msg">¿Reiniciar inmediatamente?</string>
<string name="yes">Si</string>
<string name="no">No</string>
<string name="failed_reboot">Reinicio fallido</string>
<string name="batch_authorization">empoderar</string>
<string name="batch_cancel_authorization">gasto</string>
<string name="backup">Copia de seguridad</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No hay módulos del núcleo instalados en este momento</string>
<string name="kpm_version">Versión</string>
@@ -231,7 +208,6 @@
<string name="kpm_uninstall">Desinstalar</string>
<string name="kpm_uninstall_success">Desinstalado con éxito</string>
<string name="kpm_uninstall_failed">Error al desinstalar</string>
<string name="kpm_install">Instalar</string>
<string name="kpm_install_success">Carga exitosa del módulo kpm</string>
<string name="kpm_install_failed">Error al cargar el módulo kpm</string>
<string name="kpm_args">Parámetros</string>
@@ -245,8 +221,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra será una rama relativamente independiente de KSU en el futuro, pero todavía apreciamos el KernelSU oficial y MKSU etc. ¡por sus contribuciones!</string>
<string name="not_supported">Sin soporte</string>
<string name="supported">Apoyado</string>
<string name="home_kpm_module">"Número de módulos KPM: %d "</string>
<string name="kpm_invalid_file">Archivo KPM inválido</string>
<string name="kernel_patched">Kernel no parcheado</string>
<string name="kernel_not_enabled">Kernel no configurado</string>
<string name="custom_settings">Ajustes personalizados</string>
@@ -254,19 +228,13 @@
<string name="kpm_install_mode_load">Cargar</string>
<string name="kpm_install_mode_embed">Insertar</string>
<string name="kpm_install_mode_description">Por favor seleccione: %1\$s Modo de instalación del Módulo \n\nCarga: Cargar temporalmente el módulo \nInsertar: Instalar permanentemente en el sistema</string>
<string name="log_failed_to_check_module_file">Error al comprobar la existencia del archivo de módulo</string>
<string name="snackbar_failed_to_check_module_file">No se puede comprobar si el archivo de módulo existe</string>
<string name="confirm_uninstall_title">Confirme las desinstalaciones</string>
<string name="confirm_uninstall_confirm">Desinstalar</string>
<string name="confirm_uninstall_dismiss">Cancelar</string>
<string name="theme_color">Color del tema</string>
<string name="invalid_file_type">¡Tipo de archivo incorrecto! Por favor seleccione el archivo .kpm.</string>
<string name="confirm_uninstall_title_with_filename">Desinstalar</string>
<string name="confirm_uninstall_content">El siguiente KPM será desinstalado: %s</string>
<string name="settings_susfs_toggle_summary">Deshabilita los ganchos kprobe creados por KernelSU, usando ganchos en línea en su lugar, que es similar al método de enganche del núcleo no GKI.</string>
<string name="image_editor_title">Ajustar imagen de fondo</string>
<string name="image_editor_hint">Usa dos dedos para acercar la imagen, y un dedo para arrastrarla para ajustar la posición</string>
<string name="background_image_error">Imposible cargar imagen</string>
<string name="reprovision">Reaprovisionamiento</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Parpadeo Kernel</string>
@@ -289,25 +257,20 @@
<string name="horizon_getting_original_slot">Obteniendo la ranura original</string>
<string name="horizon_setting_target_slot">Establecer la ranura especificada</string>
<string name="horizon_restoring_original_slot">Restaurar Ranura Predeterminada</string>
<string name="current_slot">Ranura actual%1$s </string>
<string name="current_slot">Ranura predeterminada del sistema actual%1$s </string>
<!-- Error Messages -->
<string name="horizon_copy_failed">Hubo un fallo al copiar</string>
<string name="horizon_unknown_error">Error desconocido</string>
<string name="flash_failed_message">Flash falló</string>
<!-- lkm/gki install -->
<string name="Lkm_install_methods">Reparación/instalación de LKM</string>
<string name="GKI_install_methods">Flashing AnyKernel3</string>
<string name="GKI_install_methods">Flashear kernel</string>
<string name="kernel_version_log">Versión del kernel</string>
<string name="tool_version_log">Usando la herramienta de parches%1$s</string>
<string name="configuration">Configurar</string>
<string name="app_settings">Configuración de la Aplicación</string>
<string name="tools">Herramientas</string>
<string name="currently_selected">Actualmente</string>
<!-- String resources used in SuperUser -->
<string name="clear">Eliminaciones</string>
<string name="apps_with_root">Aplicaciones con privilegios de root</string>
<string name="apps_with_custom_profile">Aplicaciones con configuraciones personalizadas</string>
<string name="other_apps">Aplicaciones con valores por defecto sin cambios</string>
<string name="no_apps_found">No se ha encontrado la solicitud</string>
<string name="selinux_enabled_toast">SELinux habilitado</string>
<string name="selinux_disabled_toast">SELinux desactivado</string>
@@ -315,25 +278,24 @@
<string name="advanced_settings">Configuraciones avanzadas</string>
<string name="appearance_settings">Personalizar la barra de herramientas.</string>
<string name="back">Retorno</string>
<string name="expand">Estar en pleno swing</string>
<string name="collapse">poner</string>
<string name="susfs_enabled">SuSFS activado</string>
<string name="susfs_disabled">SuSFS desactivado</string>
<string name="background_set_success">Fondo establecido correctamente</string>
<string name="background_removed">Eliminar fondo personalizado</string>
<string name="root_require_for_install">Requiere privilegios de root</string>
<string name="icon_switch_title">Icono alternativo</string>
<string name="icon_switch_summary">Cambiar el icono del lanzador al icono de KernelSU.</string>
<string name="icon_switched">Icono cambiado</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Mostrar función KPM</string>
<string name="show_kpm_info_summary">Mostrar información y función KPM en la barra de inicio e inferior (Necesita reabrir la aplicación)</string>
<string name="show_kpm_info_summary">Oculta la información y función del KPM en la barra de inicio e inferior</string>
<!-- Webui X settings -->
<string name="use_webuix">Select the WebUI engine to use</string>
<string name="engine_auto_select">Automatic Selection</string>
<string name="engine_force_webuix">Force the use of WebUI X</string>
<string name="engine_force_ksu">Mandatory use of KSU WebUI</string>
<string name="use_webuix">Seleccione el motor WebUI a usar</string>
<string name="engine_auto_select">Selección automática</string>
<string name="engine_force_webuix">Forzar el uso de WebUI X</string>
<string name="engine_force_ksu">Uso obligatorio de KSU WebUI</string>
<string name="use_webuix_eruda">Inyectar Eruda en WebUI X</string>
<string name="use_webuix_eruda_summary">Inyecta una consola de depuración en WebUI X para facilitar la depuración. Requiere que la depuración web esté encendida.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">Configuración DPI</string>
<string name="app_dpi_title">DPI aplicado</string>
<string name="app_dpi_summary">Ajustar la densidad de pantalla para la aplicación actual</string>
<string name="dpi_size_small">Pequeño </string>
@@ -351,21 +313,58 @@
<string name="language_follow_system">Seguir sistema</string>
<string name="language_changed">Idioma cambiado, reiniciando para aplicar cambios</string>
<string name="settings_card_dim">Ajuste de oscuridad de tarjeta</string>
<!-- Super User Related -->
<string name="scroll_to_top">Arriba</string>
<string name="scroll_to_bottom">Abajo</string>
<string name="scroll_to_top_description">Ir arriba</string>
<string name="scroll_to_bottom_description">Desplazar hacia abajo</string>
<string name="authorized">autorizado</string>
<string name="unauthorized">Sin Autorización</string>
<string name="selected">Seleccionados</string>
<string name="select">opción</string>
<string name="profile_umount_modules_disable">Desactivar módulo personalizado de desinstalación</string>
<!-- Flash related -->
<string name="error_code">código de error</string>
<string name="check_log">Por favor, compruebe el registro</string>
<string name="installing_module">Módulo instalado %1$d/%2$d</string>
<string name="module_failed_count">%d falló al instalar un nuevo módulo</string>
<string name="module_download_error">La descarga del modelo falló</string>
<string name="kernel_flashing">Kernel Flashing</string>
<string name="kernel_flashing">Parpadeo Kernel</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Arriba</string>
<string name="scroll_to_bottom">Abajo</string>
<string name="selected">Seleccionados</string>
<string name="select">opción</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">Klõpsa paigaldamiseks</string>
<string name="home_working">Töötamine</string>
<string name="home_working_version">Versioon: %d</string>
<string name="home_superuser_count">Superkasutajaid: %d</string>
<string name="home_module_count">Mooduleid: %d</string>
<string name="home_unsupported">Mittetoetatud</string>
<string name="home_unsupported_reason">KernelSU toetab hetkel vaid GSI tuumasid</string>
<string name="home_kernel">Tuum</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS Version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">Manageri versioon</string>
<string name="home_fingerprint">Sõrmejälg</string>
<string name="home_selinux_status">SELinuxi olek</string>
<string name="selinux_status_disabled">Keelatud</string>
<string name="selinux_status_enforcing">Jõustav</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="uninstall">Eemalda</string>
<string name="restore">Restore</string>
<string name="module_install">Paigalda</string>
<string name="install">Paigalda</string>
<string name="reboot">Taaskäivita</string>
@@ -61,10 +55,6 @@
<string name="profile_template">Mall</string>
<string name="profile_custom">Kohandatud</string>
<string name="profile_name">Profiili nimi</string>
<string name="profile_namespace">Haagi nimeruum</string>
<string name="profile_namespace_inherited">Päritud</string>
<string name="profile_namespace_global">Globaalne</string>
<string name="profile_namespace_individual">Individuaalne</string>
<string name="profile_groups">Grupid</string>
<string name="profile_capabilities">Võimekused</string>
<string name="profile_selinux_context">SELinux kontekst</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Rakenduse avamisel kontrolli automaatselt uuendusi</string>
<string name="grant_root_failed">Juurkasutaja andmine ebaõnnestus!</string>
<string name="action">Action</string>
<string name="open">Ava</string>
<string name="close">Close</string>
<string name="enable_web_debugging">Luba WebView silumine</string>
<string name="enable_web_debugging_summary">Saab kasutada WebUI silumiseks, palun luba ainult vajadusel.</string>
@@ -136,9 +125,6 @@
<string name="selected_lkm">Valitud LKM: %s</string>
<string name="save_log">Salvesta Logid</string>
<string name="log_saved">Logs saved</string>
<string name="status_supported">Supported</string>
<string name="status_not_supported">Not Supported</string>
<string name="status_unknown">Unknown</string>
<string name="sus_su_mode">SuS SU mode:</string>
<!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string>
@@ -172,14 +158,11 @@
<string name="settings_custom_background">Custom App Background</string>
<string name="settings_custom_background_summary">Select an image as background</string>
<string name="settings_card_alpha">Navigation bar transparency</string>
<string name="settings_restore_default">Restore default</string>
<string name="home_android_version">Android version</string>
<string name="home_device_model">Device model</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string>
<string name="using_mksu_manager">You are using the SukiSU Beta manager</string>
<string name="module_install_multiple_confirm">Are you sure you want to install the selected %d modules?</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -210,20 +193,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Gray</string>
<string name="color_yellow">Yellow</string>
<string name="flash_option">Brush Options</string>
<string name="flash_option_tip">Select the file to be flashed</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string>
<string name="root_required">Requires root privileges</string>
<string name="copy_failed">File Copy Failure</string>
<string name="reboot_complete_title">Scrubbing complete</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="failed_reboot">Reboot Failed</string>
<string name="batch_authorization">empower</string>
<string name="batch_cancel_authorization">withdraw</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string>
<string name="kpm_version">Version</string>
@@ -231,7 +208,6 @@
<string name="kpm_uninstall">Uninstall</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string>
<string name="kpm_install">Install</string>
<string name="kpm_install_success">Load of kpm module successful</string>
<string name="kpm_install_failed">Load of kpm module failed</string>
<string name="kpm_args">Parameters</string>
@@ -245,8 +221,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string>
<string name="not_supported">Unsupported</string>
<string name="supported">Supported</string>
<string name="home_kpm_module">"Number of KPM modules: %d "</string>
<string name="kpm_invalid_file">Invalid KPM file</string>
<string name="kernel_patched">Kernel not patched</string>
<string name="kernel_not_enabled">Kernel not configured</string>
<string name="custom_settings">Custom settings</string>
@@ -254,19 +228,13 @@
<string name="kpm_install_mode_load">Load</string>
<string name="kpm_install_mode_embed">Embed</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string>
<string name="log_failed_to_check_module_file">Failed to check module file existence</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string>
<string name="confirm_uninstall_title">Confirm uninstallation</string>
<string name="confirm_uninstall_confirm">Uninstall</string>
<string name="confirm_uninstall_dismiss">Cancel</string>
<string name="theme_color">Theme Color</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string>
<string name="image_editor_title">Adjust background image</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string>
<string name="background_image_error">Could not load image</string>
<string name="reprovision">Reprovision</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -302,12 +270,7 @@
<string name="configuration">Configure</string>
<string name="app_settings">Application Settings</string>
<string name="tools">Tools</string>
<string name="currently_selected">Currently</string>
<!-- String resources used in SuperUser -->
<string name="clear">Removals</string>
<string name="apps_with_root">Applications with root privileges</string>
<string name="apps_with_custom_profile">Applications with customized configurations</string>
<string name="other_apps">Applications with unchanged defaults</string>
<string name="no_apps_found">Application not found</string>
<string name="selinux_enabled_toast">SELinux Enabled</string>
<string name="selinux_disabled_toast">SELinux Disabled</string>
@@ -315,13 +278,13 @@
<string name="advanced_settings">Advanced Settings</string>
<string name="appearance_settings">Customize the toolbar</string>
<string name="back">Comeback</string>
<string name="expand">Be in full swing</string>
<string name="collapse">put away</string>
<string name="susfs_enabled">SuSFS enabled</string>
<string name="susfs_disabled">SuSFS disabled</string>
<string name="background_set_success">Background set successfully</string>
<string name="background_removed">Removed custom backgrounds</string>
<string name="root_require_for_install">Requires root privileges</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string>
@@ -333,7 +296,6 @@
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI setting</string>
<string name="app_dpi_title">Applied DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
<string name="dpi_size_small">Small </string>
@@ -351,16 +313,6 @@
<string name="language_follow_system">Follow System</string>
<string name="language_changed">Language changed, restarting to apply changes</string>
<string name="settings_card_dim">Card Darkness Adjustment</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="scroll_to_top_description">Scroll to top</string>
<string name="scroll_to_bottom_description">Scroll to the bottom</string>
<string name="authorized">authorized</string>
<string name="unauthorized">unauthorized</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Disable custom uninstallation module</string>
<!-- Flash related -->
<string name="error_code">error code</string>
<string name="check_log">Please check the log</string>
@@ -368,4 +320,51 @@
<string name="module_failed_count">%d Failed to install a new module</string>
<string name="module_download_error">Module download failed</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">برای نصب ضربه بزنید</string>
<string name="home_working">به درستی کار می‌کند</string>
<string name="home_working_version">نسخه: %d</string>
<string name="home_superuser_count">برنامه های با دسترسی روت: %d</string>
<string name="home_module_count">ماژول‌ها: %d</string>
<string name="home_unsupported">پشتیبانی نشده</string>
<string name="home_unsupported_reason">کرنل اس یو فقط هسته های gki را پشتیبانی میکند</string>
<string name="home_kernel">هسته</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS Version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">نسخه برنامه</string>
<string name="home_fingerprint">اثرانگشت</string>
<string name="home_selinux_status">وضعیت SELinux</string>
<string name="selinux_status_disabled">غیرفعال</string>
<string name="selinux_status_enforcing">قانونمند</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="uninstall">لغو نصب</string>
<string name="restore">Restore</string>
<string name="module_install">نصب</string>
<string name="install">نصب</string>
<string name="reboot">راه اندازی دوباره</string>
@@ -61,10 +55,6 @@
<string name="profile_template">قالب</string>
<string name="profile_custom">شخصی سازی شده</string>
<string name="profile_name">اسم پروفایل</string>
<string name="profile_namespace">Mount namespace</string>
<string name="profile_namespace_inherited">اثر گرفته</string>
<string name="profile_namespace_global">گلوبال</string>
<string name="profile_namespace_individual">تکی</string>
<string name="profile_groups">Groups</string>
<string name="profile_capabilities">Capabilities</string>
<string name="profile_selinux_context">SELinux context</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Automatically check for updates when opening the app</string>
<string name="grant_root_failed">Failed to grant root!</string>
<string name="action">Action</string>
<string name="open">Open</string>
<string name="close">Close</string>
<string name="enable_web_debugging">Enable WebView debugging</string>
<string name="enable_web_debugging_summary">Can be used to debug WebUI. Please enable only when needed.</string>
@@ -136,9 +125,6 @@
<string name="selected_lkm">Selected LKM: %s</string>
<string name="save_log">ذخیره گزارش‌ها</string>
<string name="log_saved">Logs saved</string>
<string name="status_supported">Supported</string>
<string name="status_not_supported">Not Supported</string>
<string name="status_unknown">Unknown</string>
<string name="sus_su_mode">SuS SU mode:</string>
<!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string>
@@ -172,14 +158,11 @@
<string name="settings_custom_background">Custom App Background</string>
<string name="settings_custom_background_summary">Select an image as background</string>
<string name="settings_card_alpha">Navigation bar transparency</string>
<string name="settings_restore_default">Restore default</string>
<string name="home_android_version">Android version</string>
<string name="home_device_model">Device model</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string>
<string name="using_mksu_manager">You are using the SukiSU Beta manager</string>
<string name="module_install_multiple_confirm">Are you sure you want to install the selected %d modules?</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -210,20 +193,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Gray</string>
<string name="color_yellow">Yellow</string>
<string name="flash_option">Brush Options</string>
<string name="flash_option_tip">Select the file to be flashed</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string>
<string name="root_required">Requires root privileges</string>
<string name="copy_failed">File Copy Failure</string>
<string name="reboot_complete_title">Scrubbing complete</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="failed_reboot">Reboot Failed</string>
<string name="batch_authorization">empower</string>
<string name="batch_cancel_authorization">withdraw</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string>
<string name="kpm_version">Version</string>
@@ -231,7 +208,6 @@
<string name="kpm_uninstall">Uninstall</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string>
<string name="kpm_install">Install</string>
<string name="kpm_install_success">Load of kpm module successful</string>
<string name="kpm_install_failed">Load of kpm module failed</string>
<string name="kpm_args">Parameters</string>
@@ -245,8 +221,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string>
<string name="not_supported">Unsupported</string>
<string name="supported">Supported</string>
<string name="home_kpm_module">"Number of KPM modules: %d "</string>
<string name="kpm_invalid_file">Invalid KPM file</string>
<string name="kernel_patched">Kernel not patched</string>
<string name="kernel_not_enabled">Kernel not configured</string>
<string name="custom_settings">Custom settings</string>
@@ -254,19 +228,13 @@
<string name="kpm_install_mode_load">Load</string>
<string name="kpm_install_mode_embed">Embed</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string>
<string name="log_failed_to_check_module_file">Failed to check module file existence</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string>
<string name="confirm_uninstall_title">Confirm uninstallation</string>
<string name="confirm_uninstall_confirm">Uninstall</string>
<string name="confirm_uninstall_dismiss">Cancel</string>
<string name="theme_color">Theme Color</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string>
<string name="image_editor_title">Adjust background image</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string>
<string name="background_image_error">Could not load image</string>
<string name="reprovision">Reprovision</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -302,12 +270,7 @@
<string name="configuration">Configure</string>
<string name="app_settings">Application Settings</string>
<string name="tools">Tools</string>
<string name="currently_selected">Currently</string>
<!-- String resources used in SuperUser -->
<string name="clear">Removals</string>
<string name="apps_with_root">Applications with root privileges</string>
<string name="apps_with_custom_profile">Applications with customized configurations</string>
<string name="other_apps">Applications with unchanged defaults</string>
<string name="no_apps_found">Application not found</string>
<string name="selinux_enabled_toast">SELinux Enabled</string>
<string name="selinux_disabled_toast">SELinux Disabled</string>
@@ -315,13 +278,13 @@
<string name="advanced_settings">Advanced Settings</string>
<string name="appearance_settings">Customize the toolbar</string>
<string name="back">Comeback</string>
<string name="expand">Be in full swing</string>
<string name="collapse">put away</string>
<string name="susfs_enabled">SuSFS enabled</string>
<string name="susfs_disabled">SuSFS disabled</string>
<string name="background_set_success">Background set successfully</string>
<string name="background_removed">Removed custom backgrounds</string>
<string name="root_require_for_install">Requires root privileges</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string>
@@ -333,7 +296,6 @@
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI setting</string>
<string name="app_dpi_title">Applied DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
<string name="dpi_size_small">Small </string>
@@ -351,16 +313,6 @@
<string name="language_follow_system">Follow System</string>
<string name="language_changed">Language changed, restarting to apply changes</string>
<string name="settings_card_dim">Card Darkness Adjustment</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="scroll_to_top_description">Scroll to top</string>
<string name="scroll_to_bottom_description">Scroll to the bottom</string>
<string name="authorized">authorized</string>
<string name="unauthorized">unauthorized</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Disable custom uninstallation module</string>
<!-- Flash related -->
<string name="error_code">error code</string>
<string name="check_log">Please check the log</string>
@@ -368,4 +320,51 @@
<string name="module_failed_count">%d Failed to install a new module</string>
<string name="module_download_error">Module download failed</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">Pindutin para mag-install</string>
<string name="home_working">Gumagana</string>
<string name="home_working_version">Bersyon: %d</string>
<string name="home_superuser_count">Superusers: %d</string>
<string name="home_module_count">Mga Modyul: %d</string>
<string name="home_unsupported">Hindi Suportado</string>
<string name="home_unsupported_reason">Sinusuportahan lang ng KernelSU ang mga kernel ng GKI ngayon</string>
<string name="home_kernel">Kernel version</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS Version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">Bersyon ng Manager</string>
<string name="home_fingerprint">Fingerprint</string>
<string name="home_selinux_status">Katayuan ng SELinux</string>
<string name="selinux_status_disabled">Hindi pinagana</string>
<string name="selinux_status_enforcing">Enforcing</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="uninstall">I-uninstall</string>
<string name="restore">Restore</string>
<string name="module_install">I-install</string>
<string name="install">I-install</string>
<string name="reboot">I-reboot</string>
@@ -61,10 +55,6 @@
<string name="profile_template">Template</string>
<string name="profile_custom">Custom</string>
<string name="profile_name">Pangalan ng profile</string>
<string name="profile_namespace">I-mount ang namespace</string>
<string name="profile_namespace_inherited">Minana</string>
<string name="profile_namespace_global">Global</string>
<string name="profile_namespace_individual">Indibidwal</string>
<string name="profile_groups">Mga Grupo</string>
<string name="profile_capabilities">Mga Kakayanan</string>
<string name="profile_selinux_context">Konteksto ng SELinux</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Automatically check for updates when opening the app</string>
<string name="grant_root_failed">Failed to grant root!</string>
<string name="action">Action</string>
<string name="open">Open</string>
<string name="close">Close</string>
<string name="enable_web_debugging">Enable WebView debugging</string>
<string name="enable_web_debugging_summary">Can be used to debug WebUI. Please enable only when needed.</string>
@@ -136,9 +125,6 @@
<string name="selected_lkm">Selected LKM: %s</string>
<string name="save_log">I-save ang mga Log</string>
<string name="log_saved">Logs saved</string>
<string name="status_supported">Supported</string>
<string name="status_not_supported">Not Supported</string>
<string name="status_unknown">Unknown</string>
<string name="sus_su_mode">SuS SU mode:</string>
<!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string>
@@ -172,14 +158,11 @@
<string name="settings_custom_background">Custom App Background</string>
<string name="settings_custom_background_summary">Select an image as background</string>
<string name="settings_card_alpha">Navigation bar transparency</string>
<string name="settings_restore_default">Restore default</string>
<string name="home_android_version">Android version</string>
<string name="home_device_model">Device model</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string>
<string name="using_mksu_manager">You are using the SukiSU Beta manager</string>
<string name="module_install_multiple_confirm">Are you sure you want to install the selected %d modules?</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -210,20 +193,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Gray</string>
<string name="color_yellow">Yellow</string>
<string name="flash_option">Brush Options</string>
<string name="flash_option_tip">Select the file to be flashed</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string>
<string name="root_required">Requires root privileges</string>
<string name="copy_failed">File Copy Failure</string>
<string name="reboot_complete_title">Scrubbing complete</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="failed_reboot">Reboot Failed</string>
<string name="batch_authorization">empower</string>
<string name="batch_cancel_authorization">withdraw</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string>
<string name="kpm_version">Version</string>
@@ -231,7 +208,6 @@
<string name="kpm_uninstall">Uninstall</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string>
<string name="kpm_install">Install</string>
<string name="kpm_install_success">Load of kpm module successful</string>
<string name="kpm_install_failed">Load of kpm module failed</string>
<string name="kpm_args">Parameters</string>
@@ -245,8 +221,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string>
<string name="not_supported">Unsupported</string>
<string name="supported">Supported</string>
<string name="home_kpm_module">"Number of KPM modules: %d "</string>
<string name="kpm_invalid_file">Invalid KPM file</string>
<string name="kernel_patched">Kernel not patched</string>
<string name="kernel_not_enabled">Kernel not configured</string>
<string name="custom_settings">Custom settings</string>
@@ -254,19 +228,13 @@
<string name="kpm_install_mode_load">Load</string>
<string name="kpm_install_mode_embed">Embed</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string>
<string name="log_failed_to_check_module_file">Failed to check module file existence</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string>
<string name="confirm_uninstall_title">Confirm uninstallation</string>
<string name="confirm_uninstall_confirm">Uninstall</string>
<string name="confirm_uninstall_dismiss">Cancel</string>
<string name="theme_color">Theme Color</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string>
<string name="image_editor_title">Adjust background image</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string>
<string name="background_image_error">Could not load image</string>
<string name="reprovision">Reprovision</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -302,12 +270,7 @@
<string name="configuration">Configure</string>
<string name="app_settings">Application Settings</string>
<string name="tools">Tools</string>
<string name="currently_selected">Currently</string>
<!-- String resources used in SuperUser -->
<string name="clear">Removals</string>
<string name="apps_with_root">Applications with root privileges</string>
<string name="apps_with_custom_profile">Applications with customized configurations</string>
<string name="other_apps">Applications with unchanged defaults</string>
<string name="no_apps_found">Application not found</string>
<string name="selinux_enabled_toast">SELinux Enabled</string>
<string name="selinux_disabled_toast">SELinux Disabled</string>
@@ -315,13 +278,13 @@
<string name="advanced_settings">Advanced Settings</string>
<string name="appearance_settings">Customize the toolbar</string>
<string name="back">Comeback</string>
<string name="expand">Be in full swing</string>
<string name="collapse">put away</string>
<string name="susfs_enabled">SuSFS enabled</string>
<string name="susfs_disabled">SuSFS disabled</string>
<string name="background_set_success">Background set successfully</string>
<string name="background_removed">Removed custom backgrounds</string>
<string name="root_require_for_install">Requires root privileges</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string>
@@ -333,7 +296,6 @@
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI setting</string>
<string name="app_dpi_title">Applied DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
<string name="dpi_size_small">Small </string>
@@ -351,16 +313,6 @@
<string name="language_follow_system">Follow System</string>
<string name="language_changed">Language changed, restarting to apply changes</string>
<string name="settings_card_dim">Card Darkness Adjustment</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="scroll_to_top_description">Scroll to top</string>
<string name="scroll_to_bottom_description">Scroll to the bottom</string>
<string name="authorized">authorized</string>
<string name="unauthorized">unauthorized</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Disable custom uninstallation module</string>
<!-- Flash related -->
<string name="error_code">error code</string>
<string name="check_log">Please check the log</string>
@@ -368,4 +320,51 @@
<string name="module_failed_count">%d Failed to install a new module</string>
<string name="module_download_error">Module download failed</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">Appuyez ici pour installer</string>
<string name="home_working">Fonctionnel</string>
<string name="home_working_version">Version : %d</string>
<string name="home_superuser_count">Super-utilisateurs : %d</string>
<string name="home_module_count">Modules: %d</string>
<string name="home_unsupported">Non pris en charge</string>
<string name="home_unsupported_reason">KernelSU ne prend désormais en charge que les noyaux GKI</string>
<string name="home_kernel">Noyau</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">Version SuSFS</string>
<string name="home_susfs_sus_su">SuS Su</string>
<string name="home_manager_version">Version du gestionnaire</string>
<string name="home_fingerprint">Empreinte digitale</string>
<string name="home_selinux_status">Mode SELinux</string>
<string name="selinux_status_disabled">Désactivé</string>
<string name="selinux_status_enforcing">Enforcing</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Trier par action</string>
<string name="module_sort_enabled_first">Trier par activé</string>
<string name="uninstall">Désinstaller</string>
<string name="restore">Restaure</string>
<string name="module_install">Installer</string>
<string name="install">Installer</string>
<string name="reboot">Redémarrer</string>
@@ -61,10 +55,6 @@
<string name="profile_template">Modèle</string>
<string name="profile_custom">Personnalisé</string>
<string name="profile_name">Nom du profil</string>
<string name="profile_namespace">Espace de noms de montage</string>
<string name="profile_namespace_inherited">Hérité</string>
<string name="profile_namespace_global">Global</string>
<string name="profile_namespace_individual">Individuel</string>
<string name="profile_groups">Groupes</string>
<string name="profile_capabilities">Capacités</string>
<string name="profile_selinux_context">Contexte SELinux</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Vérifier automatiquement les mises à jour à l\'ouverture de l\'application</string>
<string name="grant_root_failed">Échec de l\'octroi des privilèges root!</string>
<string name="action">Action</string>
<string name="open">Ouvrir</string>
<string name="close">Fermer</string>
<string name="enable_web_debugging">Activer le débogage WebView</string>
<string name="enable_web_debugging_summary">Peut être utilisé pour déboguer WebUI. Activez uniquement cette option si nécessaire.</string>
@@ -138,9 +127,6 @@
<string name="selected_lkm">LKM sélectionné: %s</string>
<string name="save_log">Enregistrer les journaux</string>
<string name="log_saved">Journaux enregistrés</string>
<string name="status_supported">Supporté</string>
<string name="status_not_supported">Non supporté</string>
<string name="status_unknown">Inconnu</string>
<string name="sus_su_mode">Mode Sus</string>
<!-- Module related -->
<string name="module_install_confirm">confirmer l\'installation du module %1$s?</string>
@@ -174,14 +160,11 @@
<string name="settings_custom_background">Arrière-plan personnalisé de l\'application</string>
<string name="settings_custom_background_summary">Image as arrière-plan</string>
<string name="settings_card_alpha">Transparence de la barre de navigation</string>
<string name="settings_restore_default">Restaurer par défaut</string>
<string name="home_android_version">Version Android</string>
<string name="home_device_model">Modèle du téléphone</string>
<string name="su_not_allowed">Donner un super-utilisateur à %s n\'est pas autorisé</string>
<string name="settings_disable_su">Désactiver la compatibilité su</string>
<string name="settings_disable_su_summary">Désactiver temporairement l\'accès des applications aux privilèges root via la commande su (les processus root existants ne seront pas affectés).</string>
<string name="using_mksu_manager">Vous utilisez le gestionnaire SukiSU Beta</string>
<string name="module_install_multiple_confirm">Êtes-vous sûr de vouloir installer les modules %d sélectionnés ?</string>
<string name="module_install_multiple_confirm_with_names">Êtes-vous sûr de vouloir installer les modules %1$d suivants ? \n\n%2$s</string>
<string name="more_settings">Autres configurations</string>
<string name="selinux">SELinux</string>
@@ -212,20 +195,14 @@
<string name="color_pink">Rose</string>
<string name="color_gray">Gris</string>
<string name="color_yellow">Jaune</string>
<string name="flash_option">Options du flash</string>
<string name="flash_option_tip">Sélectionnez le fichier à installer</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Fichier noyau AnyKernel3</string>
<string name="root_required">Nécessite les privilèges root</string>
<string name="copy_failed">Échec de la copie du fichier</string>
<string name="reboot_complete_title">Traitement terminé</string>
<string name="reboot_complete_msg">Redémarrer immédiatement ?</string>
<string name="yes">Oui</string>
<string name="no">Non</string>
<string name="failed_reboot">Échec du redémarrage</string>
<string name="batch_authorization">ePouvoir</string>
<string name="batch_cancel_authorization">retirer</string>
<string name="backup">Sauvegarder</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">Aucun module de noyau installé pour le moment</string>
<string name="kpm_version">Version</string>
@@ -233,7 +210,6 @@
<string name="kpm_uninstall">Désinstaller</string>
<string name="kpm_uninstall_success">Désinstallé avec succès</string>
<string name="kpm_uninstall_failed">Échec de la désinstallation : </string>
<string name="kpm_install">Installer</string>
<string name="kpm_install_success">Chargement du module kpm réussi</string>
<string name="kpm_install_failed">Le chargement du module kpm a échoué</string>
<string name="kpm_args">Paramètres</string>
@@ -247,8 +223,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra sera une branche relativement indépendante de KSU dans le futur, mais nous apprécions toujours le KernelSU officiel, MKSU etc. pour leurs contributions!</string>
<string name="not_supported">Non pris en charge</string>
<string name="supported">Pris en charge</string>
<string name="home_kpm_module">"Nombre de modules KPM : %d "</string>
<string name="kpm_invalid_file">Fichier KPM invalide</string>
<string name="kernel_patched">Noyau non corrigé</string>
<string name="kernel_not_enabled">Noyau non configuré</string>
<string name="custom_settings">Paramètres personnalisés</string>
@@ -256,19 +230,13 @@
<string name="kpm_install_mode_load">Charger</string>
<string name="kpm_install_mode_embed">Intégrer</string>
<string name="kpm_install_mode_description">Veuillez sélectionner : %1\$s Mode d\'installation du module \n\nCharge : Chargez temporairement le module \nIntégré: Installez définitivement dans le système</string>
<string name="log_failed_to_check_module_file">Impossible de vérifier l\'existence du fichier du module</string>
<string name="snackbar_failed_to_check_module_file">Impossible de vérifier si le fichier du module existe</string>
<string name="confirm_uninstall_title">Confirmer la désinstallation.</string>
<string name="confirm_uninstall_confirm">Désinstaller</string>
<string name="confirm_uninstall_dismiss">Annuler</string>
<string name="theme_color">Couleur du thème</string>
<string name="invalid_file_type">Type de fichier incorrect ! Veuillez sélectionner un fichier .kpm.</string>
<string name="confirm_uninstall_title_with_filename">Désinstaller</string>
<string name="confirm_uninstall_content">Le KPM suivant sera désinstallé : %s</string>
<string name="settings_susfs_toggle_summary">Désactivez les crochets kprobe créés par KernelSU, en utilisant des crochets en ligne à la place, ce qui est similaire à la méthode de crochet du noyau non-GKI.</string>
<string name="image_editor_title">Ajuster l\'image de fond</string>
<string name="image_editor_hint">Utilisez deux doigts pour zoomer l\'image, et un doigt pour le faire glisser pour ajuster la position</string>
<string name="background_image_error">Impossible de charger l\'image</string>
<string name="reprovision">Remise à disposition</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Clignotement du noyau</string>
@@ -298,18 +266,13 @@
<string name="flash_failed_message">Échec du flash</string>
<!-- lkm/gki install -->
<string name="Lkm_install_methods">Réparation/installation LKM</string>
<string name="GKI_install_methods">Flashing AnyKernel3</string>
<string name="GKI_install_methods">Flash du noyau…</string>
<string name="kernel_version_log">Version du noyau%1$s</string>
<string name="tool_version_log">Utilisation de l\'outil de correctifs%1$s</string>
<string name="configuration">Configurer</string>
<string name="app_settings">Paramètres de l\'application</string>
<string name="tools">Outils</string>
<string name="currently_selected">Actuellement</string>
<!-- String resources used in SuperUser -->
<string name="clear">Suppressions</string>
<string name="apps_with_root">Applications avec droits root</string>
<string name="apps_with_custom_profile">Applications avec configurations personnalisées</string>
<string name="other_apps">Applications avec valeurs par défaut non modifiées</string>
<string name="no_apps_found">Application introuvable</string>
<string name="selinux_enabled_toast">SELinux activé</string>
<string name="selinux_disabled_toast">SELinux désactivé</string>
@@ -317,25 +280,24 @@
<string name="advanced_settings">Paramètres avancés</string>
<string name="appearance_settings">Choisir les boutons à afficher</string>
<string name="back">Reviens</string>
<string name="expand">Etre en plein swing</string>
<string name="collapse">rangé</string>
<string name="susfs_enabled">SuSFS activé</string>
<string name="susfs_disabled">SuSFS désactivé</string>
<string name="background_set_success">Fond d\'écran défini avec succès</string>
<string name="background_removed">Fond d\'écran personnalisé supprimé</string>
<string name="root_require_for_install">Nécessite les privilèges root</string>
<string name="icon_switch_title">Icône alternative</string>
<string name="icon_switch_summary">Changer l\'icône du lanceur en icône de KernelSU.</string>
<string name="icon_switched">Icône changée</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Afficher la fonction KPM</string>
<string name="show_kpm_info_summary">Afficher les informations et fonctions KPM dans la barre d\'accueil et du bas (nécessite de rouvrir l\'application)</string>
<string name="show_kpm_info_summary">Masque les informations et fonctions KPM dans la barre d\'accueil et en bas</string>
<!-- Webui X settings -->
<string name="use_webuix">Select the WebUI engine to use</string>
<string name="engine_auto_select">Automatic Selection</string>
<string name="engine_force_webuix">Force the use of WebUI X</string>
<string name="engine_force_ksu">Mandatory use of KSU WebUI</string>
<string name="use_webuix">Sélectionnez le moteur WebUI à utiliser</string>
<string name="engine_auto_select">Sélectionner automatiquement</string>
<string name="engine_force_webuix">Forcer l\'utilisation de WebUI X</string>
<string name="engine_force_ksu">Utilisation obligatoire de KSU WebUI</string>
<string name="use_webuix_eruda">Injecter Eruda dans WebUI X</string>
<string name="use_webuix_eruda_summary">Injectez une console de débogage dans WebUI X pour faciliter le débogage. Nécessite que le débogage soit activé.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">Réglage du DPI</string>
<string name="app_dpi_title">DPI appliqué</string>
<string name="app_dpi_summary">Ajuster la densité d\'affichage de l\'écran pour l\'application actuelle uniquement</string>
<string name="dpi_size_small">Petit </string>
@@ -353,21 +315,58 @@
<string name="language_follow_system">Suivre le paramètre système</string>
<string name="language_changed">Langue modifiée, redémarrage pour appliquer les modifications</string>
<string name="settings_card_dim">Ajustement de l\'obscurité de la carte</string>
<!-- Super User Related -->
<string name="scroll_to_top">En haut</string>
<string name="scroll_to_bottom">En Bas</string>
<string name="scroll_to_top_description">Aller en haut</string>
<string name="scroll_to_bottom_description">Faire défiler vers le bas</string>
<string name="authorized">Autorisé</string>
<string name="unauthorized">non autorisé</string>
<string name="selected">Sélectionné</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Désactiver le module de désinstallation personnalisé</string>
<!-- Flash related -->
<string name="error_code">code d\'erreur</string>
<string name="check_log">Veuillez vérifier le journal</string>
<string name="installing_module">Module en cours d\'installation %1$d/%2$d</string>
<string name="module_failed_count">%d a échoué à installer un nouveau module</string>
<string name="module_download_error">Le téléchargement du modèle a échoué</string>
<string name="kernel_flashing">Kernel Flashing</string>
<string name="kernel_flashing">Clignotement du noyau</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">En haut</string>
<string name="scroll_to_bottom">En Bas</string>
<string name="selected">Sélectionné</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">इंस्टाल करने के लिए क्लिक करें</string>
<string name="home_working">काम कर रहा है</string>
<string name="home_working_version">वर्जन: %d</string>
<string name="home_superuser_count">सुपरयूजर : %d</string>
<string name="home_module_count">मॉड्यूल्स : %d</string>
<string name="home_unsupported">सपोर्ट नहीं करता है</string>
<string name="home_unsupported_reason">KernelSU अभी केवल GKI कर्नल्स को सपोर्ट करता है</string>
<string name="home_kernel">कर्नल</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS Version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">मैनेजर वर्जन</string>
<string name="home_fingerprint">फिंगरप्रिंट</string>
<string name="home_selinux_status">SELinux स्थिति</string>
<string name="selinux_status_disabled">डिसेबल्ड (बंद)</string>
<string name="selinux_status_enforcing">एनफोर्सिंग</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="uninstall">अनइंस्टॉल करें</string>
<string name="restore">Restore</string>
<string name="module_install">इंस्टाल करें</string>
<string name="install">इंस्टाल करें</string>
<string name="reboot">रीबूट करें</string>
@@ -61,10 +55,6 @@
<string name="profile_template">टेम्पलेट</string>
<string name="profile_custom">कस्टम</string>
<string name="profile_name">प्रोफाइल का नाम</string>
<string name="profile_namespace">Namspace माउंट करें</string>
<string name="profile_namespace_inherited">Inherited</string>
<string name="profile_namespace_global">Global</string>
<string name="profile_namespace_individual">Individual</string>
<string name="profile_groups">समूह</string>
<string name="profile_capabilities">क्षमताएं</string>
<string name="profile_selinux_context">SELinux context</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Automatically check for updates when opening the app</string>
<string name="grant_root_failed">Failed to grant root!</string>
<string name="action">Action</string>
<string name="open">Open</string>
<string name="close">Close</string>
<string name="enable_web_debugging">Enable WebView debugging</string>
<string name="enable_web_debugging_summary">Can be used to debug WebUI. Please enable only when needed.</string>
@@ -136,9 +125,6 @@
<string name="selected_lkm">Selected LKM: %s</string>
<string name="save_log">लॉग सहेजें</string>
<string name="log_saved">Logs saved</string>
<string name="status_supported">Supported</string>
<string name="status_not_supported">Not Supported</string>
<string name="status_unknown">Unknown</string>
<string name="sus_su_mode">SuS SU mode:</string>
<!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string>
@@ -172,14 +158,11 @@
<string name="settings_custom_background">Custom App Background</string>
<string name="settings_custom_background_summary">Select an image as background</string>
<string name="settings_card_alpha">Navigation bar transparency</string>
<string name="settings_restore_default">Restore default</string>
<string name="home_android_version">Android version</string>
<string name="home_device_model">Device model</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string>
<string name="using_mksu_manager">You are using the SukiSU Beta manager</string>
<string name="module_install_multiple_confirm">Are you sure you want to install the selected %d modules?</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -210,20 +193,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Gray</string>
<string name="color_yellow">Yellow</string>
<string name="flash_option">Brush Options</string>
<string name="flash_option_tip">Select the file to be flashed</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string>
<string name="root_required">Requires root privileges</string>
<string name="copy_failed">File Copy Failure</string>
<string name="reboot_complete_title">Scrubbing complete</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="failed_reboot">Reboot Failed</string>
<string name="batch_authorization">empower</string>
<string name="batch_cancel_authorization">withdraw</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string>
<string name="kpm_version">Version</string>
@@ -231,7 +208,6 @@
<string name="kpm_uninstall">Uninstall</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string>
<string name="kpm_install">Install</string>
<string name="kpm_install_success">Load of kpm module successful</string>
<string name="kpm_install_failed">Load of kpm module failed</string>
<string name="kpm_args">Parameters</string>
@@ -245,8 +221,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string>
<string name="not_supported">Unsupported</string>
<string name="supported">Supported</string>
<string name="home_kpm_module">"Number of KPM modules: %d "</string>
<string name="kpm_invalid_file">Invalid KPM file</string>
<string name="kernel_patched">Kernel not patched</string>
<string name="kernel_not_enabled">Kernel not configured</string>
<string name="custom_settings">Custom settings</string>
@@ -254,19 +228,13 @@
<string name="kpm_install_mode_load">Load</string>
<string name="kpm_install_mode_embed">Embed</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string>
<string name="log_failed_to_check_module_file">Failed to check module file existence</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string>
<string name="confirm_uninstall_title">Confirm uninstallation</string>
<string name="confirm_uninstall_confirm">Uninstall</string>
<string name="confirm_uninstall_dismiss">Cancel</string>
<string name="theme_color">Theme Color</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string>
<string name="image_editor_title">Adjust background image</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string>
<string name="background_image_error">Could not load image</string>
<string name="reprovision">Reprovision</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -302,12 +270,7 @@
<string name="configuration">Configure</string>
<string name="app_settings">Application Settings</string>
<string name="tools">Tools</string>
<string name="currently_selected">Currently</string>
<!-- String resources used in SuperUser -->
<string name="clear">Removals</string>
<string name="apps_with_root">Applications with root privileges</string>
<string name="apps_with_custom_profile">Applications with customized configurations</string>
<string name="other_apps">Applications with unchanged defaults</string>
<string name="no_apps_found">Application not found</string>
<string name="selinux_enabled_toast">SELinux Enabled</string>
<string name="selinux_disabled_toast">SELinux Disabled</string>
@@ -315,13 +278,13 @@
<string name="advanced_settings">Advanced Settings</string>
<string name="appearance_settings">Customize the toolbar</string>
<string name="back">Comeback</string>
<string name="expand">Be in full swing</string>
<string name="collapse">put away</string>
<string name="susfs_enabled">SuSFS enabled</string>
<string name="susfs_disabled">SuSFS disabled</string>
<string name="background_set_success">Background set successfully</string>
<string name="background_removed">Removed custom backgrounds</string>
<string name="root_require_for_install">Requires root privileges</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string>
@@ -333,7 +296,6 @@
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI setting</string>
<string name="app_dpi_title">Applied DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
<string name="dpi_size_small">Small </string>
@@ -351,16 +313,6 @@
<string name="language_follow_system">Follow System</string>
<string name="language_changed">Language changed, restarting to apply changes</string>
<string name="settings_card_dim">Card Darkness Adjustment</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="scroll_to_top_description">Scroll to top</string>
<string name="scroll_to_bottom_description">Scroll to the bottom</string>
<string name="authorized">authorized</string>
<string name="unauthorized">unauthorized</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Disable custom uninstallation module</string>
<!-- Flash related -->
<string name="error_code">error code</string>
<string name="check_log">Please check the log</string>
@@ -368,4 +320,51 @@
<string name="module_failed_count">%d Failed to install a new module</string>
<string name="module_download_error">Module download failed</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">Kliknite da instalirate</string>
<string name="home_working">Radi</string>
<string name="home_working_version">Verzija: %d</string>
<string name="home_superuser_count">Superkorisnici: %d</string>
<string name="home_module_count">Module: %d</string>
<string name="home_unsupported">Nepodržano</string>
<string name="home_unsupported_reason">KernelSU samo podržava GKI kernele sad</string>
<string name="home_kernel">Kernel</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS Version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">Verzija Voditelja</string>
<string name="home_fingerprint">Otisak prsta</string>
<string name="home_selinux_status">SELinux stanje</string>
<string name="selinux_status_disabled">Isključeno</string>
<string name="selinux_status_enforcing">U Provođenju</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="uninstall">Deinstalirajte</string>
<string name="restore">Restore</string>
<string name="module_install">Instalirajte</string>
<string name="install">Instalirajte</string>
<string name="reboot">Ponovno pokrenite</string>
@@ -61,10 +55,6 @@
<string name="profile_template">Šablon</string>
<string name="profile_custom">Prilagođeno</string>
<string name="profile_name">Naziv profila</string>
<string name="profile_namespace">Imenski prostor nosača</string>
<string name="profile_namespace_inherited">Naslijeđen</string>
<string name="profile_namespace_global">Globalan</string>
<string name="profile_namespace_individual">Pojedinačan</string>
<string name="profile_groups">Grupe</string>
<string name="profile_capabilities">Sposobnosti</string>
<string name="profile_selinux_context">SELinux kontekst</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Automatically check for updates when opening the app</string>
<string name="grant_root_failed">Failed to grant root!</string>
<string name="action">Action</string>
<string name="open">Open</string>
<string name="close">Close</string>
<string name="enable_web_debugging">Enable WebView debugging</string>
<string name="enable_web_debugging_summary">Can be used to debug WebUI. Please enable only when needed.</string>
@@ -136,9 +125,6 @@
<string name="selected_lkm">Selected LKM: %s</string>
<string name="save_log">Spremi Zapise</string>
<string name="log_saved">Logs saved</string>
<string name="status_supported">Supported</string>
<string name="status_not_supported">Not Supported</string>
<string name="status_unknown">Unknown</string>
<string name="sus_su_mode">SuS SU mode:</string>
<!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string>
@@ -172,14 +158,11 @@
<string name="settings_custom_background">Custom App Background</string>
<string name="settings_custom_background_summary">Select an image as background</string>
<string name="settings_card_alpha">Navigation bar transparency</string>
<string name="settings_restore_default">Restore default</string>
<string name="home_android_version">Android version</string>
<string name="home_device_model">Device model</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string>
<string name="using_mksu_manager">You are using the SukiSU Beta manager</string>
<string name="module_install_multiple_confirm">Are you sure you want to install the selected %d modules?</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -210,20 +193,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Gray</string>
<string name="color_yellow">Yellow</string>
<string name="flash_option">Brush Options</string>
<string name="flash_option_tip">Select the file to be flashed</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string>
<string name="root_required">Requires root privileges</string>
<string name="copy_failed">File Copy Failure</string>
<string name="reboot_complete_title">Scrubbing complete</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="failed_reboot">Reboot Failed</string>
<string name="batch_authorization">empower</string>
<string name="batch_cancel_authorization">withdraw</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string>
<string name="kpm_version">Version</string>
@@ -231,7 +208,6 @@
<string name="kpm_uninstall">Uninstall</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string>
<string name="kpm_install">Install</string>
<string name="kpm_install_success">Load of kpm module successful</string>
<string name="kpm_install_failed">Load of kpm module failed</string>
<string name="kpm_args">Parameters</string>
@@ -245,8 +221,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string>
<string name="not_supported">Unsupported</string>
<string name="supported">Supported</string>
<string name="home_kpm_module">"Number of KPM modules: %d "</string>
<string name="kpm_invalid_file">Invalid KPM file</string>
<string name="kernel_patched">Kernel not patched</string>
<string name="kernel_not_enabled">Kernel not configured</string>
<string name="custom_settings">Custom settings</string>
@@ -254,19 +228,13 @@
<string name="kpm_install_mode_load">Load</string>
<string name="kpm_install_mode_embed">Embed</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string>
<string name="log_failed_to_check_module_file">Failed to check module file existence</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string>
<string name="confirm_uninstall_title">Confirm uninstallation</string>
<string name="confirm_uninstall_confirm">Uninstall</string>
<string name="confirm_uninstall_dismiss">Cancel</string>
<string name="theme_color">Theme Color</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string>
<string name="image_editor_title">Adjust background image</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string>
<string name="background_image_error">Could not load image</string>
<string name="reprovision">Reprovision</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -302,12 +270,7 @@
<string name="configuration">Configure</string>
<string name="app_settings">Application Settings</string>
<string name="tools">Tools</string>
<string name="currently_selected">Currently</string>
<!-- String resources used in SuperUser -->
<string name="clear">Removals</string>
<string name="apps_with_root">Applications with root privileges</string>
<string name="apps_with_custom_profile">Applications with customized configurations</string>
<string name="other_apps">Applications with unchanged defaults</string>
<string name="no_apps_found">Application not found</string>
<string name="selinux_enabled_toast">SELinux Enabled</string>
<string name="selinux_disabled_toast">SELinux Disabled</string>
@@ -315,13 +278,13 @@
<string name="advanced_settings">Advanced Settings</string>
<string name="appearance_settings">Customize the toolbar</string>
<string name="back">Comeback</string>
<string name="expand">Be in full swing</string>
<string name="collapse">put away</string>
<string name="susfs_enabled">SuSFS enabled</string>
<string name="susfs_disabled">SuSFS disabled</string>
<string name="background_set_success">Background set successfully</string>
<string name="background_removed">Removed custom backgrounds</string>
<string name="root_require_for_install">Requires root privileges</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string>
@@ -333,7 +296,6 @@
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI setting</string>
<string name="app_dpi_title">Applied DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
<string name="dpi_size_small">Small </string>
@@ -351,16 +313,6 @@
<string name="language_follow_system">Follow System</string>
<string name="language_changed">Language changed, restarting to apply changes</string>
<string name="settings_card_dim">Card Darkness Adjustment</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="scroll_to_top_description">Scroll to top</string>
<string name="scroll_to_bottom_description">Scroll to the bottom</string>
<string name="authorized">authorized</string>
<string name="unauthorized">unauthorized</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Disable custom uninstallation module</string>
<!-- Flash related -->
<string name="error_code">error code</string>
<string name="check_log">Please check the log</string>
@@ -368,4 +320,51 @@
<string name="module_failed_count">%d Failed to install a new module</string>
<string name="module_download_error">Module download failed</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">Kattintson a telepítéshez</string>
<string name="home_working">Működik</string>
<string name="home_working_version">Verzió: %d</string>
<string name="home_superuser_count">Engedélyezett alkalmazások: %d</string>
<string name="home_module_count">Modulok: %d</string>
<string name="home_unsupported">Nem támogatott</string>
<string name="home_unsupported_reason">A KernelSU jelenleg csak GKI kerneleket támogat</string>
<string name="home_kernel">Kernel</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS Version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">Alkalmazás verziója</string>
<string name="home_fingerprint">Ujjlenyomat</string>
<string name="home_selinux_status">SELinux állapot</string>
<string name="selinux_status_disabled">Letiltva</string>
<string name="selinux_status_enforcing">Kényszerített</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="uninstall">Eltávolítás</string>
<string name="restore">Restore</string>
<string name="module_install">Telepítés</string>
<string name="install">Telepítés</string>
<string name="reboot">Újraindítás</string>
@@ -61,10 +55,6 @@
<string name="profile_template">Sablon</string>
<string name="profile_custom">Egyedi</string>
<string name="profile_name">Profil neve</string>
<string name="profile_namespace">Névtér csatlakoztatása</string>
<string name="profile_namespace_inherited">Örökölt</string>
<string name="profile_namespace_global">Globális</string>
<string name="profile_namespace_individual">Különálló</string>
<string name="profile_groups">Csoportok</string>
<string name="profile_capabilities">Jogosultságok</string>
<string name="profile_selinux_context">SELinux kontextus</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Automatikusan keressen frissítéseket az alkalmazás megnyitásakor</string>
<string name="grant_root_failed">A root jog megadása sikertelen!</string>
<string name="action">Művelet</string>
<string name="open">Megnyitás</string>
<string name="close">Close</string>
<string name="enable_web_debugging">WebView hibakeresés engedélyezése</string>
<string name="enable_web_debugging_summary">A WebUI hibakeresésére használható, csak szükség esetén engedélyezze.</string>
@@ -136,9 +125,6 @@
<string name="selected_lkm">Kiválasztott LKM: %s</string>
<string name="save_log">Naplók mentése</string>
<string name="log_saved">Mentett naplók</string>
<string name="status_supported">Supported</string>
<string name="status_not_supported">Not Supported</string>
<string name="status_unknown">Unknown</string>
<string name="sus_su_mode">SuS SU mode:</string>
<!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string>
@@ -172,14 +158,11 @@
<string name="settings_custom_background">Custom App Background</string>
<string name="settings_custom_background_summary">Select an image as background</string>
<string name="settings_card_alpha">Navigation bar transparency</string>
<string name="settings_restore_default">Restore default</string>
<string name="home_android_version">Android version</string>
<string name="home_device_model">Device model</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string>
<string name="using_mksu_manager">You are using the SukiSU Beta manager</string>
<string name="module_install_multiple_confirm">Are you sure you want to install the selected %d modules?</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -210,20 +193,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Gray</string>
<string name="color_yellow">Yellow</string>
<string name="flash_option">Brush Options</string>
<string name="flash_option_tip">Select the file to be flashed</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string>
<string name="root_required">Requires root privileges</string>
<string name="copy_failed">File Copy Failure</string>
<string name="reboot_complete_title">Scrubbing complete</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="failed_reboot">Reboot Failed</string>
<string name="batch_authorization">empower</string>
<string name="batch_cancel_authorization">withdraw</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string>
<string name="kpm_version">Version</string>
@@ -231,7 +208,6 @@
<string name="kpm_uninstall">Uninstall</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string>
<string name="kpm_install">Install</string>
<string name="kpm_install_success">Load of kpm module successful</string>
<string name="kpm_install_failed">Load of kpm module failed</string>
<string name="kpm_args">Parameters</string>
@@ -245,8 +221,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string>
<string name="not_supported">Unsupported</string>
<string name="supported">Supported</string>
<string name="home_kpm_module">"Number of KPM modules: %d "</string>
<string name="kpm_invalid_file">Invalid KPM file</string>
<string name="kernel_patched">Kernel not patched</string>
<string name="kernel_not_enabled">Kernel not configured</string>
<string name="custom_settings">Custom settings</string>
@@ -254,19 +228,13 @@
<string name="kpm_install_mode_load">Load</string>
<string name="kpm_install_mode_embed">Embed</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string>
<string name="log_failed_to_check_module_file">Failed to check module file existence</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string>
<string name="confirm_uninstall_title">Confirm uninstallation</string>
<string name="confirm_uninstall_confirm">Uninstall</string>
<string name="confirm_uninstall_dismiss">Cancel</string>
<string name="theme_color">Theme Color</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string>
<string name="image_editor_title">Adjust background image</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string>
<string name="background_image_error">Could not load image</string>
<string name="reprovision">Reprovision</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -302,12 +270,7 @@
<string name="configuration">Configure</string>
<string name="app_settings">Application Settings</string>
<string name="tools">Tools</string>
<string name="currently_selected">Currently</string>
<!-- String resources used in SuperUser -->
<string name="clear">Removals</string>
<string name="apps_with_root">Applications with root privileges</string>
<string name="apps_with_custom_profile">Applications with customized configurations</string>
<string name="other_apps">Applications with unchanged defaults</string>
<string name="no_apps_found">Application not found</string>
<string name="selinux_enabled_toast">SELinux Enabled</string>
<string name="selinux_disabled_toast">SELinux Disabled</string>
@@ -315,13 +278,13 @@
<string name="advanced_settings">Advanced Settings</string>
<string name="appearance_settings">Customize the toolbar</string>
<string name="back">Comeback</string>
<string name="expand">Be in full swing</string>
<string name="collapse">put away</string>
<string name="susfs_enabled">SuSFS enabled</string>
<string name="susfs_disabled">SuSFS disabled</string>
<string name="background_set_success">Background set successfully</string>
<string name="background_removed">Removed custom backgrounds</string>
<string name="root_require_for_install">Requires root privileges</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string>
@@ -333,7 +296,6 @@
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI setting</string>
<string name="app_dpi_title">Applied DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
<string name="dpi_size_small">Small </string>
@@ -351,16 +313,6 @@
<string name="language_follow_system">Follow System</string>
<string name="language_changed">Language changed, restarting to apply changes</string>
<string name="settings_card_dim">Card Darkness Adjustment</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="scroll_to_top_description">Scroll to top</string>
<string name="scroll_to_bottom_description">Scroll to the bottom</string>
<string name="authorized">authorized</string>
<string name="unauthorized">unauthorized</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Disable custom uninstallation module</string>
<!-- Flash related -->
<string name="error_code">error code</string>
<string name="check_log">Please check the log</string>
@@ -368,4 +320,51 @@
<string name="module_failed_count">%d Failed to install a new module</string>
<string name="module_download_error">Module download failed</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,13 +5,10 @@
<string name="home_click_to_install">Klik untuk menginstal</string>
<string name="home_working">Berfungsi</string>
<string name="home_working_version">Versi: %d</string>
<string name="home_superuser_count">SuperUser: %d</string>
<string name="home_module_count">Modul: %d</string>
<string name="home_unsupported">Tidak didukung</string>
<string name="home_unsupported_reason">KernelSU saat ini hanya mendukung kernel GKI</string>
<string name="home_kernel">Kernel</string>
<string name="home_manager_version">Versi manager</string>
<string name="home_fingerprint">Identitas</string>
<string name="home_selinux_status">Status SELinux</string>
<string name="selinux_status_disabled">Nonaktif</string>
<string name="selinux_status_enforcing">Enforcing</string>
@@ -54,10 +51,6 @@
<string name="profile_template">Templat</string>
<string name="profile_custom">Khusus</string>
<string name="profile_name">Nama profil</string>
<string name="profile_namespace">Mount Namespace</string>
<string name="profile_namespace_inherited">Diwariskan</string>
<string name="profile_namespace_global">Universal</string>
<string name="profile_namespace_individual">Individual</string>
<string name="profile_groups">Kelompok</string>
<string name="profile_capabilities">Kemampuan</string>
<string name="profile_selinux_context">Konteks SELinux</string>
@@ -111,7 +104,6 @@
<string name="select_file">Pilih berkas</string>
<string name="install_inactive_slot">Instal ke slot nonaktif (setelah OTA)</string>
<string name="grant_root_failed">Gagal memberikan akses root!</string>
<string name="open">Buka</string>
<string name="close">Tutup</string>
<string name="settings_check_update">Cek terbaru</string>
<string name="settings_check_update_summary">Cek terbaru setiap membuka aplikasi</string>
@@ -131,4 +123,81 @@
<string name="log_saved">Log disimpan</string>
<string name="module_sort_enabled_first">Urut (Diaktifkan terlebih dahulu)</string>
<string name="module_sort_action_first">Urut (Tindakan pertama)</string>
<string name="home_android_version">Versi Android</string>
<string name="home_kpm_version">Versi KPM</string>
<string name="home_susfs_version">Versi SuSFS</string>
<string name="home_device_model">Model Perangkat</string>
<string name="home_ContributionCard_kernelsu">Antusias Untuk SukiSU Ultra</string>
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra akan menjadi cabang KSU yang relatif independen di masa mendatang, tetapi kami tetap menghargai KernelSU dan MKSU resmi dan sebagainya atas kontribusi mereka!</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">Tidak ada modul kernel yang terpasang saat ini</string>
<string name="kpm_version">Versi</string>
<string name="kpm_author">Pembuat</string>
<string name="kpm_uninstall">Uninstal</string>
<string name="kpm_uninstall_success">Berhasil di Uninstal</string>
<string name="kpm_uninstall_failed">Gagal Uninstal</string>
<string name="kpm_install_success">Memuat module KPM berhasil</string>
<string name="kpm_install_failed">Memuat module KPM gagal!</string>
<string name="kpm_args">Parameter</string>
<string name="kpm_control">Eksekusi</string>
<string name="kernel_module_notice">Fungsi-fungsi modul kernel berikut dikembangkan oleh KernelPatch dan dimodifikasi untuk menyertakan fungsi modul kernel dari SukiSU Ultra</string>
<string name="settings_disable_su">Nonaktifkan kompatibilitas SU</string>
<string name="settings_disable_su_summary">Nonaktifkan sementara kemampuan aplikasi untuk mendapatkan hak akses root melalui perintah su (proses root yang sedang berjalan tidak akan terpengaruh)</string>
<string name="use_webuix">Pilih jenis webUI untuk digunakan</string>
<string name="engine_auto_select">Otomatis memilih</string>
<string name="engine_force_webuix">Paksa menggunakan WebUI X</string>
<string name="engine_force_ksu">Penggunaan wajib KSU WebUI</string>
<string name="more_settings">Setelan lainnya</string>
<string name="language_setting">Bahasa Aplikasi</string>
<string name="language_follow_system">Mengikuti sistem</string>
<string name="language_changed">Bahasa dirubah, mulai ulang aplikasi untuk menerapkan</string>
<string name="theme_mode">Tema</string>
<string name="theme_follow_system">Mengikuti sistem</string>
<string name="theme_light">Terang</string>
<string name="theme_dark">Hitam</string>
<string name="dynamic_color_title">Warna dinamik</string>
<string name="dynamic_color_summary">Warna dinamik, menggunakan sistem tema</string>
<string name="choose_theme_color">Pilih warna tema</string>
<string name="color_default">Biru</string>
<string name="color_green">Hijau</string>
<string name="color_purple">Ungu</string>
<string name="color_orange">Oren</string>
<string name="color_pink">Pink</string>
<string name="color_gray">Abu</string>
<string name="color_yellow">Kuning</string>
<string name="app_dpi_title">Ubah DPI</string>
<string name="app_dpi_summary">Pengaturan DPI hanya untuk aplikasi ini saja</string>
<string name="dpi_size_small">Kecil</string>
<string name="dpi_size_medium">Sedang</string>
<string name="dpi_size_large">Besar</string>
<string name="dpi_size_extra_large">Jumbo</string>
<string name="dpi_size_custom">Kustomisasi</string>
<string name="dpi_apply_settings">Terapkan setelan DPI</string>
<string name="dpi_confirm_title">Konfirmasi perubahan DPI</string>
<string name="dpi_confirm_message">Apa kamu yakin ingin merubah DPI aplikasi dari %1$d ke %2$d?</string>
<string name="dpi_confirm_summary">Aplikasi membutuhkan restar untuk menerapkan opsi DPI ini, perubahan ini tidak mengganggu DPI sistem</string>
<string name="dpi_applied_success">DPI telah di rubah ke %1$d, efektif setelah aplikasi di restar</string>
<string name="settings_custom_background">Latar belakang kustom</string>
<string name="settings_custom_background_summary">Pilih gambar untuk latar belakang</string>
<string name="settings_card_alpha">NavBar transparant</string>
<string name="appearance_settings">Kustomisasi toolbar</string>
<string name="icon_switch_title">Ubah ikon</string>
<string name="icon_switch_summary">Ubah ikon peluncur aplikasi ke ikon KernelSU</string>
<string name="icon_switched">Ikon dirubah</string>
<string name="show_more_module_info">Tampilkan info modul lainnya</string>
<string name="show_more_module_info_summary">Pajang info modul tambahan seperti URL pembaruan JSON</string>
<string name="simple_mode">Mode simple</string>
<string name="simple_mode_summary">Sembunyikan papan kartu di beranda</string>
<string name="hide_kernel_kernelsu_version">Sembunyikan versi kernel</string>
<string name="hide_kernel_kernelsu_version_summary">Sembunyikan versi kernel jika namanya tidak yakin</string>
<string name="hide_other_info">Sembunyikan info lain</string>
<string name="hide_other_info_summary">Sembunyikan notifikasi titik merah (jumlah Super User, modul, dan modul KPM) di bilah navigasi</string>
<string name="hide_susfs_status">Sembunyikan status SuSFs</string>
<string name="hide_susfs_status_summary">Sembunyikan status susfs di halaman awal beranda</string>
<string name="hide_link_card">Sembunyikan kartu tautan</string>
<string name="hide_link_card_summary">Sembunyikan papan kartu URL di halaman awal beranda</string>
<string name="hide_tag_card">Sembunyikan baris label modul</string>
<string name="hide_tag_card_summary">Sembunyikan label nama folder dan ukuran di kartu modul</string>
<string name="show_kpm_info">Tampilkan fungsi KPM</string>
<string name="show_kpm_info_summary">Tampilkan fungsi informasi KPM dan menu KPM di bilah navigasi</string>
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">Clicca per installare</string>
<string name="home_working">In esecuzione</string>
<string name="home_working_version">Versione: %d</string>
<string name="home_superuser_count">Applicazioni con accesso root: %d</string>
<string name="home_module_count">Moduli installati: %d</string>
<string name="home_unsupported">Non supportato</string>
<string name="home_unsupported_reason">KernelSU ora supporta solo i kernel GKI</string>
<string name="home_kernel">Kernel</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS Version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">Versione del manager</string>
<string name="home_fingerprint">Impronta della build di Android</string>
<string name="home_selinux_status">Stato di SELinux</string>
<string name="selinux_status_disabled">Disabilitato</string>
<string name="selinux_status_enforcing">Enforcing</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="uninstall">Disinstalla</string>
<string name="restore">Restore</string>
<string name="module_install">Installa</string>
<string name="install">Installa</string>
<string name="reboot">Riavvia</string>
@@ -61,10 +55,6 @@
<string name="profile_template">Modello</string>
<string name="profile_custom">Personalizzato</string>
<string name="profile_name">Nome profilo</string>
<string name="profile_namespace">Spazio dei nomi del mount</string>
<string name="profile_namespace_inherited">Ereditato</string>
<string name="profile_namespace_global">Globale</string>
<string name="profile_namespace_individual">Individuale</string>
<string name="profile_groups">Gruppi</string>
<string name="profile_capabilities">Capacità</string>
<string name="profile_selinux_context">Contesto SELinux</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Controlla automaticamente la disponibilità di aggiornamenti all\'apertura dell\'applicazione</string>
<string name="grant_root_failed">Impossibile ottenere l\'accesso root!</string>
<string name="action">Action</string>
<string name="open">Apri</string>
<string name="close">Close</string>
<string name="enable_web_debugging">Abilita il debug di WebView</string>
<string name="enable_web_debugging_summary">Può essere usato per svolgere il debug di WebUI, è consigliato attivarlo solo quando necessario.</string>
@@ -138,9 +127,6 @@
<string name="selected_lkm">LKM selezionato: %s</string>
<string name="save_log">Salva Registri</string>
<string name="log_saved">Logs saved</string>
<string name="status_supported">Supported</string>
<string name="status_not_supported">Not Supported</string>
<string name="status_unknown">Unknown</string>
<string name="sus_su_mode">SuS SU mode:</string>
<!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string>
@@ -174,14 +160,11 @@
<string name="settings_custom_background">Custom App Background</string>
<string name="settings_custom_background_summary">Select an image as background</string>
<string name="settings_card_alpha">Navigation bar transparency</string>
<string name="settings_restore_default">Restore default</string>
<string name="home_android_version">Android version</string>
<string name="home_device_model">Device model</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string>
<string name="using_mksu_manager">You are using the SukiSU Beta manager</string>
<string name="module_install_multiple_confirm">Are you sure you want to install the selected %d modules?</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -212,20 +195,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Gray</string>
<string name="color_yellow">Yellow</string>
<string name="flash_option">Brush Options</string>
<string name="flash_option_tip">Select the file to be flashed</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string>
<string name="root_required">Requires root privileges</string>
<string name="copy_failed">File Copy Failure</string>
<string name="reboot_complete_title">Scrubbing complete</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="failed_reboot">Reboot Failed</string>
<string name="batch_authorization">empower</string>
<string name="batch_cancel_authorization">withdraw</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string>
<string name="kpm_version">Version</string>
@@ -233,7 +210,6 @@
<string name="kpm_uninstall">Uninstall</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string>
<string name="kpm_install">Install</string>
<string name="kpm_install_success">Load of kpm module successful</string>
<string name="kpm_install_failed">Load of kpm module failed</string>
<string name="kpm_args">Parameters</string>
@@ -247,8 +223,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string>
<string name="not_supported">Unsupported</string>
<string name="supported">Supported</string>
<string name="home_kpm_module">"Number of KPM modules: %d "</string>
<string name="kpm_invalid_file">Invalid KPM file</string>
<string name="kernel_patched">Kernel not patched</string>
<string name="kernel_not_enabled">Kernel not configured</string>
<string name="custom_settings">Custom settings</string>
@@ -256,19 +230,13 @@
<string name="kpm_install_mode_load">Load</string>
<string name="kpm_install_mode_embed">Embed</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string>
<string name="log_failed_to_check_module_file">Failed to check module file existence</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string>
<string name="confirm_uninstall_title">Confirm uninstallation</string>
<string name="confirm_uninstall_confirm">Uninstall</string>
<string name="confirm_uninstall_dismiss">Cancel</string>
<string name="theme_color">Theme Color</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string>
<string name="image_editor_title">Adjust background image</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string>
<string name="background_image_error">Could not load image</string>
<string name="reprovision">Reprovision</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -304,12 +272,7 @@
<string name="configuration">Configure</string>
<string name="app_settings">Application Settings</string>
<string name="tools">Tools</string>
<string name="currently_selected">Currently</string>
<!-- String resources used in SuperUser -->
<string name="clear">Removals</string>
<string name="apps_with_root">Applications with root privileges</string>
<string name="apps_with_custom_profile">Applications with customized configurations</string>
<string name="other_apps">Applications with unchanged defaults</string>
<string name="no_apps_found">Application not found</string>
<string name="selinux_enabled_toast">SELinux Enabled</string>
<string name="selinux_disabled_toast">SELinux Disabled</string>
@@ -317,13 +280,13 @@
<string name="advanced_settings">Advanced Settings</string>
<string name="appearance_settings">Customize the toolbar</string>
<string name="back">Comeback</string>
<string name="expand">Be in full swing</string>
<string name="collapse">put away</string>
<string name="susfs_enabled">SuSFS enabled</string>
<string name="susfs_disabled">SuSFS disabled</string>
<string name="background_set_success">Background set successfully</string>
<string name="background_removed">Removed custom backgrounds</string>
<string name="root_require_for_install">Requires root privileges</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string>
@@ -335,7 +298,6 @@
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI setting</string>
<string name="app_dpi_title">Applied DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
<string name="dpi_size_small">Small </string>
@@ -353,16 +315,6 @@
<string name="language_follow_system">Follow System</string>
<string name="language_changed">Language changed, restarting to apply changes</string>
<string name="settings_card_dim">Card Darkness Adjustment</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="scroll_to_top_description">Scroll to top</string>
<string name="scroll_to_bottom_description">Scroll to the bottom</string>
<string name="authorized">authorized</string>
<string name="unauthorized">unauthorized</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Disable custom uninstallation module</string>
<!-- Flash related -->
<string name="error_code">error code</string>
<string name="check_log">Please check the log</string>
@@ -370,4 +322,51 @@
<string name="module_failed_count">%d Failed to install a new module</string>
<string name="module_download_error">Module download failed</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -9,27 +9,21 @@
<string name="send_log">שלח לוג</string>
<string name="selinux_status_disabled">מושבת</string>
<string name="home_support_title">תמכו בנו</string>
<string name="profile_namespace_inherited">ירושה</string>
<string name="module_magisk_conflict">מודולים מושבתים מכיוון שהם מתנגשים עם זה של Magisk!</string>
<string name="module_changelog">יומן שינויים</string>
<string name="selinux_status_permissive">התרים</string>
<string name="reboot_download">הפעלה מחדש למצב הורדה</string>
<string name="settings_umount_modules_default">טעינת מודולים כברירת מחדל</string>
<string name="profile_umount_modules_summary">הפעלת אפשרות זו תאפשר ל-KernelSU לשחזר קבצים שהשתנו על ידי המודולים עבור יישום זה.</string>
<string name="profile_namespace_individual">אישי</string>
<string name="module_failed_to_enable">הפעלת המודל נכשלה: %s</string>
<string name="force_stop_app">עצירה בכח</string>
<string name="reboot_edl" formatted="false">הפעלה מחדש למצב EDL</string>
<string name="restart_app">איתחול</string>
<string name="profile_capabilities">יכולת</string>
<string name="home_superuser_count">משתמשי על: %d</string>
<string name="module_start_downloading">מפעיל מודל: %s</string>
<string name="profile_namespace_global">גלובלי</string>
<string name="settings_umount_modules_default_summary">ערך ברירת המחדל הגלובלי עבור \"טעינת מודולים\" בפרופילי אפליקציה. אם מופעל, זה יסיר את כל שינויי המודול למערכת עבור יישומים שאין להם ערכת פרופיל.</string>
<string name="home_module_count">מודלים:%d</string>
<string name="selinux_status_enforcing">אכיפה</string>
<string name="profile_selinux_context">הקשר SELinux</string>
<string name="home_fingerprint">טביעת אצבע</string>
<string name="profile_default">ברירת מחדל</string>
<string name="launch_app">להשיק</string>
<string name="safe_mode">מצב בטוח</string>
@@ -38,7 +32,6 @@
<string name="profile_name">שם פרופיל</string>
<string name="home_support_content">KernelSU הוא, ותמיד יהיה, חינמי וקוד פתוח. עם זאת, תוכל להראות לנו שאכפת לך על ידי תרומה.</string>
<string name="uninstall">הסרה</string>
<string name="profile_namespace">טעינת מרחב שמות</string>
<string name="module_install">התקנה</string>
<string name="home_click_to_install">לחץ להתקנה</string>
<string name="profile_selinux_rules">כללים</string>

View File

@@ -5,20 +5,13 @@
<string name="home_click_to_install">タップでインストール</string>
<string name="home_working">動作中</string>
<string name="home_working_version">バージョン: %d</string>
<string name="home_superuser_count">スーパーユーザー: %d</string>
<string name="home_module_count">モジュール: %d</string>
<string name="home_unsupported">非対応</string>
<string name="home_unsupported_reason">カーネルの KernelSU ドライバが未検出です。カーネルが間違ってませんか?</string>
<string name="home_kernel">カーネルのバージョン</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS のバージョン</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">マネージャーのバージョン</string>
<string name="home_fingerprint">Fingerprint</string>
<string name="home_selinux_status">SELinux のステータス</string>
<string name="selinux_status_disabled">無効</string>
<string name="selinux_status_enforcing">Enforcing</string>
<string name="selinux_status_permissive">Permissive</string>
<string name="selinux_status_unknown">不明</string>
<string name="superuser">スーパーユーザー</string>
<string name="module_failed_to_enable">%s モジュールを ON にできませんでした</string>
@@ -28,7 +21,6 @@
<string name="module_sort_action_first">並べ替え (アクション優先)</string>
<string name="module_sort_enabled_first">並べ替え (最初に有効)</string>
<string name="uninstall">アンインストール</string>
<string name="restore">復元</string>
<string name="module_install">インストール</string>
<string name="install">インストール</string>
<string name="reboot">再起動</string>
@@ -61,12 +53,8 @@
<string name="profile_template">テンプレート</string>
<string name="profile_custom">カスタム</string>
<string name="profile_name">プロファイル名</string>
<string name="profile_namespace">名前空間のマウント</string>
<string name="profile_namespace_inherited">継承</string>
<string name="profile_namespace_global">共通</string>
<string name="profile_namespace_individual">分離</string>
<string name="profile_groups">グループ</string>
<string name="profile_capabilities">パビリティ</string>
<string name="profile_capabilities">パビリティ</string>
<string name="profile_selinux_context">SELinux コンテキスト</string>
<string name="profile_umount_modules">モジュールのアンマウント</string>
<string name="failed_to_update_app_profile">%s のアプリのプロファイルの更新をできませでした</string>
@@ -87,10 +75,9 @@
<string name="failed_to_update_sepolicy">SELinux ルールの更新に失敗しました %s</string>
<string name="module_changelog">変更履歴</string>
<string name="settings_profile_template">アプリプロファイルのテンプレート</string>
<string name="settings_profile_template_summary">アプリプロファイルのローカルおよびオンラインテンプレートを管理します</string>
<string name="settings_profile_template_summary">アプリプロファイルのローカルおよびオンラインテンプレートを管理します</string>
<string name="app_profile_template_create">テンプレートの作成</string>
<string name="app_profile_template_edit">テンプレートの編集</string>
<string name="app_profile_template_id">ID</string>
<string name="app_profile_template_id_invalid">無効なテンプレート ID</string>
<string name="app_profile_template_name">名前</string>
<string name="app_profile_template_description">説明</string>
@@ -109,21 +96,20 @@
<string name="app_profile_template_import_empty">クリップボードが空です!</string>
<string name="module_changelog_failed">変更ログの取得に失敗しました: %s</string>
<string name="settings_check_update">更新を確認する</string>
<string name="settings_check_update_summary">アプリの起動時に更新を自動で確認します</string>
<string name="settings_check_update_summary">アプリの起動時に更新を自動で確認します</string>
<string name="grant_root_failed">root の付与に失敗しました!</string>
<string name="action">アクション</string>
<string name="open">開く</string>
<string name="close">閉じる</string>
<string name="enable_web_debugging">WebView デバッグを有効化する</string>
<string name="enable_web_debugging_summary">WebUI のデバッグに使用できます。必要な場合でのみ有効化してください</string>
<string name="enable_web_debugging_summary">WebUI のデバッグに使用できます。必要な場合でのみ有効化してください</string>
<string name="direct_install">直接インストール (推奨)</string>
<string name="select_file">パッチを行うイメージを選択してください</string>
<string name="select_file">パッチを行うイメージを選択</string>
<string name="install_inactive_slot">非アクティブなスロットにインストール (OTA 後)</string>
<string name="install_inactive_slot_warning">再起動後、デバイスは**強制的に**、現在非アクティブスロットから起動します。
<string name="install_inactive_slot_warning">再起動後、デバイスは**強制的に**、現在非アクティブスロットから起動します。
\nこのオプションは、OTA が完了した後にのみ使用してください。
\n続行しますか</string>
<string name="install_next">次へ</string>
<string name="select_file_tip">%1$s のパーティションイメージを推奨します</string>
<string name="select_file_tip">%1$s のパーティションイメージを推奨します</string>
<string name="select_kmi">KMI を選択してください</string>
<string name="settings_uninstall">アンインストール</string>
<string name="settings_uninstall_temporary">一時的にアンインストールする</string>
@@ -138,9 +124,6 @@
<string name="selected_lkm">選択された LKM: %s</string>
<string name="save_log">ログを保存</string>
<string name="log_saved">保存されたログ</string>
<string name="status_supported">対応</string>
<string name="status_not_supported">非対応</string>
<string name="status_unknown">不明</string>
<string name="sus_su_mode">SuS SU モード:</string>
<!-- Module related -->
<string name="module_install_confirm">%1$s のモジュールをインストールしますか?</string>
@@ -174,36 +157,34 @@
<string name="settings_custom_background">アプリの背景を変更</string>
<string name="settings_custom_background_summary">背景にする画像を選択してください</string>
<string name="settings_card_alpha">ナビゲーションバーの透過</string>
<string name="settings_restore_default">デフォルトに復元</string>
<string name="home_android_version">Android のバージョン</string>
<string name="home_device_model">デバイスモデル</string>
<string name="su_not_allowed">%s にスーパーユーザー権限を付与することはできません</string>
<string name="settings_disable_su">su の互換性を無効化する</string>
<string name="settings_disable_su_summary">su コマンドを使用してアプリが root 権限を取得する動作を一時的に無効化します (既存の root プロセスは影響を受けません)。</string>
<string name="using_mksu_manager">SukiSU Beta Manager を使用しています。</string>
<string name="module_install_multiple_confirm">選択した %d 個のモジュールをインストールしてもよろしいですか?</string>
<string name="module_install_multiple_confirm_with_names">%1$d 個のモジュールをインストールしてもよろしいですか?\n\n%2$s</string>
<string name="more_settings">その他の設定</string>
<string name="selinux">SELinux</string>
<string name="selinux_enabled">有効</string>
<string name="selinux_disabled">無効</string>
<string name="simple_mode">シンプルモード</string>
<string name="simple_mode_summary">ON にすると不要なカードを非表示にします</string>
<string name="simple_mode_summary">ON にすると不要なカードを非表示にします</string>
<string name="hide_kernel_kernelsu_version">カーネルのバージョンを非表示</string>
<string name="hide_kernel_kernelsu_version_summary">カーネルのバージョンを非表示にします</string>
<string name="hide_kernel_kernelsu_version_summary">カーネルのバージョンを非表示にします</string>
<string name="hide_other_info">その他の情報を非表示</string>
<string name="hide_other_info_summary">ホームページ上のスーパーユーザー、モジュール、KPM モジュールの数に関する情報を非表示にします</string>
<string name="hide_other_info_summary">ナビゲーションバーページスーパーユーザー、モジュール、KPM モジュールの数に関する赤いドットを非表示にします</string>
<string name="hide_susfs_status">SuSFS ステータスを非表示</string>
<string name="hide_susfs_status_summary">ホームページ上の SuSFS ステータス情報を非表示にします</string>
<string name="hide_susfs_status_summary">ホームページ上の SuSFS ステータス情報を非表示にします</string>
<string name="hide_link_card">リンクカードのステータスを非表示</string>
<string name="hide_link_card_summary">ホームページ上のリンクカード情報を非表示にします</string>
<string name="hide_link_card_summary">ホームページ上のリンクカード情報を非表示にします</string>
<string name="hide_tag_card">モジュールラベルの行を非表示</string>
<string name="hide_tag_card_summary">モジュールカード内のフォルダ名とサイズのラベルを非表示にします。</string>
<string name="theme_mode">テーマ</string>
<string name="theme_follow_system">システムに従う</string>
<string name="theme_light">ライト</string>
<string name="theme_dark">ダーク</string>
<string name="manual_hook">手動でフック</string>
<string name="dynamic_color_title">ダイナミックカラー</string>
<string name="dynamic_color_summary">システムテーマのダイナミックカラーを使用します</string>
<string name="dynamic_color_summary">システムテーマのダイナミックカラーを使用します</string>
<string name="choose_theme_color">テーマカラーを選択</string>
<string name="color_default">ブルー</string>
<string name="color_green">グリーン</string>
@@ -212,28 +193,20 @@
<string name="color_pink">ピンク</string>
<string name="color_gray">グレー</string>
<string name="color_yellow">イエロー</string>
<string name="flash_option">ブラシの設定</string>
<string name="flash_option_tip">フラッシュするファイルを選択</string>
<string name="horizon_kernel">AnyKernel3 をインストール</string>
<string name="horizon_kernel_summary">AnyKernel3 カーネルファイルをフラッシュします</string>
<string name="root_required">root 権限が必要です</string>
<string name="copy_failed">ファイルのコピーに失敗しました</string>
<string name="reboot_complete_title">スクラブが完了しました</string>
<string name="reboot_complete_msg">すぐに再起動しますか?</string>
<string name="yes">はい</string>
<string name="no">いいえ</string>
<string name="failed_reboot">再起動に失敗しました</string>
<string name="batch_authorization">権限を付与</string>
<string name="batch_cancel_authorization">撤回する</string>
<string name="backup">バックアップ</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">カーネルモジュールは現在インストールされていません</string>
<string name="kpm_version">バージョン</string>
<string name="kpm_author">作者</string>
<string name="kpm_uninstall">アンインストール</string>
<string name="kpm_uninstall_success">アンインストールに失敗しました</string>
<string name="kpm_uninstall_failed">アンインストールに失敗しました</string>
<string name="kpm_install">インストール</string>
<string name="kpm_install_success">KPM モジュールの読み込みに成功しました</string>
<string name="kpm_install_failed">KPM モジュールの読み込みに失敗しました</string>
<string name="kpm_args">パラメータ</string>
@@ -247,8 +220,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra は将来的に KSU から比較的に独立したブランチになりますが、公式の KernelSU や MKSU などの貢献に感謝しています!</string>
<string name="not_supported">非対応</string>
<string name="supported">対応</string>
<string name="home_kpm_module">"KPM モジュールの数: %d "</string>
<string name="kpm_invalid_file">無効な KPM ファイル</string>
<string name="kernel_patched">カーネルはパッチされていません</string>
<string name="kernel_not_enabled">カーネルは未設定です</string>
<string name="custom_settings">カスタム設定</string>
@@ -256,19 +227,13 @@
<string name="kpm_install_mode_load">読み込む</string>
<string name="kpm_install_mode_embed">埋め込む</string>
<string name="kpm_install_mode_description">選択してください: %1\$s モジュールのインストールモード \n\n読み込む: モジュールを一時的に読み込みます\n埋め込む: システムで恒久的にインストールします</string>
<string name="log_failed_to_check_module_file">モジュールファイルの存在を確認できませんでした</string>
<string name="snackbar_failed_to_check_module_file">モジュールファイルが存在するか確認できません</string>
<string name="confirm_uninstall_title">アンインストールを確認</string>
<string name="confirm_uninstall_confirm">アンインストール</string>
<string name="confirm_uninstall_dismiss">キャンセル</string>
<string name="theme_color">テーマカラー</string>
<string name="invalid_file_type">ファイルの種類が間違っています!.kpm ファイルを選択してください。</string>
<string name="confirm_uninstall_title_with_filename">アンインストール</string>
<string name="confirm_uninstall_content">次の KPM がアンインストールされます: %s</string>
<string name="settings_susfs_toggle_summary">KernelSU によって作成された kprobe フックを無効化して、代替となるインラインフックを使用します。これは、非 GKI カーネルのフック方式に似た物になります。</string>
<string name="image_editor_title">背景画像を調整</string>
<string name="image_editor_hint">2 本の指で画像を拡大、1 本の指でドラッグで位置を調整します</string>
<string name="background_image_error">イメージを読み込めません</string>
<string name="image_editor_hint">2 本の指で画像を拡大、1 本の指でドラッグで位置を調整します。</string>
<string name="reprovision">再プロビジョニング</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">カーネルをフラッシュ</string>
@@ -291,7 +256,7 @@
<string name="horizon_getting_original_slot">オリジナルのスロットを取得</string>
<string name="horizon_setting_target_slot">指定するスロットを設定</string>
<string name="horizon_restoring_original_slot">デフォルトのスロットに復元</string>
<string name="current_slot">現在のスロット: %1$s </string>
<string name="current_slot">現在のシステムデフォルトスロット: %1$s </string>
<!-- Error Messages -->
<string name="horizon_copy_failed">コピーに失敗しました</string>
<string name="horizon_unknown_error">不明なエラー</string>
@@ -304,12 +269,7 @@
<string name="configuration">設定</string>
<string name="app_settings">アプリの設定</string>
<string name="tools">ツール</string>
<string name="currently_selected">現在</string>
<!-- String resources used in SuperUser -->
<string name="clear">削除</string>
<string name="apps_with_root">root アプリの権限</string>
<string name="apps_with_custom_profile">カスタマイズされたアプリ構成</string>
<string name="other_apps">その他のアプリ</string>
<string name="no_apps_found">アプリがありません</string>
<string name="selinux_enabled_toast">SELinux 有効</string>
<string name="selinux_disabled_toast">SELinux 無効</string>
@@ -317,27 +277,26 @@
<string name="advanced_settings">高度な設定</string>
<string name="appearance_settings">ツールバーをカスタマイズ</string>
<string name="back">戻る</string>
<string name="expand">展開する</string>
<string name="collapse">折りたたむ</string>
<string name="susfs_enabled">SuSFS 有効</string>
<string name="susfs_disabled">SuSFS 無効</string>
<string name="background_set_success">背景の設定が成功しました</string>
<string name="background_removed">カスタム背景を削除しました</string>
<string name="root_require_for_install">root 権限が必要です</string>
<string name="icon_switch_title">代替アイコン</string>
<string name="icon_switch_summary">ランチャーアイコンを KernelSU のアイコンに変更します。</string>
<string name="icon_switched">アイコンを変更しました</string>
<!-- KPM display settings -->
<string name="show_kpm_info">KPM 機能を表示</string>
<string name="show_kpm_info_summary">KPM の情報と機能をホームとボトムバーに表示します (アプリを開き直す必要があります)</string>
<string name="show_kpm_info">KPM 機能を表示</string>
<string name="show_kpm_info_summary">ホームとボトムバーから KPM の情報と機能を表示します</string>
<!-- Webui X settings -->
<string name="use_webuix">Select the WebUI engine to use</string>
<string name="engine_auto_select">Automatic Selection</string>
<string name="engine_force_webuix">Force the use of WebUI X</string>
<string name="engine_force_ksu">Mandatory use of KSU WebUI</string>
<string name="use_webuix">WebUI で使用するエンジン</string>
<string name="engine_auto_select">自動選択</string>
<string name="engine_force_webuix">WebUI X の使用を強制する</string>
<string name="engine_force_ksu">KSU WebUI の使用を強制する</string>
<string name="use_webuix_eruda">WebUI に Eruda をインジェクトする</string>
<string name="use_webuix_eruda_summary">デバッグを容易にするために WebUI X にデバッグコンソールを挿入します。Web デバッグが ON になっている必要があります。</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI の設定</string>
<string name="app_dpi_title">DPI の変更を適用</string>
<string name="app_dpi_summary">このアプリのみで画面表示密度を調整します</string>
<string name="app_dpi_summary">このアプリのみで画面表示密度を調整します</string>
<string name="dpi_size_small"></string>
<string name="dpi_size_medium"></string>
<string name="dpi_size_large"></string>
@@ -353,16 +312,6 @@
<string name="language_follow_system">システムに従う</string>
<string name="language_changed">言語の変更を適用するために再起動しています</string>
<string name="settings_card_dim">カードの暗さを調整</string>
<!-- Super User Related -->
<string name="scroll_to_top">上詰め</string>
<string name="scroll_to_bottom">画面下</string>
<string name="scroll_to_top_description">一番上までスクロール</string>
<string name="scroll_to_bottom_description">下までスクロールします</string>
<string name="authorized">承認済み</string>
<string name="unauthorized">未認証</string>
<string name="selected">選択中</string>
<string name="select">オプション</string>
<string name="profile_umount_modules_disable">カスタムアンインストールモジュールを無効にする</string>
<!-- Flash related -->
<string name="error_code">エラーコード</string>
<string name="check_log">ログを確認してください</string>
@@ -370,4 +319,140 @@
<string name="module_failed_count">%d モジュールのインストールに失敗しました</string>
<string name="module_download_error">モデルのダウンロードに失敗しました</string>
<string name="kernel_flashing">カーネルをフラッシュ中</string>
<!-- 分类相关 -->
<string name="category_all_apps">すべて</string>
<string name="category_custom_apps">カスタム</string>
<string name="category_default_apps">デフォルト</string>
<!-- 排序相关 -->
<string name="sort_name_asc">名前の昇順</string>
<string name="sort_name_desc">名前の降順</string>
<string name="sort_install_time_new">インストール日時 (新しい)</string>
<string name="sort_install_time_old">インストール日時 (古い)</string>
<string name="sort_size_desc">サイズの降順</string>
<string name="sort_size_asc">サイズの昇順</string>
<string name="sort_usage_freq">使用頻度</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">このカテゴリーにアプリはありません</string>
<!-- 标签相关 -->
<string name="deny_authorization">権限の認証</string>
<string name="grant_authorization">認証</string>
<string name="unmount_modules">モジュールのマウントを解除</string>
<string name="disable_unmount">アンインストールするモジュールのマウントを無効化します。</string>
<string name="expand_menu">メニューを展開</string>
<string name="collapse_menu">メニューを収納</string>
<string name="scroll_to_top">上詰め</string>
<string name="scroll_to_bottom">画面下</string>
<string name="selected">選択中</string>
<string name="select">オプション</string>
<!-- BottomSheet相关 -->
<string name="menu_options">メニューのオプション</string>
<string name="sort_options">並べ替え</string>
<string name="app_categories">アプリタイプを選択</string>
<!-- SuSFS Configuration -->
<string name="susfs_config_title">SuSFS の構成</string>
<string name="susfs_config_description">構成の説明</string>
<string name="susfs_config_description_text">この機能を使用すると SuSFS の uname の値とビルド日時の偽装をカスタマイズできます。設定する値を入力後に「適用」をタップで有効になります。</string>
<string name="susfs_uname_label">uname の値</string>
<string name="susfs_uname_placeholder">カスタム uname の値を入力してください</string>
<string name="susfs_build_time_label">ビルド日時を偽装</string>
<string name="susfs_build_time_placeholder">偽装するビルド日時を入力してください</string>
<string name="susfs_current_value">現在の値: %s</string>
<string name="susfs_current_build_time">現在のビルド日時: %s</string>
<string name="susfs_reset_to_default">デフォルトにリセット</string>
<string name="susfs_apply">適用</string>
<!-- SuSFS Reset Confirmation -->
<string name="susfs_reset_confirm_title">リセットを確認</string>
<string name="susfs_reset_confirm">リセットを確認</string>
<!-- SuSFS Toast Messages -->
<string name="susfs_binary_not_found">ksu_susfs ファイルが見つかりません</string>
<string name="susfs_command_failed">SuSFS コマンドの実行に失敗しました</string>
<string name="susfs_command_error">SuSFS コマンドの実行エラー: %s</string>
<string name="susfs_uname_set_success" formatted="false">SuSFS uname とビルド日時が正常に設定されました: %s - %s</string>
<!-- SuSFS Settings Item -->
<string name="susfs_config_setting_title">SuSFS の構成</string>
<!-- 开机自启动相关 -->
<string name="susfs_autostart_title">自動起動</string>
<string name="susfs_autostart_description">システムの起動時に自動で uname の構成を適用する</string>
<string name="susfs_autostart_requirement">有効化するには uname を構成するかパスを追加する必要があります</string>
<string name="susfs_autostart_enable_failed">自動起動の有効化に失敗しました</string>
<string name="susfs_autostart_disable_failed">自動起動の無効化に失敗しました</string>
<string name="susfs_autostart_error">自動起動の構成エラー: %s</string>
<string name="susfs_no_config_to_autostart">自動起動に利用可能な構成がありません</string>
<!-- SuSFS Tab Titles -->
<string name="susfs_tab_basic_settings">基本設定</string>
<string name="susfs_tab_sus_paths">SUS のパス</string>
<string name="susfs_tab_sus_mounts">SUS マウント</string>
<string name="susfs_tab_try_umount">アンマウントを試す</string>
<string name="susfs_tab_path_settings">パスの設定</string>
<string name="susfs_tab_enabled_features">有効な機能のステータス</string>
<!-- SuSFS Dialog Actions -->
<string name="susfs_add">追加</string>
<!-- SuSFS Path Management -->
<string name="susfs_add_sus_path">SUS パスを追加</string>
<string name="susfs_add_sus_mount">SUS マウントを追加</string>
<string name="susfs_add_try_umount">アンマウントを試すを追加</string>
<string name="susfs_path_label">パス</string>
<string name="susfs_mount_path_label">マウントのパス</string>
<string name="susfs_path_placeholder">例 : /system/addon.d</string>
<string name="susfs_no_paths_configured">SUS パスが未構成です</string>
<string name="susfs_no_mounts_configured">SUS マウントが未構成です</string>
<string name="susfs_no_umounts_configured">アンマウントを試すが未構成です</string>
<!-- SuSFS Umount Mode -->
<string name="susfs_umount_mode_label">アンマウントモード</string>
<string name="susfs_umount_mode_normal">通常のアンマウント (0)</string>
<string name="susfs_umount_mode_detach">アンマウントを分離 (1)</string>
<string name="susfs_umount_mode_normal_short">通常</string>
<string name="susfs_umount_mode_detach_short">分離</string>
<string name="susfs_umount_mode_display">モード: %1$s (%2$s)</string>
<string name="susfs_try_umount_added_success">追加されたパスのアンマウントに成功しました: %s</string>
<string name="susfs_try_umount_added_saved">アンマウントのパスの保存に成功しました: %s</string>
<!-- SuSFS Run Umount -->
<string name="susfs_run_umount_confirm_title">実行を確認してアンマウントを試す</string>
<string name="susfs_run_umount_confirm_message">設定されたすべてのアンマウントの試行操作が直ちに実行されます。続行してもよろしいですか?</string>
<!-- SuSFS Reset Categories -->
<string name="susfs_reset_paths_title">SUS パスをリセット</string>
<string name="susfs_reset_paths_message">すべての SUS パスの構成が消去されます。続行してもよろしいですか?</string>
<string name="susfs_reset_mounts_title">SUS マウントをリセット</string>
<string name="susfs_reset_mounts_message">すべての SUS マウントの構成が消去されます。続行してもよろしいですか?</string>
<string name="susfs_reset_umounts_title">リセットしてアンマウントを試す</string>
<string name="susfs_reset_umounts_message">すべてのアンマウント構成がリセットされます。続行してもよろしいですか?</string>
<!-- SuSFS Path Settings -->
<string name="susfs_android_data_path_label">Android データパス</string>
<string name="susfs_sdcard_path_label">SD カードのパス</string>
<string name="susfs_set_android_data_path">Android データパスを設定</string>
<string name="susfs_set_sdcard_path">SD カードのパスを設定</string>
<!-- SuSFS Enabled Features -->
<string name="susfs_enabled_features_description">SuSFS で有効な機能のステータスを表示します。</string>
<string name="susfs_no_features_found">機能のステータス情報が見つかりません</string>
<string name="susfs_feature_enabled">有効</string>
<string name="susfs_feature_disabled">無効</string>
<!-- Feature Labels -->
<string name="sus_path_feature_label">SUS パスの対応</string>
<string name="sus_mount_feature_label">SUS マウントの対応</string>
<string name="try_umount_feature_label">アンマウントを試すの対応</string>
<string name="spoof_uname_feature_label">uname 偽装の対応</string>
<string name="spoof_cmdline_feature_label">Cmdline/Bootconfig を偽装</string>
<string name="open_redirect_feature_label">オープンリダイレクトの対応</string>
<string name="enable_log_feature_label">ログの対応</string>
<string name="auto_default_mount_feature_label">自動でデフォルトのマウント</string>
<string name="auto_bind_mount_feature_label">自動でバインドマウント</string>
<string name="auto_try_umount_bind_feature_label">自動でバインドマウントのアンマウントを試す</string>
<string name="hide_symbols_feature_label">KSU SUSFS シンボルを非表示</string>
<string name="magic_mount_feature_label">Magic Mount の対応</string>
<string name="sus_kstat_feature_label">SUS Kstat の対応</string>
<string name="sus_su_feature_label">SUS SU モード切り替え機能</string>
<!-- 可切换状态 -->
<string name="susfs_feature_configurable">構成可能な SuSFS の機能</string>
<string name="susfs_enable_log_label">SuSFS のログ取得を有効化</string>
<string name="susfs_log_config_description">SuSFS のログ取得を有効化または無効化します。</string>
<string name="susfs_log_config_title">SuSFS ログ取得の構成</string>
<string name="susfs_log_enabled">SuSFS のログ取得を有効化中</string>
<string name="susfs_log_disabled">SuSFS のログ取得を無効化</string>
<string name="module_update_json">更新用の JSON</string>
<string name="module_update_json_copied">更新用 JSON の URL をクリップボードにコピーしました</string>
<!-- Settings related strings -->
<string name="show_more_module_info">モジュール情報の詳細を表示</string>
<string name="show_more_module_info_summary">更新用 JSON の URL など追加の情報を表示します。</string>
<!-- SuSFS 自启动相关字符串 -->
<!-- SuSFS Kstat相关字符串 -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">Click to install</string>
<string name="home_working">ಕೆಲಸ ಮಾಡುತ್ತಿದೆ</string>
<string name="home_working_version">ವರ್ಷನ್: %d</string>
<string name="home_superuser_count">ಸೂಪರ್‌ಯೂಸರ್‌ಗಳು: %d</string>
<string name="home_module_count">ಮಾಡ್ಯೂಲ್‌ಗಳು: %d</string>
<string name="home_unsupported">ಬೆಂಬಲಿತವಾಗಿಲ್ಲ</string>
<string name="home_unsupported_reason">KernelSU ಈಗ GKI ಕರ್ನಲ್‌ಗಳನ್ನು ಮಾತ್ರ ಬೆಂಬಲಿಸುತ್ತದೆ</string>
<string name="home_kernel">ಕರ್ನಲ್</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS Version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">ಮ್ಯಾನೇಜರ್ ವರ್ಷನ್</string>
<string name="home_fingerprint">Fingerprint</string>
<string name="home_selinux_status">SELinux ಸ್ಥಿತಿ</string>
<string name="selinux_status_disabled">Disabled</string>
<string name="selinux_status_enforcing">Enforcing</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="uninstall">ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್</string>
<string name="restore">Restore</string>
<string name="module_install">Install</string>
<string name="install">Install</string>
<string name="reboot">ರೀಬೂಟ್</string>
@@ -61,10 +55,6 @@
<string name="profile_template">ಟೆಂಪ್ಲೇಟ್</string>
<string name="profile_custom">ಕಸ್ಟಮ್</string>
<string name="profile_name">ಪ್ರೊಫೈಲ್ ಹೆಸರು</string>
<string name="profile_namespace">ಮೌಂಟ್ ನೇಮ್‌ಸ್ಪೇಸ್</string>
<string name="profile_namespace_inherited">ಪಿತ್ರಾರ್ಜಿತ</string>
<string name="profile_namespace_global">ಜಾಗತಿಕ</string>
<string name="profile_namespace_individual">ವೈಯಕ್ತಿಕ</string>
<string name="profile_groups">ಗುಂಪುಗಳು</string>
<string name="profile_capabilities">ಸಾಮರ್ಥ್ಯಗಳು</string>
<string name="profile_selinux_context">SELinux ಸಂದರ್ಭ</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Automatically check for updates when opening the app</string>
<string name="grant_root_failed">Failed to grant root!</string>
<string name="action">Action</string>
<string name="open">Open</string>
<string name="close">Close</string>
<string name="enable_web_debugging">Enable WebView debugging</string>
<string name="enable_web_debugging_summary">Can be used to debug WebUI. Please enable only when needed.</string>
@@ -136,9 +125,6 @@
<string name="selected_lkm">Selected LKM: %s</string>
<string name="save_log">ಲಾಗ್ಗಳನ್ನು ಉಳಿಸಿ</string>
<string name="log_saved">Logs saved</string>
<string name="status_supported">Supported</string>
<string name="status_not_supported">Not Supported</string>
<string name="status_unknown">Unknown</string>
<string name="sus_su_mode">SuS SU mode:</string>
<!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string>
@@ -172,14 +158,11 @@
<string name="settings_custom_background">Custom App Background</string>
<string name="settings_custom_background_summary">Select an image as background</string>
<string name="settings_card_alpha">Navigation bar transparency</string>
<string name="settings_restore_default">Restore default</string>
<string name="home_android_version">Android version</string>
<string name="home_device_model">Device model</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string>
<string name="using_mksu_manager">You are using the SukiSU Beta manager</string>
<string name="module_install_multiple_confirm">Are you sure you want to install the selected %d modules?</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -210,20 +193,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Gray</string>
<string name="color_yellow">Yellow</string>
<string name="flash_option">Brush Options</string>
<string name="flash_option_tip">Select the file to be flashed</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string>
<string name="root_required">Requires root privileges</string>
<string name="copy_failed">File Copy Failure</string>
<string name="reboot_complete_title">Scrubbing complete</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="failed_reboot">Reboot Failed</string>
<string name="batch_authorization">empower</string>
<string name="batch_cancel_authorization">withdraw</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string>
<string name="kpm_version">Version</string>
@@ -231,7 +208,6 @@
<string name="kpm_uninstall">Uninstall</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string>
<string name="kpm_install">Install</string>
<string name="kpm_install_success">Load of kpm module successful</string>
<string name="kpm_install_failed">Load of kpm module failed</string>
<string name="kpm_args">Parameters</string>
@@ -245,8 +221,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string>
<string name="not_supported">Unsupported</string>
<string name="supported">Supported</string>
<string name="home_kpm_module">"Number of KPM modules: %d "</string>
<string name="kpm_invalid_file">Invalid KPM file</string>
<string name="kernel_patched">Kernel not patched</string>
<string name="kernel_not_enabled">Kernel not configured</string>
<string name="custom_settings">Custom settings</string>
@@ -254,19 +228,13 @@
<string name="kpm_install_mode_load">Load</string>
<string name="kpm_install_mode_embed">Embed</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string>
<string name="log_failed_to_check_module_file">Failed to check module file existence</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string>
<string name="confirm_uninstall_title">Confirm uninstallation</string>
<string name="confirm_uninstall_confirm">Uninstall</string>
<string name="confirm_uninstall_dismiss">Cancel</string>
<string name="theme_color">Theme Color</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string>
<string name="image_editor_title">Adjust background image</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string>
<string name="background_image_error">Could not load image</string>
<string name="reprovision">Reprovision</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -302,12 +270,7 @@
<string name="configuration">Configure</string>
<string name="app_settings">Application Settings</string>
<string name="tools">Tools</string>
<string name="currently_selected">Currently</string>
<!-- String resources used in SuperUser -->
<string name="clear">Removals</string>
<string name="apps_with_root">Applications with root privileges</string>
<string name="apps_with_custom_profile">Applications with customized configurations</string>
<string name="other_apps">Applications with unchanged defaults</string>
<string name="no_apps_found">Application not found</string>
<string name="selinux_enabled_toast">SELinux Enabled</string>
<string name="selinux_disabled_toast">SELinux Disabled</string>
@@ -315,13 +278,13 @@
<string name="advanced_settings">Advanced Settings</string>
<string name="appearance_settings">Customize the toolbar</string>
<string name="back">Comeback</string>
<string name="expand">Be in full swing</string>
<string name="collapse">put away</string>
<string name="susfs_enabled">SuSFS enabled</string>
<string name="susfs_disabled">SuSFS disabled</string>
<string name="background_set_success">Background set successfully</string>
<string name="background_removed">Removed custom backgrounds</string>
<string name="root_require_for_install">Requires root privileges</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string>
@@ -333,7 +296,6 @@
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI setting</string>
<string name="app_dpi_title">Applied DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
<string name="dpi_size_small">Small </string>
@@ -351,16 +313,6 @@
<string name="language_follow_system">Follow System</string>
<string name="language_changed">Language changed, restarting to apply changes</string>
<string name="settings_card_dim">Card Darkness Adjustment</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="scroll_to_top_description">Scroll to top</string>
<string name="scroll_to_bottom_description">Scroll to the bottom</string>
<string name="authorized">authorized</string>
<string name="unauthorized">unauthorized</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Disable custom uninstallation module</string>
<!-- Flash related -->
<string name="error_code">error code</string>
<string name="check_log">Please check the log</string>
@@ -368,4 +320,51 @@
<string name="module_failed_count">%d Failed to install a new module</string>
<string name="module_download_error">Module download failed</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">이 곳을 눌러 설치하기</string>
<string name="home_working">정상 작동 중</string>
<string name="home_working_version">버전: %d</string>
<string name="home_superuser_count">루트 권한: %d개</string>
<string name="home_module_count">설치된 모듈: %d개</string>
<string name="home_unsupported">지원되지 않음</string>
<string name="home_unsupported_reason">KernelSU는 현재 GKI 커널만 지원합니다</string>
<string name="home_kernel">커널</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS Version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">매니저 버전</string>
<string name="home_fingerprint">빌드 정보</string>
<string name="home_selinux_status">SELinux 상태</string>
<string name="selinux_status_disabled">비활성화됨</string>
<string name="selinux_status_enforcing">적용</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">정렬 (동작이 있는 것 우선)</string>
<string name="module_sort_enabled_first">정렬 (활성화됨 우선)</string>
<string name="uninstall">삭제</string>
<string name="restore">Restore</string>
<string name="module_install">설치</string>
<string name="install">설치</string>
<string name="reboot">다시 시작</string>
@@ -61,10 +55,6 @@
<string name="profile_template">템플릿</string>
<string name="profile_custom">사용자 지정</string>
<string name="profile_name">프로필 이름</string>
<string name="profile_namespace">이름 공간 마운트</string>
<string name="profile_namespace_inherited">상속</string>
<string name="profile_namespace_global">전역</string>
<string name="profile_namespace_individual">개별</string>
<string name="profile_groups">사용자 그룹</string>
<string name="profile_capabilities">권한</string>
<string name="profile_selinux_context">SELinux 컨텍스트</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">앱 실행시 자동으로 업데이트 확인</string>
<string name="grant_root_failed">루트 부여 실패!</string>
<string name="action">동작</string>
<string name="open">열기</string>
<string name="close">Close</string>
<string name="enable_web_debugging">WebView 디버깅 활성화</string>
<string name="enable_web_debugging_summary">WebUI 디버깅에 사용 가능, 필요할 때만 활성화해주세요.</string>
@@ -136,9 +125,6 @@
<string name="selected_lkm">선택된 LKM: %s</string>
<string name="save_log">로그 저장</string>
<string name="log_saved">로그 저장됨</string>
<string name="status_supported">Supported</string>
<string name="status_not_supported">Not Supported</string>
<string name="status_unknown">Unknown</string>
<string name="sus_su_mode">SuS SU mode:</string>
<!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string>
@@ -172,14 +158,11 @@
<string name="settings_custom_background">Custom App Background</string>
<string name="settings_custom_background_summary">Select an image as background</string>
<string name="settings_card_alpha">Navigation bar transparency</string>
<string name="settings_restore_default">Restore default</string>
<string name="home_android_version">Android version</string>
<string name="home_device_model">Device model</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string>
<string name="using_mksu_manager">You are using the SukiSU Beta manager</string>
<string name="module_install_multiple_confirm">Are you sure you want to install the selected %d modules?</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -210,20 +193,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Gray</string>
<string name="color_yellow">Yellow</string>
<string name="flash_option">Brush Options</string>
<string name="flash_option_tip">Select the file to be flashed</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string>
<string name="root_required">Requires root privileges</string>
<string name="copy_failed">File Copy Failure</string>
<string name="reboot_complete_title">Scrubbing complete</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="failed_reboot">Reboot Failed</string>
<string name="batch_authorization">empower</string>
<string name="batch_cancel_authorization">withdraw</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string>
<string name="kpm_version">Version</string>
@@ -231,7 +208,6 @@
<string name="kpm_uninstall">Uninstall</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string>
<string name="kpm_install">Install</string>
<string name="kpm_install_success">Load of kpm module successful</string>
<string name="kpm_install_failed">Load of kpm module failed</string>
<string name="kpm_args">Parameters</string>
@@ -245,8 +221,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string>
<string name="not_supported">Unsupported</string>
<string name="supported">Supported</string>
<string name="home_kpm_module">"Number of KPM modules: %d "</string>
<string name="kpm_invalid_file">Invalid KPM file</string>
<string name="kernel_patched">Kernel not patched</string>
<string name="kernel_not_enabled">Kernel not configured</string>
<string name="custom_settings">Custom settings</string>
@@ -254,19 +228,13 @@
<string name="kpm_install_mode_load">Load</string>
<string name="kpm_install_mode_embed">Embed</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string>
<string name="log_failed_to_check_module_file">Failed to check module file existence</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string>
<string name="confirm_uninstall_title">Confirm uninstallation</string>
<string name="confirm_uninstall_confirm">Uninstall</string>
<string name="confirm_uninstall_dismiss">Cancel</string>
<string name="theme_color">Theme Color</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string>
<string name="image_editor_title">Adjust background image</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string>
<string name="background_image_error">Could not load image</string>
<string name="reprovision">Reprovision</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -302,12 +270,7 @@
<string name="configuration">Configure</string>
<string name="app_settings">Application Settings</string>
<string name="tools">Tools</string>
<string name="currently_selected">Currently</string>
<!-- String resources used in SuperUser -->
<string name="clear">Removals</string>
<string name="apps_with_root">Applications with root privileges</string>
<string name="apps_with_custom_profile">Applications with customized configurations</string>
<string name="other_apps">Applications with unchanged defaults</string>
<string name="no_apps_found">Application not found</string>
<string name="selinux_enabled_toast">SELinux Enabled</string>
<string name="selinux_disabled_toast">SELinux Disabled</string>
@@ -315,13 +278,13 @@
<string name="advanced_settings">Advanced Settings</string>
<string name="appearance_settings">Customize the toolbar</string>
<string name="back">Comeback</string>
<string name="expand">Be in full swing</string>
<string name="collapse">put away</string>
<string name="susfs_enabled">SuSFS enabled</string>
<string name="susfs_disabled">SuSFS disabled</string>
<string name="background_set_success">Background set successfully</string>
<string name="background_removed">Removed custom backgrounds</string>
<string name="root_require_for_install">Requires root privileges</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string>
@@ -333,7 +296,6 @@
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI setting</string>
<string name="app_dpi_title">Applied DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
<string name="dpi_size_small">Small </string>
@@ -351,16 +313,6 @@
<string name="language_follow_system">Follow System</string>
<string name="language_changed">Language changed, restarting to apply changes</string>
<string name="settings_card_dim">Card Darkness Adjustment</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="scroll_to_top_description">Scroll to top</string>
<string name="scroll_to_bottom_description">Scroll to the bottom</string>
<string name="authorized">authorized</string>
<string name="unauthorized">unauthorized</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Disable custom uninstallation module</string>
<!-- Flash related -->
<string name="error_code">error code</string>
<string name="check_log">Please check the log</string>
@@ -368,4 +320,51 @@
<string name="module_failed_count">%d Failed to install a new module</string>
<string name="module_download_error">Module download failed</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">Spustelėkite norėdami įdiegti</string>
<string name="home_working">Veikia</string>
<string name="home_working_version">Versija: %d</string>
<string name="home_superuser_count">Supernaudotojai: %d</string>
<string name="home_module_count">Moduliai: %d</string>
<string name="home_unsupported">Nepalaikoma</string>
<string name="home_unsupported_reason">KernelSU dabar palaiko tik GKI branduolius</string>
<string name="home_kernel">Branduolys</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS Version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">Tvarkyklės versija</string>
<string name="home_fingerprint">Pirštų atspaudas</string>
<string name="home_selinux_status">SELinux statusas</string>
<string name="selinux_status_disabled">Išjungta</string>
<string name="selinux_status_enforcing">Priverstinas</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="uninstall">Išdiegti</string>
<string name="restore">Restore</string>
<string name="module_install">Įdiegti</string>
<string name="install">Įdiegti</string>
<string name="reboot">Paleisti iš naujo</string>
@@ -61,10 +55,6 @@
<string name="profile_template">Šablonas</string>
<string name="profile_custom">Pasirinktinis</string>
<string name="profile_name">Profilio pavadinimas</string>
<string name="profile_namespace">Prijungti vardų erdvę</string>
<string name="profile_namespace_inherited">Paveldėtas</string>
<string name="profile_namespace_global">Globalus</string>
<string name="profile_namespace_individual">Individualus</string>
<string name="profile_groups">Grupės</string>
<string name="profile_capabilities">Galimybės</string>
<string name="profile_selinux_context">SELinux kontekstas</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Automatically check for updates when opening the app</string>
<string name="grant_root_failed">Failed to grant root!</string>
<string name="action">Action</string>
<string name="open">Open</string>
<string name="close">Close</string>
<string name="enable_web_debugging">Enable WebView debugging</string>
<string name="enable_web_debugging_summary">Can be used to debug WebUI. Please enable only when needed.</string>
@@ -136,9 +125,6 @@
<string name="selected_lkm">Selected LKM: %s</string>
<string name="save_log">Saglabāt Žurnālus</string>
<string name="log_saved">Logs saved</string>
<string name="status_supported">Supported</string>
<string name="status_not_supported">Not Supported</string>
<string name="status_unknown">Unknown</string>
<string name="sus_su_mode">SuS SU mode:</string>
<!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string>
@@ -172,14 +158,11 @@
<string name="settings_custom_background">Custom App Background</string>
<string name="settings_custom_background_summary">Select an image as background</string>
<string name="settings_card_alpha">Navigation bar transparency</string>
<string name="settings_restore_default">Restore default</string>
<string name="home_android_version">Android version</string>
<string name="home_device_model">Device model</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string>
<string name="using_mksu_manager">You are using the SukiSU Beta manager</string>
<string name="module_install_multiple_confirm">Are you sure you want to install the selected %d modules?</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -210,20 +193,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Gray</string>
<string name="color_yellow">Yellow</string>
<string name="flash_option">Brush Options</string>
<string name="flash_option_tip">Select the file to be flashed</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string>
<string name="root_required">Requires root privileges</string>
<string name="copy_failed">File Copy Failure</string>
<string name="reboot_complete_title">Scrubbing complete</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="failed_reboot">Reboot Failed</string>
<string name="batch_authorization">empower</string>
<string name="batch_cancel_authorization">withdraw</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string>
<string name="kpm_version">Version</string>
@@ -231,7 +208,6 @@
<string name="kpm_uninstall">Uninstall</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string>
<string name="kpm_install">Install</string>
<string name="kpm_install_success">Load of kpm module successful</string>
<string name="kpm_install_failed">Load of kpm module failed</string>
<string name="kpm_args">Parameters</string>
@@ -245,8 +221,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string>
<string name="not_supported">Unsupported</string>
<string name="supported">Supported</string>
<string name="home_kpm_module">"Number of KPM modules: %d "</string>
<string name="kpm_invalid_file">Invalid KPM file</string>
<string name="kernel_patched">Kernel not patched</string>
<string name="kernel_not_enabled">Kernel not configured</string>
<string name="custom_settings">Custom settings</string>
@@ -254,19 +228,13 @@
<string name="kpm_install_mode_load">Load</string>
<string name="kpm_install_mode_embed">Embed</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string>
<string name="log_failed_to_check_module_file">Failed to check module file existence</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string>
<string name="confirm_uninstall_title">Confirm uninstallation</string>
<string name="confirm_uninstall_confirm">Uninstall</string>
<string name="confirm_uninstall_dismiss">Cancel</string>
<string name="theme_color">Theme Color</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string>
<string name="image_editor_title">Adjust background image</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string>
<string name="background_image_error">Could not load image</string>
<string name="reprovision">Reprovision</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -302,12 +270,7 @@
<string name="configuration">Configure</string>
<string name="app_settings">Application Settings</string>
<string name="tools">Tools</string>
<string name="currently_selected">Currently</string>
<!-- String resources used in SuperUser -->
<string name="clear">Removals</string>
<string name="apps_with_root">Applications with root privileges</string>
<string name="apps_with_custom_profile">Applications with customized configurations</string>
<string name="other_apps">Applications with unchanged defaults</string>
<string name="no_apps_found">Application not found</string>
<string name="selinux_enabled_toast">SELinux Enabled</string>
<string name="selinux_disabled_toast">SELinux Disabled</string>
@@ -315,13 +278,13 @@
<string name="advanced_settings">Advanced Settings</string>
<string name="appearance_settings">Customize the toolbar</string>
<string name="back">Comeback</string>
<string name="expand">Be in full swing</string>
<string name="collapse">put away</string>
<string name="susfs_enabled">SuSFS enabled</string>
<string name="susfs_disabled">SuSFS disabled</string>
<string name="background_set_success">Background set successfully</string>
<string name="background_removed">Removed custom backgrounds</string>
<string name="root_require_for_install">Requires root privileges</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string>
@@ -333,7 +296,6 @@
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI setting</string>
<string name="app_dpi_title">Applied DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
<string name="dpi_size_small">Small </string>
@@ -351,16 +313,6 @@
<string name="language_follow_system">Follow System</string>
<string name="language_changed">Language changed, restarting to apply changes</string>
<string name="settings_card_dim">Card Darkness Adjustment</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="scroll_to_top_description">Scroll to top</string>
<string name="scroll_to_bottom_description">Scroll to the bottom</string>
<string name="authorized">authorized</string>
<string name="unauthorized">unauthorized</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Disable custom uninstallation module</string>
<!-- Flash related -->
<string name="error_code">error code</string>
<string name="check_log">Please check the log</string>
@@ -368,4 +320,51 @@
<string name="module_failed_count">%d Failed to install a new module</string>
<string name="module_download_error">Module download failed</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">Noklikšķiniet, lai instalētu</string>
<string name="home_working">Darbojas</string>
<string name="home_working_version">Versija: %d</string>
<string name="home_superuser_count">Superlietotāji: %d</string>
<string name="home_module_count">Moduļi: %d</string>
<string name="home_unsupported">Neatbalstīts</string>
<string name="home_unsupported_reason">KernelSU atbalsta tikai GKI kodolus</string>
<string name="home_kernel">Kodols</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS Version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">Pārvaldnieka versija</string>
<string name="home_fingerprint">Pirkstu nospiedums</string>
<string name="home_selinux_status">SELinux statuss</string>
<string name="selinux_status_disabled">Atspējots</string>
<string name="selinux_status_enforcing">Izpildīšana</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="uninstall">Atinstalēt</string>
<string name="restore">Restore</string>
<string name="module_install">Instalēt</string>
<string name="install">Instalēt</string>
<string name="reboot">Restartēt</string>
@@ -61,10 +55,6 @@
<string name="profile_template">Veidne</string>
<string name="profile_custom">Pielāgots</string>
<string name="profile_name">Profila vārds</string>
<string name="profile_namespace">Mount nosaukumvieta</string>
<string name="profile_namespace_inherited">Mantots</string>
<string name="profile_namespace_global">Globāli</string>
<string name="profile_namespace_individual">Individuāls</string>
<string name="profile_groups">Grupas</string>
<string name="profile_capabilities">Iespējas</string>
<string name="profile_selinux_context">SELinux konteksts</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Automātiski pārbaudīt atjauninājumus atverot aplikāciju</string>
<string name="grant_root_failed">Neizdevās piešķirt sakni!</string>
<string name="action">Action</string>
<string name="open">Atvērt</string>
<string name="close">Close</string>
<string name="enable_web_debugging">Iespējot WebView atkļūdošanu</string>
<string name="enable_web_debugging_summary">Var izmantot WebUI atkļūdošanai, lūdzu, izmantot tikai tad, kad tas ir nepieciešams.</string>
@@ -138,9 +127,6 @@
<string name="selected_lkm">Izvēlētais lkm: %s</string>
<string name="save_log">Išsaugoti Žurnalus</string>
<string name="log_saved">Logs saved</string>
<string name="status_supported">Supported</string>
<string name="status_not_supported">Not Supported</string>
<string name="status_unknown">Unknown</string>
<string name="sus_su_mode">SuS SU mode:</string>
<!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string>
@@ -174,14 +160,11 @@
<string name="settings_custom_background">Custom App Background</string>
<string name="settings_custom_background_summary">Select an image as background</string>
<string name="settings_card_alpha">Navigation bar transparency</string>
<string name="settings_restore_default">Restore default</string>
<string name="home_android_version">Android version</string>
<string name="home_device_model">Device model</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string>
<string name="using_mksu_manager">You are using the SukiSU Beta manager</string>
<string name="module_install_multiple_confirm">Are you sure you want to install the selected %d modules?</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -212,20 +195,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Gray</string>
<string name="color_yellow">Yellow</string>
<string name="flash_option">Brush Options</string>
<string name="flash_option_tip">Select the file to be flashed</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string>
<string name="root_required">Requires root privileges</string>
<string name="copy_failed">File Copy Failure</string>
<string name="reboot_complete_title">Scrubbing complete</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="failed_reboot">Reboot Failed</string>
<string name="batch_authorization">empower</string>
<string name="batch_cancel_authorization">withdraw</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string>
<string name="kpm_version">Version</string>
@@ -233,7 +210,6 @@
<string name="kpm_uninstall">Uninstall</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string>
<string name="kpm_install">Install</string>
<string name="kpm_install_success">Load of kpm module successful</string>
<string name="kpm_install_failed">Load of kpm module failed</string>
<string name="kpm_args">Parameters</string>
@@ -247,8 +223,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string>
<string name="not_supported">Unsupported</string>
<string name="supported">Supported</string>
<string name="home_kpm_module">"Number of KPM modules: %d "</string>
<string name="kpm_invalid_file">Invalid KPM file</string>
<string name="kernel_patched">Kernel not patched</string>
<string name="kernel_not_enabled">Kernel not configured</string>
<string name="custom_settings">Custom settings</string>
@@ -256,19 +230,13 @@
<string name="kpm_install_mode_load">Load</string>
<string name="kpm_install_mode_embed">Embed</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string>
<string name="log_failed_to_check_module_file">Failed to check module file existence</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string>
<string name="confirm_uninstall_title">Confirm uninstallation</string>
<string name="confirm_uninstall_confirm">Uninstall</string>
<string name="confirm_uninstall_dismiss">Cancel</string>
<string name="theme_color">Theme Color</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string>
<string name="image_editor_title">Adjust background image</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string>
<string name="background_image_error">Could not load image</string>
<string name="reprovision">Reprovision</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -304,12 +272,7 @@
<string name="configuration">Configure</string>
<string name="app_settings">Application Settings</string>
<string name="tools">Tools</string>
<string name="currently_selected">Currently</string>
<!-- String resources used in SuperUser -->
<string name="clear">Removals</string>
<string name="apps_with_root">Applications with root privileges</string>
<string name="apps_with_custom_profile">Applications with customized configurations</string>
<string name="other_apps">Applications with unchanged defaults</string>
<string name="no_apps_found">Application not found</string>
<string name="selinux_enabled_toast">SELinux Enabled</string>
<string name="selinux_disabled_toast">SELinux Disabled</string>
@@ -317,13 +280,13 @@
<string name="advanced_settings">Advanced Settings</string>
<string name="appearance_settings">Customize the toolbar</string>
<string name="back">Comeback</string>
<string name="expand">Be in full swing</string>
<string name="collapse">put away</string>
<string name="susfs_enabled">SuSFS enabled</string>
<string name="susfs_disabled">SuSFS disabled</string>
<string name="background_set_success">Background set successfully</string>
<string name="background_removed">Removed custom backgrounds</string>
<string name="root_require_for_install">Requires root privileges</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string>
@@ -335,7 +298,6 @@
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI setting</string>
<string name="app_dpi_title">Applied DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
<string name="dpi_size_small">Small </string>
@@ -353,16 +315,6 @@
<string name="language_follow_system">Follow System</string>
<string name="language_changed">Language changed, restarting to apply changes</string>
<string name="settings_card_dim">Card Darkness Adjustment</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="scroll_to_top_description">Scroll to top</string>
<string name="scroll_to_bottom_description">Scroll to the bottom</string>
<string name="authorized">authorized</string>
<string name="unauthorized">unauthorized</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Disable custom uninstallation module</string>
<!-- Flash related -->
<string name="error_code">error code</string>
<string name="check_log">Please check the log</string>
@@ -370,4 +322,51 @@
<string name="module_failed_count">%d Failed to install a new module</string>
<string name="module_download_error">Module download failed</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">इंस्टॉल साठी क्लिक करा</string>
<string name="home_working">कार्यरत</string>
<string name="home_working_version">आवृत्ती: %d</string>
<string name="home_superuser_count">सुपरयूझर: %d</string>
<string name="home_module_count">मॉड्यूल्स: %d</string>
<string name="home_unsupported">असमर्थित</string>
<string name="home_unsupported_reason">KernelSU आता फक्त GKI कर्नलचे समर्थन करते</string>
<string name="home_kernel">कर्नल</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS Version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">व्यवस्थापक आवृत्ती</string>
<string name="home_fingerprint">फिंगरप्रिंट</string>
<string name="home_selinux_status">SELinux स्थिती</string>
<string name="selinux_status_disabled">अक्षम</string>
<string name="selinux_status_enforcing">एनफोर्सिंग</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="uninstall">विस्थापित करा</string>
<string name="restore">Restore</string>
<string name="module_install">स्थापित करा</string>
<string name="install">स्थापित करा</string>
<string name="reboot">रीबूट करा</string>
@@ -61,10 +55,6 @@
<string name="profile_template">साचा</string>
<string name="profile_custom">कस्टम</string>
<string name="profile_name">प्रोफाइल नाव</string>
<string name="profile_namespace">माउंट नेमस्पेस</string>
<string name="profile_namespace_inherited">इनहेरीटेड</string>
<string name="profile_namespace_global">जागतिक</string>
<string name="profile_namespace_individual">वैयक्तिक</string>
<string name="profile_groups">गट</string>
<string name="profile_capabilities">क्षमता</string>
<string name="profile_selinux_context">SELinux संदर्भ</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Automatically check for updates when opening the app</string>
<string name="grant_root_failed">Failed to grant root!</string>
<string name="action">Action</string>
<string name="open">Open</string>
<string name="close">Close</string>
<string name="enable_web_debugging">Enable WebView debugging</string>
<string name="enable_web_debugging_summary">Can be used to debug WebUI. Please enable only when needed.</string>
@@ -136,9 +125,6 @@
<string name="selected_lkm">Selected LKM: %s</string>
<string name="save_log">लॉग जतन करा</string>
<string name="log_saved">Logs saved</string>
<string name="status_supported">Supported</string>
<string name="status_not_supported">Not Supported</string>
<string name="status_unknown">Unknown</string>
<string name="sus_su_mode">SuS SU mode:</string>
<!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string>
@@ -172,14 +158,11 @@
<string name="settings_custom_background">Custom App Background</string>
<string name="settings_custom_background_summary">Select an image as background</string>
<string name="settings_card_alpha">Navigation bar transparency</string>
<string name="settings_restore_default">Restore default</string>
<string name="home_android_version">Android version</string>
<string name="home_device_model">Device model</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string>
<string name="using_mksu_manager">You are using the SukiSU Beta manager</string>
<string name="module_install_multiple_confirm">Are you sure you want to install the selected %d modules?</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -210,20 +193,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Gray</string>
<string name="color_yellow">Yellow</string>
<string name="flash_option">Brush Options</string>
<string name="flash_option_tip">Select the file to be flashed</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string>
<string name="root_required">Requires root privileges</string>
<string name="copy_failed">File Copy Failure</string>
<string name="reboot_complete_title">Scrubbing complete</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="failed_reboot">Reboot Failed</string>
<string name="batch_authorization">empower</string>
<string name="batch_cancel_authorization">withdraw</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string>
<string name="kpm_version">Version</string>
@@ -231,7 +208,6 @@
<string name="kpm_uninstall">Uninstall</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string>
<string name="kpm_install">Install</string>
<string name="kpm_install_success">Load of kpm module successful</string>
<string name="kpm_install_failed">Load of kpm module failed</string>
<string name="kpm_args">Parameters</string>
@@ -245,8 +221,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string>
<string name="not_supported">Unsupported</string>
<string name="supported">Supported</string>
<string name="home_kpm_module">"Number of KPM modules: %d "</string>
<string name="kpm_invalid_file">Invalid KPM file</string>
<string name="kernel_patched">Kernel not patched</string>
<string name="kernel_not_enabled">Kernel not configured</string>
<string name="custom_settings">Custom settings</string>
@@ -254,19 +228,13 @@
<string name="kpm_install_mode_load">Load</string>
<string name="kpm_install_mode_embed">Embed</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string>
<string name="log_failed_to_check_module_file">Failed to check module file existence</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string>
<string name="confirm_uninstall_title">Confirm uninstallation</string>
<string name="confirm_uninstall_confirm">Uninstall</string>
<string name="confirm_uninstall_dismiss">Cancel</string>
<string name="theme_color">Theme Color</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string>
<string name="image_editor_title">Adjust background image</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string>
<string name="background_image_error">Could not load image</string>
<string name="reprovision">Reprovision</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -302,12 +270,7 @@
<string name="configuration">Configure</string>
<string name="app_settings">Application Settings</string>
<string name="tools">Tools</string>
<string name="currently_selected">Currently</string>
<!-- String resources used in SuperUser -->
<string name="clear">Removals</string>
<string name="apps_with_root">Applications with root privileges</string>
<string name="apps_with_custom_profile">Applications with customized configurations</string>
<string name="other_apps">Applications with unchanged defaults</string>
<string name="no_apps_found">Application not found</string>
<string name="selinux_enabled_toast">SELinux Enabled</string>
<string name="selinux_disabled_toast">SELinux Disabled</string>
@@ -315,13 +278,13 @@
<string name="advanced_settings">Advanced Settings</string>
<string name="appearance_settings">Customize the toolbar</string>
<string name="back">Comeback</string>
<string name="expand">Be in full swing</string>
<string name="collapse">put away</string>
<string name="susfs_enabled">SuSFS enabled</string>
<string name="susfs_disabled">SuSFS disabled</string>
<string name="background_set_success">Background set successfully</string>
<string name="background_removed">Removed custom backgrounds</string>
<string name="root_require_for_install">Requires root privileges</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string>
@@ -333,7 +296,6 @@
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI setting</string>
<string name="app_dpi_title">Applied DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
<string name="dpi_size_small">Small </string>
@@ -351,16 +313,6 @@
<string name="language_follow_system">Follow System</string>
<string name="language_changed">Language changed, restarting to apply changes</string>
<string name="settings_card_dim">Card Darkness Adjustment</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="scroll_to_top_description">Scroll to top</string>
<string name="scroll_to_bottom_description">Scroll to the bottom</string>
<string name="authorized">authorized</string>
<string name="unauthorized">unauthorized</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Disable custom uninstallation module</string>
<!-- Flash related -->
<string name="error_code">error code</string>
<string name="check_log">Please check the log</string>
@@ -368,4 +320,51 @@
<string name="module_failed_count">%d Failed to install a new module</string>
<string name="module_download_error">Module download failed</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">Tekan untuk memasang</string>
<string name="home_working">Berjalan</string>
<string name="home_working_version">Versi: %d</string>
<string name="home_superuser_count">Superusers: %d</string>
<string name="home_module_count">Modul: %d</string>
<string name="home_unsupported">Tidak Disokong</string>
<string name="home_unsupported_reason">KernelSU ketika ini hanya menyokong kernel GKI</string>
<string name="home_kernel">Kernel</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS Version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">Versi manager</string>
<string name="home_fingerprint">Cap Jari</string>
<string name="home_selinux_status">Status SELinux</string>
<string name="selinux_status_disabled">Lumpuhkan</string>
<string name="selinux_status_enforcing">Enforcing</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="uninstall">Padam</string>
<string name="restore">Restore</string>
<string name="module_install">Pasang</string>
<string name="install">Pasang</string>
<string name="reboot">Reboot</string>
@@ -61,10 +55,6 @@
<string name="profile_template">Template</string>
<string name="profile_custom">Custom</string>
<string name="profile_name">Profile name</string>
<string name="profile_namespace">Mount namespace</string>
<string name="profile_namespace_inherited">Inherited</string>
<string name="profile_namespace_global">Global</string>
<string name="profile_namespace_individual">Individual</string>
<string name="profile_groups">Groups</string>
<string name="profile_capabilities">Capabilities</string>
<string name="profile_selinux_context">SELinux context</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Automatically check for updates when opening the app</string>
<string name="grant_root_failed">Failed to grant root!</string>
<string name="action">Action</string>
<string name="open">Open</string>
<string name="close">Close</string>
<string name="enable_web_debugging">Enable WebView debugging</string>
<string name="enable_web_debugging_summary">Can be used to debug WebUI. Please enable only when needed.</string>
@@ -136,9 +125,6 @@
<string name="selected_lkm">Selected LKM: %s</string>
<string name="save_log">Simpan Log</string>
<string name="log_saved">Logs saved</string>
<string name="status_supported">Supported</string>
<string name="status_not_supported">Not Supported</string>
<string name="status_unknown">Unknown</string>
<string name="sus_su_mode">SuS SU mode:</string>
<!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string>
@@ -172,14 +158,11 @@
<string name="settings_custom_background">Custom App Background</string>
<string name="settings_custom_background_summary">Select an image as background</string>
<string name="settings_card_alpha">Navigation bar transparency</string>
<string name="settings_restore_default">Restore default</string>
<string name="home_android_version">Android version</string>
<string name="home_device_model">Device model</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string>
<string name="using_mksu_manager">You are using the SukiSU Beta manager</string>
<string name="module_install_multiple_confirm">Are you sure you want to install the selected %d modules?</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -210,20 +193,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Gray</string>
<string name="color_yellow">Yellow</string>
<string name="flash_option">Brush Options</string>
<string name="flash_option_tip">Select the file to be flashed</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string>
<string name="root_required">Requires root privileges</string>
<string name="copy_failed">File Copy Failure</string>
<string name="reboot_complete_title">Scrubbing complete</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="failed_reboot">Reboot Failed</string>
<string name="batch_authorization">empower</string>
<string name="batch_cancel_authorization">withdraw</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string>
<string name="kpm_version">Version</string>
@@ -231,7 +208,6 @@
<string name="kpm_uninstall">Uninstall</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string>
<string name="kpm_install">Install</string>
<string name="kpm_install_success">Load of kpm module successful</string>
<string name="kpm_install_failed">Load of kpm module failed</string>
<string name="kpm_args">Parameters</string>
@@ -245,8 +221,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string>
<string name="not_supported">Unsupported</string>
<string name="supported">Supported</string>
<string name="home_kpm_module">"Number of KPM modules: %d "</string>
<string name="kpm_invalid_file">Invalid KPM file</string>
<string name="kernel_patched">Kernel not patched</string>
<string name="kernel_not_enabled">Kernel not configured</string>
<string name="custom_settings">Custom settings</string>
@@ -254,19 +228,13 @@
<string name="kpm_install_mode_load">Load</string>
<string name="kpm_install_mode_embed">Embed</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string>
<string name="log_failed_to_check_module_file">Failed to check module file existence</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string>
<string name="confirm_uninstall_title">Confirm uninstallation</string>
<string name="confirm_uninstall_confirm">Uninstall</string>
<string name="confirm_uninstall_dismiss">Cancel</string>
<string name="theme_color">Theme Color</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string>
<string name="image_editor_title">Adjust background image</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string>
<string name="background_image_error">Could not load image</string>
<string name="reprovision">Reprovision</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -302,12 +270,7 @@
<string name="configuration">Configure</string>
<string name="app_settings">Application Settings</string>
<string name="tools">Tools</string>
<string name="currently_selected">Currently</string>
<!-- String resources used in SuperUser -->
<string name="clear">Removals</string>
<string name="apps_with_root">Applications with root privileges</string>
<string name="apps_with_custom_profile">Applications with customized configurations</string>
<string name="other_apps">Applications with unchanged defaults</string>
<string name="no_apps_found">Application not found</string>
<string name="selinux_enabled_toast">SELinux Enabled</string>
<string name="selinux_disabled_toast">SELinux Disabled</string>
@@ -315,13 +278,13 @@
<string name="advanced_settings">Advanced Settings</string>
<string name="appearance_settings">Customize the toolbar</string>
<string name="back">Comeback</string>
<string name="expand">Be in full swing</string>
<string name="collapse">put away</string>
<string name="susfs_enabled">SuSFS enabled</string>
<string name="susfs_disabled">SuSFS disabled</string>
<string name="background_set_success">Background set successfully</string>
<string name="background_removed">Removed custom backgrounds</string>
<string name="root_require_for_install">Requires root privileges</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string>
@@ -333,7 +296,6 @@
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI setting</string>
<string name="app_dpi_title">Applied DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
<string name="dpi_size_small">Small </string>
@@ -351,16 +313,6 @@
<string name="language_follow_system">Follow System</string>
<string name="language_changed">Language changed, restarting to apply changes</string>
<string name="settings_card_dim">Card Darkness Adjustment</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="scroll_to_top_description">Scroll to top</string>
<string name="scroll_to_bottom_description">Scroll to the bottom</string>
<string name="authorized">authorized</string>
<string name="unauthorized">unauthorized</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Disable custom uninstallation module</string>
<!-- Flash related -->
<string name="error_code">error code</string>
<string name="check_log">Please check the log</string>
@@ -368,4 +320,51 @@
<string name="module_failed_count">%d Failed to install a new module</string>
<string name="module_download_error">Module download failed</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">Klik om te installeren</string>
<string name="home_working">Werkend</string>
<string name="home_working_version">Versie: %d</string>
<string name="home_superuser_count">Supergebruikers: %d</string>
<string name="home_module_count">Modules: %d</string>
<string name="home_unsupported">Niet ondersteund</string>
<string name="home_unsupported_reason">KernelSU ondersteunt alleen GKI kernels</string>
<string name="home_kernel">Kernel</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS Version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">Manager versie</string>
<string name="home_fingerprint">Fingerprint</string>
<string name="home_selinux_status">SELinux status</string>
<string name="selinux_status_disabled">Uitgeschakeld</string>
<string name="selinux_status_enforcing">Afgedwongen</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Sorteren (actie eerst)</string>
<string name="module_sort_enabled_first">Sorteren (eerst ingeschakeld)</string>
<string name="uninstall">Verwijderen</string>
<string name="restore">Restore</string>
<string name="module_install">Installeren</string>
<string name="install">Installeren</string>
<string name="reboot">Herstart</string>
@@ -61,10 +55,6 @@
<string name="profile_template">Sjabloon</string>
<string name="profile_custom">Aangepast</string>
<string name="profile_name">Profiel naam</string>
<string name="profile_namespace">Koppel naamruimte</string>
<string name="profile_namespace_inherited">Overgenomen</string>
<string name="profile_namespace_global">Globaal</string>
<string name="profile_namespace_individual">Individuëel</string>
<string name="profile_groups">Groepen</string>
<string name="profile_capabilities">Mogelijkheden</string>
<string name="profile_selinux_context">SELinux context</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Controleer automatisch op updates bij het openen van de app</string>
<string name="grant_root_failed">Kan geen root verlenen!</string>
<string name="action">Actie</string>
<string name="open">Open</string>
<string name="close">Close</string>
<string name="enable_web_debugging">Schakel WebView-foutopsporing</string>
<string name="enable_web_debugging_summary">Kan worden gebruikt om WebUI te debuggen. Schakel dit alleen in als dat nodig is.</string>
@@ -138,9 +127,6 @@
<string name="selected_lkm">Geselecteerde LKM: %s</string>
<string name="save_log">Logboeken Opslaan</string>
<string name="log_saved">Logs opgeslagen</string>
<string name="status_supported">Supported</string>
<string name="status_not_supported">Not Supported</string>
<string name="status_unknown">Unknown</string>
<string name="sus_su_mode">SuS SU mode:</string>
<!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string>
@@ -174,14 +160,11 @@
<string name="settings_custom_background">Custom App Background</string>
<string name="settings_custom_background_summary">Select an image as background</string>
<string name="settings_card_alpha">Navigation bar transparency</string>
<string name="settings_restore_default">Restore default</string>
<string name="home_android_version">Android version</string>
<string name="home_device_model">Device model</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string>
<string name="using_mksu_manager">You are using the SukiSU Beta manager</string>
<string name="module_install_multiple_confirm">Are you sure you want to install the selected %d modules?</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -212,20 +195,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Gray</string>
<string name="color_yellow">Yellow</string>
<string name="flash_option">Brush Options</string>
<string name="flash_option_tip">Select the file to be flashed</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string>
<string name="root_required">Requires root privileges</string>
<string name="copy_failed">File Copy Failure</string>
<string name="reboot_complete_title">Scrubbing complete</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="failed_reboot">Reboot Failed</string>
<string name="batch_authorization">empower</string>
<string name="batch_cancel_authorization">withdraw</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string>
<string name="kpm_version">Version</string>
@@ -233,7 +210,6 @@
<string name="kpm_uninstall">Uninstall</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string>
<string name="kpm_install">Install</string>
<string name="kpm_install_success">Load of kpm module successful</string>
<string name="kpm_install_failed">Load of kpm module failed</string>
<string name="kpm_args">Parameters</string>
@@ -247,8 +223,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string>
<string name="not_supported">Unsupported</string>
<string name="supported">Supported</string>
<string name="home_kpm_module">"Number of KPM modules: %d "</string>
<string name="kpm_invalid_file">Invalid KPM file</string>
<string name="kernel_patched">Kernel not patched</string>
<string name="kernel_not_enabled">Kernel not configured</string>
<string name="custom_settings">Custom settings</string>
@@ -256,19 +230,13 @@
<string name="kpm_install_mode_load">Load</string>
<string name="kpm_install_mode_embed">Embed</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string>
<string name="log_failed_to_check_module_file">Failed to check module file existence</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string>
<string name="confirm_uninstall_title">Confirm uninstallation</string>
<string name="confirm_uninstall_confirm">Uninstall</string>
<string name="confirm_uninstall_dismiss">Cancel</string>
<string name="theme_color">Theme Color</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string>
<string name="image_editor_title">Adjust background image</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string>
<string name="background_image_error">Could not load image</string>
<string name="reprovision">Reprovision</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -304,12 +272,7 @@
<string name="configuration">Configure</string>
<string name="app_settings">Application Settings</string>
<string name="tools">Tools</string>
<string name="currently_selected">Currently</string>
<!-- String resources used in SuperUser -->
<string name="clear">Removals</string>
<string name="apps_with_root">Applications with root privileges</string>
<string name="apps_with_custom_profile">Applications with customized configurations</string>
<string name="other_apps">Applications with unchanged defaults</string>
<string name="no_apps_found">Application not found</string>
<string name="selinux_enabled_toast">SELinux Enabled</string>
<string name="selinux_disabled_toast">SELinux Disabled</string>
@@ -317,13 +280,13 @@
<string name="advanced_settings">Advanced Settings</string>
<string name="appearance_settings">Customize the toolbar</string>
<string name="back">Comeback</string>
<string name="expand">Be in full swing</string>
<string name="collapse">put away</string>
<string name="susfs_enabled">SuSFS enabled</string>
<string name="susfs_disabled">SuSFS disabled</string>
<string name="background_set_success">Background set successfully</string>
<string name="background_removed">Removed custom backgrounds</string>
<string name="root_require_for_install">Requires root privileges</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string>
@@ -335,7 +298,6 @@
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI setting</string>
<string name="app_dpi_title">Applied DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
<string name="dpi_size_small">Small </string>
@@ -353,16 +315,6 @@
<string name="language_follow_system">Follow System</string>
<string name="language_changed">Language changed, restarting to apply changes</string>
<string name="settings_card_dim">Card Darkness Adjustment</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="scroll_to_top_description">Scroll to top</string>
<string name="scroll_to_bottom_description">Scroll to the bottom</string>
<string name="authorized">authorized</string>
<string name="unauthorized">unauthorized</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Disable custom uninstallation module</string>
<!-- Flash related -->
<string name="error_code">error code</string>
<string name="check_log">Please check the log</string>
@@ -370,4 +322,51 @@
<string name="module_failed_count">%d Failed to install a new module</string>
<string name="module_download_error">Module download failed</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">Kliknij, aby zainstalować</string>
<string name="home_working">Działa</string>
<string name="home_working_version">Wersja: %d</string>
<string name="home_superuser_count">Superużytkownicy: %d</string>
<string name="home_module_count">Moduły: %d</string>
<string name="home_unsupported">Nieobsługiwany</string>
<string name="home_unsupported_reason">KernelSU obsługuje obecnie tylko jądra GKI</string>
<string name="home_kernel">Jądro</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS Version</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">Wersja menedżera</string>
<string name="home_fingerprint">Odcisk</string>
<string name="home_selinux_status">Status SELinux</string>
<string name="selinux_status_disabled">Wyłączony</string>
<string name="selinux_status_enforcing">Enforcing</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Sortuj (najpierw działania)</string>
<string name="module_sort_enabled_first">Sortuj (najpierw włączone)</string>
<string name="uninstall">Odinstaluj</string>
<string name="restore">Restore</string>
<string name="module_install">Instaluj</string>
<string name="install">Instaluj</string>
<string name="reboot">Uruchom ponownie</string>
@@ -61,10 +55,6 @@
<string name="profile_template">Szablon</string>
<string name="profile_custom">Własny</string>
<string name="profile_name">Nazwa profilu</string>
<string name="profile_namespace">Przestrzeń nazw montowania</string>
<string name="profile_namespace_inherited">Odziedziczona</string>
<string name="profile_namespace_global">Globalna</string>
<string name="profile_namespace_individual">Indywidualna</string>
<string name="profile_groups">Grupy</string>
<string name="profile_capabilities">Uprawnienia</string>
<string name="profile_selinux_context">Kontekst SELinux</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Wyszukuj aktualizacje automatycznie przy otwieraniu aplikacji</string>
<string name="grant_root_failed">Nie udało się przyznać roota!</string>
<string name="action">Akcja</string>
<string name="open">Otwórz</string>
<string name="close">Close</string>
<string name="enable_web_debugging">Włącz debugowanie WebView</string>
<string name="enable_web_debugging_summary">Może być użyte do debugowania WebUI. Włącz tylko w razie potrzeby.</string>
@@ -138,9 +127,6 @@
<string name="selected_lkm">Wybrano LKM: %s</string>
<string name="save_log">Zapisz dzienniki</string>
<string name="log_saved">Dzienniki zapisane</string>
<string name="status_supported">Supported</string>
<string name="status_not_supported">Not Supported</string>
<string name="status_unknown">Unknown</string>
<string name="sus_su_mode">SuS SU mode:</string>
<!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string>
@@ -174,14 +160,11 @@
<string name="settings_custom_background">Custom App Background</string>
<string name="settings_custom_background_summary">Select an image as background</string>
<string name="settings_card_alpha">Navigation bar transparency</string>
<string name="settings_restore_default">Restore default</string>
<string name="home_android_version">Android version</string>
<string name="home_device_model">Device model</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
<string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string>
<string name="using_mksu_manager">You are using the SukiSU Beta manager</string>
<string name="module_install_multiple_confirm">Are you sure you want to install the selected %d modules?</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -212,20 +195,14 @@
<string name="color_pink">Pink</string>
<string name="color_gray">Gray</string>
<string name="color_yellow">Yellow</string>
<string name="flash_option">Brush Options</string>
<string name="flash_option_tip">Select the file to be flashed</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string>
<string name="root_required">Requires root privileges</string>
<string name="copy_failed">File Copy Failure</string>
<string name="reboot_complete_title">Scrubbing complete</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="failed_reboot">Reboot Failed</string>
<string name="batch_authorization">empower</string>
<string name="batch_cancel_authorization">withdraw</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string>
<string name="kpm_version">Version</string>
@@ -233,7 +210,6 @@
<string name="kpm_uninstall">Uninstall</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string>
<string name="kpm_install">Install</string>
<string name="kpm_install_success">Load of kpm module successful</string>
<string name="kpm_install_failed">Load of kpm module failed</string>
<string name="kpm_args">Parameters</string>
@@ -247,8 +223,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string>
<string name="not_supported">Unsupported</string>
<string name="supported">Supported</string>
<string name="home_kpm_module">"Number of KPM modules: %d "</string>
<string name="kpm_invalid_file">Invalid KPM file</string>
<string name="kernel_patched">Kernel not patched</string>
<string name="kernel_not_enabled">Kernel not configured</string>
<string name="custom_settings">Custom settings</string>
@@ -256,19 +230,13 @@
<string name="kpm_install_mode_load">Load</string>
<string name="kpm_install_mode_embed">Embed</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string>
<string name="log_failed_to_check_module_file">Failed to check module file existence</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string>
<string name="confirm_uninstall_title">Confirm uninstallation</string>
<string name="confirm_uninstall_confirm">Uninstall</string>
<string name="confirm_uninstall_dismiss">Cancel</string>
<string name="theme_color">Theme Color</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string>
<string name="image_editor_title">Adjust background image</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string>
<string name="background_image_error">Could not load image</string>
<string name="reprovision">Reprovision</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -304,12 +272,7 @@
<string name="configuration">Configure</string>
<string name="app_settings">Application Settings</string>
<string name="tools">Tools</string>
<string name="currently_selected">Currently</string>
<!-- String resources used in SuperUser -->
<string name="clear">Removals</string>
<string name="apps_with_root">Applications with root privileges</string>
<string name="apps_with_custom_profile">Applications with customized configurations</string>
<string name="other_apps">Applications with unchanged defaults</string>
<string name="no_apps_found">Application not found</string>
<string name="selinux_enabled_toast">SELinux Enabled</string>
<string name="selinux_disabled_toast">SELinux Disabled</string>
@@ -317,13 +280,13 @@
<string name="advanced_settings">Advanced Settings</string>
<string name="appearance_settings">Customize the toolbar</string>
<string name="back">Comeback</string>
<string name="expand">Be in full swing</string>
<string name="collapse">put away</string>
<string name="susfs_enabled">SuSFS enabled</string>
<string name="susfs_disabled">SuSFS disabled</string>
<string name="background_set_success">Background set successfully</string>
<string name="background_removed">Removed custom backgrounds</string>
<string name="root_require_for_install">Requires root privileges</string>
<string name="icon_switch_title">Alternate icon</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string>
<string name="icon_switched">Icon switched</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string>
@@ -335,7 +298,6 @@
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">DPI setting</string>
<string name="app_dpi_title">Applied DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
<string name="dpi_size_small">Small </string>
@@ -353,16 +315,6 @@
<string name="language_follow_system">Follow System</string>
<string name="language_changed">Language changed, restarting to apply changes</string>
<string name="settings_card_dim">Card Darkness Adjustment</string>
<!-- Super User Related -->
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="scroll_to_top_description">Scroll to top</string>
<string name="scroll_to_bottom_description">Scroll to the bottom</string>
<string name="authorized">authorized</string>
<string name="unauthorized">unauthorized</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<string name="profile_umount_modules_disable">Disable custom uninstallation module</string>
<!-- Flash related -->
<string name="error_code">error code</string>
<string name="check_log">Please check the log</string>
@@ -370,4 +322,51 @@
<string name="module_failed_count">%d Failed to install a new module</string>
<string name="module_download_error">Module download failed</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Top</string>
<string name="scroll_to_bottom">Bottom</string>
<string name="selected">Selected</string>
<string name="select">option</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

View File

@@ -5,13 +5,10 @@
<string name="home_click_to_install">Clique para instalar</string>
<string name="home_working">Em execução</string>
<string name="home_working_version">Versão: %d</string>
<string name="home_superuser_count">SuperUsuários: %d</string>
<string name="home_module_count">Módulos: %d</string>
<string name="home_unsupported">Sem suporte</string>
<string name="home_unsupported_reason">KernelSU suporta apenas kernels GKI agora</string>
<string name="home_kernel">Kernel</string>
<string name="home_manager_version">Versão do gerenciador</string>
<string name="home_fingerprint">Impressão digital</string>
<string name="home_selinux_status">Status do SELinux</string>
<string name="selinux_status_disabled">Desativado</string>
<string name="selinux_status_enforcing">Impondo</string>
@@ -54,10 +51,6 @@
<string name="profile_template">Modelo</string>
<string name="profile_custom">Personalizado</string>
<string name="profile_name">Nome do perfil</string>
<string name="profile_namespace">Montar namespace</string>
<string name="profile_namespace_inherited">Herdado</string>
<string name="profile_namespace_global">Global</string>
<string name="profile_namespace_individual">Individual</string>
<string name="profile_groups">Grupos</string>
<string name="profile_capabilities">Capacidades</string>
<string name="profile_selinux_context">Contexto do SELinux</string>
@@ -102,7 +95,6 @@
<string name="settings_check_update">Verificar por atualização</string>
<string name="settings_check_update_summary">Verifique automaticamente se há atualizações ao abrir o app</string>
<string name="grant_root_failed">Falha ao conceder acesso root!</string>
<string name="open">Abrir</string>
<string name="enable_web_debugging">Ativar depuração do WebView</string>
<string name="enable_web_debugging_summary">Pode ser usado para depurar o WebUI. Por favor, ative somente quando necessário.</string>
<string name="select_file">Selecione um arquivo</string>

View File

@@ -5,16 +5,11 @@
<string name="home_click_to_install">Clique para instalar</string>
<string name="home_working">Funcionando</string>
<string name="home_working_version">Versão: %d</string>
<string name="home_superuser_count">Super Usuário: %d</string>
<string name="home_module_count">Módulos: %d</string>
<string name="home_unsupported">Sem suporte</string>
<string name="home_unsupported_reason">KernelSU suporta apenas kernels GKI agora</string>
<string name="home_kernel">Kernel</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">Versão SuSFS</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_manager_version">Versão do aplicativo</string>
<string name="home_fingerprint">Impressão digital</string>
<string name="home_selinux_status">Status do SELinux</string>
<string name="selinux_status_disabled">Desabilitado</string>
<string name="selinux_status_enforcing">Impondo</string>
@@ -28,7 +23,6 @@
<string name="module_sort_action_first">Ordenar (exceto primeiro)</string>
<string name="module_sort_enabled_first">Ordenar (Habilitado primeiro)</string>
<string name="uninstall">Desinstalar</string>
<string name="restore">Restaurar</string>
<string name="module_install">Instalar</string>
<string name="install">Instalar</string>
<string name="reboot">Reiniciar</string>
@@ -61,10 +55,6 @@
<string name="profile_template">Modelo</string>
<string name="profile_custom">Personalizado</string>
<string name="profile_name">Nome do perfil</string>
<string name="profile_namespace">Montar namespace</string>
<string name="profile_namespace_inherited">Herdado</string>
<string name="profile_namespace_global">Global</string>
<string name="profile_namespace_individual">Individual</string>
<string name="profile_groups">Grupos</string>
<string name="profile_capabilities">Capacidades</string>
<string name="profile_selinux_context">contexto SELinux</string>
@@ -112,7 +102,6 @@
<string name="settings_check_update_summary">Verifique automaticamente se há atualizações ao abrir o app</string>
<string name="grant_root_failed">Falha ao conceder acesso root!</string>
<string name="action">Ações</string>
<string name="open">Abrir</string>
<string name="close">Fechar</string>
<string name="enable_web_debugging">Ativar depuração do WebView</string>
<string name="enable_web_debugging_summary">Pode ser usado para depurar o WebUI. Por favor, ative somente quando necessário.</string>
@@ -136,9 +125,6 @@
<string name="selected_lkm">LKM selecionado: %s</string>
<string name="save_log">Salvar Registros</string>
<string name="log_saved">Registros salvos</string>
<string name="status_supported">Apoie-nos</string>
<string name="status_not_supported">Não Suportado</string>
<string name="status_unknown">Desconhecido</string>
<string name="sus_su_mode">Modo SU SuSU:</string>
<!-- Module related -->
<string name="module_install_confirm">¿confirmar la instalación del módulo %1$s?</string>
@@ -172,14 +158,11 @@
<string name="settings_custom_background">Fundo personalizado do App</string>
<string name="settings_custom_background_summary">Selecione uma imagem como plano de fundo</string>
<string name="settings_card_alpha">Transparência da barra de navegação</string>
<string name="settings_restore_default">Restaurar padrões</string>
<string name="home_android_version">Android Version </string>
<string name="home_device_model">Modelo do aparelho</string>
<string name="su_not_allowed">Conceder superusuário à %s não é permitido</string>
<string name="settings_disable_su">Desativar compatibilidade com su</string>
<string name="settings_disable_su_summary">Temporariamente desativar qualquer aplicativo de obter privilégios de superusuário através do comando Wait su (os processos raiz existentes não serão afetados).</string>
<string name="using_mksu_manager">Você está usando o gerenciador do SukiSU Beta</string>
<string name="module_install_multiple_confirm">Você tem certeza que deseja instalar os módulos %d selecionados?</string>
<string name="module_install_multiple_confirm_with_names">Tem certeza que deseja instalar os seguintes módulos %1$d ? \n\n%2$s</string>
<string name="more_settings">More settings</string>
<string name="selinux">SELinux</string>
@@ -210,20 +193,14 @@
<string name="color_pink">Rosa</string>
<string name="color_gray">Cinza</string>
<string name="color_yellow">Amarelo</string>
<string name="flash_option">Opções do pincel</string>
<string name="flash_option_tip">Selecione o arquivo a ser instalado</string>
<string name="horizon_kernel">Install Anykernel3</string>
<string name="horizon_kernel_summary">Instalar o arquivo kernel AnyKernel3</string>
<string name="root_required">Requer privilégios de superusuário</string>
<string name="copy_failed">Falha ao copiar arquivo</string>
<string name="reboot_complete_title">Esboço completo</string>
<string name="reboot_complete_msg">Reiniciar imediatamente?</string>
<string name="yes">Sim</string>
<string name="no">Não</string>
<string name="failed_reboot">Reinicialização falhou</string>
<string name="batch_authorization">empoderar</string>
<string name="batch_cancel_authorization">retirar</string>
<string name="backup">Backup</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">Não há módulos do kernel instalados neste momento</string>
<string name="kpm_version">Versão</string>
@@ -231,7 +208,6 @@
<string name="kpm_uninstall">Desinstalar</string>
<string name="kpm_uninstall_success">Desinstalado com sucesso</string>
<string name="kpm_uninstall_failed">Falha ao desinstalar</string>
<string name="kpm_install">Instalar</string>
<string name="kpm_install_success">Carregamento do módulo kpm com sucesso</string>
<string name="kpm_install_failed">Falha ao carregar o módulo kpm</string>
<string name="kpm_args">Parâmetros</string>
@@ -245,8 +221,6 @@
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra será uma ramificação relativamente independente da KSU no futuro, mas ainda apreciamos o KernelSU e o MKSU, etc. para suas contribuições!</string>
<string name="not_supported">Sem suporte</string>
<string name="supported">Apoie-nos</string>
<string name="home_kpm_module">"Número de módulos KPM: %d "</string>
<string name="kpm_invalid_file">Arquivo KPM inválido</string>
<string name="kernel_patched">Kernel não corrigido</string>
<string name="kernel_not_enabled">Kernel não configurado</string>
<string name="custom_settings">Configurações personalizadas</string>
@@ -254,19 +228,13 @@
<string name="kpm_install_mode_load">Carga</string>
<string name="kpm_install_mode_embed">Embutir</string>
<string name="kpm_install_mode_description">Por favor seleccione: %1\$s Modo de instalación del Módulo \n\nCarga: Cargar temporalmente el módulo \nInsertar: Instalar permanentemente en el sistema</string>
<string name="log_failed_to_check_module_file">Falha ao verificar a existência do arquivo do módulo</string>
<string name="snackbar_failed_to_check_module_file">Não foi possível verificar se o arquivo do módulo existe</string>
<string name="confirm_uninstall_title">Confirmar Desinstalação</string>
<string name="confirm_uninstall_confirm">Desinstalar</string>
<string name="confirm_uninstall_dismiss">Cancelar</string>
<string name="theme_color">Cor do tema</string>
<string name="invalid_file_type">Tipo de arquivo incorreto! Selecione o arquivo .kpm.</string>
<string name="confirm_uninstall_title_with_filename">Desinstalar</string>
<string name="confirm_uninstall_content">O seguinte KPM será desinstalado: %s</string>
<string name="settings_susfs_toggle_summary">Desative os hooks kprobe criados pelo KernelSU, usando ganchos embutidos em vez disso, o que é semelhante ao método de gancho do kernel GKI.</string>
<string name="image_editor_title">Ajustar imagem de fundo</string>
<string name="image_editor_hint">Use dois dedos para ampliar a imagem e um dedo para arrastá-la para ajustar a posição</string>
<string name="background_image_error">Não foi possível carregar a imagem</string>
<string name="reprovision">Restituição</string>
<!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string>
@@ -289,25 +257,20 @@
<string name="horizon_getting_original_slot">Obtendo o espaço original</string>
<string name="horizon_setting_target_slot">Configurando o slot especificado</string>
<string name="horizon_restoring_original_slot">Restaurar Slot Padrão</string>
<string name="current_slot">Slot Atual%1$s </string>
<string name="current_slot">Slot padrão do sistema atual%1$s </string>
<!-- Error Messages -->
<string name="horizon_copy_failed">Falha ao copiar</string>
<string name="horizon_unknown_error">Você parece estar convertendo de um formato com degradação para&#10;&#10;um sem perdas. Esteja ciente que a perda de qualidade não pode ser desfeita,&#10;&#10;então este processo não melhorará a qualidade do áudio e provavelmente&#10;&#10;aumentará o tamanho do arquivo. Continuar assim mesmo?</string>
<string name="flash_failed_message">Flash falhou</string>
<!-- lkm/gki install -->
<string name="Lkm_install_methods">LKM reparo/instalação</string>
<string name="GKI_install_methods">Flashing AnyKernel3</string>
<string name="GKI_install_methods">Flasheando kernel</string>
<string name="kernel_version_log">Kernel</string>
<string name="tool_version_log">Usando a ferramenta de correção%1$s</string>
<string name="configuration">Configurar</string>
<string name="app_settings">Configurações Do Aplicativo</string>
<string name="tools">Ferramentas</string>
<string name="currently_selected">Atual</string>
<!-- String resources used in SuperUser -->
<string name="clear">Remoções</string>
<string name="apps_with_root">Aplicativos com privilégios de superusuário</string>
<string name="apps_with_custom_profile">Aplicativos com configurações personalizadas</string>
<string name="other_apps">Aplicações com padrões não alterados</string>
<string name="no_apps_found">Aplicativo não encontrado</string>
<string name="selinux_enabled_toast">SELinux habilitado</string>
<string name="selinux_disabled_toast">SELinux Desativado</string>
@@ -315,25 +278,24 @@
<string name="advanced_settings">Configurações Avançadas</string>
<string name="appearance_settings">Personaliza a barra de ferramentas.</string>
<string name="back">Retorno</string>
<string name="expand">Esteja em pleno balanço</string>
<string name="collapse">jogou fora</string>
<string name="susfs_enabled">SuSFS habilitado</string>
<string name="susfs_disabled">SuSFS desativado</string>
<string name="background_set_success">Fundo definido com sucesso</string>
<string name="background_removed">Remover</string>
<string name="root_require_for_install">Requer privilégios de superusuário</string>
<string name="icon_switch_title">Ícone alternativo</string>
<string name="icon_switch_summary">Alterar o ícone do launcher para o ícone do KernelSU.</string>
<string name="icon_switched">Ícone alterado</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Exibir função KPM</string>
<string name="show_kpm_info_summary">Exibir informações e funções do KPM na barra inicial e inferior (Precisa reabrir o aplicativo)</string>
<string name="show_kpm_info_summary">Oculta as informações e funções do KPM na barra inicial e inferior</string>
<!-- Webui X settings -->
<string name="use_webuix">Select the WebUI engine to use</string>
<string name="engine_auto_select">Automatic Selection</string>
<string name="engine_force_webuix">Force the use of WebUI X</string>
<string name="engine_force_ksu">Mandatory use of KSU WebUI</string>
<string name="use_webuix">Selecione o mecanismo de WebUI para usar</string>
<string name="engine_auto_select">Seleção automática</string>
<string name="engine_force_webuix">Forçar o uso de WebUI X</string>
<string name="engine_force_ksu">Uso obrigatório do KSU WebUI</string>
<string name="use_webuix_eruda">Injetar Eruda na WebUI X</string>
<string name="use_webuix_eruda_summary">Injetar um console de depuração na WebUI X para facilitar a depuração. Requer depuração da web para estar ligada.</string>
<!-- DPI setting related strings -->
<string name="dpi_settings">Configuração de DPI</string>
<string name="app_dpi_title">DPI aplicado</string>
<string name="app_dpi_summary">Ajustar a densidade de exibição da tela apenas para o aplicativo atual</string>
<string name="dpi_size_small">Pequeno </string>
@@ -351,16 +313,6 @@
<string name="language_follow_system">Padrão do sistema</string>
<string name="language_changed">Idioma alterado, reiniciando para aplicar as alterações</string>
<string name="settings_card_dim">Ajuste da escuridão do cartão</string>
<!-- Super User Related -->
<string name="scroll_to_top">Mais votados</string>
<string name="scroll_to_bottom">Parte Inferior</string>
<string name="scroll_to_top_description">Rolar para o topo</string>
<string name="scroll_to_bottom_description">Role até o final</string>
<string name="authorized">autorizado</string>
<string name="unauthorized">Não autorizado</string>
<string name="selected">Selecionado</string>
<string name="select">opção</string>
<string name="profile_umount_modules_disable">Desativar o módulo personalizado de desinstalação</string>
<!-- Flash related -->
<string name="error_code">Código de erro</string>
<string name="check_log">Por favor, verifique o log</string>
@@ -368,4 +320,51 @@
<string name="module_failed_count">%d Falha ao instalar um novo módulo</string>
<string name="module_download_error">Falha ao baixar módulo</string>
<string name="kernel_flashing">Kernel Flashing</string>
<!-- 分类相关 -->
<string name="category_all_apps">All</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string>
<string name="category_default_apps">Default</string>
<!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string>
<string name="sort_name_desc">Name descending</string>
<string name="sort_install_time_new">Installation time (new)</string>
<string name="sort_install_time_old">Installation time (old)</string>
<string name="sort_size_desc">descending order of size</string>
<string name="sort_size_asc">ascending order of size</string>
<string name="sort_usage_freq">frequency of use</string>
<!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string>
<!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Delegation of authority</string>
<string name="grant_authorization">Authorizations</string>
<string name="unmount_modules">Unmounting Module Mounts</string>
<string name="disable_unmount">Disable uninstall module mounting</string>
<string name="expand_menu">Expand menu</string>
<string name="collapse_menu">Put away the menu</string>
<string name="scroll_to_top">Mais votados</string>
<string name="scroll_to_bottom">Parte Inferior</string>
<string name="selected">Selecionado</string>
<string name="select">opção</string>
<!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string>
<string name="sort_options">Sort by</string>
<string name="app_categories">Application Type Selection</string>
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
</resources>

Some files were not shown because too many files have changed in this diff Show More