Compare commits

...
Author SHA1 Message Date
gdlbo 8d41d423f8 fix close dialog 2024-03-03 14:01:46 +03:00
gdlbo 37a4ba4462 rewritten ContactsSyncAcitvity 2024-03-03 13:33:36 +03:00
gdlbo 7fba308f99 rewritten ContactsSyncReporter 2024-03-03 12:55:27 +03:00
gdlbo 5ef2f2f6cd rewritten ContactsSyncUtils 2024-03-03 12:51:31 +03:00
gdlbo 522f6cd42b removed useless cache buttons 2024-03-03 09:53:02 +03:00
gdlbo 7dd9e5ff3a more gzip support 2024-03-02 23:33:18 +03:00
Artur Skubei 07f8542f56 SponsorPost vote system (#1562)
also added gzip support for all methods
2024-03-02 22:24:15 +03:00
Artur Skubei 6b1e6f07c5 Internal VK Proxy Support (#1579)
thanks @awers24 for tests
2024-03-02 21:47:34 +03:00
gdlbo 5466dd72dd some lastfm fixes 2024-03-01 22:50:31 +03:00
Artur Skubei 5ac3b9cf6e Another ndk fix (#1572) 2024-02-25 22:07:42 +03:00
Artur Skubei de6edc795a Update build.yml 2024-02-25 21:46:27 +03:00
Artur Skubei 19d36272cb ndk fix (#1571) 2024-02-25 21:43:08 +03:00
gdlbo d2fe435ad2 added music fragment
migration from media content
2024-02-25 19:47:23 +03:00
gdlbo b6e7d24979 Update VTVerifications.java 2024-02-20 11:48:35 +03:00
gdlbo d10d5eca4b fixed auto updating filters 2024-02-19 15:39:41 +03:00
gdlbo 67f1477907 Revert "improve code readability, remove redundant constructions"
This reverts commit b05a239b90.
2024-02-19 11:38:11 +03:00
gdlbo 18ef4eda21 Revert "rollback to for-loops with improvements"
This reverts commit 84cf9ba10a.
2024-02-19 11:38:10 +03:00
Tahgolov 84cf9ba10a rollback to for-loops with improvements 2024-02-18 23:07:19 +03:00
Tahgolov b05a239b90 improve code readability, remove redundant constructions 2024-02-18 23:05:31 +03:00
gdlbo 8959558c64 Fixed 5.1 false coloring and improved coloring speed/app performance (#1566) 2024-02-18 14:52:22 +03:00
gdlbo e19ed8845d fix #1343 2024-02-18 02:08:16 +03:00
gdlbo b5ae2662db fix noad 2024-02-17 22:27:56 +03:00
gdlbo d4710663ff disabler force traffic saver v2 2024-02-16 03:58:30 +03:00
gdlbo 18f40e0da9 fixed useless false visibility vkZ
ofc jk (vkx)
2024-02-14 23:12:20 +03:00
gdlbo 9ff8c1d9fe refactored FoafBase
added check for vk messenger accounts
rewritten all legacy code
2024-02-14 23:03:19 +03:00
gdlbo 91440e4f8b refactored VTVerifs
speedup processIds + removed getting 1337 verifs (depreciated)
2024-02-14 22:13:22 +03:00
gdlbo a195e05d7b refactored sig checker
support for new android versions
2024-02-14 22:10:59 +03:00
gdlbo 8866bf90c7 refactored webview injector
speedup by runtime injection evaluateJavascript
2024-02-14 22:10:33 +03:00
gdlbo eab5b7074e refactored superapp utils
removed old vk pay and events
2024-02-14 21:45:31 +03:00
gdlbo bdee6c08c0 disable events in superapp 2024-02-14 21:16:41 +03:00
gdlbo 0744613aa0 Update preferences_debug.xml 2024-02-14 19:31:02 +03:00
gdlbo f6de4c5bc9 some toggles fixes
probably may fixed slow messages load
fixed default feed
2024-02-14 19:11:16 +03:00
gdlbo f59e93aab6 fix #1551 2024-02-14 19:03:23 +03:00
gdlbo 2d97341886 video-covers disabler 2024-02-14 17:53:05 +03:00
gdlbo b247c5c090 some config network fixes 2024-02-14 17:06:35 +03:00
gdlbo fd6e866f6f fixed bug nonmilk
Reported by https://4pda.to/forum/index.php?showuser=1502902
2024-02-14 16:45:45 +03:00
gdlbo 780ebce3ff disable libverify by default
2fa fix
2024-02-12 12:31:06 +03:00
gdlbo 2a85b3a4f0 fixes for whitelists 2024-02-09 15:41:18 +03:00
gdlbo 413701d28e SponsorPost summ 2024-02-07 16:40:54 +03:00
gdlbo 016bd342c4 added summary for sponsorpost 2024-02-07 16:33:54 +03:00
gdlbo d04b2249f0 enable metadata by default 2024-02-07 16:07:59 +03:00
gdlbo 8eb7ded6ba fixed autoupdate filters 2024-02-07 15:49:04 +03:00
gdlbo 1f9c6fd80c added disabling sponsorpost 2024-02-07 15:47:05 +03:00
gdlbo 4ec84e3754 cleanup build gradle 2024-02-07 14:58:06 +03:00
gdlbo ad3f70f4ac Sponsorpost integration (#1553) 2024-02-07 13:55:53 +03:00
gdlbo 611f4d3159 updated run configs 2024-02-06 18:37:30 +03:00
mexanoz 7319714140 fix setting metadata for certain tracks (#1507) 2024-02-04 15:10:34 +03:00
gdlbo 857db4879a vkui theming fixes
thx @awers24
2024-02-02 14:27:35 +03:00
gdlbo b5db820733 new feature
useless
2024-02-01 23:40:10 +03:00
gdlbo c668105003 some translations update 2024-01-31 11:46:46 +03:00
gdlbo dd6bbcbc2c fix auto translation 2024-01-31 11:42:07 +03:00
gdlbo 4ed0749027 Revert "Profiles/Groups resp fixes (#1532)"
This reverts commit a6b56e0e87.
2024-01-31 03:22:06 +03:00
gdlbo 3b834c2688 Update Genius.java 2024-01-31 01:56:10 +03:00
gdlbo 0c5a40bedc enable stories 2024-01-31 00:46:57 +03:00
gdlbo 8146b863b1 fix crash 2024-01-30 12:21:53 +03:00
gdlbo c64f8a1b2d disabler force traffic saver 2024-01-30 11:47:08 +03:00
gdlbo dd6916c08a removed random proxy 2024-01-30 11:35:49 +03:00
gdlbo 58c14fbd4f added all server features disabler for users who doesnt have unlimited internet 2024-01-30 11:28:38 +03:00
gdlbo 3b830f5e2e added fragile user data pref 2024-01-30 11:08:19 +03:00
gdlbo c304313be9 updated deps 2024-01-13 19:14:51 +03:00
Denis 3068ff76c1 Fix crash (#1542) 2023-12-31 13:04:55 +03:00
gdlbo a6b56e0e87 Profiles/Groups resp fixes (#1532) 2023-12-13 23:08:32 +03:00
gdlbo 5360ca6c5e updated translations 2023-12-13 23:07:40 +03:00
gdlbo f2ac845797 Update FFMpeg.java 2023-10-14 16:05:51 +03:00
gdlbo a85e55a594 meta data pref 2023-10-12 22:45:43 +03:00
gdlbo e2775db4e5 fixed english translation 2023-10-12 20:19:17 +03:00
gdlbo 589e8928a0 Bitrate upgrade (#1498)
libvkmedia.so armv7/arm64
2023-10-12 19:57:00 +03:00
gdlbo cd189b1dda fixed id3v2 meta 2023-10-10 23:15:11 +03:00
gdlbo 14c111a3e6 some music fixes 2023-10-10 22:53:16 +03:00
gdlbo b506c56346 fixed compiling issue 2023-10-07 03:13:24 +03:00
gdlbo bbbc94e510 added facebook graph disabler 2023-10-07 03:07:31 +03:00
gdlbo 8cb2c380e7 fixed adding "null" to track name 2023-10-06 12:44:55 +03:00
gdlbo b9879f9ed7 updated appcenter 2023-10-04 19:44:24 +03:00
gdlbo cf05e051e8 added summary for advanced online info 2023-10-04 13:47:47 +03:00
gdlbo 963c4d81ba upped ver 2023-10-04 13:37:20 +03:00
gdlbo 099c699702 added vkn online fix disabler 2023-10-04 13:37:07 +03:00
gdlbo 1117fc19d4 added force tablet mode 2023-10-02 16:28:08 +03:00
gdlbo 78dca26063 fix #1489 2023-10-02 14:52:52 +03:00
gdlbo f5180f61d5 fixed empty text from ssfs 2023-09-30 14:37:49 +03:00
gdlbo 540fffdcc9 fixed download issue 2023-09-30 03:15:14 +03:00
gdlbo 5357c60eaa Update TelegramStickersGrabber.java 2023-09-30 02:33:52 +03:00
gdlbo c59f29121f Refactoted Telegram Stickers downloader and settings (#1485) 2023-09-29 19:58:33 +03:00
gdlbo bd38cab377 autoupdated disabler 2023-09-28 17:40:49 +03:00
gdlbo 0058431590 deleted useless summ and updated translation 2023-09-28 17:01:38 +03:00
gdlbo bf4cf2be53 adfree + free from server connection (#1481) 2023-09-28 16:10:30 +03:00
gdlbo aac86a9952 Update InstallGMSFragment.java
added inotia00 microg information
2023-09-28 11:09:40 +03:00
gdlbo ae00e72bac added more microg instructions 2023-09-27 23:55:56 +03:00
gdlbo fea984f6fd fixed null foaf crash app 2023-09-27 23:34:37 +03:00
gdlbo d870c2f984 Update VTSettings.java 2023-09-27 22:12:12 +03:00
gdlbo f7f43928cf cleanup and refactor code
also fixed ts merging
2023-09-25 14:44:27 +03:00
Vologhat 1accb45f12 Merge remote-tracking branch 'origin/main' 2023-09-24 18:43:40 +03:00
Vologhat d9f53920e5 optimize music cache logic 2023-09-24 18:39:12 +03:00
gdlbo 76d91332d7 added recommendation icons 2023-09-23 16:04:45 +03:00
gdlbo 728cbde683 added xiaomi battery dozing information 2023-09-23 14:58:13 +03:00
gdlbo 60c98cd998 some settings improves 2023-09-23 14:50:18 +03:00
gdlbo f1d106e0f0 added gms info in device info
installed microg/gms and push service
2023-09-23 11:17:43 +03:00
gdlbo c92194e90b app.revanced.android.gms support (#1474) 2023-09-23 10:53:05 +03:00
gdlbo 91683af807 deleted useless file 2023-09-23 01:50:43 +03:00
gdlbo c5c898aa4e added recommendations for app fixes + added more gmsless instructions 2023-09-23 01:22:13 +03:00
gdlbo 25634b2469 cache info/clean improvements 2023-09-22 23:27:08 +03:00
gdlbo b8e764d09d Update AboutAppFragment.smali 2023-09-15 19:31:09 +03:00
gdlbo 17ed32857a fixed information about cache settings 2023-09-15 19:05:34 +03:00
gdlbo d631d07e0f removed useless update toast 2023-09-15 19:03:14 +03:00
gdlbo 2ec4c69832 added "Data and storage" item to settings 2023-09-15 18:40:38 +03:00
abslike 6426c965c6 Fix button black text in bots 2023-09-15 18:38:27 +03:00
gdlbo 4f6d410185 stories disabled by default 2023-09-15 18:09:29 +03:00
gdlbo 18a899f439 updated and refactored vt settings 2023-09-15 18:08:28 +03:00
gdlbo 7e5b3fe233 superapp audio item fix 2023-09-14 12:08:16 +03:00
gdlbo 4abd0eec6c fix compile 2023-09-14 11:28:08 +03:00
gdlbo cf17ed64c7 fixed invert in cached playlist 2023-07-30 16:49:30 +03:00
gdlbo a2dd7c1e06 fixed strange code 2023-07-29 17:06:12 +03:00
gdlbo 021fe66bec invert cached tracks list 2023-07-29 16:48:30 +03:00
gdlbo 1b3896f4ca fix colors issue 2023-07-28 19:01:57 +03:00
gdlbo fc9ccf66d1 fix #1409 2023-07-28 18:49:11 +03:00
Vologhat d205f2894b rewrite StickersFragment.java
- move add tgs action to toolbar
- some optimizations
2023-07-14 12:53:57 +03:00
Vologhat 7afc04b2b2 fix tgs packs download 2023-07-14 12:48:45 +03:00
Vologhat 584ee96ee0 fix #1406 2023-07-14 12:37:50 +03:00
gdlbo 66f7ea1b79 Update VTVerifications.java 2023-07-11 21:47:53 +03:00
gdlbo 7b0a83458b Update README.md 2023-07-08 18:03:41 +03:00
gdlbo cdaf7909d4 fix old android crash accenting 2023-07-04 23:23:18 +03:00
gdlbo c70ab388c1 fixed account saving 2023-07-04 22:55:22 +03:00
gdlbo 50c66c2703 fix music metrics 2023-07-04 19:56:12 +03:00
gdlbo 357e520bb0 some code fixes 2023-07-04 18:57:06 +03:00
gdlbo 6379ce5741 cleanup code 2023-07-04 13:42:04 +03:00
Vologhat 02807739a1 fix #1394 2023-07-02 22:32:26 +03:00
gdlbo 40635ab75a fix #1388 2023-07-02 13:44:47 +03:00
gdlbo 32e1bfe6fd fix messages color accent 2023-07-02 00:04:10 +03:00
gdlbo 281a0e8499 updated translations 2023-07-01 18:45:45 +03:00
gdlbo 220c61afe1 Update preferences_themes.xml 2023-07-01 18:33:46 +03:00
Vologhat 7a632d5224 Update preferences_themes.xml 2023-07-01 18:31:23 +03:00
Vologhat 3218c1a46b add optionally theme cache invalidation every update 2023-07-01 18:29:47 +03:00
Vologhat b2028d86ba add optionally theme cache invalidation every update 2023-07-01 18:24:42 +03:00
gdlbo 45ed5879e6 Update build.gradle 2023-07-01 17:46:06 +03:00
gdlbo 48479dd064 removed old color engine prefs 2023-07-01 17:33:45 +03:00
gdlbo 3b556b81a1 Update StandartFilter.txt 2023-07-01 17:33:05 +03:00
gdlbo 526c9a607a auto refactor imports 2023-07-01 16:42:33 +03:00
Vologhat 81752895ab Revert "auto refactor code"
This reverts commit ad970d097a.
2023-07-01 16:39:36 +03:00
gdlbo ad970d097a auto refactor code 2023-07-01 16:38:42 +03:00
gdlbo bc2010b49d gradle downgrade 2023-07-01 16:34:27 +03:00
Vologhat ff4a4094ff add type validating of resource value 2023-07-01 16:15:20 +03:00
abslike 3629e71098 Update monet dark and amoled theme (nomilkshake) (#1378) 2023-06-27 22:21:45 +03:00
Vologhat b955ac355f fix #1386 2023-06-27 22:17:43 +03:00
Vologhat 409279eca0 fix apk path building 2023-06-27 17:32:28 +03:00
Vologhat ea0a0f1d93 Optimize build scripts
- rewrite the"exportDex" task group
- move  the logic of deleting temporary files into a gradle script
- fix "APPCENTER_KEY" property defining while debug building
2023-06-27 16:42:07 +03:00
gdlbo 3cc81dfddc fix #1376 2023-06-19 05:06:22 +03:00
gdlbo 86041e6031 invert exceptions filters 2023-06-19 01:40:22 +03:00
gdlbo e140ce2661 fixed monet msg colors 2023-06-19 00:46:27 +03:00
gdlbo f6f15132a2 Update build.yml 2023-06-18 18:35:53 +03:00
gdlbo e73751ecf3 Update build.yml 2023-06-18 18:26:12 +03:00
gdlbo 3c0516b4cd cleanup ThemesUtils.java 2023-06-18 18:20:48 +03:00
gdlbo 38d9f4a818 update gradle 2023-06-18 18:20:25 +03:00
gdlbo 207fa4f2e7 fixed memories vkui 2023-06-18 02:38:39 +03:00
abslikeandabslike f9f778b8f4 Updating light nonmilkshake theme (#1374)
Co-authored-by: abslike <abslike@vk.com>
2023-06-17 21:46:13 +03:00
gdlbo 962dcdec67 fixed search engine issue 2023-06-16 22:45:02 +03:00
gdlbo 486026b8aa updated translations 2023-06-14 17:36:34 +03:00
gdlbo e78d08fb94 added frag title for data sett 2023-06-12 16:32:47 +03:00
gdlbo a5e81dbd87 some data sett updated 2023-06-12 16:30:22 +03:00
gdlbo 49051dae9a added filtered buttons for profile #767 2023-06-12 15:28:37 +03:00
gdlbo 94236c87e3 fix incorrect sig 2023-06-10 20:32:06 +03:00
gdlbo 449ba8c768 cleanup NewsFeedFiltersUtils.java 2023-06-10 20:08:28 +03:00
gdlbo 0da81c01e9 fixed monet theme applying 2023-06-10 20:08:13 +03:00
gdlbo b4a0b7e1ea Fixed false filtering of users' own messages 2023-06-10 18:06:13 +03:00
abslikeandabslike f2209eca49 Updating Light and Dark milkshake monet theme (#1359)
Co-authored-by: abslike <abslike@vk.com>
2023-06-10 15:08:13 +03:00
gdlbo 4a004971c6 Update CatalogJsonInjector.java 2023-05-30 19:25:30 +03:00
gdlbo e400b8761c fixed false injection cache playlist in old audio catalog 2023-05-30 17:17:59 +03:00
Vologhat ff8e7b7f41 fix incorrect displaying of selected image searcher 2023-05-30 12:31:21 +03:00
gdlbo 2c501606be amoled vkui issues fix 2023-05-28 18:02:09 +03:00
gdlbo 73420fe1c4 updated vkui injection for new versions 2023-05-28 15:50:11 +03:00
Vologhat 337f81346c replace microsoft icon to bing icon 2023-05-27 20:13:04 +03:00
Vologhat 06f9a4545b added sauceNAO and trace.moe icons 2023-05-27 14:36:09 +03:00
gdlbo fa99df93c4 refactoring some code 2023-05-26 21:03:23 +03:00
Vologhat adcd2472d5 rewrite and fix PhotoViewer hook
- optimize code
- create SearchEngine enum for image searchers
- fix "search photo" on non-monet theme
- fix icon colors in photo viewer context menu
2023-05-26 16:46:43 +03:00
gdlbo 7527b9a07e added update button for all non-dev users 2023-05-26 14:47:49 +03:00
gdlbo 800c223baa fixed dropdown monet icons in menu 2023-05-26 14:37:06 +03:00
gdlbo d1123d3ccf Update MediaNative.java 2023-05-25 23:18:15 +03:00
gdlbo f61fc99d9c Revert "upgraded voice bitrate"
This reverts commit 64303b1709.
2023-05-25 23:04:09 +03:00
gdlbo 60653cc739 medianative converted to java 2023-05-25 23:03:00 +03:00
gdlbo d25bba10b0 fixed profiles crash 2023-05-25 17:06:48 +03:00
gdlbo 3b67ecaa5e deleted voip libs
-10 mb
2023-05-25 17:06:29 +03:00
gdlbo 6600f32392 some settings update 2023-05-25 16:48:04 +03:00
gdlbo 64303b1709 upgraded voice bitrate
opus_encoder_ctl

16000 -> 48000
2023-05-24 20:34:57 +03:00
gdlbo 5c7e50d61e delete pin fix
good fix
2023-05-24 15:18:39 +03:00
gdlbo f68ad105a6 Update Preferences.java 2023-05-24 01:32:02 +03:00
gdlbo 164479da1d disabled profiles/groups rename 2023-05-24 01:00:53 +03:00
gdlbo d93bf41d28 fixed discover bug 2023-05-23 23:43:23 +03:00
gdlbo 38a2b3f2b2 cleanup banner msg code 2023-05-23 23:17:20 +03:00
gdlbo 342534676c fixed another strange issue with banners 2023-05-23 23:08:53 +03:00
gdlbo 56a6a6de03 fixed messages issue 2023-05-23 23:03:10 +03:00
gdlbo d1445c2801 disable language change for miui
https://xiaomi.eu/community/threads/miui-14-per-app-language-support.69022

china number one!!!!!!!!!
2023-05-23 22:28:13 +03:00
gdlbo 6d3ddede38 Update WebViewColoringUtils.java 2023-05-22 19:01:39 +03:00
gdlbo 08dae9b342 Experimental proguard config with hooks refactoring (#1323)
fixed telegram stickers issue
speedup webview coloring
refactored VKUIHook
fixed duplication of eruda
added a check for duplication of adding styles for coloring vkui
2023-05-22 18:48:15 +03:00
gdlbo 8244b31631 fixed issue with aidl 2023-05-21 03:10:23 +03:00
gdlbo 8b29870df9 fixed vk classes crash 2023-05-21 02:57:07 +03:00
gdlbo ab1d0bde0d Update TelegramStickersGrabber.java 2023-05-21 00:59:40 +03:00
gdlbo 782f8a881d updated desugar runtime library 2023-05-21 00:58:39 +03:00
gdlbo b712630809 fixed logging issues 2023-05-21 00:58:19 +03:00
gdlbo b6698287a0 Update proguard-rules.pro 2023-05-21 00:21:59 +03:00
aliveoutside 1b5bfb0ea6 daily mix fix 2023-05-20 19:02:01 +03:00
gdlbo 59d5b83d7b fixed catalog injectors issues
cache playlist fixed
daily mix fixed
2023-05-20 16:32:33 +03:00
gdlbo 9c127931cf updated translations 2023-05-20 14:47:29 +03:00
gdlbo 6f552ee0cb some code cleanup 2023-05-20 14:36:47 +03:00
gdlbo ae1520e189 added logs shrink for release builds 2023-05-20 13:52:43 +03:00
gdlbo 8fae9e952f updated gradle version 2023-05-20 13:52:00 +03:00
gdlbo e6047ffe8a updated appcenter libs 2023-05-20 13:51:26 +03:00
gdlbo b987643ad7 Update arrays.xml 2023-05-19 20:19:43 +03:00
gdlbo b93ce2dd95 fixed issues with translation 2023-05-19 20:18:23 +03:00
gdlbo 1c845c5b34 added more translations 2023-05-19 20:13:51 +03:00
Denis c4af19432d Add compression types translation (#1312) 2023-05-19 19:49:23 +03:00
gdlbo 0c289f8bbb added support for many attachments 10+ (#1311) 2023-05-19 19:34:30 +03:00
Saoqq c68d424b59 Update ffmpeg libs (#1057)
* Update ffmpeg libs

* Bring back metadata writing
2023-05-17 17:45:45 +03:00
aliveoutside 46bac84276 fix daily mix title in playlist view 2023-05-17 11:39:50 +03:00
aliveoutside 16260c5666 temp daily mix fix 2023-05-17 10:55:02 +03:00
gdlbo 594f24d640 Refactored issues with photo compression (#1300)
Added new ways of compression
Added photo copy button
2023-05-15 21:28:45 +03:00
Denis 0deafb5606 Update features.md - editing the list of functions (#1297) 2023-05-15 12:19:27 +03:00
gdlbo 2e3b45a88f Revert "Multithreading verifs downloading"
This reverts commit 0e94efc4f7.
2023-05-14 17:30:14 +03:00
gdlbo 5a7a628117 Revert "added multithread download for some large methods"
This reverts commit 34a0615003.
2023-05-14 17:30:14 +03:00
gdlbo 2d96619c67 Create Multithreading.java 2023-05-13 15:43:29 +03:00
gdlbo 34a0615003 added multithread download for some large methods 2023-05-13 15:07:27 +03:00
gdlbo 0e94efc4f7 Multithreading verifs downloading 2023-05-13 14:38:29 +03:00
gdlbo a11a88e23f moved debug activation to long click of logo/appver 2023-05-12 22:22:27 +03:00
gdlbo 72eb342b98 updated version.properties parsing + cleanup code 2023-05-12 22:00:09 +03:00
gdlbo edb011ccbf Update About.java 2023-05-12 21:19:08 +03:00
gdlbo 8b32e16428 check_for_slow_speed (#1293) 2023-05-12 19:51:27 +03:00
gdlbo d4b457b01d fixed detection admin for kick button 2023-05-12 19:50:48 +03:00
Denis 3d61780240 Sort features in README.md (#1294) 2023-05-12 16:01:09 +03:00
gdlbo 44092032ca Update Requests.java 2023-05-10 19:47:00 +03:00
gdlbo 2800ccdaea refactored dnr/dnt modules 2023-05-10 19:40:33 +03:00
gdlbo a0cce72c64 kick button for admins in chats 2023-05-10 18:01:19 +03:00
gdlbo cbca43c929 Update README.md 2023-05-10 14:14:56 +03:00
gdlbo 0324c9edb7 updated docs for building 2023-05-10 14:13:17 +03:00
Denis c7d34ece2f added features in features list and sorting (#1119)
* added feature text feature

* Add new features in list

* fix text

* Update features.md

* Add dev feature "sync account" and backup settings

* Update - Add genius

* Update features.md - delete unreleased features
2023-05-09 19:38:34 +03:00
gdlbo 681dd177b8 fixed offline genius issue 2023-05-07 12:09:18 +03:00
gdlbo 4405b04285 removed useless conv bar recomms 2023-05-06 23:40:04 +03:00
gdlbo 3c4e981839 fixed lyrics for genius 2023-05-06 23:27:30 +03:00
gdlbo e318634e56 fix some genius issues 2023-05-06 22:49:12 +03:00
aliveoutside 5ea515f6f4 fetch the lyrics from genius even when vk didn't provide them 2023-05-06 19:23:22 +03:00
gdlbo 22cd1a8e22 some audio code cleanup 2023-05-06 12:24:37 +03:00
gdlbo ba0169cb4c fixed thumbnails in online cache catalog and shuffle 2023-05-06 11:51:23 +03:00
gdlbo 5f0458c587 refactored cache tracklist injector and added shuffle button 2023-05-06 11:03:40 +03:00
gdlbo 7b840a1721 added app category for oreo+ 2023-05-05 23:00:07 +03:00
gdlbo 78036bb3db deleted snet 2023-05-05 22:59:24 +03:00
gdlbo da52a7557f cleanup code 2023-05-05 20:48:39 +03:00
Vologhat 6eae209d04 fixed building drm key url and AES-128 decoding 2023-05-05 20:48:39 +03:00
Vologhat 683f0346e2 added null-check of base uri,fixed filename comparator 2023-05-05 20:48:39 +03:00
gdlbo c95b4e7f86 added new cache insert track method 2023-05-05 20:48:39 +03:00
Vologhat 64c55d4b01 init 2023-05-05 20:48:39 +03:00
gdlbo cc55d5ddaa new btn injector for groups 2023-04-29 19:24:55 +03:00
gdlbo 522290e4a5 Update GroupsCatalogInjector.java 2023-04-28 22:26:38 +03:00
gdlbo 78191b716a Update GroupsCatalogInjector.java 2023-04-28 22:16:20 +03:00
gdlbo dcf14266f2 cleanup catalog json injector 2023-04-28 22:11:53 +03:00
gdlbo a295e11a9d fixed issues with music 2023-04-28 21:58:14 +03:00
gdlbo 67ba4319f8 fixed groups fix for catalogs 2023-04-28 21:30:33 +03:00
aliveoutside f4d4c622eb fix #1235 2023-04-28 21:19:50 +03:00
gdlbo 0d61904b19 Update GmsUtils.java 2023-04-26 19:41:22 +03:00
gdlbo 8d9d025f11 some cleanup 2023-04-23 17:22:41 +03:00
gdlbo 6cac613f70 fixed microg pushes 2023-04-20 18:24:29 +03:00
gdlbo a5d0f1b730 microg settings and force microg usage 2023-04-20 16:14:52 +03:00
gdlbo 47465356fa fixed some spoof issues 2023-04-20 15:44:49 +03:00
gdlbo 4c6eed7dad added support for microg 2023-04-20 15:36:09 +03:00
gdlbo 7bdc8b21e4 updated jars 2023-04-20 15:31:59 +03:00
gdlbo 21fc171363 Update ThemesFragment.java 2023-04-03 21:11:55 +03:00
gdlbo fb09513ca7 samsung best fix 2023-04-03 17:43:55 +03:00
gdlbo dc49c75992 Update OEMDetector.java 2023-04-03 16:30:19 +03:00
gdlbo dd289f1933 another theme at start fix..? 2023-04-03 16:01:34 +03:00
gdlbo 360c5db990 fixed shit miui issue 2023-04-03 15:54:08 +03:00
gdlbo 0df490dc55 fixed perms 2023-04-03 15:46:16 +03:00
gdlbo 064f5d8b31 some wallpapers fixes 2023-04-02 21:37:06 +03:00
gdlbo 40f3d74f07 fixed strange bug 2023-04-02 19:54:52 +03:00
awers24 cd08354b5e ukrainian translation 2023-03-31 08:58:19 +03:00
mysh228 64a9a3c1e8 belarusian translation 2023-03-30 20:09:53 +03:00
gdlbo 8770712687 dockbar editor moved to dockbar settings in appearance sett 2023-03-30 14:25:05 +03:00
gdlbo 009f856b33 deleted useless vk apps menu in dockbar editor 2023-03-30 14:24:06 +03:00
gdlbo 022c264740 removed recomm menu in discover 2023-03-30 14:23:39 +03:00
gdlbo dd2d79e474 Update DataSettingsFragment.java 2023-03-29 00:07:40 +03:00
gdlbo f2fe2ec362 added language settings for a13+ 2023-03-28 22:42:45 +03:00
k1zn 46ef15d9c8 /ru/ translate [main] 2023-03-28 02:13:05 +05:00
k1zn 93a507a314 /ru/ localization 2023-03-28 01:36:38 +05:00
gdlbo a3853a012d Сохранение аккаунтов (#1165) 2023-03-27 21:55:57 +03:00
gdlbo 10ed61acfc new color engine now is optional 2023-03-27 21:00:40 +03:00
aliveoutside 8b434d4cae revert apktool 2023-03-27 19:00:13 +03:00
gdlbo 92a33995bd fixed adaptive icons 2023-03-27 17:35:47 +03:00
gdlbo d994439561 fixed cringe build update detection v2 2023-03-25 22:44:58 +03:00
gdlbo ed751bdc30 fixed cringe build update detection 2023-03-25 22:24:33 +03:00
gdlbo ababaad45f revert old theme engine for monet theme 2023-03-25 20:32:44 +03:00
gdlbo 9a76492c06 Update custom_thumb_selector.xml 2023-03-21 16:15:38 +03:00
gdlbo 2d19254d51 fixed start issue 2023-03-21 16:13:18 +03:00
gdlbo d557abe6e9 md3 switch 2023-03-21 16:05:55 +03:00
gdlbo 658c4bcaf6 fixed issue with system theme applying + crashes 2023-03-21 15:21:31 +03:00
gdlbo 7b12be3736 disabled switch coloring 2023-03-20 00:30:06 +03:00
gdlbo 9e2bfe83b8 Revert "disable out api inj for pinned msg"
This reverts commit 8ca73197d6.
2023-03-19 21:06:30 +03:00
gdlbo 817bdd8198 Update strings.xml 2023-03-19 21:06:22 +03:00
gdlbo 230f8e5cd3 Update GiftSendFragment$b.smali 2023-03-19 19:37:32 +03:00
gdlbo cfce4cd1ff fixed polls colors 2023-03-19 19:06:21 +03:00
gdlbo c9c602b1f9 added new icons 2023-03-19 18:14:25 +03:00
gdlbo 8ca73197d6 disable out api inj for pinned msg 2023-03-19 12:17:43 +03:00
gdlbo 2cf60aedac added enc key delete 2023-03-19 12:05:32 +03:00
gdlbo 207a63117e added identity frag support 2023-03-18 19:55:21 +03:00
gdlbo 14e92e7352 removed calls pref 2023-03-18 19:35:08 +03:00
gdlbo 23c60bdf2d reduced logging + reworked debug menu 2023-03-18 19:23:07 +03:00
gdlbo 680dcf9cf2 useCustomPrefsStyle optional 2023-03-18 13:36:36 +03:00
gdlbo 5249600b76 many build features upgrades 2023-03-18 13:10:12 +03:00
gdlbo bc5a401e0e useCustomPrefsStyle true 2023-03-18 11:37:43 +03:00
gdlbo 125c2d3d69 fix switches 2023-03-18 03:14:42 +03:00
gdlbo db95b53d41 added text coloring 2023-03-17 22:31:08 +03:00
gdlbo f29532b518 fix system theme changer 2023-03-15 23:49:25 +03:00
gdlbo ebb6d7d5fd update dev icon
vk premium shock content
2023-03-15 21:49:20 +03:00
gdlbo 46ad8635f1 fix all RadioButtons and SwitchCompats buttons 2023-03-15 21:29:50 +03:00
gdlbo 507dbee4c0 switch tricks 2023-03-15 20:45:59 +03:00
aliveoutside 1dfe5971be track opened settings 2023-03-15 19:18:48 +03:00
aliveoutside 898967128a fixup build 2023-03-15 16:02:45 +03:00
aliveoutside ffa71a8087 add buildtypes 2023-03-15 15:51:36 +03:00
aliveoutside fbb470ed74 remove duplicated crash logging 2023-03-15 15:20:19 +03:00
aliveoutside 0954c8de6e move exportDex task under deps 2023-03-15 13:17:31 +03:00
aliveoutside 39585b053b fix recursive method in AnalyticsHelper 2023-03-15 13:09:57 +03:00
gdlbo 20e966e039 updated start information 2023-03-15 11:07:59 +03:00
gdlbo 99e50e4122 fixed app crash 2023-03-15 11:00:09 +03:00
gdlbo e8477097b6 Update OtherFragment.java 2023-03-15 03:29:16 +03:00
gdlbo 241b6bace5 Update build.gradle 2023-03-15 03:27:26 +03:00
gdlbo 1a5a325ff3 Update OtherFragment.java 2023-03-15 02:36:20 +03:00
gdlbo 3352b0f01c fixed metrics disabler 2023-03-15 01:37:21 +03:00
gdlbo a90ae1be64 added appcenter metrics/crash logger 2023-03-15 01:19:25 +03:00
gdlbo 4d7ff28d97 added support for language config 2023-03-14 02:52:06 +03:00
gdlbo f72967b0d3 Update apktool framework to sdk 33 2023-03-14 02:51:49 +03:00
gdlbo ea2531eaca Update apktool.jar 2023-03-14 02:50:52 +03:00
gdlbo d36fe43541 fix action menu icons color 2023-03-12 00:27:38 +03:00
gdlbo 3acec6a29d Update ThemesFragment.java 2023-03-11 23:32:08 +03:00
gdlbo 5a73f8a4ed Update write_bar_audio.xml 2023-03-11 23:24:28 +03:00
gdlbo 6ecc44c29e Update M3UDownloader.java 2023-03-11 23:21:18 +03:00
gdlbo 2e180707db Update FriendRequestHolder.smali 2023-03-11 22:35:32 +03:00
gdlbo 5176a51c95 fixed crash 2023-03-11 22:33:28 +03:00
gdlbo 0f298b4fe3 Update M3UDownloader.java 2023-03-11 22:26:05 +03:00
gdlbo 51c94d7334 some fixes 2023-03-07 12:49:33 +03:00
spiky-s 07156f1c6a added VKWebAppGetConfig vkbridge event support (#1134) 2023-03-05 16:26:43 +03:00
gdlbo 4a933110e9 fixed false applying theme 2023-03-05 15:56:46 +03:00
gdlbo 8bf424f549 fixed choice icons for photo engine selection 2023-03-05 15:45:03 +03:00
gdlbo f477232cbe Update ThemesUtils.java 2023-03-05 15:05:11 +03:00
gdlbo 80af934df3 upgraded system theming 2023-03-05 14:55:53 +03:00
gdlbo 6d97ee38cd fixed theme applying 2023-03-05 14:09:01 +03:00
gdlbo dedf1a0b1c added debugging for webview + reworked vkui inj 2023-03-04 22:02:18 +03:00
gdlbo 692e7cefad Update VerifyInfoHelper.java 2023-03-02 18:06:08 +03:00
gdlbo dc91f59048 added dev verifs
test test
2023-03-02 15:56:47 +03:00
gdlbo 4b59f732e9 senseless reapplication of filters removed 2023-03-02 14:09:24 +03:00
gdlbo 7e0b083a9a Update AssetManagerHelper.java 2023-03-02 11:57:17 +03:00
gdlbo 60336238f2 fixes 2023-02-28 18:22:36 +03:00
gdlbo 1dd12c45ef Update ThemesCore.java 2023-02-28 18:07:29 +03:00
gdlbo 91fc6f4cad Update VTSettings.java 2023-02-28 18:05:47 +03:00
gdlbo 9e07ddcdf5 improvements 2023-02-25 19:24:37 +03:00
gdlbo 23e89c31eb Update MainActivityInjector.java 2023-02-25 19:14:32 +03:00
Vologhat 876478f2c6 add implementation of https://developer.android.com/reference/android/content/Intent#ACTION_APPLICATION_PREFERENCES 2023-02-25 18:27:05 +03:00
gdlbo 96b8f99e93 some fixes 2023-02-25 15:37:23 +03:00
gdlbo d31fa5cdcc Update AndroidManifest.xml 2023-02-25 15:26:12 +03:00
Vologhat cc034226a0 add navigation click action 2023-02-24 01:39:09 +03:00
Vologhat 785c51a64a fix mod apk making 2023-02-23 16:17:10 +03:00
gdlbo 478206e0ac Update .gitignore 2023-02-21 22:33:03 +03:00
aliveoutside 6f474408a5 update readme 2023-02-21 18:42:19 +03:00
Vologhat b74cbe54ed Performance improvements and cache invalidation fix
* Combining assets.zip and res.zip for better performance
* Fix apk path on cache invalidation
2023-02-21 11:31:49 +03:00
Saoqqandsaoq a45e6a7f2a Refactor wp (#944)
* Extract couple filters to separate classes

* Move ImageEffects to separate file

* Refactor effects to use bitmap

* Reformat code, extract last batch of effects to classes

* Shitty intermediate refactor

* Still intermediate sh**, buildable btw

* More refactoring, still looks disgusting, but a bit better)

* Add fixme about order

* Remove unused stuff

* Remove unused code, prevent re-creating of drawable

* Refactor img effects to native

* Add native lib sources

* Implement Dim, Mosaic and Blur in native

* Add pre-built libs

* Get rid of filter abstraction

* Include native build

* Force rust toolchains

* Fix typos

* Comment not used smali

* Simplify wallpapers handling

* Fixes after main merge

* Minor fixes, add prebuilt lib, disable auto re-builds for native

* Fix missed copyscpec for native builds

* Fix entry for dim effect

* Fix resizing to respect current image dimensions

* Wtf? who stole NDK from actions

* Learning GH actions

I don't want to read the docs

* Revert "Learning GH actions"

This reverts commit f6f9a97d10.

* Revert "Wtf? who stole NDK from actions"

This reverts commit 1d0f1b8879.

* Try out latest LTS just why not

---------

Co-authored-by: saoq <wfmfe@ya.ru>
2023-02-21 09:20:35 +03:00
gdlbo 0d8c52548f Update ThemesManager.java 2023-02-19 21:15:09 +03:00
gdlbo 973b4980a1 Update VKThemeHelper$b.smali 2023-02-19 19:35:46 +03:00
gdlbo b85305e416 fixed emoji 2023-02-19 19:10:46 +03:00
gdlbo 942f049bc5 fixed some hardcode 2023-02-19 18:51:33 +03:00
gdlbo e01322c8d5 fixed crash 2023-02-19 18:32:24 +03:00
gdlbo 1764dc015d fixed all theme bugs 2023-02-19 18:10:33 +03:00
gdlbo 44aff4f30d refactor code 2023-02-19 16:49:02 +03:00
Vologhat 9fd01db880 revert attribute hooks for monet 2023-02-19 16:48:20 +03:00
gdlbo 9264e7f5df Update DNRInjector.java 2023-02-19 16:17:15 +03:00
gdlbo 4fcbea2a35 Update Device.java 2023-02-19 16:01:48 +03:00
gdlbo 60dcb4fb87 fixes 2023-02-19 15:38:57 +03:00
Vologhat 314e4de27d new way of color modification 2023-02-19 15:31:50 +03:00
gdlbo c9eac43919 Update StickersFragment.java 2023-02-19 15:28:33 +03:00
gdlbo 52806a85cc genius 2023-02-19 14:43:22 +03:00
gdlbo e3512bc832 Update Genius.java 2023-02-18 17:03:47 +03:00
gdlbo d43aef7526 genius switch moved to mediacontent 2023-02-18 14:57:16 +03:00
gdlbo 46da6e1ee1 Update Genius.java 2023-02-18 14:55:08 +03:00
gdlbo ed1f99a490 fixed feat moment 2023-02-18 14:19:27 +03:00
gdlbo e46d078ec0 genius lyrics test
only for songs with vk lyrics
2023-02-17 23:09:22 +03:00
gdlbo 1c0048c57c Update AudioGetLyrics.java 2023-02-17 18:36:54 +03:00
gdlbo bb94460c35 added support for new lyrics
thanks @egormetlitsky
2023-02-17 18:36:22 +03:00
gdlbo 0fb5e5b17e splash a12+ 2023-02-15 22:02:23 +03:00
gdlbo 196610f5fe Update Device.java 2023-02-15 21:54:58 +03:00
gdlbo 46579a9f40 fixed translations 2023-02-15 21:53:27 +03:00
gdlbo 424413c3da Update LibVKXClient.java 2023-02-15 21:41:23 +03:00
gdlbo b0753eefcf Update preferences_feed.xml 2023-02-15 09:26:02 +03:00
gdlbo 39e72cf766 animated splash for sdk 12
not ready lol
2023-02-14 21:51:25 +03:00
gdlbo 4e51e65bc3 updated translations 2023-02-14 21:43:42 +03:00
gdlbo e3c694d7c3 added group stories adblock 2023-02-13 18:57:29 +03:00
gdlbo b44dae69a6 some proxy updates 2023-02-13 12:35:38 +03:00
gdlbo efb909ce64 fix artists catalog 2023-02-12 14:24:17 +03:00
Saoqqandsaoq 62c11b90dc Forward calls from msg to off VK apps (#1094)
Co-authored-by: saoq <wfmfe@ya.ru>
2023-02-12 02:18:27 +03:00
gdlbo a15cd9bd0b fixed compressing jpegs 2023-02-08 18:32:58 +03:00
gdlbo 6d9f4a23c8 added newsfeed update dialog 2023-02-08 18:00:36 +03:00
gdlbo 0677f77fde Update BackupManager.java 2023-02-08 17:55:26 +03:00
gdlbo 1b274fdb91 Update DockBarEditorManager.java 2023-02-08 17:08:22 +03:00
gdlbo c4bf9f8f88 some switch fixes 2023-02-08 16:41:56 +03:00
gdlbo e9a98afae9 Update ThemesCore.java 2023-02-07 01:35:36 +03:00
gdlbo 856bd63b43 updated VTSettings.java 2023-02-07 00:48:35 +03:00
gdlbo 606c908b90 some color fixes 2023-02-07 00:09:52 +03:00
gdlbo 0adc9ca3fd updated switch cases 2023-02-06 21:47:33 +03:00
gdlbo 3345382383 jdk upped to 14 2023-02-06 21:35:48 +03:00
gdlbo 7e7f8d0efa Update InterfaceFragment.java 2023-02-06 20:00:17 +03:00
gdlbo 84e0601b76 refactoring 2023-02-06 02:51:32 +03:00
gdlbo bc43b788d8 Update ThemesCore.java 2023-02-06 02:19:36 +03:00
gdlbo 22bd830353 fix #1062 2023-02-06 01:03:31 +03:00
gdlbo c2ff38044c fixed проксi moment 2023-02-05 23:53:28 +03:00
Pavel af312540df Escape character in values-be (#1088) 2023-02-04 21:44:00 +03:00
mysh228 1cee582dbf Apostrophes fixes in arrays 2023-02-04 00:52:05 +03:00
mysh228 664ea02dd0 Apostrophes fix 2023-02-04 00:52:05 +03:00
mysh228 4fe85d264d Belarusian translation 2023-02-04 00:52:05 +03:00
gdlbo e8a1d814c1 fixed false injection 2023-02-03 16:07:42 +03:00
gdlbo 76d0dd2ad6 disabled vigo 2023-02-03 15:56:17 +03:00
gdlbo 4658338fbb Update strings.xml 2023-02-03 15:25:07 +03:00
awers24 745ccd6e1d ukrainian translate (#1083)
* ukrainian translation
2023-02-02 20:52:24 +03:00
k1zn da76da8e35 Update strings.xml 2023-02-01 20:25:08 +05:00
gdlbo 249d1de1a1 Update R.java 2023-01-31 14:50:54 +03:00
gdlbo 1a82b40a7f Update RandomProxy.java 2023-01-31 14:43:01 +03:00
k1zn 83093be566 another translate 2023-01-31 15:58:24 +05:00
gdlbo 5994172095 fixed undelete msg
fixed all bugs omg
2023-01-30 21:36:13 +03:00
gdlbo a645e2fe32 Update CallsHook.java 2023-01-30 18:07:55 +03:00
gdlbo 87f59b2ea8 Update R.java 2023-01-29 15:44:26 +03:00
gdlbo 131bd0bdcc fixed def music catalog 2023-01-29 15:24:19 +03:00
gdlbo 7618c37d4c fix samsung awful icon system 2023-01-27 19:35:37 +03:00
gdlbo 41f978cc26 added monochrome for old icon 2023-01-27 18:44:58 +03:00
gdlbo 489246347f code cleanup 2023-01-27 17:37:49 +03:00
gdlbo a68e580436 fix null link crash for music tracks 2023-01-27 16:12:27 +03:00
gdlbo 0ef33f5c52 Update AndroidUtils.java 2023-01-27 15:41:02 +03:00
gdlbo daac037285 code cleanup 2023-01-24 18:12:01 +03:00
k1zn 09f9adafb0 translate 2023-01-24 15:26:08 +05:00
gdlbo f746753b15 updated translator 2023-01-21 17:28:00 +03:00
gdlbo 2b3da25099 Update AndroidUtils.java 2023-01-21 16:56:00 +03:00
gdlbo 94e8c49784 added links verif dialog 2023-01-21 16:50:23 +03:00
gdlbo afef886293 fixed calls moment 2023-01-21 15:58:37 +03:00
gdlbo acf3a77fe7 Implementation of domain verification 2023-01-16 17:42:03 +03:00
gdlbo 7de0d9a269 updated device info collector for simplify gh issues 2023-01-16 17:26:04 +03:00
dalvesrever 75732deb61 simplify OnPreferenceClickListener implementations
add NavigatorUtils
2023-01-15 19:45:12 +03:00
dalvesrever 923586cc33 close #1014; Make message text selectable 2023-01-15 18:30:15 +03:00
abslike eac9b2f83a Fix highlight on Amoled+Monet theme (#1041)
* Fix monet

* Try to fix part 2

* Fixed outgoing message

* Update styles.xml

* FIX MONET PART IV

* fix monet part of endless

* fix monet on white theme

* Fix highlight

* Fix highlight and other

* Fix text + highlight

* Fix highlight and text

* highlight

* Monet fixes

* Fix monet

* build fix

* build fixes

* Update styles.xml

* fix highlightes Amoled theme

* fix highlight Amoled theme
2023-01-14 12:53:48 +03:00
xsafter bfc718bc98 Рефактор Utils (#1000)
* Refactor:обновил Deprecated в новых Андроидах вызовы в некоторых утилитах

* Refactor:обновил Deprecated в новых Андроидах вызовы в некоторых утилитах

* Пофиксил
2023-01-11 13:41:46 +03:00
gdlbo effab03fd2 Merge pull request #1027 from Saoqq/vk-im-calls-forward
Quick calls integration with VK messenger app
2023-01-11 12:55:34 +03:00
saoq 6b1501b0fa Fix fun name 2023-01-10 23:52:58 +03:00
saoq 4f2d97fd7b Support VK off client 2023-01-10 23:39:48 +03:00
saoq 26b1db0900 Quick calls integration with VK messenger app 2023-01-10 19:21:24 +03:00
k1zn 6936079803 fix #1026 2023-01-10 20:51:25 +05:00
gdlbo eba6c43d4c dockbar and superapp editor moved 2023-01-06 18:48:49 +03:00
gdlbo 6667dc0be8 added manual verif data update 2023-01-06 16:32:14 +03:00
gdlbo 26e59629aa some settings refactoring 2023-01-06 16:25:58 +03:00
gdlbo 14f9f6dcf8 fixed msg preview 2023-01-06 16:10:41 +03:00
gdlbo 0a8ecd8b0a Update FeedFragment.java 2023-01-06 14:47:23 +03:00
gdlbo a4113ba6d5 auto refactor xmls 2023-01-06 14:47:16 +03:00
gdlbo 4f5193f170 Update Preferences.java 2023-01-06 14:28:52 +03:00
gdlbo 81a62d5400 some code updates 2023-01-03 13:59:39 +03:00
gdlbo 1a7031ead1 fixed init filters 2023-01-01 18:43:05 +03:00
Vologhat 40a1ab64cb add generateRjava task to gradle script 2023-01-01 18:30:48 +03:00
gdlbo 78f0eae9c3 fix #1001 2023-01-01 18:23:32 +03:00
Vologhat b5de88a370 update R.java 2023-01-01 18:19:32 +03:00
Vologhat 1e9a6c6840 fix shell script 2023-01-01 18:12:46 +03:00
gdlbo eb8939021d Update styles.xml 2023-01-01 18:04:34 +03:00
Vologhat a53f90367e fix item swipe disappearance 2023-01-01 17:45:01 +03:00
gdlbo f19aae542e fixed dialog stats from dialogs list 2023-01-01 16:15:38 +03:00
gdlbo f34b895485 added some photo quality magic 2023-01-01 16:13:48 +03:00
gdlbo 5c194891ba disabled more stats 2023-01-01 15:45:25 +03:00
Vologhat e7c08406a5 replace tags with ids 2023-01-01 15:29:42 +03:00
Vologhat c3a08ea7a8 change item width to match_parent 2023-01-01 15:23:25 +03:00
Vologhat 69ea193771 refactor CategorizedAdapter, DockBarEditor, SuperAppEditor 2023-01-01 15:08:32 +03:00
gdlbo 562bfc0ed0 added webview wrapper 2023-01-01 15:08:22 +03:00
Vologhat 919d7cb19d refactor CategorizedAdapter, DockBarEditor, SuperAppEditor 2023-01-01 15:06:55 +03:00
gdlbo 0a766038da updated icon for dialog stats 2022-12-31 23:04:26 +03:00
gdlbo dabc79cdb2 chat stats 2022-12-31 21:42:42 +03:00
gdlbo 4cb73d669a Update StickerPackAdapter.java 2022-12-30 17:50:03 +03:00
gdlbo dfddb13d2d Update CatalogJsonInjector.java 2022-12-30 17:45:39 +03:00
Vologhat f17c57bac2 add tgs stickers preview in settings 2022-12-30 17:32:14 +03:00
Vologhat a6c4c376c3 fix tgs stickers updating on keyboard stickers panel 2022-12-30 17:12:16 +03:00
gdlbo 3e4f14678e fixed nonmilk profile hide 2022-12-30 16:35:20 +03:00
gdlbo f860eb2cc0 Merge pull request #995 from psamur/main
New icons in profile buttons
2022-12-30 16:01:46 +03:00
gdlbo 2a6b9da4ef ImBanner cleanup code 2022-12-30 15:58:10 +03:00
Pavel 6224a4afdf new icons in profile buttons 2022-12-30 15:54:12 +03:00
gdlbo 8650124860 refactored ssfs utils 2022-12-30 15:35:55 +03:00
gdlbo 5e35a61473 refactored profile buttons injector 2022-12-30 14:52:29 +03:00
Vologhat 578f1a2221 add launch task 2022-12-30 14:28:30 +03:00
gdlbo 0fb3ff6c53 deleted useless logs 2022-12-30 02:38:28 +03:00
abslike 7fbfbd1e1e Fix Monet on nonmilkshake (#991) 2022-12-30 02:35:08 +03:00
gdlbo 71de558e5c ssfs update
added support for im banners
2022-12-30 02:31:09 +03:00
gdlbo 606b89a4ec ssfs update
added profile hide
2022-12-30 01:34:15 +03:00
Vologhat b4bdb3070a fix tgs preference summary 2022-12-29 20:53:01 +03:00
Vologhat 9f4b5990b7 refactor PreferencesUtil.java to PreferenceFragmentUtils.java 2022-12-29 19:08:15 +03:00
Vologhat 93b28b0a8f add non-null annotation 2022-12-29 19:04:11 +03:00
gdlbo ed0587b9b6 Merge pull request #988 from psamur/main
"View all..." normal translation
2022-12-29 10:43:16 +03:00
Pavel 6ce72dfc8b - bad translate + normal translate requested in VKTCH 2022-12-29 01:21:10 +03:00
gdlbo 65f44d32ca Update ThemesUtils.java 2022-12-28 23:41:45 +03:00
k1zn 8e57d5ab44 fix crash notf name and translate
crash
2022-12-29 00:52:17 +05:00
gdlbo c2b6bffb17 added articles colors inj 2022-12-28 22:17:43 +03:00
gdlbo 550fbf8f6c Merge pull request #982 from abslike/patch-2
Fix monet in messages(nomilkshake)
2022-12-28 22:01:49 +03:00
gdlbo 79d3287143 fixed #969 again for muted accent 2022-12-28 21:56:34 +03:00
gdlbo 2242e37315 fixed outgoing msg highlighted status 2022-12-28 21:50:21 +03:00
gdlbo 7099da0387 fixed searchDialog 2022-12-28 21:39:56 +03:00
k1zn 9b29288351 fix #986 2022-12-28 22:07:03 +05:00
abslike e000bd7971 Fix monet in messages(nomilkshake) 2022-12-28 00:40:24 +05:00
gdlbo 8eb725148f added search engine selection 2022-12-27 18:05:54 +03:00
gdlbo af1d175415 fix #969 2022-12-27 16:28:19 +03:00
Vologhat 92edbd4686 add keyaboard popup 2022-12-27 16:20:31 +03:00
gdlbo 8d9812ebe0 fix #978 2022-12-27 15:54:55 +03:00
gdlbo 33477e809c fixed #974 2022-12-27 15:22:10 +03:00
Vologhat 04f4f7d2ad fix #972 2022-12-27 11:54:08 +03:00
gdlbo 80b8399cb8 added link to bot in tg stickers info 2022-12-27 01:05:51 +03:00
gdlbo 483c9eda4d added more anime pic search engine 2022-12-27 00:38:38 +03:00
gdlbo c76a7a5332 fixed crash SYSTEM_UI_FLAG_LIGHT_STATUS_BAR 2022-12-26 23:20:07 +03:00
gdlbo c470062d70 fixed crash getColor 2022-12-26 23:11:42 +03:00
gdlbo 52f69c792d fixed google pic search for Ukraine users 2022-12-26 21:51:45 +03:00
Vologhat 33f150eb43 uncomment and refactor ota code 2022-12-26 21:49:48 +03:00
gdlbo e165f388f5 fixed google pic search 2022-12-26 21:39:24 +03:00
Vologhat 761ff263be fix qualities list sorting 2022-12-26 20:46:47 +03:00
gdlbo 8918f203fc disabled accent for nonmilk 2022-12-26 19:29:46 +03:00
gdlbo 6039d0cf43 fixed msgs 2022-12-26 13:32:30 +03:00
gdlbo af902f945e Update styles.xml 2022-12-26 13:12:44 +03:00
gdlbo a90d96b00f disabled accents in nonmilk + enabled monet for nonmilk 2022-12-26 12:14:25 +03:00
gdlbo 550d3dadd8 some themesutils code fixes 2022-12-26 11:58:53 +03:00
gdlbo 82720adb61 fixed statusbar in audioplayer 2022-12-26 11:29:41 +03:00
gdlbo 2a3e12b39a fixed borders in monet 2022-12-26 11:06:43 +03:00
gdlbo 87407b0007 fixed accent hardcode in search 2022-12-26 10:50:44 +03:00
gdlbo ff2e33d9a2 fixed header text in monet nonmilk 2022-12-25 19:02:05 +03:00
Vologhat 61b6b0a1ec replace qualified name with import 2022-12-25 18:43:36 +03:00
gdlbo 9db18f526a Update ThemesCore.java 2022-12-25 18:31:10 +03:00
gdlbo 043253ffff disabled outgoing msg accenting in dark theme 2022-12-25 18:02:56 +03:00
gdlbo 756ab2b7c0 fixed muted colors on nonmilk 2022-12-25 17:56:59 +03:00
gdlbo 2ba5aef993 fixed accents exceptions 2022-12-25 17:54:08 +03:00
gdlbo ab3bd09ab7 fixed colors exceptions 2022-12-25 17:35:58 +03:00
gdlbo 7990d269aa refactored icon manager 2022-12-25 16:58:13 +03:00
gdlbo fffda61a83 fixup! disabled monet for nonmilk 2022-12-25 16:04:25 +03:00
gdlbo d817ccd292 disabled monet for nonmilk 2022-12-25 16:03:31 +03:00
gdlbo 02de3699cc fixed fix separator
dead fix xd
2022-12-24 13:53:53 +03:00
aliveoutside 81b214bcff fix vkui BottomConfirmButton 2022-12-24 13:24:17 +03:00
gdlbo 5dcf50fdc2 some sharing dialog fixes 2022-12-24 12:46:38 +03:00
gdlbo 81d4f9ec99 fixed search bar tint 2022-12-23 17:19:30 +03:00
gdlbo 29596b5dd1 fixed menu items coloring with monet theme 2022-12-23 17:10:30 +03:00
gdlbo b789840498 fixed control_foreground + control_background 2022-12-23 16:18:40 +03:00
gdlbo fce6c2b14f fixed vkim unread dot text 2022-12-23 16:05:54 +03:00
aliveoutside f2ac2c6a37 [monet] impl disabled buttons color 2022-12-23 15:45:40 +03:00
aliveoutside 61881f4e9d [monet] improve vkui buttons 2022-12-23 15:31:54 +03:00
aliveoutside 92f74aa5fb [monet] fix friends recom card background 2022-12-23 15:13:48 +03:00
aliveoutside 0c968de977 [monet] fix buttons tint in friends list 2022-12-23 14:51:50 +03:00
gdlbo 51efc8f4c6 disabled alpha picker 2022-12-21 19:41:33 +03:00
aliveoutside 4dbf1756e1 [monet] fix icon placeholder color on amoled theme 2022-12-21 19:16:24 +03:00
aliveoutside 8d4d88e099 [monet] fix icon placeholder color on dark theme 2022-12-21 19:10:28 +03:00
aliveoutside dd953d39e7 [monet] fix icon placeholder color 2022-12-21 18:52:26 +03:00
aliveoutside 4902938016 [monet] add a small accent to background_content 2022-12-21 18:36:16 +03:00
gdlbo 54de4fd060 Update styles.xml 2022-12-21 18:33:08 +03:00
gdlbo 6d9f3029d3 Update styles.xml 2022-12-19 14:23:52 +03:00
gdlbo 332fe678b9 Update styles.xml 2022-12-19 13:49:55 +03:00
gdlbo 04eee5cc26 Update JsonInjectors.java 2022-12-19 13:33:35 +03:00
Vologhat bc94f1ac77 reduce redundant reflection usage 2022-12-17 14:51:39 +03:00
gdlbo fc423d5ccd fixed cards colors 2022-12-16 20:31:28 +03:00
gdlbo f0993bee15 Update HomeFragment.smali 2022-12-16 19:58:28 +03:00
k1zn 22ef4bd646 Update strings.xml 2022-12-16 19:24:16 +05:00
k1zn c4cc678c82 add summary to themes 2022-12-16 19:22:47 +05:00
k1zn 350c25faff translate 2022-12-16 19:08:41 +05:00
aliveoutside 89ea35dd82 [monet] make newsfeed less ugly 2022-12-16 17:04:46 +03:00
aliveoutside cd858266a8 fix highlight monet color by @absl1ke 2022-12-16 16:42:11 +03:00
gdlbo 0549b07c49 Update stickers_keyboard_navigation.xml 2022-12-14 17:22:46 +03:00
gdlbo a7fd5536f6 fixed writebar issues 2022-12-14 17:11:29 +03:00
gdlbo 1397653b55 disabled NOTIFICATION_ANIM toggle 2022-12-14 15:57:59 +03:00
gdlbo ec1a0fc2d5 separator fixes 2022-12-14 15:57:47 +03:00
gdlbo b75dca5515 disabled shadow in milk news 2022-12-14 15:57:36 +03:00
gdlbo f31fade75a disabled clipdata ddos 2022-12-14 15:57:24 +03:00
gdlbo 347e0fb9c4 some monet fixes 2022-12-14 15:01:07 +03:00
gdlbo bf1a73f606 Update build.gradle 2022-12-13 22:10:23 +03:00
gdlbo 82e268ffa7 Update styles.xml 2022-12-13 22:10:11 +03:00
gdlbo f3acbf74a8 Update ThemesUtils.java 2022-12-13 20:37:22 +03:00
gdlbo 7126af6240 Update styles.xml 2022-12-13 20:20:29 +03:00
gdlbo ef2946a700 Update PhotoViewer.java 2022-12-13 20:08:09 +03:00
gdlbo 8821574412 fix 2022-12-13 19:59:20 +03:00
gdlbo 8257a374da monet separator fixes 2022-12-13 19:46:47 +03:00
gdlbo 3985593842 Update build.gradle 2022-12-13 18:54:23 +03:00
gdlbo 92d8c9a90d Update styles.xml 2022-12-12 22:41:56 +03:00
gdlbo 6f9c325b0d Update styles.xml 2022-12-12 22:37:02 +03:00
gdlbo 1010821cf4 Revert "add CompoundButton hook"
This reverts commit 04488314b5.
2022-12-12 22:16:08 +03:00
gdlbo 012dfa7063 fixed cards in monet style 2022-12-12 21:56:49 +03:00
gdlbo 01adf656e2 added support for monet light style 2022-12-12 17:04:37 +03:00
gdlbo bb64ed8d2a monet prefs imp 2022-12-12 16:47:08 +03:00
gdlbo 1ec78a8fbd some theme upgrades
monet theme disabled
amoled theme switch
some fixes with vkui inj
2022-12-12 16:34:52 +03:00
k1zn f1436ebbde fix music downloading with proxy 2022-12-11 23:32:13 +05:00
k1zn c4efb751c9 miui checks fix 2022-12-11 18:23:40 +05:00
Vologhat 6e902d4bca add miui checks 2022-12-11 15:54:03 +03:00
Vologhat 07b49a4a74 Merge branch 'main' of https://github.com/vtosters/lite 2022-12-11 15:51:22 +03:00
gdlbo c6fdf65137 fixed btns color 2022-12-11 15:50:59 +03:00
gdlbo 18e2554d5e fixed btns color 2022-12-11 14:17:03 +03:00
Vologhat 04488314b5 add CompoundButton hook 2022-12-11 14:12:29 +03:00
gdlbo 3eec52db3b fixed null crash csl in BottomNavigationItemView 2022-12-11 14:00:25 +03:00
gdlbo 132df6080e added useful feature 2022-12-11 13:33:55 +03:00
gdlbo d8f91bc730 fixed vologhat's best code reviewing 2022-12-11 13:32:44 +03:00
Vologhat 270c2af5c1 small messages downloader refactoring 2022-12-10 22:41:31 +03:00
Vologhat 99c500ed69 load placeholder image firstly 2022-12-10 22:21:40 +03:00
gdlbo 8174be1768 updated monet theme 2022-12-10 12:51:14 +03:00
Vologhat a88f59bac1 load user avatar image asynchronously 2022-12-09 21:03:50 +03:00
aliveoutside 1eaa3748c4 Merge remote-tracking branch 'origin/main' 2022-12-09 18:39:18 +03:00
aliveoutside 27836f72f5 Merge branch 'accents' 2022-12-09 18:35:03 +03:00
Saoqqandsaoq 70e048a1ad Add zipalign to CI and build.sh (#928)
* Add zipalign to CI and build.sh

* Revert accidentally removed cleanup

Co-authored-by: saoq <wfmfe@ya.ru>
2022-12-09 18:33:44 +03:00
aliveoutside e915b26918 fix incorrect downloaded tracks length
closes #868
2022-12-09 18:07:40 +03:00
gdlbo 8a6a92f77b upgraded color refs 2022-12-08 14:36:33 +03:00
gdlbo cb492b5949 handle color + highlight color fix 2022-12-08 13:43:57 +03:00
gdlbo f15e4c004d color handles 2022-12-08 13:28:50 +03:00
gdlbo f7f2cf3e58 color cursor 2022-12-08 13:01:22 +03:00
gdlbo 578fa86f19 Update ThemesUtils.java 2022-12-07 18:46:23 +03:00
gdlbo a9bcb19ebf Update StandartFilter.txt 2022-12-07 18:40:07 +03:00
gdlbo cf6b993172 Update EditTextExt.smali 2022-12-07 18:32:34 +03:00
gdlbo 145a6a668b Update date_picker_selector.xml 2022-12-07 18:08:37 +03:00
gdlbo 6b2752db67 Update ColorReferences.java 2022-12-07 18:03:51 +03:00
gdlbo 58fb6224f4 color imp 2022-12-07 17:51:53 +03:00
gdlbo b6406bcebf fixed some coloring 2022-12-07 17:33:21 +03:00
gdlbo 6c7733f1a0 updated code 2022-12-07 17:17:04 +03:00
gdlbo 5373002666 some mbsh updates 2022-12-07 16:49:58 +03:00
gdlbo 4005ac2ef1 Update ColorReferences.java 2022-12-07 10:26:47 +03:00
gdlbo 30de30cf64 fixed many colors 2022-12-07 01:41:22 +03:00
gdlbo 0feeacb533 Update ColorReferences.java 2022-12-06 22:03:17 +03:00
gdlbo de511d15a6 some code upgrades 2022-12-06 18:45:33 +03:00
aliveoutside dc1be1434a Merge pull request #931 from rekayno/patch-1
Update build.yml
2022-12-06 18:32:45 +03:00
gdlbo 6b88996962 fixed ssfs 2022-12-06 16:59:22 +03:00
gdlbo bb35b2b252 Update styles.xml 2022-12-05 17:14:51 +03:00
gdlbo b2f1cfea5e Update ThemesUtils.java 2022-12-05 16:38:44 +03:00
gdlbo 2748ec6902 added muted coloring 2022-12-05 16:19:05 +03:00
gdlbo 17b9c7075e muted accent 2022-12-05 15:20:28 +03:00
gdlbo fd070323b0 Update TextViewHook.java 2022-12-05 14:49:26 +03:00
gdlbo 03a43326b7 tablayout color fix 2022-12-05 14:34:02 +03:00
gdlbo a0b28b6c12 fixed crash 2022-12-05 13:34:48 +03:00
gdlbo 5d46edb91a Update TogglesHook.java 2022-12-05 13:32:41 +03:00
gdlbo 0e751533b5 fixed crashes 2022-12-05 12:53:58 +03:00
gdlbo 32d5ba792a Update PhotoListFragment.smali 2022-12-05 12:47:45 +03:00
gdlbo eb96137c3a ultra upgraded theming csl 2022-12-05 01:20:02 +03:00
gdlbo 09f7a07226 Update SuperAppEditorFragment.java 2022-12-05 00:52:56 +03:00
gdlbo 251f9935aa fixed toolbar 2022-12-05 00:43:20 +03:00
gdlbo a75070f8d3 Update ToolbarHook.java 2022-12-05 00:04:04 +03:00
gdlbo 972921a05c OverlayTextView hooked 2022-12-04 23:31:38 +03:00
gdlbo 3b2586ade5 some hooks update 2022-12-04 23:11:07 +03:00
gdlbo 58ea05cc9d updated toolbar icons hook 2022-12-04 22:33:13 +03:00
gdlbo 441baac671 Update ViewInjector.java 2022-12-04 22:23:34 +03:00
Vologhat a1efd38048 add toolbar icons hook 2022-12-04 22:21:40 +03:00
gdlbo d8be2fe7b7 some hooks updates 2022-12-04 22:14:29 +03:00
k1zn 27fdbf2407 [accents] translate colorpickers 2022-12-04 17:27:31 +05:00
k1zn fd954f5bab [accents] translate 2022-12-04 01:21:48 +05:00
gdlbo 3295e40231 Update vkim_bg_dialog_bar_button_primary.xml 2022-12-03 16:15:54 +03:00
gdlbo f88596025f fixed sending icon im msgs 2022-12-03 15:22:34 +03:00
gdlbo 9c5f584d1b disabled calls button 2022-12-03 15:19:20 +03:00
gdlbo 537a3759d0 fixed accent resetting 2022-12-03 14:57:12 +03:00
gdlbo f2fcc5f4d1 some hardcode color fixes 2022-12-02 19:58:09 +03:00
gdlbo db651c462a Update ThemesFragment.java 2022-12-02 19:27:13 +03:00
gdlbo 4f06fda96d Update styles.xml 2022-12-02 19:19:22 +03:00
gdlbo 1344e88b95 added alpha dark/amoled theme monet on sdk 31
todo light theme
2022-12-02 18:53:20 +03:00
Vologhat 23dd5a71e0 add new accent choices 2022-12-02 18:48:47 +03:00
Vologhat 810e5c72c1 add palettes 2022-12-02 18:48:22 +03:00
Vologhat 045daeea47 update ModalBottomSheetWrapper 2022-12-02 18:45:40 +03:00
Vologhat f45de44c75 add color picker by Martin Stone
Add own modification of HSV-Alpha Color Picker for Android https://github.com/martin-stone/hsv-alpha-color-picker-android
2022-12-02 18:37:12 +03:00
gdlbo d2911e5b6b updated msg colors 2022-12-02 14:52:54 +03:00
gdlbo 576890189c fixed accent fragment and color resetting 2022-12-02 13:44:08 +03:00
gdlbo 5ce6ab3aa8 removed global context from adding prefs 2022-12-02 13:43:50 +03:00
Vologhat 1451e2d3ac downgrade buildToolsVersion 2022-12-02 11:53:39 +03:00
Vologhat 95958a85e9 Update IOUtils.java 2022-12-02 11:52:49 +03:00
Vologhat 9f2b3edbe8 Update IOUtils.java 2022-12-01 23:23:55 +03:00
gdlbo ee4249c688 Revert "Update IOUtils.java"
This reverts commit 2f46c193dd.
2022-12-01 23:17:40 +03:00
Vologhat 2f46c193dd Update IOUtils.java 2022-12-01 23:08:29 +03:00
Vologhat 09807a2954 coloring outgoing messages in accent 2022-12-01 22:52:21 +03:00
gdlbo 163cd44dcc getAccenedColorStateList 2022-12-01 21:45:40 +03:00
gdlbo 2bdff722d4 Updated default accent color 2022-12-01 20:46:49 +03:00
gdlbo e206e85324 updated color hooks 2022-12-01 20:34:48 +03:00
rekayno 40159a2a9f Update build.yml
update actions
2022-11-30 17:00:49 +03:00
Denis 54d59e1f2f Update README.md 2022-11-30 15:01:33 +05:00
Vologhat 1b797325f0 Update MessagesPreviewAdapter.java 2022-11-30 11:49:02 +03:00
Vologhat 63c3c0ee32 refactoring 2022-11-30 00:26:58 +03:00
Vologhat 4b6a7aeb84 invalidate color state of dockbar tab titles 2022-11-29 23:16:36 +03:00
Vologhat 38f65997a6 add input format for color string, and reset button 2022-11-29 22:13:30 +03:00
Vologhat d718851d0c fix accent color resetting 2022-11-29 16:00:31 +03:00
gdlbo b30ad26f54 fixed vk cringe bg color in volume control 2022-11-28 12:23:26 +03:00
gdlbo 5f5fb650f2 fixed volume control color 2022-11-28 12:06:05 +03:00
gdlbo 76260981c5 disabled useless hide button 2022-11-28 12:01:29 +03:00
gdlbo ceb84ed6f6 reply bar fix 2022-11-28 11:51:47 +03:00
gdlbo e8a2c3af56 ssfs update 2022-11-27 15:20:27 +03:00
gdlbo 80e78fa2c1 some music coloring 2022-11-27 02:34:22 +03:00
gdlbo 7b35501461 coloring playlists icons 2022-11-27 02:13:40 +03:00
gdlbo c9cfc5e749 updated msg recoloring 2022-11-27 00:36:39 +03:00
gdlbo f0a915be05 Merge pull request #920 from Saoqq/r/sh-build-script
Refactor buildscripts
2022-11-26 18:19:26 +03:00
saoq f2b8624cc4 Update README.md 2022-11-26 01:38:33 +03:00
saoq ccaa10d224 Extract dex move to gradle task, apply to CI .yml 2022-11-26 01:38:22 +03:00
saoqq 6325d8fe68 Remove complication for Win script call, fix sh script invocation 2022-11-25 23:04:37 +03:00
saoqq e243522f95 Ensure Win buildscript works 2022-11-25 21:52:22 +03:00
saoq d87a59bcb0 Refactor build scripts 2022-11-25 08:56:52 +03:00
saoq 724fafc3fd Make build.sh dir independent 2022-11-25 06:13:31 +03:00
gdlbo 8c03ab60fc updated attrs and some swipe coloring 2022-11-24 15:00:02 +03:00
gdlbo 985ced6e3c deleted useless hook 2022-11-24 11:57:49 +03:00
aliveoutside 88339feb12 [accents] create a separate fragment for accents 2022-11-23 23:29:01 +03:00
aliveoutside 2bcf5d1c2d [accents] highlight edittext field 2022-11-23 23:08:01 +03:00
aliveoutside 77f9c60be7 [accents] replace AlertDialog with VkAlertDialog 2022-11-23 23:06:31 +03:00
aliveoutside 76468d8863 [WIP] Accent picker in settings 2022-11-23 22:24:25 +03:00
gdlbo c17e604db6 fixed cringe code + coloring bug 2022-11-22 22:31:32 +03:00
gdlbo 1a96f77aa1 some crash fixes 2022-11-22 21:34:48 +03:00
gdlbo 3fd0757fd4 Update DialogActionsListView.smali 2022-11-22 21:06:26 +03:00
gdlbo 989075a3d2 Update DrawableExt.smali 2022-11-22 20:21:29 +03:00
aliveoutside 802d88cad7 fix AppCompatResources 2022-11-22 20:09:12 +03:00
gdlbo 95a0451c6b fixed dw coloring 2022-11-22 20:06:56 +03:00
aliveoutside 3b83f05bf0 init ThemesCore 2022-11-22 19:08:47 +03:00
aliveoutside c7d350f5b1 remove logger from TextViewHook 2022-11-22 19:08:39 +03:00
gdlbo d3eeaf5f23 removed some hardcode 2022-11-22 19:06:06 +03:00
aliveoutside 4dcea46be7 recolor CSL where it is possible 2022-11-22 18:06:32 +03:00
aliveoutside 96de61fd15 move some stuff from ThemesUtils 2022-11-22 18:00:12 +03:00
aliveoutside 47f4c5c911 Init 2022-11-22 16:58:09 +03:00
aliveoutside fcbf9238cf wait for the pfp loaded in settings
fixes #912
2022-11-21 10:51:05 +03:00
gdlbo 4a8a2adb4e Update MediaFragment.java 2022-11-14 21:06:03 +03:00
gdlbo 501e39429b Update WebCachePreloader.smali 2022-11-14 15:38:05 +03:00
gdlbo 604d19cc40 upgraded link parser 2022-11-14 14:56:21 +03:00
gdlbo a29e0dcf4b fixed articles 2022-11-14 14:26:42 +03:00
gdlbo ec551dcb33 BusinessNotif disabler 2022-11-13 20:33:46 +03:00
gdlbo cc4690965a Update preferences_feed.xml 2022-11-13 19:47:31 +03:00
gdlbo 65f32d3686 fixed articles 2022-11-13 18:15:33 +03:00
gdlbo bf15bb93ee support story download to video downloader btn 2022-11-10 15:27:15 +03:00
gdlbo cb3c537f1d updated ad filter 2022-11-10 14:58:44 +03:00
Vologhat bb0c845e74 Merge branch 'main' of https://github.com/vtosters/lite 2022-11-09 17:15:32 +03:00
Vologhat a4c88d0924 Fix video downloader 2022-11-09 17:14:00 +03:00
gdlbo 7f0b6c3c3d disabled undelete by default 2022-11-09 16:20:17 +03:00
gdlbo 31eedf4d6d updated feed settings 2022-11-09 11:48:31 +03:00
gdlbo bf23cc7305 deleted unused features 2022-11-09 11:09:57 +03:00
gdlbo 6bef2f1ea9 upd proxy information 2022-11-09 11:02:06 +03:00
gdlbo e561356690 deleted video analytics 2022-11-09 10:31:59 +03:00
gdlbo 64d6e4b529 deleted old abt lib 2022-11-09 10:20:40 +03:00
gdlbo 34d067d192 deleted some vk perf trackers 2022-11-08 18:53:02 +03:00
gdlbo c50511a12f deleted vk updates + google play core 2022-11-08 18:33:37 +03:00
gdlbo 0b748c16e4 deleted google ads lib 2022-11-08 18:21:46 +03:00
gdlbo f88dd17480 deleted measurement lib 2022-11-08 18:16:49 +03:00
gdlbo 892e9874cb deleted 60% of firebase lib 2022-11-08 18:11:34 +03:00
gdlbo 82a24e4abf Update GetFullUserProfile.smali 2022-11-08 16:18:57 +03:00
gdlbo 2631757a05 updated TGS Grabber
@egormetlitsky
2022-11-08 16:01:26 +03:00
gdlbo b2f7754ec9 updated old token req 2022-11-08 15:29:28 +03:00
aliveoutside 2175800f33 run auto code reformat 2022-11-02 16:10:56 +03:00
aliveoutside ab16fdcecb optimize imports 2022-11-02 16:01:38 +03:00
aliveoutside a34cad6837 move everything music related to "music" package 2022-11-02 15:57:23 +03:00
k1zn 34b2357a20 translate + move music settings above 2022-10-31 13:35:12 +05:00
gdlbo e47d6acbf1 fixed show cached pl 2022-10-30 00:54:59 +03:00
aliveoutside a5bd532570 use a singleton for okhttp so it will reduce OkHttpClients count 2022-10-29 19:16:21 +03:00
aliveoutside e4124f459f [music] move catalog json injector to separate package 2022-10-29 18:45:48 +03:00
aliveoutside 03328137df [music] fix not loading "main" page 2022-10-29 18:19:27 +03:00
Vologhat 906036854c maybe music fix 2022-10-29 17:57:39 +03:00
gdlbo 1dad82d61c Update MediaFragment.java 2022-10-28 03:51:39 +03:00
gdlbo 0d9f8360ce Update MediaFragment.java 2022-10-28 03:43:59 +03:00
gdlbo 5dc5f001f2 new feature old music catalog 2022-10-28 03:41:55 +03:00
gdlbo b6d26515ce added support of cache pl to empty pl catalog 2022-10-28 03:37:30 +03:00
gdlbo f02971e00d Update build.gradle 2022-10-28 03:00:01 +03:00
gdlbo 827bb9d9ce refactored catalog injector for caching 2022-10-28 02:57:28 +03:00
gdlbo 4a5a6b58e1 Update JsonInjectors.java 2022-10-26 10:36:25 +03:00
gdlbo fa2a1b083d AppVerHook 2022-10-26 10:11:24 +03:00
gdlbo d372b670c0 AppVerHook 2022-10-26 08:01:33 +03:00
gdlbo 86afcaeacb Update ModernSearchView.smali 2022-10-26 07:50:41 +03:00
gdlbo 027c7a7151 fix null crash 2022-10-26 00:09:32 +03:00
aliveoutside 7f304950a8 [music] support new catalogs 2022-10-22 20:32:16 +03:00
Vologhat fc44a9b263 fix apk install 2022-10-20 21:28:11 +03:00
Vologhat 235b287a36 fix telegram stickers notification crash 2022-10-18 16:14:47 +03:00
Vologhat 9317e86d66 Update build.gradle 2022-10-15 21:46:21 +03:00
aliveoutside 23f1b6c26b load ffmpeg-kit directly from libs folder via System.loadLibrary
add arm64 libs
2022-10-15 21:43:03 +03:00
aliveoutside a7d50bca26 remove ffmpeg libs from assets 2022-10-15 21:40:23 +03:00
aliveoutside 92fbd071de reduce ffmpeg-kit size 2022-10-15 21:12:56 +03:00
Vologhat b7860b857f Updated arm32-v7a libs 2022-10-15 20:20:36 +03:00
Vologhat cd0914041d arm64-v8a support 2022-10-15 15:05:41 +03:00
Vologhat 9f0230d935 Update R.java 2022-10-14 22:19:38 +03:00
Vologhat a05865c6a8 Added R.java generator and executing scripts 2022-10-14 22:14:56 +03:00
k1zn d678ff5e9b translate 2022-10-14 19:35:37 +05:00
gdlbo 4829acd869 fix slow stickers load + some imp 2022-10-14 00:43:17 +03:00
gdlbo 6df6fdf01c miniapps ban 2022-10-14 00:08:23 +03:00
k1zn 4a2e73d676 fix context crash 2022-10-13 21:44:37 +05:00
aliveoutside 4c5a1c5a17 download track synchronously 2022-10-13 03:17:17 +03:00
aliveoutside 1aedacf401 remove useless ffmpeg banner in logs 2022-10-13 03:17:05 +03:00
aliveoutside 9d4bffd8aa use an executor to download tracks 2022-10-13 02:52:23 +03:00
aliveoutside ede17b31a2 move vkexecutors receiving to separate package 2022-10-13 02:52:23 +03:00
aliveoutside e94f93facb update telegram stickers entry icons 2022-10-13 02:52:23 +03:00
gdlbo 2460b27af1 Update LastFMScrobbler.java 2022-10-12 23:59:50 +03:00
gdlbo 9cb9bf4167 max quality for external videos 2022-10-12 22:04:08 +03:00
gdlbo 6753dc9a8c superapp restart app 2022-10-12 21:34:05 +03:00
gdlbo c257e3a5ce refactored video alert adapter 2022-10-12 21:28:02 +03:00
k1zn a055656424 в 2022-10-12 18:30:06 +05:00
k1zn 4882315bf4 another translate 2022-10-12 18:27:31 +05:00
k1zn 1d8f998a5f translate 2022-10-12 18:08:13 +05:00
k1zn ff945b76b8 fix localization bug 2022-10-12 17:50:34 +05:00
gdlbo 2d14c78a90 fixed some long titles 2022-10-12 03:13:52 +03:00
gdlbo 10d1a40bd8 some code imp 2022-10-12 02:35:36 +03:00
gdlbo 78e3757cf4 deleted unused code 2022-10-12 01:58:02 +03:00
gdlbo 2aef797efe some dev fixes 2022-10-12 01:24:50 +03:00
gdlbo 20999810ab fixed load verifs from notif 2022-10-12 00:48:03 +03:00
gdlbo d8c45ffeff fix #695 2022-10-12 00:33:40 +03:00
gdlbo 05d339eeb0 fix #695 2022-10-12 00:29:01 +03:00
gdlbo e50366da8a added #701 2022-10-12 00:02:53 +03:00
gdlbo 915b31477b fix 700 2022-10-11 23:50:15 +03:00
aliveoutside 9d2878b9dc revert "fixed redundant thread creation" b9a55799
it breaks Telegram stickers downloading, we'll investigate later
2022-10-09 15:54:26 +03:00
gdlbo bcfefe777d fix executer 2022-10-09 01:38:47 +03:00
k1zn b69e55606a fix some mistake 2022-10-09 02:32:17 +05:00
k1zn 2f06d2a008 refactoring autocache code 2022-10-09 02:31:08 +05:00
aliveoutside d151d27063 fix #831 2022-10-09 00:23:35 +03:00
gdlbo ad128f1e7e Update OTADownloader.java 2022-10-08 23:52:22 +03:00
gdlbo efe8a2c883 fix toast dl dialogs 2022-10-08 23:11:19 +03:00
aliveoutside 5def26131b [foaf] fix regexes and run the dialog from ui thread 2022-10-08 23:06:53 +03:00
gdlbo a586e4e240 Update FoafBase.java 2022-10-08 22:46:31 +03:00
Vologhat 5e66a5b924 Merge branch 'main' of https://github.com/vtosters/lite 2022-10-08 20:54:54 +03:00
Vologhat 98a58c9e94 regenerated R.java and public.xml, replaced getIdentifier calls to id constants 2022-10-08 20:54:18 +03:00
aliveoutside baba2c0009 [music] download playlist synchronously 2022-10-08 17:45:36 +03:00
aliveoutside 2ae3f48d9a [music] move temp tses dir to app internal storage 2022-10-08 17:45:36 +03:00
k1zn 9e5eae49d1 remove shadow from attachments 2022-10-08 19:19:36 +05:00
Vologhat 9e50a116ef Merge pull request #824 from zelvalea/main
Чрезмерное создание потоков
2022-10-08 14:23:37 +03:00
Vologhat 19fb86ca58 refactored last.fm scrobbler 2022-10-08 10:37:47 +03:00
zelva e7db1e2359 cleanup and fixed unwanted races 2022-10-07 14:42:04 +03:00
aliveoutside bc25be1a27 Merge pull request #823 from vtosters/gettext-removing
remove clipdata$item gettext
2022-10-07 12:21:58 +03:00
k1zn a583c98f44 fix renaming app bug 2022-10-06 18:24:57 +05:00
gdlbo d40162caa1 disabled auto theme for non milk users 2022-10-05 20:57:15 +03:00
Sunmisc 5bc4451355 cleanup 2022-10-05 16:22:20 +03:00
Sunmisc b62de5b90e cleanup 2022-10-05 16:21:59 +03:00
Sunmisc e79322a18c cleaned up and got rid of deprecated class 2022-10-05 16:16:34 +03:00
Sunmisc b9a55799fe fixed redundant thread creation 2022-10-05 15:49:25 +03:00
gdlbo 9ba210e166 fixed crash 2022-10-05 15:33:34 +03:00
k1zn eab3549ff9 remove clipdata$item gettext 2022-10-05 16:58:25 +05:00
Vologhat 98bbdf872b returned alert dialog for disabling Doze and refactored code 2022-10-04 00:51:16 +03:00
Vologhat d17e4849eb remove comment 2022-10-04 00:28:34 +03:00
Vologhat 18709ac89f added permission in AndroidManifest.xml for ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS flag 2022-10-04 00:27:50 +03:00
gdlbo 9de8e3e409 newsfeed notif counter feature 2022-10-03 23:53:59 +03:00
gdlbo 3f3d1c7f28 Update DisableBattery.java 2022-10-03 22:59:55 +03:00
gdlbo 5250ba39d2 Update ContactsUtils.java 2022-10-03 22:59:48 +03:00
gdlbo ae08e57c80 magic fix 2022-10-03 21:29:04 +03:00
gdlbo 2f24eb6145 Update README.md 2022-10-03 20:28:43 +03:00
Denis 88fa60fcfb Update README.md 2022-10-03 20:19:28 +03:00
Denis df2d5ceb12 Update README.md 2022-10-03 20:19:28 +03:00
Denis f2bc275430 Update README.md 2022-10-03 20:19:28 +03:00
Denis fbf7a3520b Update README.md 2022-10-03 20:19:28 +03:00
Denis 510952913b Update features.md 2022-10-03 20:19:28 +03:00
Denis 39c05533d0 Create features.md 2022-10-03 20:19:28 +03:00
gdlbo 4f7d00b0a0 fixed saving pics...? 2022-10-03 19:53:33 +03:00
k1zn 12e9c14838 Update README.md 2022-10-03 20:17:31 +05:00
k1zn 072fd007ca Update README.md 2022-10-03 19:57:43 +05:00
k1zn 002bf7e155 Update README.md 2022-10-03 19:55:17 +05:00
gdlbo 1a8da81f1e added settings tab name in tabbar 2022-10-03 11:56:51 +03:00
gdlbo 4ca5f7d2c5 fixed def system theme val 2022-10-03 11:45:41 +03:00
gdlbo 4bcbaf0d7a Update Scrobbler.java 2022-10-03 02:59:31 +03:00
gdlbo eb95b8f41e fixed autocaching 2022-10-03 02:12:44 +03:00
gdlbo f77fb0152e fixed caching path 2022-10-03 01:27:40 +03:00
gdlbo 528736a18e fixed crash 2022-10-03 01:22:46 +03:00
Pavel f00084692f songs -> tracks, new cache playlist cover 2022-10-02 21:51:52 +05:00
Pavel 901b6b5cf8 update cache playlist cover 2022-10-02 21:51:52 +05:00
aliveoutside a4711ffd4b [music] remove duplicate notification about track caching 2022-10-02 19:45:10 +03:00
aliveoutside aacfad3122 [music] fix "Unable to play track" if album is null 2022-10-02 19:32:12 +03:00
aliveoutside e53f1efc2d [music] scrobble album if it is not empty 2022-10-02 19:28:07 +03:00
aliveoutside 8e85844bd3 [music] insert the cached track only if it not in database, else ignore 2022-10-02 18:41:47 +03:00
aliveoutside a5ac9f35e7 [music] don't cache the track if it is cached already 2022-10-02 18:29:35 +03:00
gdlbo 65244f254a Update SystemInfo.java 2022-10-01 23:08:24 +03:00
gdlbo 88c150fcfc some music cache imp 2022-10-01 19:02:25 +03:00
k1zn a0b23f8590 return notif counter for newsfeed (on milkshake) 2022-10-01 17:44:39 +05:00
gdlbo d4cebf403a added cached playlist in online 2022-09-30 21:03:34 +03:00
Erik Kiznov 86ab876cff update logos link in readme 2022-09-29 23:45:42 +05:00
Erik Kiznov 2c69214210 newsfeed - default value "recent" 2022-09-29 23:21:59 +05:00
Erik Kiznov 1cfc61d6f5 fix null str in friends requests 2022-09-29 22:29:41 +05:00
gdlbo 29a98e6360 fixed crash 2022-09-29 20:25:44 +03:00
Erik Kiznov 01a8be4e18 hide "user_message" in friend request item 2022-09-29 18:58:22 +05:00
Erik Kiznov 2c3415839e Update FriendsGetRequests$a.smali 2022-09-29 18:41:21 +05:00
gdlbo 0c3d7f1d73 fixes detection 2022-09-28 17:45:01 +03:00
gdlbo 576999b582 added device info frag + fixed miui detection 2022-09-28 17:40:37 +03:00
gdlbo 0af6f8166d Update Preferences.java 2022-09-27 21:27:30 +03:00
gdlbo 750c166961 Update Preferences.java 2022-09-27 21:25:11 +03:00
Vologhat 4d7d5ea125 "getprop" execution to reflection replacement for reason XIAOMI 2022-09-27 21:21:41 +03:00
Vologhat c8e6468068 fix xiaomi shit (maybe) 2022-09-27 20:50:54 +03:00
gdlbo 00fdbe371f some imp 2022-09-27 20:25:42 +03:00
Vologhat b6f8707a60 added one ui check and miui ui version info 2022-09-27 19:03:04 +03:00
gdlbo 3be07cb211 some themes ref 2022-09-27 18:27:24 +03:00
Vologhat cfed0a59ff code refactoring 2 2022-09-27 17:23:52 +03:00
Vologhat 8080cad8c9 code refactoring 2022-09-27 17:15:46 +03:00
Pavel 60afca9f4d Normal elements positioning in settings 2022-09-27 14:31:10 +03:00
gdlbo 665516944e themes imp 2022-09-27 11:41:21 +03:00
Vologhat ecce32bfe7 fixed fucking alert dialog 2022-09-25 20:56:39 +03:00
Vologhat ae059dadfe refactored vk alert dialog and imagine array adapter 2022-09-25 20:51:30 +03:00
Vologhat 2be8c6a11a refactored vk alert dialog and imagine array adapter 2022-09-25 20:02:03 +03:00
Erik Kiznov 0447c580e4 remove "do not get ads" 2022-09-24 23:22:08 +05:00
Erik Kiznov 291097e852 Update NewsfeedHook.java 2022-09-24 23:01:02 +05:00
Denis 8c7d103be7 Update README.md
Добавил нововведения
2022-09-24 18:01:32 +05:00
Vologhat 427653a796 fixed alert dialogs 2022-09-24 05:00:20 +03:00
gdlbo 0044771a06 fix notif appname 2022-09-23 16:44:12 +03:00
gdlbo 9eb0231e1a cleanup code 2022-09-23 16:30:49 +03:00
gdlbo 83178cbd6c fixed ios def icons colors mb 2022-09-23 15:26:42 +03:00
gdlbo 9c0c27d16b caching playlists 2022-09-23 14:54:12 +03:00
Erik Kiznov 70d597f6e8 fix ios writebar attach (mb) 2022-09-23 11:23:12 +05:00
Erik Kiznov 990e2f3e09 Revert "im_ic_attach → im_ic_add_circle"
This reverts commit fb524186d1.
2022-09-23 11:21:10 +05:00
Erik Kiznov 3d4be416d8 mediacontent 2022-09-22 23:12:07 +05:00
gdlbo 11d12fc397 fix caching 2022-09-22 21:01:26 +03:00
gdlbo caf70b72b5 fix compiling 2022-09-22 20:09:05 +03:00
gdlbo f6d860c439 Merge remote-tracking branch 'origin/music'
# Conflicts:
#	app/src/main/java/ru/vtosters/lite/ui/fragments/MediaFragment.java
#	app/src/main/java/ru/vtosters/lite/utils/ContactsUtils.java
#	app/src/main/java/ru/vtosters/lite/utils/ThemesUtils.java
#	smali/res/values-ru/strings.xml
#	smali/res/values/strings.xml
2022-09-22 19:51:52 +03:00
gdlbo 7d99f06053 Update build.gradle 2022-09-22 19:47:05 +03:00
Erik Kiznov b4e260d7cb [music] translate app error string 2022-09-21 23:50:32 +05:00
Erik Kiznov 46281102cb fix get current activity (maybe) 2022-09-21 23:35:44 +05:00
gdlbo b237ec034a some null checks 2022-09-21 21:13:22 +03:00
Erik Kiznov bfae3b5a7d [music] translate strings 2022-09-21 23:05:01 +05:00
gdlbo 5311aa0fb9 speedup db cache cleaning + some imp 2022-09-21 20:50:02 +03:00
gdlbo 2dd61e4cce deleted useless buttons in mbsh 2022-09-21 20:36:34 +03:00
gdlbo 63b97d280b vkx playlist caching 2022-09-20 20:25:23 +03:00
aliveoutside 529d4afb3b [music] download mp3 via VK X if integration is enabled 2022-09-20 19:50:23 +03:00
aliveoutside d2de67bcc3 [music] support subtitles 2022-09-20 19:03:06 +03:00
aliveoutside d02d6ceac1 [music] use callback onfailure 2022-09-20 19:03:06 +03:00
gdlbo 4ac4ae03f1 Update MusicNotificationBuilder.java 2022-09-19 22:48:35 +03:00
gdlbo 4534ed1156 caching/downloading own music (without playlists) 2022-09-19 22:14:55 +03:00
aliveoutside c18bdb3abb [music] playlist caching 2022-09-19 20:11:43 +03:00
inotflying fb524186d1 im_ic_attach → im_ic_add_circle 2022-09-19 17:27:58 +03:00
aliveoutside 827f10392f [music] use executorservice in download playlist hook
so it won't freeze the ui
2022-09-19 15:31:40 +03:00
aliveoutside 105f2c76c0 [music] support playlists with more than 1000 tracks 2022-09-19 14:56:56 +03:00
aliveoutside 2e6617ec83 [music] [PlaylistConverter] add track to playlist only if it has a vaild download url 2022-09-19 13:58:23 +03:00
gdlbo 8806f36182 ios writebar lol 2022-09-18 22:09:48 +03:00
aliveoutside 07ca91d8a2 [music] move notifySavingToCache to MusicNotificationBuilder 2022-09-18 18:59:19 +03:00
aliveoutside 4443f69056 [music] move callback and notification builders to their own packages 2022-09-18 18:59:19 +03:00
gdlbo 4cc0b04b68 Delete VKListHelper.java 2022-09-18 18:55:12 +03:00
gdlbo 89f2e7cf51 Update MusicBottomSheetHook.java 2022-09-18 18:42:12 +03:00
aliveoutside 8b36fea7a5 [music] fix track caching 2022-09-18 18:35:48 +03:00
aliveoutside e5848f2f91 [music] remove hardcoded track name in M3UDownloader 2022-09-18 18:29:20 +03:00
Erik Kiznov 5448b2f27e [music] translate notification text 2022-09-18 19:48:25 +05:00
Erik Kiznov 253b3bdcb9 [main] translate video history error
this commit is already in c3a17ca4ca (music branch)
2022-09-18 13:57:24 +05:00
Erik Kiznov c3a17ca4ca [music] translate all strings 2022-09-18 13:54:55 +05:00
Erik Kiznov 4cf7422997 [main] translate all strings 2022-09-18 13:05:18 +05:00
Erik Kiznov 270fca127b [main] translate all strings 2022-09-18 13:00:15 +05:00
aliveoutside 8b614f786d 100% fix crash on start 2022-09-18 00:54:22 +03:00
Vologhat 415d3fb3a7 added thumbnails support for music cache 2022-09-18 00:35:49 +03:00
Vologhat 593086d3b1 fixed ffmpeg convertation 2022-09-17 21:53:38 +03:00
aliveoutside f3fda343d2 potentially fix crash on start related to system theme changer 2022-09-17 21:49:33 +03:00
gdlbo 6633eb8f60 some caching stuff 2022-09-17 20:51:40 +03:00
gdlbo 65d66007e0 auto caching 2022-09-17 20:24:18 +03:00
aliveoutside 9763f54bf5 [music] use double quotes instead of single quotes in ffmpeg 2022-09-17 20:23:46 +03:00
aliveoutside 6be6b5c714 [music] fix after merge 2022-09-17 20:23:46 +03:00
aliveoutside f7c4663329 [music] move notification callback outside of PlaylistDownloader 2022-09-17 20:23:45 +03:00
gdlbo 03c19bc9cf delete from cache 2022-09-17 20:09:32 +03:00
gdlbo c27410d359 caching.... 2022-09-17 20:03:27 +03:00
gdlbo 00dda2141b cache lol 2022-09-17 20:03:14 +03:00
aliveoutside 68c3a1d137 [music] make PlaylistDownloader more generic 2022-09-17 19:25:16 +03:00
aliveoutside e60ab4a54e [music] some docs for TrackDownloader 2022-09-17 19:25:04 +03:00
gdlbo d9d57428ce cache files impl 2022-09-17 18:45:39 +03:00
aliveoutside 78d30f9546 [music] The refactoring
one class should only do a one thing and do it great
2022-09-17 18:45:22 +03:00
gdlbo db1b95b15a disabled cache file path 2022-09-17 18:21:31 +03:00
gdlbo d27c191800 Fixed unpl songs 2022-09-17 17:00:43 +03:00
gdlbo 682d9bdef1 empty cache 2022-09-17 16:43:57 +03:00
gdlbo 6f3565a4e3 Update MusicBottomSheetHook.java 2022-09-17 16:10:20 +03:00
gdlbo a7e70dabe5 fix vkx caching 2022-09-17 16:06:27 +03:00
gdlbo d602766fc4 Merge remote-tracking branch 'origin/main' into music 2022-09-17 15:14:05 +03:00
gdlbo 5c95ae3dd0 fixCTX 2022-09-17 15:13:40 +03:00
gdlbo 0e354123fc new cache btn 2022-09-17 14:54:58 +03:00
gdlbo db51fb01c0 added caching vkx music from app 2022-09-17 01:53:52 +03:00
gdlbo cfdf283457 fixes 2022-09-17 01:25:58 +03:00
gdlbo 724e8b9308 some buttons inject 2022-09-17 01:06:19 +03:00
iTaysonLab 46a05c916c add separate playlist support 2022-09-16 22:37:17 +02:00
iTaysonLab c814a1b384 logs 2022-09-16 22:04:00 +02:00
aliveoutside d1eed0fbd5 do not reapply theme on every config change 2022-09-16 23:01:31 +03:00
iTaysonLab 6faa7dbb74 Merge branch 'music' of https://github.com/vtosters/lite into music 2022-09-16 21:50:22 +02:00
iTaysonLab 57e8c32629 Implement libvkx playlist injecting 2022-09-16 21:49:24 +02:00
aliveoutside 9b6425442a refactor converter code a bit 2022-09-16 21:50:01 +03:00
gdlbo 025f582f6a getTracksInPlaylist 2022-09-16 21:40:50 +03:00
gdlbo 2dec7b28f4 vkx lib update + vkx cache dev 2022-09-16 20:16:20 +03:00
gdlbo 30886adc62 fix strange crash 2022-09-16 18:59:48 +03:00
gdlbo 761d32dab6 logs 2022-09-16 17:08:35 +03:00
gdlbo 7dbebc1cd1 Update PlaylistHelper.java 2022-09-16 16:43:04 +03:00
gdlbo dd6c793979 Merge remote-tracking branch 'origin/main' into music 2022-09-16 16:11:04 +03:00
aliveoutside c441823d94 use new catalog for artist search
fixes #745
2022-09-16 15:45:39 +03:00
aliveoutside 090c82dd40 append id3 tags to downloaded tracks 2022-09-16 13:03:56 +03:00
aliveoutside a7a5a3cd4c add coreLibraryDesugaring so we can use some cool java apis
https://developer.android.com/studio/write/java8-support#library-desugaring
2022-09-16 13:03:40 +03:00
aliveoutside 0e36807bd6 Merge branch 'main' into music 2022-09-16 00:46:15 +03:00
aliveoutside 24c41e5a6d bypass android notification updates rate limits 2022-09-16 00:37:08 +03:00
aliveoutside 22e12b6422 close streams in IOUtils 2022-09-16 00:13:09 +03:00
gdlbo 0efdefb207 ThemeChanging meme 2022-09-15 23:57:20 +03:00
aliveoutside 80d2045fbb update build.gradle 2022-09-15 23:51:18 +03:00
aliveoutside 7bb0d69a96 parallel .ts downloading 2022-09-15 23:43:42 +03:00
aliveoutside 96d71394fd merge .ts files more properly
use copying instead of recoding merged .ts to mp3

fixes #688
fixes #630
2022-09-15 23:41:05 +03:00
aliveoutside 371f9ae4a6 what the fuck? @Vologhat 2022-09-15 22:51:25 +03:00
gdlbo b439165246 fixed icon + vkx playlists playing 2022-09-15 21:35:50 +03:00
gdlbo 07eefdcea9 playlist bs inj + fix getTrackFile 2022-09-15 21:02:38 +03:00
aliveoutside 9d8533e066 fix external video player 2022-09-15 20:30:27 +03:00
gdlbo 37f39f29ab Merge remote-tracking branch 'origin/main' into music 2022-09-15 19:47:59 +03:00
gdlbo 84d2d583a3 fix crash for applying theme 2022-09-15 19:46:27 +03:00
aliveoutside f2c73c6ede [music] speed up downloading like 100x times 2022-09-15 19:40:16 +03:00
aliveoutside 59e92e30f2 [music] merge .ts files with Java:
using Java NIO on android O+
using FileOutputStream on older androids
2022-09-15 19:19:46 +03:00
aliveoutside be1bc8efbb remove gridmedia from recommendations 2022-09-15 18:58:53 +03:00
gdlbo ac0206f5ab Merge branch 'main' into music
# Conflicts:
#	app/src/main/java/ru/vtosters/lite/music/MP3Downloader.java
2022-09-15 18:42:31 +03:00
gdlbo e576fa0be5 powersave flex 2022-09-15 18:05:31 +03:00
gdlbo 1e0e432d57 Update ContactsUtils.java 2022-09-15 17:24:35 +03:00
gdlbo 3a1c93d4d0 fix params media frag 2022-09-15 16:46:49 +03:00
gdlbo 378e6192c7 hide system anims 2022-09-15 16:38:29 +03:00
gdlbo 67d0a4c88d added dialog for clear vid history 2022-09-15 16:28:44 +03:00
gdlbo d59297d348 deleted old video frag 2022-09-15 16:15:55 +03:00
gdlbo 1da12a02b6 Create update_jars_brew.sh 2022-09-15 15:58:39 +03:00
gdlbo 9ceee0b3d9 disabled anim sett for a13 2022-09-15 15:56:45 +03:00
aliveoutside 281b4d9773 allow to change order of telegram stickers 2022-09-15 00:34:48 +03:00
aliveoutside 18714288d7 partially fix contacts import 2022-09-14 00:24:12 +03:00
aliveoutside 8ac098e4f8 Merge pull request #739
Remove old music catalog
2022-09-13 22:02:24 +03:00
inotflying eda5ab139e Remove old music catalog 2022-09-13 20:23:50 +03:00
gdlbo ab3221cc01 getInfo -> execute + VKMeHandler codebase 2022-09-11 14:31:58 +03:00
gdlbo 92d4ff2027 tablet fixes 2022-09-11 02:35:59 +03:00
gdlbo cedf5d263a tablet fixes 2022-09-11 02:29:47 +03:00
gdlbo 08909baf2f no shopping anymore 2022-09-11 02:01:36 +03:00
gdlbo 383bafae92 fixed splash 2022-09-11 01:54:03 +03:00
gdlbo c2661e11ec Update JsonInjectors.java 2022-09-11 01:33:16 +03:00
gdlbo 9c4ccce409 test upload contacts 2022-09-11 01:18:48 +03:00
gdlbo c1b2409baa contacts hack v2 2022-09-11 00:46:54 +03:00
gdlbo 54ee9f6c5b Update ContactsUtils.java 2022-09-10 23:55:05 +03:00
gdlbo d83033e983 contacts hack 2022-09-10 23:49:32 +03:00
Vologhat 92c0369332 added system theme warning dialog 2022-09-10 22:45:15 +03:00
gdlbo d796455bbe fix crash with unsupported msg 2022-09-10 21:35:25 +03:00
gdlbo dc4743f2a3 fix restart sett 2022-09-10 19:54:20 +03:00
aliveoutside 94c8736bc1 android:configChanges - uiMode 2022-09-10 19:36:01 +03:00
aliveoutside e05255263b remove useless log 2022-09-10 18:58:54 +03:00
aliveoutside e916b5fcc8 check the system theme on app start 2022-09-10 18:52:49 +03:00
aliveoutside 09e0dbd01d switch theme when "Use system theme" switch changed to true 2022-09-10 18:48:30 +03:00
aliveoutside 84e5ce6dc2 add system theme switch to settings 2022-09-10 18:42:47 +03:00
aliveoutside 2520b709bd remove dead code in ThemesUtils 2022-09-10 17:47:41 +03:00
aliveoutside 0ed16b0836 follow system theme (light/dark) 2022-09-10 17:35:41 +03:00
aliveoutside 6e55514edf Update README.md 2022-09-10 16:55:14 +03:00
aliveoutside 93d515b423 add russian string for play_in_vkx 2022-09-10 16:49:14 +03:00
aliveoutside b88ecd97fc pass playlist and action id to the hook 2022-09-10 16:46:05 +03:00
aliveoutside 5c1b39c79f pass playback context to vk x 2022-09-10 16:33:34 +03:00
aliveoutside bae7263554 implement "Play in VK X" quick action in track bottomsheet
resolves #723
2022-09-10 16:09:38 +03:00
aliveoutside 9fc5aa4fc3 Merge branch 'vtl-remaster' into music
# Conflicts:
#	app/libs/classes-dex2jar.jar
#	app/libs/classes2-dex2jar.jar
#	app/libs/classes3-dex2jar.jar
#	app/libs/classes4-dex2jar.jar
#	app/libs/classes5-dex2jar.jar
#	app/src/main/java/ru/vtosters/lite/downloaders/notifications/NotificationChannels.java
#	app/src/main/java/ru/vtosters/lite/music/MP3Downloader.java
2022-08-19 13:54:46 +03:00
Vologhat f6555f49d8 beta stuff for music 2022-07-31 22:14:49 +03:00
2655 changed files with 95697 additions and 450679 deletions
+1 -4
View File
@@ -19,9 +19,6 @@ assignees: ''
**Скриншот ошибки**
**Информация об устройстве:**
- Устройство: Samsung Galaxy J1 Mini
- OS: Android 9 | OneUi 3.0
- Коммит: fa12e8f (В О Приложении написана версия коммита)
**Скопируйте сюда информацию об устройстве нажав на кнопку "Скопировать информацию об устройстве" в Настройках -> Другое и удалите этот текст**
**Дополнительная информация о баге или мыслях почему оно может происходить (если есть)**
+86
View File
@@ -0,0 +1,86 @@
### Весь функционал модификации
# Реклама
* Блокировка рекламы в ленте +
* Блокировка историй с возможной рекламой +
* Блокировка постов:
* С источником
* С MiniApp
* Через фильтры групп, слов
* Возможность добавлять в вайтлист фильтров группы, чтобы в них не удалялись посты+
* Возможность отключить рекомендации от ВК
* Отключение отправки метрики
# Интерфейс и внешний вид
* Округление дат
* 1 января в 4:20
* 1 января в 4:20:00
* 1 января 2000 в 4:20:00
* Округление чисел
* Возможность отключить блок историй наверху ленты
* Возможность отключить боковую камеру в разделе «Новости»
* Возможность отключить блок «Что у вас нового?» в разделе «Новости»
* Возможность показывать лайки у постов справа
* Возможность менять стартовый раздел при запуске приложения
* Анимации фрагментов
* Возможность изменять размер закругления картинок (аватарок и прочего)
* Возможность отключить редизайн видеопостов
* Возможность отключить блок миниаппов/VK Pay/Superapp
* Возможность отключить сокращение названий разделов в меню
* Возможность скрыть блок рекомендаций друзей в разделе «Друзья»
* Возможность скрыть подписи в настройках
* Анимированный экран входа для Android 12+
* Редактор докбара
* Редактор элементов Superapp
* Возможность отключать новый дизайн версий VK (Milkshake)
* Название заголовков в докбаре
* Возможность использовать свой акцент для иконок
* Возможность отключить счётчики в докбаре
* Смена иконки приложения (содержит много уникальных иконок для донатеров)
* Возможность покрасить панель навигации, веб-страницы
* Обои в сообщениях
* Возможность выключения кнопки записи голосовых сообщений
* Возможность скрыть блок рекомендаций в сообщениях
* Режим **VK Me**
* Возможность вернуть вкладку уведомлений для режима VK Me
* Встроенный переводчик текста для сообщений
* Альтернативный дизайн эмодзи меню
* Возможность использовать системные эмодзи
* Панель ввода из приложения VK для iOS
* Сокращение постов **(Показать полностью)**
* Результаты опросов без участия
# Медиаконтент
* Интеграция с <a href="https://www.last.fm/">LAST.FM</a> (а также возможность скробблинга)
* Возможность **кешировать музыку / автокешировать ее при прослушивании**
* Возможность выбирать раздел музыки, открываемый по умолчанию
* Возможность скачивать видео, очищать историю просмотра видео
* Возможность найти фотографию через поисковые системы ?
* Интеграция с <a href="https://vkx.app/">VK X</a>
* Поддержка новых текстов в музыке (и с Genius в том числе)
# Сообщения
* Шифрование сообщений
* Возможность видеть удаленные сообщения
* Нечиталка/неписалка для ЛС/бесед/ботов/групп
* Возможность загружать свои стикерпаки из Telegram во ВКонтакте
* Возможнсть использовать Enter с аппаратной клавиатуры
# Активность
* Возможность сохранять удалённые сообщения
* Функционал, позволяющий оставаться в «оффлайне» (принудительный оффлайн/не отправлять статус онлайна и т.п.)
* Возможность отключить информацию о том, что вы просмотрели историю/прослушали голосовое сообщение
* Возможность видеть онлайн пользователей, если у вас скрыт онлайн через VK Messenger
* Возможность сохранять настройки бесшумных сообщений/сообщений-бомбочек
* Отключить уведомление о том, что вы сделали скриншот в беседе
* Отключение редиректа через away.php
* Отключение бизнес-уведомлений
# Прокси
* Поддержка сторонних прокси, таких как: Zaborona, VikaMobile, рандомные прокси и прочие
* Возможность использовать **HTTP/HTTPS/SOCKS** прокси, менять домены **API/OAuth/Static**
# Другое
* Автоочистка кеша при достижении указанного вами значения (**100/500 MB, 1/2/5 GB**)
* Возможность создания резервной копии (бекапа) настроек и аккаунтов
+46
View File
@@ -0,0 +1,46 @@
<svg width="306" height="48" viewBox="0 0 306 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M85.5063 24.1875C87.475 23.2688 88.7437 21.7375 88.7437 19.375C88.7437 15.7875 85.4625 13.25 80.7375 13.25H69.8438V36H81.2188C86.1188 36 89.5313 33.3313 89.5313 29.7C89.5313 26.9438 87.7375 24.8875 85.5063 24.1875ZM80.7375 17.4063C82.4875 17.4063 83.7125 18.4563 83.7125 19.9C83.7125 21.3438 82.4875 22.35 80.7375 22.35H74.875V17.4063H80.7375ZM74.875 31.8438V26.2875H81.2188C83.1875 26.2875 84.5 27.425 84.5 29.0875C84.5 30.75 83.1875 31.8438 81.2188 31.8438H74.875Z" fill="white"/>
<path d="M104.403 36V17.8438H112.278V13.25H91.4966V17.8438H99.3716V36H104.403Z" fill="white"/>
<path d="M125.768 36.4375C132.899 36.4375 137.931 31.5375 137.931 24.625C137.931 17.7125 132.899 12.8125 125.768 12.8125C118.637 12.8125 113.606 17.7125 113.606 24.625C113.606 31.5375 118.637 36.4375 125.768 36.4375ZM125.768 31.8438C121.656 31.8438 118.856 28.9125 118.856 24.625C118.856 20.3375 121.656 17.4063 125.768 17.4063C129.881 17.4063 132.681 20.3375 132.681 24.625C132.681 28.9125 129.881 31.8438 125.768 31.8438Z" fill="white"/>
<path d="M152.848 36.4375C157.617 36.4375 162.123 33.9875 163.83 29.2188L159.105 28.4313C158.098 30.4438 155.867 31.8438 153.155 31.8438C149.086 31.8438 146.242 28.8688 146.242 24.625C146.242 20.3813 149.086 17.4063 153.155 17.4063C155.78 17.4063 157.967 18.7625 158.93 20.7313L163.655 19.9438C161.992 15.2625 157.705 12.8125 152.848 12.8125C145.892 12.8125 140.992 17.7563 140.992 24.625C140.992 31.4938 145.892 36.4375 152.848 36.4375Z" fill="white"/>
<path d="M177.633 36V17.8438H185.508V13.25H164.727V17.8438H172.602V36H177.633Z" fill="white"/>
<path d="M210.461 24.3625C210.461 17.8 205.561 12.8125 198.648 12.8125C191.736 12.8125 186.836 17.7563 186.836 24.625C186.836 31.4938 191.736 36.4375 198.648 36.4375C203.373 36.4375 207.836 34.2063 209.542 29.875L204.817 29.0875C203.723 30.7063 201.623 31.8438 198.954 31.8438C195.104 31.8438 192.567 29.4813 192.086 25.9813H210.373C210.417 25.5 210.461 24.975 210.461 24.3625ZM198.648 17.1875C201.798 17.1875 204.161 19.2 204.992 22.0438H192.392C193.223 19.1125 195.586 17.1875 198.648 17.1875Z" fill="white"/>
<path d="M219.412 44.9688V32.5438C220.987 34.425 223.831 36.4375 227.812 36.4375C234.331 36.4375 238.925 31.4938 238.925 24.625C238.925 17.7563 234.331 12.8125 227.812 12.8125C223.656 12.8125 220.769 15 219.194 16.925L218.144 13.25H214.381V44.9688H219.412ZM226.587 31.9313C222.344 31.9313 219.412 28.9125 219.412 24.625C219.412 20.3375 222.344 17.3188 226.587 17.3188C230.787 17.3188 233.675 20.3375 233.675 24.625C233.675 28.9125 230.787 31.9313 226.587 31.9313Z" fill="white"/>
<path d="M253.849 36.4375C258.618 36.4375 263.124 33.9875 264.831 29.2188L260.106 28.4313C259.099 30.4438 256.868 31.8438 254.156 31.8438C250.087 31.8438 247.243 28.8688 247.243 24.625C247.243 20.3813 250.087 17.4063 254.156 17.4063C256.781 17.4063 258.968 18.7625 259.931 20.7313L264.656 19.9438C262.993 15.2625 258.706 12.8125 253.849 12.8125C246.893 12.8125 241.993 17.7563 241.993 24.625C241.993 31.4938 246.893 36.4375 253.849 36.4375Z" fill="white"/>
<g clip-path="url(#clip0_428_625)">
<path d="M12.6749 41.8159H9.53384C8.99172 41.8159 8.55225 42.2554 8.55225 42.7975V47.0184C8.55225 47.5605 8.99172 48 9.53384 48H12.6749C13.2171 48 13.6565 47.5605 13.6565 47.0184V42.7975C13.6565 42.2554 13.2171 41.8159 12.6749 41.8159Z" fill="#9C9C9C"/>
<path d="M23.8649 41.8159H20.7238C20.1817 41.8159 19.7422 42.2554 19.7422 42.7975V47.0184C19.7422 47.5605 20.1817 48 20.7238 48H23.8649C24.407 48 24.8465 47.5605 24.8465 47.0184V42.7975C24.8465 42.2554 24.407 41.8159 23.8649 41.8159Z" fill="#9C9C9C"/>
<path d="M39.6686 41.8159H36.5275C35.9854 41.8159 35.5459 42.2554 35.5459 42.7975V47.0184C35.5459 47.5605 35.9854 48 36.5275 48H39.6686C40.2107 48 40.6502 47.5605 40.6502 47.0184V42.7975C40.6502 42.2554 40.2107 41.8159 39.6686 41.8159Z" fill="#9C9C9C"/>
<path d="M50.859 41.8159H47.7179C47.1758 41.8159 46.7363 42.2554 46.7363 42.7975V47.0184C46.7363 47.5605 47.1758 48 47.7179 48H50.859C51.4012 48 51.8406 47.5605 51.8406 47.0184V42.7975C51.8406 42.2554 51.4012 41.8159 50.859 41.8159Z" fill="#9C9C9C"/>
<path d="M38.7852 4.37598H16.503C15.6899 4.37598 15.0306 5.03519 15.0306 5.84837V25.4803C15.0306 26.2935 15.6899 26.9527 16.503 26.9527H38.7852C39.5984 26.9527 40.2576 26.2935 40.2576 25.4803V5.84837C40.2576 5.03519 39.5984 4.37598 38.7852 4.37598Z" fill="#FECE12"/>
<path d="M38.7855 4.37598H19.0554C18.2422 4.37598 17.583 5.03519 17.583 5.84837V25.4803C17.583 26.2935 18.2422 26.9527 19.0554 26.9527H38.7855C39.5986 26.9527 40.2578 26.2935 40.2578 25.4803V5.84837C40.2578 5.03519 39.5986 4.37598 38.7855 4.37598Z" fill="#FD9115"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.1335 8.28128C19.7782 8.14803 19.5982 7.75197 19.7315 7.39665C19.7315 7.39665 19.7316 7.39619 19.7318 7.39572L19.7319 7.39538C19.732 7.39518 19.7322 7.39479 19.7322 7.39479L19.7323 7.39425L19.7325 7.39387C19.7326 7.39353 19.7327 7.3932 19.7328 7.39286L19.7335 7.39123C19.7338 7.39043 19.7341 7.38959 19.7344 7.38875C19.7353 7.38647 19.7363 7.38406 19.7373 7.38152C19.7375 7.38088 19.7378 7.38023 19.738 7.37958C19.7407 7.37307 19.7437 7.36574 19.7472 7.35764C19.7541 7.34146 19.7629 7.32218 19.7737 7.30029C19.7953 7.25658 19.8252 7.20196 19.8654 7.14044C19.9456 7.01743 20.0681 6.86517 20.2472 6.71899C20.6184 6.41618 21.1776 6.18456 21.9718 6.21511C22.937 6.25224 23.4046 6.85229 23.6912 7.22007L23.7019 7.23384C24.0007 7.61706 24.0827 7.68699 24.3012 7.68699C24.6147 7.68699 24.7594 7.57228 25.1058 7.28263C25.4712 6.97695 25.9872 6.55817 26.9024 6.55816C27.3396 6.55816 27.6971 6.65327 28.0026 6.81173C28.2952 6.96356 28.513 7.16121 28.6682 7.30401C28.9881 7.59832 29.0893 7.68698 29.3564 7.68698C29.681 7.68698 29.9319 7.53706 30.3702 7.24055L30.4105 7.21321C30.8055 6.94538 31.3766 6.55814 32.1539 6.55815C32.9977 6.55816 33.4997 7.00806 33.8227 7.29944C34.1698 7.61244 34.2741 7.68699 34.4608 7.68698C34.6387 7.68698 34.7881 7.58812 35.1711 7.23256C35.1852 7.2194 35.1999 7.20567 35.2151 7.19147C35.526 6.90098 36.0503 6.41092 36.8165 6.41092C37.5494 6.41092 38.0909 6.77863 38.4193 7.09126C38.5863 7.25042 38.7122 7.40793 38.7968 7.52599C38.8395 7.58557 38.8728 7.63659 38.8965 7.67478C38.9084 7.69391 38.9179 7.70996 38.9252 7.72239C38.9288 7.7286 38.9319 7.73393 38.9343 7.7383C38.935 7.73942 38.9356 7.74048 38.9361 7.74148L38.9376 7.74413C38.9381 7.74499 38.9385 7.74577 38.9389 7.7465L38.9395 7.74755L38.9398 7.74803C38.9399 7.74823 38.94 7.74849 38.94 7.74849C39.123 8.08101 39.0016 8.49881 38.6691 8.68169C38.3376 8.86402 37.9214 8.74401 37.7375 8.41378C37.7361 8.41135 37.7333 8.40671 37.7293 8.40012C37.7197 8.38463 37.7031 8.35896 37.6798 8.32651C37.6325 8.26054 37.562 8.17264 37.4714 8.08639C37.2844 7.90825 37.0653 7.78515 36.8165 7.78515C36.6387 7.78515 36.4891 7.88404 36.1061 8.23958C36.0919 8.25279 36.0772 8.26656 36.0619 8.2808C35.7511 8.57129 35.2268 9.06122 34.4608 9.06122C33.7146 9.06123 33.2417 8.62953 32.956 8.36866L32.9559 8.36855C32.9372 8.35157 32.9194 8.33531 32.9024 8.31995C32.5997 8.0469 32.439 7.93238 32.1539 7.93238C31.8293 7.93237 31.5785 8.08229 31.1402 8.3788C31.127 8.38769 31.1137 8.39674 31.1001 8.40593C30.7052 8.67377 30.1339 9.06122 29.3564 9.06122C28.541 9.06122 28.0824 8.63527 27.7867 8.36062C27.7699 8.34502 27.7536 8.32988 27.7378 8.31536C27.5863 8.17597 27.4851 8.0914 27.3697 8.03158C27.2672 7.9784 27.1278 7.93239 26.9024 7.93239C26.4925 7.9324 26.2968 8.07803 25.9874 8.33677C25.9725 8.34919 25.9573 8.36196 25.9418 8.37504L25.9417 8.37514C25.6135 8.65136 25.1264 9.06123 24.3012 9.06123C23.3796 9.06123 22.9207 8.46907 22.6505 8.12042C22.6395 8.10612 22.6287 8.09223 22.6182 8.07881C22.3395 7.72125 22.2176 7.59982 21.9189 7.58833C21.437 7.56979 21.2109 7.70628 21.1159 7.78384C21.0619 7.82784 21.031 7.86884 21.0162 7.89153C21.0121 7.8977 21.0094 7.90239 21.0078 7.90523C20.8654 8.24322 20.4801 8.41124 20.1335 8.28128ZM21.0133 7.89175L21.0141 7.88973C21.0146 7.88854 21.0151 7.88728 21.0156 7.88595C21.0157 7.88576 21.0157 7.88557 21.0158 7.88538C21.0161 7.88452 21.0165 7.88362 21.0169 7.88269L21.0173 7.88139C21.0156 7.88578 21.0139 7.89015 21.0122 7.89448L21.0133 7.89175ZM37.7382 8.41496C37.7387 8.41581 37.7388 8.41595 37.7384 8.41533L37.7382 8.41496Z" fill="#E65C28"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.1335 11.5866C19.7782 11.4533 19.5982 11.0573 19.7315 10.7019C19.7315 10.7019 19.7316 10.7015 19.7318 10.701L19.732 10.7005L19.7322 10.7001C19.7322 10.6998 19.7324 10.6995 19.7325 10.6992C19.7326 10.6989 19.7327 10.6985 19.7328 10.6982L19.7334 10.6966C19.7338 10.6958 19.7341 10.6949 19.7344 10.694C19.7352 10.692 19.7361 10.6899 19.7369 10.6877L19.738 10.6849C19.7407 10.6784 19.7437 10.671 19.7472 10.6629C19.7541 10.6468 19.7629 10.6275 19.7737 10.6056C19.7953 10.5619 19.8252 10.5073 19.8654 10.4457C19.9456 10.3227 20.0681 10.1705 20.2472 10.0243C20.6184 9.72148 21.1776 9.48987 21.9718 9.52041C22.937 9.55754 23.4046 10.1576 23.6912 10.5254L23.7019 10.5391C24.0007 10.9224 24.0827 10.9923 24.3012 10.9923C24.6147 10.9923 24.7594 10.8776 25.1058 10.5879C25.4712 10.2823 25.9872 9.86347 26.9024 9.86347C27.3396 9.86346 27.6971 9.95856 28.0026 10.117C28.2952 10.2689 28.513 10.4665 28.6682 10.6093C28.9881 10.9036 29.0893 10.9923 29.3564 10.9923C29.681 10.9923 29.9319 10.8424 30.3702 10.5459C30.3822 10.5377 30.3944 10.5295 30.4068 10.5211L30.4105 10.5185C30.8055 10.2507 31.3766 9.86344 32.1539 9.86345C32.9977 9.86346 33.4997 10.3134 33.8227 10.6047C34.1698 10.9177 34.2741 10.9923 34.4608 10.9923C34.6387 10.9923 34.7881 10.8934 35.1711 10.5379C35.1852 10.5247 35.1999 10.511 35.215 10.4969L35.2151 10.4968C35.526 10.2063 36.0503 9.71622 36.8165 9.71622C37.5494 9.71622 38.0909 10.0839 38.4193 10.3966C38.5863 10.5557 38.7122 10.7132 38.7968 10.8313C38.8395 10.8909 38.8728 10.9419 38.8965 10.9801C38.9084 10.9992 38.9179 11.0153 38.9252 11.0277C38.9265 11.03 38.9278 11.0321 38.9289 11.0342C38.931 11.0377 38.9328 11.0408 38.9343 11.0436C38.9351 11.0449 38.9357 11.0461 38.9364 11.0472C38.9368 11.048 38.9372 11.0487 38.9376 11.0494C38.938 11.05 38.9383 11.0506 38.9386 11.0512L38.9389 11.0518L38.9395 11.0528L38.9398 11.0533C38.9399 11.0535 38.8965 10.9801 38.8965 10.9801L38.94 11.0538C39.123 11.3863 39.0016 11.8041 38.6691 11.987C38.3376 12.1693 37.9214 12.0493 37.7376 11.7192C37.7362 11.7168 37.7334 11.7121 37.7293 11.7054C37.7197 11.6899 37.7031 11.6643 37.6798 11.6318C37.6325 11.5658 37.562 11.4779 37.4714 11.3917C37.2844 11.2135 37.0653 11.0904 36.8165 11.0904C36.6387 11.0904 36.4891 11.1893 36.1061 11.5449C36.0919 11.5581 36.0772 11.5719 36.0619 11.5861C35.7511 11.8766 35.2268 12.3665 34.4608 12.3665C33.7146 12.3665 33.2417 11.9348 32.956 11.674L32.9558 11.6738C32.9372 11.6568 32.9194 11.6406 32.9024 11.6252C32.5997 11.3522 32.439 11.2377 32.1539 11.2377C31.8293 11.2377 31.5785 11.3876 31.1402 11.6841C31.127 11.693 31.1136 11.7021 31.1001 11.7113C30.7052 11.9791 30.1339 12.3665 29.3564 12.3665C28.541 12.3665 28.0824 11.9406 27.7867 11.6659C27.7699 11.6503 27.7536 11.6352 27.7378 11.6207C27.5863 11.4813 27.4851 11.3967 27.3697 11.3369C27.2672 11.2837 27.1278 11.2377 26.9024 11.2377C26.4925 11.2377 26.2968 11.3833 25.9874 11.6421L25.9738 11.6535C25.9691 11.6574 25.9643 11.6614 25.9595 11.6654C25.9536 11.6704 25.9477 11.6754 25.9417 11.6804C25.6134 11.9567 25.1264 12.3665 24.3012 12.3665C23.3796 12.3665 22.9207 11.7744 22.6505 11.4257C22.6395 11.4114 22.6287 11.3975 22.6182 11.3841C22.3395 11.0265 22.2176 10.9051 21.9189 10.8936C21.437 10.8751 21.2109 11.0116 21.1159 11.0891C21.0619 11.1331 21.031 11.1741 21.0162 11.1968C21.0121 11.203 21.0094 11.2077 21.0078 11.2105C20.8654 11.5485 20.4801 11.7165 20.1335 11.5866ZM21.0122 11.1998L21.0133 11.1971L21.0146 11.1938L21.0156 11.1913L21.0158 11.1908C21.0161 11.1899 21.0164 11.189 21.0169 11.188L21.0173 11.1867C21.0157 11.1911 21.0139 11.1954 21.0122 11.1998ZM37.7386 11.7209C37.7387 11.7211 37.7387 11.721 37.7384 11.7206L37.7386 11.7209Z" fill="#E65C28"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.1335 14.8258C19.7782 14.6926 19.5982 14.2966 19.7315 13.9412C19.7315 13.9412 19.7316 13.9407 19.7318 13.9402C19.7318 13.9402 19.7321 13.9397 19.7322 13.9394C19.7322 13.939 19.7324 13.9387 19.7325 13.9384L19.7326 13.938C19.7327 13.9378 19.7328 13.9376 19.7328 13.9374C19.733 13.937 19.7331 13.9366 19.7333 13.9362C19.7337 13.9353 19.7341 13.9343 19.7344 13.9333C19.7349 13.9321 19.7354 13.931 19.7358 13.9298L19.7372 13.9262L19.738 13.9241C19.7407 13.9177 19.7437 13.9103 19.7472 13.9022C19.7541 13.8861 19.7629 13.8668 19.7737 13.8449C19.7953 13.8011 19.8252 13.7465 19.8654 13.685C19.9456 13.562 20.0681 13.4097 20.2472 13.2636C20.6184 12.9607 21.1776 12.7291 21.9718 12.7597C22.937 12.7968 23.4046 13.3968 23.6912 13.7646L23.7019 13.7784C24.0007 14.1616 24.0827 14.2316 24.3012 14.2316C24.6147 14.2316 24.7594 14.1168 25.1058 13.8272C25.4712 13.5215 25.9872 13.1027 26.9024 13.1027C27.3396 13.1027 27.6971 13.1978 28.0026 13.3563C28.2952 13.5081 28.513 13.7058 28.6682 13.8486C28.9881 14.1428 29.0893 14.2316 29.3564 14.2316C29.681 14.2316 29.9319 14.0816 30.3702 13.7851L30.4105 13.7578C30.8055 13.4899 31.3766 13.1027 32.1539 13.1027C32.9977 13.1027 33.4997 13.5526 33.8227 13.844C34.1698 14.157 34.2741 14.2316 34.4608 14.2316C34.6387 14.2316 34.7881 14.1326 35.1711 13.7771C35.1852 13.764 35.1999 13.7502 35.2151 13.736C35.526 13.4455 36.0503 12.9555 36.8165 12.9555C37.5494 12.9555 38.0909 13.3232 38.4193 13.6358C38.5863 13.795 38.7122 13.9525 38.7968 14.0706C38.8395 14.1301 38.8728 14.1811 38.8965 14.2193C38.9084 14.2385 38.9179 14.2546 38.9252 14.2669L38.9311 14.2771L38.9343 14.2828L38.9357 14.2853L38.9376 14.2887C38.9379 14.2892 38.9382 14.2897 38.9384 14.2902C38.9386 14.2905 38.9388 14.2908 38.9389 14.2911L38.9392 14.2916L38.9395 14.2921L38.9398 14.2926L38.94 14.293C39.123 14.6256 39.0016 15.0434 38.6691 15.2262C38.3382 15.4082 37.9228 15.289 37.7385 14.96C37.7387 14.9603 37.7386 14.9602 37.7386 14.9602L37.7385 14.96L37.7384 14.9599L37.7383 14.9597L37.7381 14.9594C37.7376 14.9585 37.7366 14.9568 37.7352 14.9545C37.7337 14.952 37.7317 14.9487 37.7293 14.9447C37.7197 14.9292 37.7031 14.9035 37.6798 14.8711C37.6325 14.8051 37.562 14.7172 37.4714 14.631C37.2844 14.4528 37.0653 14.3297 36.8165 14.3297C36.6387 14.3297 36.4891 14.4286 36.1061 14.7841C36.0919 14.7973 36.0772 14.8111 36.062 14.8253C35.7511 15.1158 35.2269 15.6058 34.4608 15.6058C33.7147 15.6058 33.2418 15.1742 32.9561 14.9133C32.9374 14.8963 32.9195 14.8799 32.9024 14.8645C32.5997 14.5914 32.439 14.477 32.1539 14.477C31.8293 14.477 31.5785 14.6269 31.1402 14.9234C31.127 14.9323 31.1136 14.9414 31.0999 14.9507C30.705 15.2185 30.1338 15.6058 29.3564 15.6058C28.541 15.6058 28.0824 15.1798 27.7867 14.9052L27.7865 14.905C27.7698 14.8895 27.7536 14.8744 27.7378 14.8599C27.5863 14.7205 27.4851 14.636 27.3697 14.5761C27.2672 14.5229 27.1278 14.477 26.9024 14.477C26.4925 14.477 26.2968 14.6226 25.9874 14.8813C25.9725 14.8938 25.9572 14.9066 25.9416 14.9197C25.6134 15.196 25.1263 15.6058 24.3012 15.6058C23.3796 15.6058 22.9207 15.0136 22.6506 14.665L22.6474 14.6609C22.6374 14.648 22.6277 14.6355 22.6182 14.6233C22.3395 14.2658 22.2176 14.1444 21.9189 14.1329C21.437 14.1144 21.2109 14.2508 21.1159 14.3284C21.0619 14.3724 21.031 14.4134 21.0162 14.4361C21.0121 14.4422 21.0094 14.4469 21.0078 14.4498C20.8654 14.7878 20.4801 14.9559 20.1335 14.8258ZM21.0123 14.4389L21.0133 14.4363L21.0141 14.4344C21.0146 14.4332 21.0151 14.4319 21.0156 14.4306L21.0162 14.429C21.0149 14.4323 21.0136 14.4356 21.0123 14.4389ZM21.0066 14.4519C21.0064 14.4524 21.0062 14.4528 21.0062 14.4528C21.006 14.4531 21.0062 14.4528 21.0066 14.4519ZM21.0173 14.4261L21.0164 14.4283L21.0169 14.4272C21.017 14.4269 21.0171 14.4265 21.0173 14.4261Z" fill="#E65C28"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.7315 17.4268C19.5982 17.7821 19.7782 18.1782 20.1335 18.3115C20.4801 18.4414 20.8654 18.2734 21.0078 17.9354C21.0094 17.9326 21.0121 17.9279 21.0162 17.9217C21.031 17.899 21.0619 17.858 21.1159 17.814C21.2109 17.7365 21.437 17.6 21.9189 17.6185C22.2176 17.63 22.3395 17.7514 22.6182 18.109C22.6286 18.1223 22.6393 18.1361 22.6503 18.1502L22.6505 18.1506C22.9207 18.4993 23.3796 19.0914 24.3012 19.0914C25.1264 19.0914 25.6135 18.6815 25.9417 18.4053C25.9573 18.3922 25.9725 18.3794 25.9874 18.3669C26.2968 18.1082 26.4925 17.9626 26.9024 17.9626C27.1278 17.9626 27.2672 18.0086 27.3697 18.0618C27.4851 18.1216 27.5863 18.2061 27.7378 18.3455C27.746 18.353 27.7542 18.3607 27.7626 18.3684C27.7705 18.3758 27.7786 18.3832 27.7867 18.3908C28.0824 18.6654 28.541 19.0914 29.3564 19.0914C30.1339 19.0914 30.7052 18.7039 31.1001 18.4361L31.101 18.4355C31.1143 18.4265 31.1273 18.4177 31.1402 18.409C31.5785 18.1125 31.8293 17.9625 32.1539 17.9626C32.439 17.9626 32.5997 18.0771 32.9024 18.3501C32.9195 18.3655 32.9373 18.3818 32.956 18.3988C33.2417 18.6597 33.7146 19.0914 34.4608 19.0914C35.2268 19.0914 35.7511 18.6015 36.0619 18.311L36.0623 18.3106C36.0774 18.2965 36.092 18.2829 36.1061 18.2698C36.4891 17.9142 36.6387 17.8153 36.8165 17.8153C37.0653 17.8153 37.2844 17.9384 37.4714 18.1166C37.562 18.2028 37.6325 18.2907 37.6798 18.3567C37.7031 18.3891 37.7197 18.4148 37.7293 18.4303C37.7333 18.4369 37.7361 18.4415 37.7375 18.444C37.9214 18.7742 38.3376 18.8942 38.6691 18.7119C39.0016 18.529 39.123 18.1112 38.94 17.7787L38.9398 17.7782L38.9395 17.7777L38.9389 17.7767L38.9384 17.7756C38.9382 17.7753 38.9381 17.7751 38.9379 17.7748L38.9376 17.7743L38.9364 17.7721C38.9358 17.771 38.9351 17.7698 38.9343 17.7685C38.9319 17.7641 38.9288 17.7588 38.9252 17.7526C38.9179 17.7401 38.9084 17.7241 38.8965 17.705C38.8728 17.6668 38.8395 17.6158 38.7968 17.5562C38.7122 17.4381 38.5863 17.2806 38.4193 17.1214C38.0909 16.8088 37.5494 16.4411 36.8165 16.4411C36.0503 16.4411 35.526 16.9312 35.2151 17.2216C35.1999 17.2358 35.1852 17.2496 35.1711 17.2627C34.7881 17.6183 34.6387 17.7172 34.4608 17.7172C34.2741 17.7172 34.1698 17.6426 33.8227 17.3296C33.4997 17.0382 32.9977 16.5883 32.1539 16.5883C31.3766 16.5883 30.8055 16.9756 30.4105 17.2434C30.3969 17.2527 30.3834 17.2618 30.3702 17.2707C29.9319 17.5672 29.681 17.7172 29.3564 17.7172C29.0893 17.7172 28.9881 17.6285 28.6682 17.3342C28.513 17.1914 28.2952 16.9937 28.0026 16.8419C27.6971 16.6834 27.3396 16.5883 26.9024 16.5883C25.9872 16.5883 25.4712 17.0071 25.1058 17.3128C24.7594 17.6025 24.6147 17.7172 24.3012 17.7172C24.0827 17.7172 24.0007 17.6472 23.7019 17.264L23.6912 17.2502C23.4046 16.8825 22.937 16.2824 21.9718 16.2453C21.1776 16.2147 20.6184 16.4464 20.2472 16.7492C20.0681 16.8953 19.9456 17.0476 19.8654 17.1706C19.8252 17.2321 19.7953 17.2868 19.7737 17.3305C19.7629 17.3524 19.7541 17.3716 19.7472 17.3878C19.7437 17.3959 19.7407 17.4032 19.738 17.4098L19.7373 17.4117C19.7363 17.4143 19.7353 17.4167 19.7344 17.4189C19.7341 17.4197 19.7338 17.4205 19.7335 17.4212L19.7335 17.4214C19.7332 17.422 19.733 17.4225 19.7328 17.423C19.7327 17.4234 19.7326 17.4237 19.7325 17.424L19.7325 17.4241C19.7323 17.4244 19.7322 17.4247 19.7322 17.425C19.7322 17.425 19.732 17.4253 19.732 17.4255L19.7318 17.4259C19.7316 17.4264 19.7315 17.4268 19.7315 17.4268ZM21.0133 17.9219L21.0122 17.9247C21.0139 17.9203 21.0156 17.916 21.0173 17.9116L21.0169 17.9129C21.0164 17.914 21.016 17.9151 21.0156 17.9161C21.0151 17.9174 21.0146 17.9187 21.0142 17.9198L21.0133 17.9219ZM21.0066 17.9376C21.0064 17.938 21.0062 17.9384 21.0062 17.9384C21.006 17.9387 21.0062 17.9384 21.0066 17.9376ZM37.7382 18.4451C37.7387 18.446 37.7388 18.4461 37.7384 18.4455L37.7382 18.4451Z" fill="#E65C28"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.7315 20.7321C19.5982 21.0874 19.7782 21.4835 20.1335 21.6168C20.4801 21.7467 20.8654 21.5787 21.0078 21.2407C21.0094 21.2379 21.0121 21.2332 21.0162 21.227C21.031 21.2043 21.0619 21.1633 21.1159 21.1193C21.2109 21.0418 21.437 20.9053 21.9189 20.9238C22.2176 20.9353 22.3395 21.0567 22.6182 21.4143C22.624 21.4217 22.6298 21.4292 22.6358 21.4368C22.6406 21.4431 22.6456 21.4494 22.6505 21.4559C22.9207 21.8046 23.3796 22.3967 24.3012 22.3967C25.1264 22.3967 25.6134 21.9868 25.9417 21.7106C25.9573 21.6975 25.9725 21.6847 25.9874 21.6722C26.2968 21.4135 26.4925 21.2679 26.9024 21.2679C27.1278 21.2679 27.2672 21.3139 27.3697 21.3671C27.4851 21.4269 27.5863 21.5114 27.7378 21.6508C27.7535 21.6652 27.7696 21.6802 27.7863 21.6957L27.7867 21.6961C28.0824 21.9708 28.541 22.3967 29.3564 22.3967C30.1339 22.3967 30.7052 22.0093 31.1001 21.7414C31.1136 21.7322 31.127 21.7232 31.1402 21.7143C31.5785 21.4178 31.8293 21.2679 32.1539 21.2679C32.439 21.2679 32.5997 21.3824 32.9024 21.6554C32.9194 21.6708 32.9372 21.687 32.9558 21.7039L32.956 21.7041C33.2417 21.965 33.7146 22.3967 34.4608 22.3967C35.2268 22.3967 35.7511 21.9068 36.0619 21.6163C36.0772 21.602 36.0919 21.5883 36.1061 21.5751C36.4891 21.2195 36.6387 21.1206 36.8165 21.1206C37.0653 21.1206 37.2844 21.2437 37.4714 21.4219C37.562 21.5081 37.6325 21.596 37.6798 21.662C37.7031 21.6944 37.7197 21.7201 37.7293 21.7356C37.7334 21.7423 37.7362 21.747 37.7376 21.7494C37.9215 22.0795 38.3376 22.1995 38.6691 22.0172C39.0016 21.8343 39.123 21.4165 38.94 21.084C38.94 21.084 38.9399 21.0837 38.9398 21.0835L38.9395 21.083L38.9389 21.082L38.9383 21.0807C38.9381 21.0804 38.9379 21.08 38.9376 21.0796C38.9367 21.0779 38.9356 21.076 38.9343 21.0738C38.9319 21.0694 38.9288 21.0641 38.9252 21.0579C38.9179 21.0454 38.9084 21.0294 38.8965 21.0103C38.8728 20.9721 38.8395 20.921 38.7968 20.8615C38.7122 20.7434 38.5863 20.5859 38.4193 20.4267C38.0909 20.1141 37.5494 19.7464 36.8165 19.7464C36.0503 19.7464 35.526 20.2365 35.2151 20.5269L35.2147 20.5274C35.1996 20.5414 35.1851 20.555 35.1711 20.568C34.7881 20.9236 34.6387 21.0225 34.4608 21.0225C34.2741 21.0225 34.1698 20.9479 33.8227 20.6349C33.4997 20.3435 32.9977 19.8936 32.1539 19.8936C31.3766 19.8936 30.8055 20.2809 30.4105 20.5487C30.3969 20.5579 30.3834 20.5671 30.3702 20.576C29.9319 20.8725 29.681 21.0225 29.3564 21.0225C29.0893 21.0225 28.9881 20.9338 28.6682 20.6395C28.513 20.4967 28.2952 20.299 28.0026 20.1472C27.6971 19.9887 27.3396 19.8936 26.9024 19.8936C25.9872 19.8936 25.4712 20.3124 25.1058 20.6181C24.7594 20.9078 24.6147 21.0225 24.3012 21.0225C24.0827 21.0225 24.0007 20.9525 23.7019 20.5693L23.6912 20.5555C23.4046 20.1878 22.937 19.5877 21.9718 19.5506C21.1776 19.52 20.6184 19.7517 20.2472 20.0545C20.0681 20.2006 19.9456 20.3529 19.8654 20.4759C19.8252 20.5374 19.7953 20.5921 19.7737 20.6358C19.7629 20.6577 19.7541 20.6769 19.7472 20.6931C19.7437 20.7012 19.7407 20.7085 19.738 20.7151L19.7366 20.7189C19.7358 20.7207 19.7351 20.7225 19.7344 20.7242C19.7341 20.7251 19.7338 20.7259 19.7335 20.7267L19.7328 20.7283C19.7328 20.7286 19.7327 20.7288 19.7326 20.729L19.7325 20.7294C19.7324 20.7297 19.7322 20.73 19.7322 20.7303L19.732 20.7307L19.7318 20.7312L19.7315 20.7321ZM21.0133 21.2272L21.0122 21.23C21.0139 21.2256 21.0157 21.2212 21.0173 21.2168L21.0169 21.2182C21.0164 21.2193 21.016 21.2204 21.0156 21.2214C21.0151 21.2227 21.0146 21.2239 21.0142 21.2251L21.0133 21.2272ZM21.0066 21.2429C21.0064 21.2433 21.0062 21.2437 21.0062 21.2437C21.006 21.244 21.0062 21.2437 21.0066 21.2429ZM37.7386 21.7511C37.7387 21.7513 37.7387 21.7512 37.7384 21.7508L37.7386 21.7511Z" fill="#E65C28"/>
<path d="M44.4787 0H22.0984C21.2852 0 20.626 0.659213 20.626 1.47239V21.1043C20.626 21.9175 21.2852 22.5767 22.0984 22.5767H44.4787C45.2919 22.5767 45.9511 21.9175 45.9511 21.1043V1.47239C45.9511 0.659213 45.2919 0 44.4787 0Z" fill="#FECE12"/>
<path d="M44.4783 0H24.7483C23.9351 0 23.2759 0.659213 23.2759 1.47239V21.1043C23.2759 21.9175 23.9351 22.5767 24.7483 22.5767H44.4783C45.2915 22.5767 45.9507 21.9175 45.9507 21.1043V1.47239C45.9507 0.659213 45.2915 0 44.4783 0Z" fill="#FD9115"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M25.3835 4.22513C25.0282 4.09188 24.8482 3.69581 24.9815 3.34049C24.9815 3.34049 24.9816 3.34003 24.9818 3.33957L24.9819 3.33922C24.982 3.33903 24.9822 3.33864 24.9822 3.33864L24.9823 3.3381L24.9825 3.33771C24.9826 3.33738 24.9827 3.33705 24.9828 3.33671L24.9835 3.33508C24.9838 3.33427 24.9841 3.33344 24.9844 3.33259C24.9853 3.33032 24.9863 3.32791 24.9873 3.32537C24.9875 3.32473 24.9878 3.32408 24.988 3.32342C24.9907 3.31692 24.9937 3.30958 24.9972 3.30149C25.0041 3.28531 25.0129 3.26603 25.0237 3.24414C25.0453 3.20043 25.0752 3.14581 25.1154 3.08429C25.1956 2.96128 25.3181 2.80902 25.4972 2.66284C25.8684 2.36003 26.4276 2.12841 27.2218 2.15896C28.187 2.19609 28.6546 2.79613 28.9412 3.16391L28.9519 3.17769C29.2507 3.56091 29.3327 3.63084 29.5512 3.63084C29.8647 3.63084 30.0094 3.51613 30.3558 3.22647C30.7212 2.92079 31.2372 2.50202 32.1524 2.50201C32.5896 2.50201 32.9471 2.59711 33.2526 2.75558C33.5452 2.90741 33.763 3.10506 33.9182 3.24786C34.2381 3.54216 34.3393 3.63083 34.6064 3.63083C34.931 3.63083 35.1819 3.48091 35.6202 3.1844L35.6606 3.15706C36.0555 2.88923 36.6266 2.50199 37.4039 2.502C38.2477 2.50201 38.7497 2.95191 39.0728 3.24329C39.4198 3.55629 39.5241 3.63084 39.7108 3.63083C39.8887 3.63083 40.0382 3.53196 40.4211 3.17641C40.4352 3.16324 40.4499 3.14952 40.4651 3.13532C40.776 2.84483 41.3003 2.35477 42.0665 2.35477C42.7994 2.35477 43.3409 2.72247 43.6693 3.03511C43.8363 3.19427 43.9622 3.35177 44.0468 3.46984C44.0895 3.52942 44.1228 3.58044 44.1465 3.61863C44.1584 3.63776 44.1679 3.65381 44.1752 3.66624C44.1788 3.67245 44.1819 3.67778 44.1843 3.68215C44.185 3.68327 44.1856 3.68433 44.1861 3.68533L44.1876 3.68798C44.1881 3.68883 44.1885 3.68962 44.1889 3.69035L44.1895 3.6914L44.1898 3.69188C44.1899 3.69208 44.19 3.69234 44.19 3.69234C44.373 4.02485 44.2516 4.44266 43.9191 4.62554C43.5876 4.80787 43.1714 4.68786 42.9875 4.35763C42.9861 4.3552 42.9833 4.35056 42.9793 4.34397C42.9697 4.32848 42.9531 4.30281 42.9298 4.27036C42.8825 4.20439 42.812 4.11649 42.7214 4.03024C42.5344 3.85209 42.3153 3.729 42.0665 3.729C41.8887 3.729 41.7391 3.82789 41.3561 4.18343C41.3419 4.19664 41.3272 4.2104 41.3119 4.22465C41.0011 4.51514 40.4769 5.00506 39.7108 5.00506C38.9646 5.00507 38.4917 4.57338 38.206 4.3125L38.2059 4.3124C38.1873 4.29542 38.1694 4.27916 38.1524 4.26379C37.8497 3.99074 37.689 3.87623 37.4039 3.87623C37.0793 3.87622 36.8285 4.02614 36.3902 4.32265C36.377 4.33154 36.3637 4.34059 36.3501 4.34978C35.9552 4.61761 35.3839 5.00506 34.6064 5.00506C33.791 5.00506 33.3324 4.57912 33.0367 4.30447C33.0199 4.28887 33.0036 4.27373 32.9878 4.25921C32.8363 4.11981 32.7351 4.03525 32.6197 3.97543C32.5172 3.92225 32.3778 3.87624 32.1524 3.87624C31.7425 3.87625 31.5468 4.02188 31.2374 4.28062C31.2225 4.29304 31.2073 4.30581 31.1918 4.31889L31.1917 4.31899C30.8635 4.5952 30.3764 5.00507 29.5512 5.00507C28.6296 5.00507 28.1707 4.41292 27.9005 4.06426C27.8895 4.04997 27.8787 4.03608 27.8682 4.02265C27.5895 3.6651 27.4676 3.54367 27.1689 3.53218C26.687 3.51364 26.4609 3.65013 26.3659 3.72769C26.3119 3.77169 26.281 3.81269 26.2662 3.83538C26.2621 3.84154 26.2594 3.84624 26.2578 3.84907C26.1154 4.18707 25.7301 4.35508 25.3835 4.22513ZM26.2633 3.8356L26.2641 3.83358C26.2646 3.83238 26.2651 3.83112 26.2656 3.8298C26.2657 3.82961 26.2657 3.82942 26.2658 3.82923C26.2661 3.82836 26.2665 3.82747 26.2669 3.82654L26.2673 3.82524C26.2656 3.82963 26.2639 3.83399 26.2622 3.83833L26.2633 3.8356ZM42.9882 4.35881C42.9887 4.35966 42.9888 4.3598 42.9884 4.35917L42.9882 4.35881Z" fill="#E65C28"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M25.3835 7.53042C25.0282 7.39718 24.8482 7.00111 24.9815 6.64579C24.9815 6.64579 24.9816 6.64531 24.9818 6.64488L24.982 6.64436L24.9822 6.64394C24.9822 6.64364 24.9824 6.64334 24.9825 6.64304C24.9826 6.6427 24.9827 6.64235 24.9828 6.642L24.9834 6.64044C24.9838 6.63962 24.9841 6.63875 24.9844 6.63789C24.9852 6.63589 24.9861 6.63379 24.9869 6.63159L24.988 6.62873C24.9907 6.62221 24.9937 6.61488 24.9972 6.60678C25.0041 6.59061 25.0129 6.57134 25.0237 6.54945C25.0453 6.50573 25.0752 6.4511 25.1154 6.38959C25.1956 6.26657 25.3181 6.11432 25.4972 5.96814C25.8684 5.66532 26.4276 5.43372 27.2218 5.46425C28.187 5.50138 28.6546 6.10143 28.9412 6.46921L28.9519 6.48298C29.2507 6.86621 29.3327 6.93615 29.5512 6.93615C29.8647 6.93615 30.0094 6.82143 30.3558 6.53177C30.7212 6.2261 31.2372 5.80731 32.1524 5.80731C32.5896 5.8073 32.9471 5.90241 33.2526 6.06088C33.5452 6.21271 33.763 6.41036 33.9182 6.55317C34.2381 6.84746 34.3393 6.93614 34.6064 6.93614C34.931 6.93614 35.1819 6.78621 35.6202 6.4897C35.6322 6.48157 35.6444 6.4733 35.6568 6.46491L35.6605 6.46235C36.0555 6.19453 36.6266 5.80728 37.4039 5.80729C38.2477 5.8073 38.7497 6.25722 39.0728 6.54858C39.4198 6.86158 39.5241 6.93614 39.7108 6.93614C39.8887 6.93614 40.0382 6.83726 40.4211 6.48171C40.4352 6.46857 40.4499 6.45488 40.465 6.44072L40.4651 6.44062C40.776 6.15013 41.3003 5.66006 42.0665 5.66006C42.7994 5.66006 43.3409 6.02777 43.6693 6.34041C43.8363 6.49957 43.9622 6.65707 44.0468 6.77515C44.0895 6.83472 44.1228 6.88573 44.1465 6.92393C44.1584 6.94307 44.1679 6.95911 44.1752 6.97153C44.1765 6.97381 44.1778 6.97598 44.1789 6.97801C44.181 6.98153 44.1828 6.98468 44.1843 6.98744C44.1851 6.98873 44.1857 6.98992 44.1864 6.99103C44.1868 6.99182 44.1872 6.99257 44.1876 6.99328C44.188 6.99389 44.1883 6.99446 44.1886 6.99501L44.1889 6.99565L44.1895 6.99669L44.1898 6.99718C44.1899 6.99738 44.1465 6.92393 44.1465 6.92393L44.19 6.99764C44.373 7.33015 44.2516 7.74795 43.9191 7.93084C43.5876 8.11315 43.1714 7.99317 42.9876 7.66301C42.9862 7.66061 42.9834 7.65593 42.9793 7.64928C42.9697 7.63379 42.9531 7.60812 42.9298 7.57567C42.8825 7.50969 42.812 7.42179 42.7214 7.33555C42.5344 7.15739 42.3153 7.0343 42.0665 7.0343C41.8887 7.0343 41.7391 7.13318 41.3561 7.48873C41.3419 7.50193 41.3272 7.5157 41.3119 7.52995C41.0011 7.82045 40.4768 8.31037 39.7108 8.31037C38.9646 8.31037 38.4917 7.87867 38.206 7.6178L38.2058 7.6176C38.1872 7.60066 38.1694 7.58443 38.1524 7.56909C37.8497 7.29604 37.689 7.18153 37.4039 7.18153C37.0793 7.18153 36.8285 7.33144 36.3902 7.62795C36.377 7.63685 36.3636 7.64591 36.3501 7.65511C35.9552 7.92294 35.3839 8.31037 34.6064 8.31037C33.791 8.31037 33.3324 7.88442 33.0367 7.60977C33.0199 7.59416 33.0036 7.57903 32.9878 7.56451C32.8363 7.42511 32.7351 7.34055 32.6197 7.28073C32.5172 7.22754 32.3778 7.18155 32.1524 7.18155C31.7425 7.18155 31.5468 7.32717 31.2374 7.58591L31.2238 7.5973C31.2191 7.60126 31.2143 7.60524 31.2095 7.60926C31.2036 7.61422 31.1977 7.61923 31.1917 7.62429C30.8634 7.90051 30.3764 8.31038 29.5512 8.31038C28.6296 8.31038 28.1707 7.71822 27.9005 7.36957C27.8895 7.35527 27.8787 7.34137 27.8682 7.32795C27.5895 6.97039 27.4676 6.84896 27.1689 6.83748C26.687 6.81893 26.4609 6.95543 26.3659 7.03298C26.3119 7.07699 26.281 7.11799 26.2662 7.14067C26.2621 7.14685 26.2594 7.15154 26.2578 7.15438C26.1154 7.49238 25.7301 7.66038 25.3835 7.53042ZM26.2622 7.14363L26.2633 7.1409L26.2646 7.1376L26.2656 7.13511L26.2658 7.13465C26.2661 7.13374 26.2664 7.1328 26.2669 7.13185L26.2673 7.13052C26.2657 7.13491 26.2639 7.13929 26.2622 7.14363ZM42.9886 7.66476C42.9887 7.66496 42.9887 7.66486 42.9884 7.66448L42.9886 7.66476Z" fill="#E65C28"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M25.3835 10.7697C25.0282 10.6365 24.8482 10.2404 24.9815 9.88507C24.9815 9.88507 24.9816 9.88458 24.9818 9.88409C24.9818 9.88409 24.9821 9.8835 24.9822 9.88321C24.9822 9.88287 24.9824 9.88255 24.9825 9.88223L24.9826 9.88189C24.9827 9.88168 24.9828 9.88147 24.9828 9.88125C24.983 9.88087 24.9831 9.88047 24.9833 9.88008C24.9837 9.87914 24.9841 9.87816 24.9844 9.87712C24.9849 9.87598 24.9854 9.87481 24.9858 9.8736L24.9872 9.87003L24.988 9.868C24.9907 9.86152 24.9937 9.85415 24.9972 9.84601C25.0041 9.82991 25.0129 9.8106 25.0237 9.78871C25.0453 9.74499 25.0752 9.69037 25.1154 9.62886C25.1956 9.50584 25.3181 9.35358 25.4972 9.2074C25.8684 8.90459 26.4276 8.67298 27.2218 8.70352C28.187 8.74065 28.6546 9.34069 28.9412 9.70847L28.9519 9.72225C29.2507 10.1054 29.3327 10.1754 29.5512 10.1754C29.8647 10.1754 30.0094 10.0607 30.3558 9.77103C30.7212 9.46536 31.2372 9.04658 32.1524 9.04658C32.5896 9.04657 32.9471 9.14167 33.2526 9.30014C33.5452 9.45197 33.763 9.64962 33.9182 9.79243C34.2381 10.0867 34.3393 10.1754 34.6064 10.1754C34.931 10.1754 35.1819 10.0254 35.6202 9.72896L35.6606 9.70162C36.0555 9.43379 36.6266 9.04655 37.4039 9.04656C38.2477 9.04657 38.7497 9.49648 39.0728 9.78785C39.4198 10.1008 39.5241 10.1754 39.7108 10.1754C39.8887 10.1754 40.0382 10.0765 40.4211 9.72097C40.4352 9.7078 40.4499 9.69408 40.4651 9.67988C40.776 9.38939 41.3003 8.89933 42.0665 8.89933C42.7994 8.89933 43.3409 9.26703 43.6693 9.57967C43.8363 9.73884 43.9622 9.89636 44.0468 10.0144C44.0895 10.0739 44.1228 10.125 44.1465 10.1632C44.1584 10.1823 44.1679 10.1984 44.1752 10.2108L44.1811 10.221L44.1843 10.2267L44.1857 10.2292L44.1876 10.2326C44.1879 10.233 44.1882 10.2335 44.1884 10.234C44.1886 10.2343 44.1888 10.2346 44.1889 10.2349L44.1892 10.2354L44.1895 10.236L44.1898 10.2365L44.19 10.2369C44.373 10.5694 44.2516 10.9872 43.9191 11.1701C43.5882 11.3521 43.1728 11.2329 42.9885 10.9039C42.9887 10.9041 42.9886 10.9041 42.9886 10.9041L42.9885 10.9039L42.9884 10.9038L42.9883 10.9035L42.9881 10.9033C42.9876 10.9023 42.9866 10.9007 42.9852 10.8983C42.9837 10.8958 42.9817 10.8925 42.9793 10.8886C42.9697 10.8731 42.9531 10.8473 42.9298 10.8149C42.8825 10.749 42.812 10.661 42.7214 10.5748C42.5344 10.3967 42.3153 10.2736 42.0665 10.2736C41.8887 10.2736 41.7391 10.3724 41.3561 10.728C41.3419 10.7412 41.3272 10.7549 41.312 10.7692C41.0011 11.0597 40.4769 11.5497 39.7108 11.5497C38.9647 11.5497 38.4918 11.118 38.2061 10.8572C38.1874 10.8401 38.1695 10.8238 38.1524 10.8084C37.8497 10.5353 37.689 10.4208 37.4039 10.4208C37.0793 10.4208 36.8285 10.5707 36.3902 10.8673C36.377 10.8762 36.3636 10.8853 36.35 10.8945C35.955 11.1623 35.3838 11.5497 34.6064 11.5497C33.791 11.5497 33.3324 11.1237 33.0367 10.849L33.0366 10.8489C33.0198 10.8333 33.0036 10.8182 32.9878 10.8037C32.8363 10.6644 32.7351 10.5798 32.6197 10.52C32.5172 10.4668 32.3778 10.4208 32.1524 10.4208C31.7425 10.4208 31.5468 10.5664 31.2374 10.8251C31.2225 10.8376 31.2072 10.8505 31.1916 10.8636C30.8634 11.1398 30.3763 11.5497 29.5512 11.5497C28.6296 11.5497 28.1707 10.9575 27.9006 10.6088L27.8974 10.6047C27.8874 10.5919 27.8777 10.5793 27.8682 10.5672C27.5895 10.2097 27.4676 10.0883 27.1689 10.0768C26.687 10.0582 26.4609 10.1947 26.3659 10.2722C26.3119 10.3163 26.281 10.3572 26.2662 10.3799C26.2621 10.3861 26.2594 10.3908 26.2578 10.3936C26.1154 10.7317 25.7301 10.8997 25.3835 10.7697ZM26.2623 10.3828L26.2633 10.3802L26.2641 10.3783C26.2646 10.377 26.2651 10.3757 26.2656 10.3744L26.2662 10.3728C26.2649 10.3762 26.2636 10.3795 26.2623 10.3828ZM26.2566 10.3958C26.2564 10.3962 26.2562 10.3967 26.2562 10.3967C26.256 10.397 26.2562 10.3966 26.2566 10.3958ZM26.2673 10.3699L26.2664 10.3721L26.2669 10.3711C26.267 10.3707 26.2671 10.3703 26.2673 10.3699Z" fill="#E65C28"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M24.9815 13.3707C24.8482 13.726 25.0282 14.1221 25.3835 14.2553C25.7301 14.3853 26.1154 14.2172 26.2578 13.8792C26.2594 13.8764 26.2621 13.8717 26.2662 13.8656C26.281 13.8429 26.3119 13.8019 26.3659 13.7579C26.4609 13.6803 26.687 13.5438 27.1689 13.5624C27.4676 13.5738 27.5895 13.6953 27.8682 14.0528C27.8786 14.0661 27.8893 14.0799 27.9003 14.0941L27.9005 14.0944C28.1707 14.4431 28.6296 15.0352 29.5512 15.0352C30.3764 15.0352 30.8635 14.6254 31.1917 14.3492C31.2073 14.336 31.2225 14.3232 31.2374 14.3108C31.5468 14.0521 31.7425 13.9064 32.1524 13.9064C32.3778 13.9064 32.5172 13.9524 32.6197 14.0056C32.7351 14.0654 32.8363 14.15 32.9878 14.2894C32.996 14.2969 33.0042 14.3045 33.0126 14.3123C33.0205 14.3196 33.0286 14.3271 33.0367 14.3346C33.3324 14.6093 33.791 15.0352 34.6064 15.0352C35.3839 15.0352 35.9552 14.6478 36.3501 14.38L36.351 14.3793C36.3643 14.3704 36.3773 14.3615 36.3902 14.3528C36.8285 14.0563 37.0793 13.9064 37.4039 13.9064C37.689 13.9064 37.8497 14.0209 38.1524 14.294C38.1695 14.3094 38.1873 14.3257 38.206 14.3427C38.4917 14.6036 38.9646 15.0352 39.7108 15.0352C40.4768 15.0352 41.0011 14.5453 41.3119 14.2548L41.3123 14.2545C41.3274 14.2404 41.342 14.2267 41.3561 14.2136C41.7391 13.8581 41.8887 13.7592 42.0665 13.7592C42.3153 13.7592 42.5344 13.8823 42.7214 14.0604C42.812 14.1467 42.8825 14.2346 42.9298 14.3005C42.9531 14.333 42.9697 14.3587 42.9793 14.3741C42.9833 14.3807 42.9861 14.3854 42.9875 14.3878C43.1714 14.718 43.5876 14.838 43.9191 14.6557C44.2516 14.4728 44.373 14.055 44.19 13.7225L44.1898 13.7221L44.1895 13.7216L44.1889 13.7205L44.1884 13.7195C44.1882 13.7192 44.1881 13.7189 44.1879 13.7186L44.1876 13.7182L44.1864 13.716C44.1858 13.7148 44.1851 13.7136 44.1843 13.7123C44.1819 13.708 44.1788 13.7026 44.1752 13.6964C44.1679 13.684 44.1584 13.6679 44.1465 13.6488C44.1228 13.6106 44.0895 13.5596 44.0468 13.5C43.9622 13.3819 43.8363 13.2244 43.6693 13.0653C43.3409 12.7526 42.7994 12.3849 42.0665 12.3849C41.3003 12.3849 40.776 12.875 40.4651 13.1655C40.4499 13.1797 40.4352 13.1934 40.4211 13.2066C40.0382 13.5621 39.8887 13.661 39.7108 13.661C39.5241 13.661 39.4198 13.5865 39.0728 13.2735C38.7497 12.9821 38.2477 12.5322 37.4039 12.5322C36.6266 12.5322 36.0555 12.9194 35.6606 13.1872C35.6469 13.1965 35.6334 13.2056 35.6202 13.2146C35.1819 13.5111 34.931 13.661 34.6064 13.661C34.3393 13.661 34.2381 13.5723 33.9182 13.278C33.763 13.1352 33.5452 12.9376 33.2526 12.7858C32.9471 12.6273 32.5896 12.5322 32.1524 12.5322C31.2372 12.5322 30.7212 12.951 30.3558 13.2566C30.0094 13.5463 29.8647 13.661 29.5512 13.661C29.3327 13.661 29.2507 13.5911 28.9519 13.2079L28.9412 13.1941C28.6546 12.8263 28.187 12.2263 27.2218 12.1891C26.4276 12.1586 25.8684 12.3902 25.4972 12.693C25.3181 12.8392 25.1956 12.9914 25.1154 13.1145C25.0752 13.176 25.0453 13.2306 25.0237 13.2743C25.0129 13.2962 25.0041 13.3155 24.9972 13.3317C24.9937 13.3398 24.9907 13.3471 24.988 13.3536L24.9873 13.3556C24.9863 13.3581 24.9853 13.3605 24.9844 13.3628C24.9841 13.3636 24.9838 13.3643 24.9835 13.3651L24.9835 13.3653C24.9832 13.3658 24.983 13.3664 24.9828 13.3669C24.9827 13.3672 24.9826 13.3675 24.9825 13.3679L24.9825 13.368C24.9823 13.3682 24.9822 13.3685 24.9822 13.3688C24.9822 13.3688 24.982 13.3691 24.982 13.3693L24.9818 13.3697C24.9816 13.3702 24.9815 13.3707 24.9815 13.3707ZM26.2633 13.8658L26.2622 13.8685C26.2639 13.8642 26.2656 13.8598 26.2673 13.8554L26.2669 13.8567C26.2664 13.8578 26.266 13.8589 26.2656 13.86C26.2651 13.8613 26.2646 13.8625 26.2642 13.8637L26.2633 13.8658ZM26.2566 13.8814C26.2564 13.8819 26.2562 13.8823 26.2562 13.8823C26.256 13.8825 26.2562 13.8822 26.2566 13.8814ZM42.9882 14.389C42.9887 14.3898 42.9888 14.39 42.9884 14.3893L42.9882 14.389Z" fill="#E65C28"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M24.9815 16.676C24.8482 17.0313 25.0282 17.4274 25.3835 17.5606C25.7301 17.6906 26.1154 17.5225 26.2578 17.1846C26.2594 17.1817 26.2621 17.177 26.2662 17.1708C26.281 17.1482 26.3119 17.1072 26.3659 17.0632C26.4609 16.9856 26.687 16.8491 27.1689 16.8677C27.4676 16.8791 27.5895 17.0006 27.8682 17.3581C27.874 17.3655 27.8798 17.373 27.8858 17.3807C27.8906 17.3869 27.8956 17.3933 27.9005 17.3997C28.1707 17.7484 28.6296 18.3406 29.5512 18.3406C30.3764 18.3406 30.8634 17.9307 31.1917 17.6545C31.2073 17.6414 31.2225 17.6285 31.2374 17.6161C31.5468 17.3573 31.7425 17.2117 32.1524 17.2117C32.3778 17.2117 32.5172 17.2577 32.6197 17.3109C32.7351 17.3707 32.8363 17.4553 32.9878 17.5947C33.0035 17.6091 33.0197 17.6241 33.0363 17.6396L33.0367 17.6399C33.3324 17.9146 33.791 18.3405 34.6064 18.3405C35.3839 18.3405 35.9552 17.9531 36.3501 17.6853C36.3636 17.6761 36.377 17.667 36.3902 17.6581C36.8285 17.3616 37.0793 17.2117 37.4039 17.2117C37.689 17.2117 37.8497 17.3262 38.1524 17.5993C38.1694 17.6146 38.1872 17.6308 38.2058 17.6478L38.206 17.648C38.4917 17.9088 38.9646 18.3405 39.7108 18.3405C40.4768 18.3405 41.0011 17.8506 41.3119 17.5601C41.3272 17.5459 41.3419 17.5321 41.3561 17.5189C41.7391 17.1634 41.8887 17.0645 42.0665 17.0645C42.3153 17.0645 42.5344 17.1876 42.7214 17.3657C42.812 17.452 42.8825 17.5399 42.9298 17.6058C42.9531 17.6383 42.9697 17.664 42.9793 17.6794C42.9834 17.6861 42.9862 17.6908 42.9876 17.6932C43.1715 18.0234 43.5877 18.1433 43.9191 17.961C44.2516 17.7781 44.373 17.3603 44.19 17.0278C44.19 17.0278 44.1899 17.0276 44.1898 17.0274L44.1895 17.0269L44.1889 17.0258L44.1883 17.0246C44.1881 17.0242 44.1879 17.0238 44.1876 17.0234C44.1867 17.0218 44.1856 17.0198 44.1843 17.0176C44.1819 17.0133 44.1788 17.0079 44.1752 17.0017C44.1679 16.9893 44.1584 16.9732 44.1465 16.9541C44.1228 16.9159 44.0895 16.8649 44.0468 16.8053C43.9622 16.6872 43.8363 16.5297 43.6693 16.3706C43.3409 16.0579 42.7994 15.6902 42.0665 15.6902C41.3003 15.6902 40.776 16.1803 40.4651 16.4708L40.4647 16.4712C40.4496 16.4853 40.4351 16.4989 40.4211 16.5119C40.0382 16.8674 39.8887 16.9663 39.7108 16.9663C39.5241 16.9663 39.4198 16.8918 39.0728 16.5788C38.7497 16.2874 38.2477 15.8375 37.4039 15.8375C36.6266 15.8375 36.0555 16.2247 35.6605 16.4925C35.6469 16.5018 35.6334 16.5109 35.6202 16.5199C35.1819 16.8164 34.931 16.9663 34.6064 16.9663C34.3393 16.9663 34.2381 16.8776 33.9182 16.5833C33.763 16.4405 33.5452 16.2429 33.2526 16.0911C32.9471 15.9326 32.5896 15.8375 32.1524 15.8375C31.2372 15.8375 30.7212 16.2563 30.3558 16.5619C30.0094 16.8516 29.8647 16.9663 29.5512 16.9663C29.3327 16.9663 29.2507 16.8964 28.9519 16.5132L28.9412 16.4994C28.6546 16.1316 28.187 15.5316 27.2218 15.4944C26.4276 15.4639 25.8684 15.6955 25.4972 15.9983C25.3181 16.1445 25.1956 16.2967 25.1154 16.4198C25.0752 16.4813 25.0453 16.5359 25.0237 16.5796C25.0129 16.6015 25.0041 16.6208 24.9972 16.637C24.9937 16.6451 24.9907 16.6524 24.988 16.6589L24.9866 16.6627C24.9858 16.6646 24.9851 16.6664 24.9844 16.6681C24.9841 16.6689 24.9838 16.6698 24.9835 16.6706L24.9828 16.6722C24.9828 16.6724 24.9827 16.6727 24.9826 16.6729L24.9825 16.6732C24.9824 16.6735 24.9822 16.6738 24.9822 16.6741L24.982 16.6746L24.9818 16.6751L24.9815 16.676ZM26.2633 17.1711L26.2622 17.1738C26.2639 17.1695 26.2657 17.1651 26.2673 17.1607L26.2669 17.162C26.2664 17.1631 26.266 17.1642 26.2656 17.1653C26.2651 17.1666 26.2646 17.1678 26.2642 17.1689L26.2633 17.1711ZM26.2566 17.1868C26.2564 17.1872 26.2562 17.1876 26.2562 17.1876C26.256 17.1878 26.2562 17.1875 26.2566 17.1868ZM42.9886 17.6949C42.9887 17.6951 42.9887 17.695 42.9884 17.6947L42.9886 17.6949Z" fill="#E65C28"/>
<path d="M6 18.0614C6 14.0497 9.25211 10.7976 13.2638 10.7976H46.7362C50.7479 10.7976 54 14.0497 54 18.0614V43.9755C54 44.7887 53.3408 45.4479 52.5276 45.4479H7.27607C6.57132 45.4479 6 44.8766 6 44.1718V18.0614Z" fill="#B4B4B4"/>
<path d="M22 18.0614C22 14.0497 25.2521 10.7976 29.2638 10.7976H46.7362C50.7479 10.7976 54 14.0497 54 18.0614V43.9755C54 44.7887 53.3408 45.4479 52.5276 45.4479H22V18.0614Z" fill="#C4C4C4"/>
<path d="M6 43.7793H22V45.448H6.83436C6.37355 45.448 6 45.0744 6 44.6137V43.7793Z" fill="#C4C4C4"/>
<path d="M13.2637 36.6135H15.1288C15.6709 36.6135 16.1104 36.1741 16.1104 35.6319L16.1104 20.5154C16.1104 19.9732 15.6709 19.5338 15.1288 19.5338H13.2637C12.7216 19.5338 12.2821 19.9732 12.2821 20.5154L12.2821 35.6319C12.2821 36.1741 12.7216 36.6135 13.2637 36.6135Z" fill="#2F2F2F"/>
<path d="M15.5217 23.2668C16.3891 23.2668 17.0923 22.5637 17.0923 21.6963C17.0923 20.8289 16.3891 20.1257 15.5217 20.1257H9.14137C8.27397 20.1257 7.57081 20.8289 7.57081 21.6963C7.57081 22.5637 8.27397 23.2668 9.14137 23.2668H15.5217Z" fill="#4A4A4A"/>
<path d="M12.4782 23.2668C13.3455 23.2668 14.0487 22.5637 14.0487 21.6963C14.0487 20.8289 13.3455 20.1257 12.4782 20.1257H9.14073C8.27334 20.1257 7.57018 20.8289 7.57018 21.6963C7.57018 22.5637 8.27334 23.2668 9.14073 23.2668H12.4782Z" fill="#808080"/>
<path d="M39.4829 35.0918C32.8878 35.0918 29.1261 29.915 28.9694 21.3005H32.2729C32.3815 27.6233 34.8169 30.3015 36.746 30.8537V21.3005H39.8568V26.7536C41.7618 26.5189 43.7631 24.034 44.4382 21.3005H47.5489C47.0305 24.669 44.8603 27.1539 43.317 28.1755C44.8603 29.0038 47.3321 31.1713 48.2724 35.0918H44.8482C44.1127 32.4689 42.2802 30.4395 39.8568 30.1635V35.0918H39.4829Z" fill="#2F2F2F"/>
</g>
<path d="M280.512 16.7987V14.5839H273.476V2.60403H271V16.7987H280.512Z" fill="white"/>
<path d="M283.458 4.83893C284.304 4.83893 284.923 4.25503 284.923 3.42953C284.923 2.60403 284.304 2 283.458 2C282.591 2 281.972 2.60403 281.972 3.42953C281.972 4.25503 282.591 4.83893 283.458 4.83893ZM284.634 16.7987V6.32886H282.261V16.7987H284.634Z" fill="white"/>
<path d="M291.606 14.7852C290.801 14.7852 290.409 14.4027 290.409 13.6174V8.34228H293.607V6.32886H290.409V3.30872H288.635L288.036 6.32886H286.282V8.34228H288.036V13.6174C288.036 15.6711 289.254 16.7987 291.606 16.7987H293.607L293.813 14.7852H291.606Z" fill="white"/>
<path d="M306 11.443C306 8.42282 303.689 6.12752 300.429 6.12752C297.169 6.12752 294.858 8.40268 294.858 11.5638C294.858 14.7248 297.169 17 300.429 17C302.657 17 304.762 15.9732 305.567 13.9799L303.338 13.6174C302.822 14.3624 301.832 14.8859 300.573 14.8859C298.758 14.8859 297.561 13.7987 297.334 12.1879H305.959C305.979 11.9664 306 11.7248 306 11.443ZM300.429 8.14094C301.915 8.14094 303.029 9.06711 303.421 10.3758H297.478C297.87 9.02684 298.985 8.14094 300.429 8.14094Z" fill="white"/>
<defs>
<clipPath id="clip0_428_625">
<rect width="48" height="48" fill="white" transform="translate(6)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 44 KiB

+39
View File
@@ -0,0 +1,39 @@
<svg width="306" height="48" viewBox="0 0 306 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M85.5063 24.1875C87.475 23.2688 88.7437 21.7375 88.7437 19.375C88.7437 15.7875 85.4625 13.25 80.7375 13.25H69.8438V36H81.2188C86.1188 36 89.5313 33.3313 89.5313 29.7C89.5313 26.9438 87.7375 24.8875 85.5063 24.1875ZM80.7375 17.4063C82.4875 17.4063 83.7125 18.4563 83.7125 19.9C83.7125 21.3438 82.4875 22.35 80.7375 22.35H74.875V17.4063H80.7375ZM74.875 31.8438V26.2875H81.2188C83.1875 26.2875 84.5 27.425 84.5 29.0875C84.5 30.75 83.1875 31.8438 81.2188 31.8438H74.875Z" fill="black"/>
<path d="M104.403 36V17.8438H112.278V13.25H91.4966V17.8438H99.3716V36H104.403Z" fill="black"/>
<path d="M125.768 36.4375C132.899 36.4375 137.931 31.5375 137.931 24.625C137.931 17.7125 132.899 12.8125 125.768 12.8125C118.637 12.8125 113.606 17.7125 113.606 24.625C113.606 31.5375 118.637 36.4375 125.768 36.4375ZM125.768 31.8438C121.656 31.8438 118.856 28.9125 118.856 24.625C118.856 20.3375 121.656 17.4063 125.768 17.4063C129.881 17.4063 132.681 20.3375 132.681 24.625C132.681 28.9125 129.881 31.8438 125.768 31.8438Z" fill="black"/>
<path d="M152.848 36.4375C157.617 36.4375 162.123 33.9875 163.83 29.2188L159.105 28.4313C158.098 30.4438 155.867 31.8438 153.155 31.8438C149.086 31.8438 146.242 28.8688 146.242 24.625C146.242 20.3813 149.086 17.4063 153.155 17.4063C155.78 17.4063 157.967 18.7625 158.93 20.7313L163.655 19.9438C161.992 15.2625 157.705 12.8125 152.848 12.8125C145.892 12.8125 140.992 17.7563 140.992 24.625C140.992 31.4938 145.892 36.4375 152.848 36.4375Z" fill="black"/>
<path d="M177.633 36V17.8438H185.508V13.25H164.727V17.8438H172.602V36H177.633Z" fill="black"/>
<path d="M210.461 24.3625C210.461 17.8 205.561 12.8125 198.648 12.8125C191.736 12.8125 186.836 17.7563 186.836 24.625C186.836 31.4938 191.736 36.4375 198.648 36.4375C203.373 36.4375 207.836 34.2063 209.542 29.875L204.817 29.0875C203.723 30.7063 201.623 31.8438 198.954 31.8438C195.104 31.8438 192.567 29.4813 192.086 25.9813H210.373C210.417 25.5 210.461 24.975 210.461 24.3625ZM198.648 17.1875C201.798 17.1875 204.161 19.2 204.992 22.0438H192.392C193.223 19.1125 195.586 17.1875 198.648 17.1875Z" fill="black"/>
<path d="M219.412 44.9688V32.5438C220.987 34.425 223.831 36.4375 227.812 36.4375C234.331 36.4375 238.925 31.4938 238.925 24.625C238.925 17.7563 234.331 12.8125 227.812 12.8125C223.656 12.8125 220.769 15 219.194 16.925L218.144 13.25H214.381V44.9688H219.412ZM226.587 31.9313C222.344 31.9313 219.412 28.9125 219.412 24.625C219.412 20.3375 222.344 17.3188 226.587 17.3188C230.787 17.3188 233.675 20.3375 233.675 24.625C233.675 28.9125 230.787 31.9313 226.587 31.9313Z" fill="black"/>
<path d="M253.849 36.4375C258.618 36.4375 263.124 33.9875 264.831 29.2188L260.106 28.4313C259.099 30.4438 256.868 31.8438 254.156 31.8438C250.087 31.8438 247.243 28.8688 247.243 24.625C247.243 20.3813 250.087 17.4063 254.156 17.4063C256.781 17.4063 258.968 18.7625 259.931 20.7313L264.656 19.9438C262.993 15.2625 258.706 12.8125 253.849 12.8125C246.893 12.8125 241.993 17.7563 241.993 24.625C241.993 31.4938 246.893 36.4375 253.849 36.4375Z" fill="black"/>
<path d="M12.6749 41.8159H9.53384C8.99172 41.8159 8.55225 42.2554 8.55225 42.7975V47.0184C8.55225 47.5605 8.99172 48 9.53384 48H12.6749C13.2171 48 13.6565 47.5605 13.6565 47.0184V42.7975C13.6565 42.2554 13.2171 41.8159 12.6749 41.8159Z" fill="#9C9C9C"/>
<path d="M23.8649 41.8159H20.7238C20.1817 41.8159 19.7422 42.2554 19.7422 42.7975V47.0184C19.7422 47.5605 20.1817 48 20.7238 48H23.8649C24.407 48 24.8465 47.5605 24.8465 47.0184V42.7975C24.8465 42.2554 24.407 41.8159 23.8649 41.8159Z" fill="#9C9C9C"/>
<path d="M39.6686 41.8159H36.5275C35.9854 41.8159 35.5459 42.2554 35.5459 42.7975V47.0184C35.5459 47.5605 35.9854 48 36.5275 48H39.6686C40.2107 48 40.6502 47.5605 40.6502 47.0184V42.7975C40.6502 42.2554 40.2107 41.8159 39.6686 41.8159Z" fill="#9C9C9C"/>
<path d="M50.859 41.8159H47.7179C47.1758 41.8159 46.7363 42.2554 46.7363 42.7975V47.0184C46.7363 47.5605 47.1758 48 47.7179 48H50.859C51.4012 48 51.8406 47.5605 51.8406 47.0184V42.7975C51.8406 42.2554 51.4012 41.8159 50.859 41.8159Z" fill="#9C9C9C"/>
<path d="M38.7852 4.37598H16.503C15.6899 4.37598 15.0306 5.03519 15.0306 5.84837V25.4803C15.0306 26.2935 15.6899 26.9527 16.503 26.9527H38.7852C39.5984 26.9527 40.2576 26.2935 40.2576 25.4803V5.84837C40.2576 5.03519 39.5984 4.37598 38.7852 4.37598Z" fill="#FECE12"/>
<path d="M38.7855 4.37598H19.0554C18.2422 4.37598 17.583 5.03519 17.583 5.84837V25.4803C17.583 26.2935 18.2422 26.9527 19.0554 26.9527H38.7855C39.5986 26.9527 40.2578 26.2935 40.2578 25.4803V5.84837C40.2578 5.03519 39.5986 4.37598 38.7855 4.37598Z" fill="#FD9115"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.1335 8.28128C19.7782 8.14803 19.5982 7.75197 19.7315 7.39665C19.7315 7.39665 19.7316 7.39619 19.7318 7.39572L19.7319 7.39538C19.732 7.39518 19.7322 7.39479 19.7322 7.39479L19.7323 7.39425L19.7325 7.39387C19.7326 7.39353 19.7327 7.3932 19.7328 7.39286L19.7335 7.39123C19.7338 7.39043 19.7341 7.38959 19.7344 7.38875C19.7353 7.38647 19.7363 7.38406 19.7373 7.38152C19.7375 7.38088 19.7378 7.38023 19.738 7.37958C19.7407 7.37307 19.7437 7.36574 19.7472 7.35764C19.7541 7.34146 19.7629 7.32218 19.7737 7.30029C19.7953 7.25658 19.8252 7.20196 19.8654 7.14044C19.9456 7.01743 20.0681 6.86517 20.2472 6.71899C20.6184 6.41618 21.1776 6.18456 21.9718 6.21511C22.937 6.25224 23.4046 6.85229 23.6912 7.22007L23.7019 7.23384C24.0007 7.61706 24.0827 7.68699 24.3012 7.68699C24.6147 7.68699 24.7594 7.57228 25.1058 7.28263C25.4712 6.97695 25.9872 6.55817 26.9024 6.55816C27.3396 6.55816 27.6971 6.65327 28.0026 6.81173C28.2952 6.96356 28.513 7.16121 28.6682 7.30401C28.9881 7.59832 29.0893 7.68698 29.3564 7.68698C29.681 7.68698 29.9319 7.53706 30.3702 7.24055L30.4105 7.21321C30.8055 6.94538 31.3766 6.55814 32.1539 6.55815C32.9977 6.55816 33.4997 7.00806 33.8227 7.29944C34.1698 7.61244 34.2741 7.68699 34.4608 7.68698C34.6387 7.68698 34.7881 7.58812 35.1711 7.23256C35.1852 7.2194 35.1999 7.20567 35.2151 7.19147C35.526 6.90098 36.0503 6.41092 36.8165 6.41092C37.5494 6.41092 38.0909 6.77863 38.4193 7.09126C38.5863 7.25042 38.7122 7.40793 38.7968 7.52599C38.8395 7.58557 38.8728 7.63659 38.8965 7.67478C38.9084 7.69391 38.9179 7.70996 38.9252 7.72239C38.9288 7.7286 38.9319 7.73393 38.9343 7.7383C38.935 7.73942 38.9356 7.74048 38.9361 7.74148L38.9376 7.74413C38.9381 7.74499 38.9385 7.74577 38.9389 7.7465L38.9395 7.74755L38.9398 7.74803C38.9399 7.74823 38.94 7.74849 38.94 7.74849C39.123 8.08101 39.0016 8.49881 38.6691 8.68169C38.3376 8.86402 37.9214 8.74401 37.7375 8.41378C37.7361 8.41135 37.7333 8.40671 37.7293 8.40012C37.7197 8.38463 37.7031 8.35896 37.6798 8.32651C37.6325 8.26054 37.562 8.17264 37.4714 8.08639C37.2844 7.90825 37.0653 7.78515 36.8165 7.78515C36.6387 7.78515 36.4891 7.88404 36.1061 8.23958C36.0919 8.25279 36.0772 8.26656 36.0619 8.2808C35.7511 8.57129 35.2268 9.06122 34.4608 9.06122C33.7146 9.06123 33.2417 8.62953 32.956 8.36866L32.9559 8.36855C32.9372 8.35157 32.9194 8.33531 32.9024 8.31995C32.5997 8.0469 32.439 7.93238 32.1539 7.93238C31.8293 7.93237 31.5785 8.08229 31.1402 8.3788C31.127 8.38769 31.1137 8.39674 31.1001 8.40593C30.7052 8.67377 30.1339 9.06122 29.3564 9.06122C28.541 9.06122 28.0824 8.63527 27.7867 8.36062C27.7699 8.34502 27.7536 8.32988 27.7378 8.31536C27.5863 8.17597 27.4851 8.0914 27.3697 8.03158C27.2672 7.9784 27.1278 7.93239 26.9024 7.93239C26.4925 7.9324 26.2968 8.07803 25.9874 8.33677C25.9725 8.34919 25.9573 8.36196 25.9418 8.37504L25.9417 8.37514C25.6135 8.65136 25.1264 9.06123 24.3012 9.06123C23.3796 9.06123 22.9207 8.46907 22.6505 8.12042C22.6395 8.10612 22.6287 8.09223 22.6182 8.07881C22.3395 7.72125 22.2176 7.59982 21.9189 7.58833C21.437 7.56979 21.2109 7.70628 21.1159 7.78384C21.0619 7.82784 21.031 7.86884 21.0162 7.89153C21.0121 7.8977 21.0094 7.90239 21.0078 7.90523C20.8654 8.24322 20.4801 8.41124 20.1335 8.28128ZM21.0133 7.89175L21.0141 7.88973C21.0146 7.88854 21.0151 7.88728 21.0156 7.88595C21.0157 7.88576 21.0157 7.88557 21.0158 7.88538C21.0161 7.88452 21.0165 7.88362 21.0169 7.88269L21.0173 7.88139C21.0156 7.88578 21.0139 7.89015 21.0122 7.89448L21.0133 7.89175ZM37.7382 8.41496C37.7387 8.41581 37.7388 8.41595 37.7384 8.41533L37.7382 8.41496Z" fill="#E65C28"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.1335 11.5866C19.7782 11.4533 19.5982 11.0573 19.7315 10.7019C19.7315 10.7019 19.7316 10.7015 19.7318 10.701L19.732 10.7005L19.7322 10.7001C19.7322 10.6998 19.7324 10.6995 19.7325 10.6992C19.7326 10.6989 19.7327 10.6985 19.7328 10.6982L19.7334 10.6966C19.7338 10.6958 19.7341 10.6949 19.7344 10.694C19.7352 10.692 19.7361 10.6899 19.7369 10.6877L19.738 10.6849C19.7407 10.6784 19.7437 10.671 19.7472 10.6629C19.7541 10.6468 19.7629 10.6275 19.7737 10.6056C19.7953 10.5619 19.8252 10.5073 19.8654 10.4457C19.9456 10.3227 20.0681 10.1705 20.2472 10.0243C20.6184 9.72148 21.1776 9.48987 21.9718 9.52041C22.937 9.55754 23.4046 10.1576 23.6912 10.5254L23.7019 10.5391C24.0007 10.9224 24.0827 10.9923 24.3012 10.9923C24.6147 10.9923 24.7594 10.8776 25.1058 10.5879C25.4712 10.2823 25.9872 9.86347 26.9024 9.86347C27.3396 9.86346 27.6971 9.95856 28.0026 10.117C28.2952 10.2689 28.513 10.4665 28.6682 10.6093C28.9881 10.9036 29.0893 10.9923 29.3564 10.9923C29.681 10.9923 29.9319 10.8424 30.3702 10.5459C30.3822 10.5377 30.3944 10.5295 30.4068 10.5211L30.4105 10.5185C30.8055 10.2507 31.3766 9.86344 32.1539 9.86345C32.9977 9.86346 33.4997 10.3134 33.8227 10.6047C34.1698 10.9177 34.2741 10.9923 34.4608 10.9923C34.6387 10.9923 34.7881 10.8934 35.1711 10.5379C35.1852 10.5247 35.1999 10.511 35.215 10.4969L35.2151 10.4968C35.526 10.2063 36.0503 9.71622 36.8165 9.71622C37.5494 9.71622 38.0909 10.0839 38.4193 10.3966C38.5863 10.5557 38.7122 10.7132 38.7968 10.8313C38.8395 10.8909 38.8728 10.9419 38.8965 10.9801C38.9084 10.9992 38.9179 11.0153 38.9252 11.0277C38.9265 11.03 38.9278 11.0321 38.9289 11.0342C38.931 11.0377 38.9328 11.0408 38.9343 11.0436C38.9351 11.0449 38.9357 11.0461 38.9364 11.0472C38.9368 11.048 38.9372 11.0487 38.9376 11.0494C38.938 11.05 38.9383 11.0506 38.9386 11.0512L38.9389 11.0518L38.9395 11.0528L38.9398 11.0533C38.9399 11.0535 38.8965 10.9801 38.8965 10.9801L38.94 11.0538C39.123 11.3863 39.0016 11.8041 38.6691 11.987C38.3376 12.1693 37.9214 12.0493 37.7376 11.7192C37.7362 11.7168 37.7334 11.7121 37.7293 11.7054C37.7197 11.6899 37.7031 11.6643 37.6798 11.6318C37.6325 11.5658 37.562 11.4779 37.4714 11.3917C37.2844 11.2135 37.0653 11.0904 36.8165 11.0904C36.6387 11.0904 36.4891 11.1893 36.1061 11.5449C36.0919 11.5581 36.0772 11.5719 36.0619 11.5861C35.7511 11.8766 35.2268 12.3665 34.4608 12.3665C33.7146 12.3665 33.2417 11.9348 32.956 11.674L32.9558 11.6738C32.9372 11.6568 32.9194 11.6406 32.9024 11.6252C32.5997 11.3522 32.439 11.2377 32.1539 11.2377C31.8293 11.2377 31.5785 11.3876 31.1402 11.6841C31.127 11.693 31.1136 11.7021 31.1001 11.7113C30.7052 11.9791 30.1339 12.3665 29.3564 12.3665C28.541 12.3665 28.0824 11.9406 27.7867 11.6659C27.7699 11.6503 27.7536 11.6352 27.7378 11.6207C27.5863 11.4813 27.4851 11.3967 27.3697 11.3369C27.2672 11.2837 27.1278 11.2377 26.9024 11.2377C26.4925 11.2377 26.2968 11.3833 25.9874 11.6421L25.9738 11.6535C25.9691 11.6574 25.9643 11.6614 25.9595 11.6654C25.9536 11.6704 25.9477 11.6754 25.9417 11.6804C25.6134 11.9567 25.1264 12.3665 24.3012 12.3665C23.3796 12.3665 22.9207 11.7744 22.6505 11.4257C22.6395 11.4114 22.6287 11.3975 22.6182 11.3841C22.3395 11.0265 22.2176 10.9051 21.9189 10.8936C21.437 10.8751 21.2109 11.0116 21.1159 11.0891C21.0619 11.1331 21.031 11.1741 21.0162 11.1968C21.0121 11.203 21.0094 11.2077 21.0078 11.2105C20.8654 11.5485 20.4801 11.7165 20.1335 11.5866ZM21.0122 11.1998L21.0133 11.1971L21.0146 11.1938L21.0156 11.1913L21.0158 11.1908C21.0161 11.1899 21.0164 11.189 21.0169 11.188L21.0173 11.1867C21.0157 11.1911 21.0139 11.1954 21.0122 11.1998ZM37.7386 11.7209C37.7387 11.7211 37.7387 11.721 37.7384 11.7206L37.7386 11.7209Z" fill="#E65C28"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.1335 14.8258C19.7782 14.6926 19.5982 14.2966 19.7315 13.9412C19.7315 13.9412 19.7316 13.9407 19.7318 13.9402C19.7318 13.9402 19.7321 13.9397 19.7322 13.9394C19.7322 13.939 19.7324 13.9387 19.7325 13.9384L19.7326 13.938C19.7327 13.9378 19.7328 13.9376 19.7328 13.9374C19.733 13.937 19.7331 13.9366 19.7333 13.9362C19.7337 13.9353 19.7341 13.9343 19.7344 13.9333C19.7349 13.9321 19.7354 13.931 19.7358 13.9298L19.7372 13.9262L19.738 13.9241C19.7407 13.9177 19.7437 13.9103 19.7472 13.9022C19.7541 13.8861 19.7629 13.8668 19.7737 13.8449C19.7953 13.8011 19.8252 13.7465 19.8654 13.685C19.9456 13.562 20.0681 13.4097 20.2472 13.2636C20.6184 12.9607 21.1776 12.7291 21.9718 12.7597C22.937 12.7968 23.4046 13.3968 23.6912 13.7646L23.7019 13.7784C24.0007 14.1616 24.0827 14.2316 24.3012 14.2316C24.6147 14.2316 24.7594 14.1168 25.1058 13.8272C25.4712 13.5215 25.9872 13.1027 26.9024 13.1027C27.3396 13.1027 27.6971 13.1978 28.0026 13.3563C28.2952 13.5081 28.513 13.7058 28.6682 13.8486C28.9881 14.1428 29.0893 14.2316 29.3564 14.2316C29.681 14.2316 29.9319 14.0816 30.3702 13.7851L30.4105 13.7578C30.8055 13.4899 31.3766 13.1027 32.1539 13.1027C32.9977 13.1027 33.4997 13.5526 33.8227 13.844C34.1698 14.157 34.2741 14.2316 34.4608 14.2316C34.6387 14.2316 34.7881 14.1326 35.1711 13.7771C35.1852 13.764 35.1999 13.7502 35.2151 13.736C35.526 13.4455 36.0503 12.9555 36.8165 12.9555C37.5494 12.9555 38.0909 13.3232 38.4193 13.6358C38.5863 13.795 38.7122 13.9525 38.7968 14.0706C38.8395 14.1301 38.8728 14.1811 38.8965 14.2193C38.9084 14.2385 38.9179 14.2546 38.9252 14.2669L38.9311 14.2771L38.9343 14.2828L38.9357 14.2853L38.9376 14.2887C38.9379 14.2892 38.9382 14.2897 38.9384 14.2902C38.9386 14.2905 38.9388 14.2908 38.9389 14.2911L38.9392 14.2916L38.9395 14.2921L38.9398 14.2926L38.94 14.293C39.123 14.6256 39.0016 15.0434 38.6691 15.2262C38.3382 15.4082 37.9228 15.289 37.7385 14.96C37.7387 14.9603 37.7386 14.9602 37.7386 14.9602L37.7385 14.96L37.7384 14.9599L37.7383 14.9597L37.7381 14.9594C37.7376 14.9585 37.7366 14.9568 37.7352 14.9545C37.7337 14.952 37.7317 14.9487 37.7293 14.9447C37.7197 14.9292 37.7031 14.9035 37.6798 14.8711C37.6325 14.8051 37.562 14.7172 37.4714 14.631C37.2844 14.4528 37.0653 14.3297 36.8165 14.3297C36.6387 14.3297 36.4891 14.4286 36.1061 14.7841C36.0919 14.7973 36.0772 14.8111 36.062 14.8253C35.7511 15.1158 35.2269 15.6058 34.4608 15.6058C33.7147 15.6058 33.2418 15.1742 32.9561 14.9133C32.9374 14.8963 32.9195 14.8799 32.9024 14.8645C32.5997 14.5914 32.439 14.477 32.1539 14.477C31.8293 14.477 31.5785 14.6269 31.1402 14.9234C31.127 14.9323 31.1136 14.9414 31.0999 14.9507C30.705 15.2185 30.1338 15.6058 29.3564 15.6058C28.541 15.6058 28.0824 15.1798 27.7867 14.9052L27.7865 14.905C27.7698 14.8895 27.7536 14.8744 27.7378 14.8599C27.5863 14.7205 27.4851 14.636 27.3697 14.5761C27.2672 14.5229 27.1278 14.477 26.9024 14.477C26.4925 14.477 26.2968 14.6226 25.9874 14.8813C25.9725 14.8938 25.9572 14.9066 25.9416 14.9197C25.6134 15.196 25.1263 15.6058 24.3012 15.6058C23.3796 15.6058 22.9207 15.0136 22.6506 14.665L22.6474 14.6609C22.6374 14.648 22.6277 14.6355 22.6182 14.6233C22.3395 14.2658 22.2176 14.1444 21.9189 14.1329C21.437 14.1144 21.2109 14.2508 21.1159 14.3284C21.0619 14.3724 21.031 14.4134 21.0162 14.4361C21.0121 14.4422 21.0094 14.4469 21.0078 14.4498C20.8654 14.7878 20.4801 14.9559 20.1335 14.8258ZM21.0123 14.4389L21.0133 14.4363L21.0141 14.4344C21.0146 14.4332 21.0151 14.4319 21.0156 14.4306L21.0162 14.429C21.0149 14.4323 21.0136 14.4356 21.0123 14.4389ZM21.0066 14.4519C21.0064 14.4524 21.0062 14.4528 21.0062 14.4528C21.006 14.4531 21.0062 14.4528 21.0066 14.4519ZM21.0173 14.4261L21.0164 14.4283L21.0169 14.4272C21.017 14.4269 21.0171 14.4265 21.0173 14.4261Z" fill="#E65C28"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.7315 17.4268C19.5982 17.7821 19.7782 18.1782 20.1335 18.3115C20.4801 18.4414 20.8654 18.2734 21.0078 17.9354C21.0094 17.9326 21.0121 17.9279 21.0162 17.9217C21.031 17.899 21.0619 17.858 21.1159 17.814C21.2109 17.7365 21.437 17.6 21.9189 17.6185C22.2176 17.63 22.3395 17.7514 22.6182 18.109C22.6286 18.1223 22.6393 18.1361 22.6503 18.1502L22.6505 18.1506C22.9207 18.4993 23.3796 19.0914 24.3012 19.0914C25.1264 19.0914 25.6135 18.6815 25.9417 18.4053C25.9573 18.3922 25.9725 18.3794 25.9874 18.3669C26.2968 18.1082 26.4925 17.9626 26.9024 17.9626C27.1278 17.9626 27.2672 18.0086 27.3697 18.0618C27.4851 18.1216 27.5863 18.2061 27.7378 18.3455C27.746 18.353 27.7542 18.3607 27.7626 18.3684C27.7705 18.3758 27.7786 18.3832 27.7867 18.3908C28.0824 18.6654 28.541 19.0914 29.3564 19.0914C30.1339 19.0914 30.7052 18.7039 31.1001 18.4361L31.101 18.4355C31.1143 18.4265 31.1273 18.4177 31.1402 18.409C31.5785 18.1125 31.8293 17.9625 32.1539 17.9626C32.439 17.9626 32.5997 18.0771 32.9024 18.3501C32.9195 18.3655 32.9373 18.3818 32.956 18.3988C33.2417 18.6597 33.7146 19.0914 34.4608 19.0914C35.2268 19.0914 35.7511 18.6015 36.0619 18.311L36.0623 18.3106C36.0774 18.2965 36.092 18.2829 36.1061 18.2698C36.4891 17.9142 36.6387 17.8153 36.8165 17.8153C37.0653 17.8153 37.2844 17.9384 37.4714 18.1166C37.562 18.2028 37.6325 18.2907 37.6798 18.3567C37.7031 18.3891 37.7197 18.4148 37.7293 18.4303C37.7333 18.4369 37.7361 18.4415 37.7375 18.444C37.9214 18.7742 38.3376 18.8942 38.6691 18.7119C39.0016 18.529 39.123 18.1112 38.94 17.7787L38.9398 17.7782L38.9395 17.7777L38.9389 17.7767L38.9384 17.7756C38.9382 17.7753 38.9381 17.7751 38.9379 17.7748L38.9376 17.7743L38.9364 17.7721C38.9358 17.771 38.9351 17.7698 38.9343 17.7685C38.9319 17.7641 38.9288 17.7588 38.9252 17.7526C38.9179 17.7401 38.9084 17.7241 38.8965 17.705C38.8728 17.6668 38.8395 17.6158 38.7968 17.5562C38.7122 17.4381 38.5863 17.2806 38.4193 17.1214C38.0909 16.8088 37.5494 16.4411 36.8165 16.4411C36.0503 16.4411 35.526 16.9312 35.2151 17.2216C35.1999 17.2358 35.1852 17.2496 35.1711 17.2627C34.7881 17.6183 34.6387 17.7172 34.4608 17.7172C34.2741 17.7172 34.1698 17.6426 33.8227 17.3296C33.4997 17.0382 32.9977 16.5883 32.1539 16.5883C31.3766 16.5883 30.8055 16.9756 30.4105 17.2434C30.3969 17.2527 30.3834 17.2618 30.3702 17.2707C29.9319 17.5672 29.681 17.7172 29.3564 17.7172C29.0893 17.7172 28.9881 17.6285 28.6682 17.3342C28.513 17.1914 28.2952 16.9937 28.0026 16.8419C27.6971 16.6834 27.3396 16.5883 26.9024 16.5883C25.9872 16.5883 25.4712 17.0071 25.1058 17.3128C24.7594 17.6025 24.6147 17.7172 24.3012 17.7172C24.0827 17.7172 24.0007 17.6472 23.7019 17.264L23.6912 17.2502C23.4046 16.8825 22.937 16.2824 21.9718 16.2453C21.1776 16.2147 20.6184 16.4464 20.2472 16.7492C20.0681 16.8953 19.9456 17.0476 19.8654 17.1706C19.8252 17.2321 19.7953 17.2868 19.7737 17.3305C19.7629 17.3524 19.7541 17.3716 19.7472 17.3878C19.7437 17.3959 19.7407 17.4032 19.738 17.4098L19.7373 17.4117C19.7363 17.4143 19.7353 17.4167 19.7344 17.4189C19.7341 17.4197 19.7338 17.4205 19.7335 17.4212V17.4214C19.7332 17.422 19.733 17.4225 19.7328 17.423C19.7327 17.4234 19.7326 17.4237 19.7325 17.424V17.4241C19.7323 17.4244 19.7322 17.4247 19.7322 17.425C19.7322 17.425 19.732 17.4253 19.732 17.4255L19.7318 17.4259C19.7316 17.4264 19.7315 17.4268 19.7315 17.4268ZM21.0133 17.9219L21.0122 17.9247C21.0139 17.9203 21.0156 17.916 21.0173 17.9116L21.0169 17.9129C21.0164 17.914 21.016 17.9151 21.0156 17.9161C21.0151 17.9174 21.0146 17.9187 21.0142 17.9198L21.0133 17.9219ZM21.0066 17.9376C21.0064 17.938 21.0062 17.9384 21.0062 17.9384C21.006 17.9387 21.0062 17.9384 21.0066 17.9376ZM37.7382 18.4451C37.7387 18.446 37.7388 18.4461 37.7384 18.4455L37.7382 18.4451Z" fill="#E65C28"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.7315 20.7321C19.5982 21.0874 19.7782 21.4835 20.1335 21.6168C20.4801 21.7467 20.8654 21.5787 21.0078 21.2407C21.0094 21.2379 21.0121 21.2332 21.0162 21.227C21.031 21.2043 21.0619 21.1633 21.1159 21.1193C21.2109 21.0418 21.437 20.9053 21.9189 20.9238C22.2176 20.9353 22.3395 21.0567 22.6182 21.4143C22.624 21.4217 22.6298 21.4292 22.6358 21.4368C22.6406 21.4431 22.6456 21.4494 22.6505 21.4559C22.9207 21.8046 23.3796 22.3967 24.3012 22.3967C25.1264 22.3967 25.6134 21.9868 25.9417 21.7106C25.9573 21.6975 25.9725 21.6847 25.9874 21.6722C26.2968 21.4135 26.4925 21.2679 26.9024 21.2679C27.1278 21.2679 27.2672 21.3139 27.3697 21.3671C27.4851 21.4269 27.5863 21.5114 27.7378 21.6508C27.7535 21.6652 27.7696 21.6802 27.7863 21.6957L27.7867 21.6961C28.0824 21.9708 28.541 22.3967 29.3564 22.3967C30.1339 22.3967 30.7052 22.0093 31.1001 21.7414C31.1136 21.7322 31.127 21.7232 31.1402 21.7143C31.5785 21.4178 31.8293 21.2679 32.1539 21.2679C32.439 21.2679 32.5997 21.3824 32.9024 21.6554C32.9194 21.6708 32.9372 21.687 32.9558 21.7039L32.956 21.7041C33.2417 21.965 33.7146 22.3967 34.4608 22.3967C35.2268 22.3967 35.7511 21.9068 36.0619 21.6163C36.0772 21.602 36.0919 21.5883 36.1061 21.5751C36.4891 21.2195 36.6387 21.1206 36.8165 21.1206C37.0653 21.1206 37.2844 21.2437 37.4714 21.4219C37.562 21.5081 37.6325 21.596 37.6798 21.662C37.7031 21.6944 37.7197 21.7201 37.7293 21.7356C37.7334 21.7423 37.7362 21.747 37.7376 21.7494C37.9215 22.0795 38.3376 22.1995 38.6691 22.0172C39.0016 21.8343 39.123 21.4165 38.94 21.084C38.94 21.084 38.9399 21.0837 38.9398 21.0835L38.9395 21.083L38.9389 21.082L38.9383 21.0807C38.9381 21.0804 38.9379 21.08 38.9376 21.0796C38.9367 21.0779 38.9356 21.076 38.9343 21.0738C38.9319 21.0694 38.9288 21.0641 38.9252 21.0579C38.9179 21.0454 38.9084 21.0294 38.8965 21.0103C38.8728 20.9721 38.8395 20.921 38.7968 20.8615C38.7122 20.7434 38.5863 20.5859 38.4193 20.4267C38.0909 20.1141 37.5494 19.7464 36.8165 19.7464C36.0503 19.7464 35.526 20.2365 35.2151 20.5269L35.2147 20.5274C35.1996 20.5414 35.1851 20.555 35.1711 20.568C34.7881 20.9236 34.6387 21.0225 34.4608 21.0225C34.2741 21.0225 34.1698 20.9479 33.8227 20.6349C33.4997 20.3435 32.9977 19.8936 32.1539 19.8936C31.3766 19.8936 30.8055 20.2809 30.4105 20.5487C30.3969 20.5579 30.3834 20.5671 30.3702 20.576C29.9319 20.8725 29.681 21.0225 29.3564 21.0225C29.0893 21.0225 28.9881 20.9338 28.6682 20.6395C28.513 20.4967 28.2952 20.299 28.0026 20.1472C27.6971 19.9887 27.3396 19.8936 26.9024 19.8936C25.9872 19.8936 25.4712 20.3124 25.1058 20.6181C24.7594 20.9078 24.6147 21.0225 24.3012 21.0225C24.0827 21.0225 24.0007 20.9525 23.7019 20.5693L23.6912 20.5555C23.4046 20.1878 22.937 19.5877 21.9718 19.5506C21.1776 19.52 20.6184 19.7517 20.2472 20.0545C20.0681 20.2006 19.9456 20.3529 19.8654 20.4759C19.8252 20.5374 19.7953 20.5921 19.7737 20.6358C19.7629 20.6577 19.7541 20.6769 19.7472 20.6931C19.7437 20.7012 19.7407 20.7085 19.738 20.7151L19.7366 20.7189C19.7358 20.7207 19.7351 20.7225 19.7344 20.7242C19.7341 20.7251 19.7338 20.7259 19.7335 20.7267L19.7328 20.7283C19.7328 20.7286 19.7327 20.7288 19.7326 20.729L19.7325 20.7294C19.7324 20.7297 19.7322 20.73 19.7322 20.7303L19.732 20.7307L19.7318 20.7312L19.7315 20.7321ZM21.0133 21.2272L21.0122 21.23C21.0139 21.2256 21.0157 21.2212 21.0173 21.2168L21.0169 21.2182C21.0164 21.2193 21.016 21.2204 21.0156 21.2214C21.0151 21.2227 21.0146 21.2239 21.0142 21.2251L21.0133 21.2272ZM21.0066 21.2429C21.0064 21.2433 21.0062 21.2437 21.0062 21.2437C21.006 21.244 21.0062 21.2437 21.0066 21.2429ZM37.7386 21.7511C37.7387 21.7513 37.7387 21.7512 37.7384 21.7508L37.7386 21.7511Z" fill="#E65C28"/>
<path d="M44.4787 0H22.0984C21.2852 0 20.626 0.659213 20.626 1.47239V21.1043C20.626 21.9175 21.2852 22.5767 22.0984 22.5767H44.4787C45.2919 22.5767 45.9511 21.9175 45.9511 21.1043V1.47239C45.9511 0.659213 45.2919 0 44.4787 0Z" fill="#FECE12"/>
<path d="M44.4783 0H24.7483C23.9351 0 23.2759 0.659213 23.2759 1.47239V21.1043C23.2759 21.9175 23.9351 22.5767 24.7483 22.5767H44.4783C45.2915 22.5767 45.9507 21.9175 45.9507 21.1043V1.47239C45.9507 0.659213 45.2915 0 44.4783 0Z" fill="#FD9115"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M25.3835 4.22513C25.0282 4.09188 24.8482 3.69581 24.9815 3.34049C24.9815 3.34049 24.9816 3.34003 24.9818 3.33957L24.9819 3.33922C24.982 3.33903 24.9822 3.33864 24.9822 3.33864L24.9823 3.3381L24.9825 3.33771C24.9826 3.33738 24.9827 3.33705 24.9828 3.33671L24.9835 3.33508C24.9838 3.33427 24.9841 3.33344 24.9844 3.33259C24.9853 3.33032 24.9863 3.32791 24.9873 3.32537C24.9875 3.32473 24.9878 3.32408 24.988 3.32342C24.9907 3.31692 24.9937 3.30958 24.9972 3.30149C25.0041 3.28531 25.0129 3.26603 25.0237 3.24414C25.0453 3.20043 25.0752 3.14581 25.1154 3.08429C25.1956 2.96128 25.3181 2.80902 25.4972 2.66284C25.8684 2.36003 26.4276 2.12841 27.2218 2.15896C28.187 2.19609 28.6546 2.79613 28.9412 3.16391L28.9519 3.17769C29.2507 3.56091 29.3327 3.63084 29.5512 3.63084C29.8647 3.63084 30.0094 3.51613 30.3558 3.22647C30.7212 2.92079 31.2372 2.50202 32.1524 2.50201C32.5896 2.50201 32.9471 2.59711 33.2526 2.75558C33.5452 2.90741 33.763 3.10506 33.9182 3.24786C34.2381 3.54216 34.3393 3.63083 34.6064 3.63083C34.931 3.63083 35.1819 3.48091 35.6202 3.1844L35.6606 3.15706C36.0555 2.88923 36.6266 2.50199 37.4039 2.502C38.2477 2.50201 38.7497 2.95191 39.0728 3.24329C39.4198 3.55629 39.5241 3.63084 39.7108 3.63083C39.8887 3.63083 40.0382 3.53196 40.4211 3.17641C40.4352 3.16324 40.4499 3.14952 40.4651 3.13532C40.776 2.84483 41.3003 2.35477 42.0665 2.35477C42.7994 2.35477 43.3409 2.72247 43.6693 3.03511C43.8363 3.19427 43.9622 3.35177 44.0468 3.46984C44.0895 3.52942 44.1228 3.58044 44.1465 3.61863C44.1584 3.63776 44.1679 3.65381 44.1752 3.66624C44.1788 3.67245 44.1819 3.67778 44.1843 3.68215C44.185 3.68327 44.1856 3.68433 44.1861 3.68533L44.1876 3.68798C44.1881 3.68883 44.1885 3.68962 44.1889 3.69035L44.1895 3.6914L44.1898 3.69188C44.1899 3.69208 44.19 3.69234 44.19 3.69234C44.373 4.02485 44.2516 4.44266 43.9191 4.62554C43.5876 4.80787 43.1714 4.68786 42.9875 4.35763C42.9861 4.3552 42.9833 4.35056 42.9793 4.34397C42.9697 4.32848 42.9531 4.30281 42.9298 4.27036C42.8825 4.20439 42.812 4.11649 42.7214 4.03024C42.5344 3.85209 42.3153 3.729 42.0665 3.729C41.8887 3.729 41.7391 3.82789 41.3561 4.18343C41.3419 4.19664 41.3272 4.2104 41.3119 4.22465C41.0011 4.51514 40.4769 5.00506 39.7108 5.00506C38.9646 5.00507 38.4917 4.57338 38.206 4.3125L38.2059 4.3124C38.1873 4.29542 38.1694 4.27916 38.1524 4.26379C37.8497 3.99074 37.689 3.87623 37.4039 3.87623C37.0793 3.87622 36.8285 4.02614 36.3902 4.32265C36.377 4.33154 36.3637 4.34059 36.3501 4.34978C35.9552 4.61761 35.3839 5.00506 34.6064 5.00506C33.791 5.00506 33.3324 4.57912 33.0367 4.30447C33.0199 4.28887 33.0036 4.27373 32.9878 4.25921C32.8363 4.11981 32.7351 4.03525 32.6197 3.97543C32.5172 3.92225 32.3778 3.87624 32.1524 3.87624C31.7425 3.87625 31.5468 4.02188 31.2374 4.28062C31.2225 4.29304 31.2073 4.30581 31.1918 4.31889L31.1917 4.31899C30.8635 4.5952 30.3764 5.00507 29.5512 5.00507C28.6296 5.00507 28.1707 4.41292 27.9005 4.06426C27.8895 4.04997 27.8787 4.03608 27.8682 4.02265C27.5895 3.6651 27.4676 3.54367 27.1689 3.53218C26.687 3.51364 26.4609 3.65013 26.3659 3.72769C26.3119 3.77169 26.281 3.81269 26.2662 3.83538C26.2621 3.84154 26.2594 3.84624 26.2578 3.84907C26.1154 4.18707 25.7301 4.35508 25.3835 4.22513ZM26.2633 3.8356L26.2641 3.83358C26.2646 3.83238 26.2651 3.83112 26.2656 3.8298C26.2657 3.82961 26.2657 3.82942 26.2658 3.82923C26.2661 3.82836 26.2665 3.82747 26.2669 3.82654L26.2673 3.82524C26.2656 3.82963 26.2639 3.83399 26.2622 3.83833L26.2633 3.8356ZM42.9882 4.35881C42.9887 4.35966 42.9888 4.3598 42.9884 4.35917L42.9882 4.35881Z" fill="#E65C28"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M25.3835 7.53042C25.0282 7.39718 24.8482 7.00111 24.9815 6.64579C24.9815 6.64579 24.9816 6.64531 24.9818 6.64488L24.982 6.64436L24.9822 6.64394C24.9822 6.64364 24.9824 6.64334 24.9825 6.64304C24.9826 6.6427 24.9827 6.64235 24.9828 6.642L24.9834 6.64044C24.9838 6.63962 24.9841 6.63875 24.9844 6.63789C24.9852 6.63589 24.9861 6.63379 24.9869 6.63159L24.988 6.62873C24.9907 6.62221 24.9937 6.61488 24.9972 6.60678C25.0041 6.59061 25.0129 6.57134 25.0237 6.54945C25.0453 6.50573 25.0752 6.4511 25.1154 6.38959C25.1956 6.26657 25.3181 6.11432 25.4972 5.96814C25.8684 5.66532 26.4276 5.43372 27.2218 5.46425C28.187 5.50138 28.6546 6.10143 28.9412 6.46921L28.9519 6.48298C29.2507 6.86621 29.3327 6.93615 29.5512 6.93615C29.8647 6.93615 30.0094 6.82143 30.3558 6.53177C30.7212 6.2261 31.2372 5.80731 32.1524 5.80731C32.5896 5.8073 32.9471 5.90241 33.2526 6.06088C33.5452 6.21271 33.763 6.41036 33.9182 6.55317C34.2381 6.84746 34.3393 6.93614 34.6064 6.93614C34.931 6.93614 35.1819 6.78621 35.6202 6.4897C35.6322 6.48157 35.6444 6.4733 35.6568 6.46491L35.6605 6.46235C36.0555 6.19453 36.6266 5.80728 37.4039 5.80729C38.2477 5.8073 38.7497 6.25722 39.0728 6.54858C39.4198 6.86158 39.5241 6.93614 39.7108 6.93614C39.8887 6.93614 40.0382 6.83726 40.4211 6.48171C40.4352 6.46857 40.4499 6.45488 40.465 6.44072L40.4651 6.44062C40.776 6.15013 41.3003 5.66006 42.0665 5.66006C42.7994 5.66006 43.3409 6.02777 43.6693 6.34041C43.8363 6.49957 43.9622 6.65707 44.0468 6.77515C44.0895 6.83472 44.1228 6.88573 44.1465 6.92393C44.1584 6.94307 44.1679 6.95911 44.1752 6.97153C44.1765 6.97381 44.1778 6.97598 44.1789 6.97801C44.181 6.98153 44.1828 6.98468 44.1843 6.98744C44.1851 6.98873 44.1857 6.98992 44.1864 6.99103C44.1868 6.99182 44.1872 6.99257 44.1876 6.99328C44.188 6.99389 44.1883 6.99446 44.1886 6.99501L44.1889 6.99565L44.1895 6.99669L44.1898 6.99718C44.1899 6.99738 44.1465 6.92393 44.1465 6.92393L44.19 6.99764C44.373 7.33015 44.2516 7.74795 43.9191 7.93084C43.5876 8.11315 43.1714 7.99317 42.9876 7.66301C42.9862 7.66061 42.9834 7.65593 42.9793 7.64928C42.9697 7.63379 42.9531 7.60812 42.9298 7.57567C42.8825 7.50969 42.812 7.42179 42.7214 7.33555C42.5344 7.15739 42.3153 7.0343 42.0665 7.0343C41.8887 7.0343 41.7391 7.13318 41.3561 7.48873C41.3419 7.50193 41.3272 7.5157 41.3119 7.52995C41.0011 7.82045 40.4768 8.31037 39.7108 8.31037C38.9646 8.31037 38.4917 7.87867 38.206 7.6178L38.2058 7.6176C38.1872 7.60066 38.1694 7.58443 38.1524 7.56909C37.8497 7.29604 37.689 7.18153 37.4039 7.18153C37.0793 7.18153 36.8285 7.33144 36.3902 7.62795C36.377 7.63685 36.3636 7.64591 36.3501 7.65511C35.9552 7.92294 35.3839 8.31037 34.6064 8.31037C33.791 8.31037 33.3324 7.88442 33.0367 7.60977C33.0199 7.59416 33.0036 7.57903 32.9878 7.56451C32.8363 7.42511 32.7351 7.34055 32.6197 7.28073C32.5172 7.22754 32.3778 7.18155 32.1524 7.18155C31.7425 7.18155 31.5468 7.32717 31.2374 7.58591L31.2238 7.5973C31.2191 7.60126 31.2143 7.60524 31.2095 7.60926C31.2036 7.61422 31.1977 7.61923 31.1917 7.62429C30.8634 7.90051 30.3764 8.31038 29.5512 8.31038C28.6296 8.31038 28.1707 7.71822 27.9005 7.36957C27.8895 7.35527 27.8787 7.34137 27.8682 7.32795C27.5895 6.97039 27.4676 6.84896 27.1689 6.83748C26.687 6.81893 26.4609 6.95543 26.3659 7.03298C26.3119 7.07699 26.281 7.11799 26.2662 7.14067C26.2621 7.14685 26.2594 7.15154 26.2578 7.15438C26.1154 7.49238 25.7301 7.66038 25.3835 7.53042ZM26.2622 7.14363L26.2633 7.1409L26.2646 7.1376L26.2656 7.13511L26.2658 7.13465C26.2661 7.13374 26.2664 7.1328 26.2669 7.13185L26.2673 7.13052C26.2657 7.13491 26.2639 7.13929 26.2622 7.14363ZM42.9886 7.66476C42.9887 7.66496 42.9887 7.66486 42.9884 7.66448L42.9886 7.66476Z" fill="#E65C28"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M25.3835 10.7697C25.0282 10.6365 24.8482 10.2404 24.9815 9.88507C24.9815 9.88507 24.9816 9.88458 24.9818 9.88409C24.9818 9.88409 24.9821 9.8835 24.9822 9.88321C24.9822 9.88287 24.9824 9.88255 24.9825 9.88223L24.9826 9.88189C24.9827 9.88168 24.9828 9.88147 24.9828 9.88125C24.983 9.88087 24.9831 9.88047 24.9833 9.88008C24.9837 9.87914 24.9841 9.87816 24.9844 9.87712C24.9849 9.87598 24.9854 9.87481 24.9858 9.8736L24.9872 9.87003L24.988 9.868C24.9907 9.86152 24.9937 9.85415 24.9972 9.84601C25.0041 9.82991 25.0129 9.8106 25.0237 9.78871C25.0453 9.74499 25.0752 9.69037 25.1154 9.62886C25.1956 9.50584 25.3181 9.35358 25.4972 9.2074C25.8684 8.90459 26.4276 8.67298 27.2218 8.70352C28.187 8.74065 28.6546 9.34069 28.9412 9.70847L28.9519 9.72225C29.2507 10.1054 29.3327 10.1754 29.5512 10.1754C29.8647 10.1754 30.0094 10.0607 30.3558 9.77103C30.7212 9.46536 31.2372 9.04658 32.1524 9.04658C32.5896 9.04657 32.9471 9.14167 33.2526 9.30014C33.5452 9.45197 33.763 9.64962 33.9182 9.79243C34.2381 10.0867 34.3393 10.1754 34.6064 10.1754C34.931 10.1754 35.1819 10.0254 35.6202 9.72896L35.6606 9.70162C36.0555 9.43379 36.6266 9.04655 37.4039 9.04656C38.2477 9.04657 38.7497 9.49648 39.0728 9.78785C39.4198 10.1008 39.5241 10.1754 39.7108 10.1754C39.8887 10.1754 40.0382 10.0765 40.4211 9.72097C40.4352 9.7078 40.4499 9.69408 40.4651 9.67988C40.776 9.38939 41.3003 8.89933 42.0665 8.89933C42.7994 8.89933 43.3409 9.26703 43.6693 9.57967C43.8363 9.73884 43.9622 9.89636 44.0468 10.0144C44.0895 10.0739 44.1228 10.125 44.1465 10.1632C44.1584 10.1823 44.1679 10.1984 44.1752 10.2108L44.1811 10.221L44.1843 10.2267L44.1857 10.2292L44.1876 10.2326C44.1879 10.233 44.1882 10.2335 44.1884 10.234C44.1886 10.2343 44.1888 10.2346 44.1889 10.2349L44.1892 10.2354L44.1895 10.236L44.1898 10.2365L44.19 10.2369C44.373 10.5694 44.2516 10.9872 43.9191 11.1701C43.5882 11.3521 43.1728 11.2329 42.9885 10.9039C42.9887 10.9041 42.9886 10.9041 42.9886 10.9041L42.9885 10.9039L42.9884 10.9038L42.9883 10.9035L42.9881 10.9033C42.9876 10.9023 42.9866 10.9007 42.9852 10.8983C42.9837 10.8958 42.9817 10.8925 42.9793 10.8886C42.9697 10.8731 42.9531 10.8473 42.9298 10.8149C42.8825 10.749 42.812 10.661 42.7214 10.5748C42.5344 10.3967 42.3153 10.2736 42.0665 10.2736C41.8887 10.2736 41.7391 10.3724 41.3561 10.728C41.3419 10.7412 41.3272 10.7549 41.312 10.7692C41.0011 11.0597 40.4769 11.5497 39.7108 11.5497C38.9647 11.5497 38.4918 11.118 38.2061 10.8572C38.1874 10.8401 38.1695 10.8238 38.1524 10.8084C37.8497 10.5353 37.689 10.4208 37.4039 10.4208C37.0793 10.4208 36.8285 10.5707 36.3902 10.8673C36.377 10.8762 36.3636 10.8853 36.35 10.8945C35.955 11.1623 35.3838 11.5497 34.6064 11.5497C33.791 11.5497 33.3324 11.1237 33.0367 10.849L33.0366 10.8489C33.0198 10.8333 33.0036 10.8182 32.9878 10.8037C32.8363 10.6644 32.7351 10.5798 32.6197 10.52C32.5172 10.4668 32.3778 10.4208 32.1524 10.4208C31.7425 10.4208 31.5468 10.5664 31.2374 10.8251C31.2225 10.8376 31.2072 10.8505 31.1916 10.8636C30.8634 11.1398 30.3763 11.5497 29.5512 11.5497C28.6296 11.5497 28.1707 10.9575 27.9006 10.6088L27.8974 10.6047C27.8874 10.5919 27.8777 10.5793 27.8682 10.5672C27.5895 10.2097 27.4676 10.0883 27.1689 10.0768C26.687 10.0582 26.4609 10.1947 26.3659 10.2722C26.3119 10.3163 26.281 10.3572 26.2662 10.3799C26.2621 10.3861 26.2594 10.3908 26.2578 10.3936C26.1154 10.7317 25.7301 10.8997 25.3835 10.7697ZM26.2623 10.3828L26.2633 10.3802L26.2641 10.3783C26.2646 10.377 26.2651 10.3757 26.2656 10.3744L26.2662 10.3728C26.2649 10.3762 26.2636 10.3795 26.2623 10.3828ZM26.2566 10.3958C26.2564 10.3962 26.2562 10.3967 26.2562 10.3967C26.256 10.397 26.2562 10.3966 26.2566 10.3958ZM26.2673 10.3699L26.2664 10.3721L26.2669 10.3711C26.267 10.3707 26.2671 10.3703 26.2673 10.3699Z" fill="#E65C28"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M24.9815 13.3707C24.8482 13.726 25.0282 14.1221 25.3835 14.2553C25.7301 14.3853 26.1154 14.2172 26.2578 13.8792C26.2594 13.8764 26.2621 13.8717 26.2662 13.8656C26.281 13.8429 26.3119 13.8019 26.3659 13.7579C26.4609 13.6803 26.687 13.5438 27.1689 13.5624C27.4676 13.5738 27.5895 13.6953 27.8682 14.0528C27.8786 14.0661 27.8893 14.0799 27.9003 14.0941L27.9005 14.0944C28.1707 14.4431 28.6296 15.0352 29.5512 15.0352C30.3764 15.0352 30.8635 14.6254 31.1917 14.3492C31.2073 14.336 31.2225 14.3232 31.2374 14.3108C31.5468 14.0521 31.7425 13.9064 32.1524 13.9064C32.3778 13.9064 32.5172 13.9524 32.6197 14.0056C32.7351 14.0654 32.8363 14.15 32.9878 14.2894C32.996 14.2969 33.0042 14.3045 33.0126 14.3123C33.0205 14.3196 33.0286 14.3271 33.0367 14.3346C33.3324 14.6093 33.791 15.0352 34.6064 15.0352C35.3839 15.0352 35.9552 14.6478 36.3501 14.38L36.351 14.3793C36.3643 14.3704 36.3773 14.3615 36.3902 14.3528C36.8285 14.0563 37.0793 13.9064 37.4039 13.9064C37.689 13.9064 37.8497 14.0209 38.1524 14.294C38.1695 14.3094 38.1873 14.3257 38.206 14.3427C38.4917 14.6036 38.9646 15.0352 39.7108 15.0352C40.4768 15.0352 41.0011 14.5453 41.3119 14.2548L41.3123 14.2545C41.3274 14.2404 41.342 14.2267 41.3561 14.2136C41.7391 13.8581 41.8887 13.7592 42.0665 13.7592C42.3153 13.7592 42.5344 13.8823 42.7214 14.0604C42.812 14.1467 42.8825 14.2346 42.9298 14.3005C42.9531 14.333 42.9697 14.3587 42.9793 14.3741C42.9833 14.3807 42.9861 14.3854 42.9875 14.3878C43.1714 14.718 43.5876 14.838 43.9191 14.6557C44.2516 14.4728 44.373 14.055 44.19 13.7225L44.1898 13.7221L44.1895 13.7216L44.1889 13.7205L44.1884 13.7195C44.1882 13.7192 44.1881 13.7189 44.1879 13.7186L44.1876 13.7182L44.1864 13.716C44.1858 13.7148 44.1851 13.7136 44.1843 13.7123C44.1819 13.708 44.1788 13.7026 44.1752 13.6964C44.1679 13.684 44.1584 13.6679 44.1465 13.6488C44.1228 13.6106 44.0895 13.5596 44.0468 13.5C43.9622 13.3819 43.8363 13.2244 43.6693 13.0653C43.3409 12.7526 42.7994 12.3849 42.0665 12.3849C41.3003 12.3849 40.776 12.875 40.4651 13.1655C40.4499 13.1797 40.4352 13.1934 40.4211 13.2066C40.0382 13.5621 39.8887 13.661 39.7108 13.661C39.5241 13.661 39.4198 13.5865 39.0728 13.2735C38.7497 12.9821 38.2477 12.5322 37.4039 12.5322C36.6266 12.5322 36.0555 12.9194 35.6606 13.1872C35.6469 13.1965 35.6334 13.2056 35.6202 13.2146C35.1819 13.5111 34.931 13.661 34.6064 13.661C34.3393 13.661 34.2381 13.5723 33.9182 13.278C33.763 13.1352 33.5452 12.9376 33.2526 12.7858C32.9471 12.6273 32.5896 12.5322 32.1524 12.5322C31.2372 12.5322 30.7212 12.951 30.3558 13.2566C30.0094 13.5463 29.8647 13.661 29.5512 13.661C29.3327 13.661 29.2507 13.5911 28.9519 13.2079L28.9412 13.1941C28.6546 12.8263 28.187 12.2263 27.2218 12.1891C26.4276 12.1586 25.8684 12.3902 25.4972 12.693C25.3181 12.8392 25.1956 12.9914 25.1154 13.1145C25.0752 13.176 25.0453 13.2306 25.0237 13.2743C25.0129 13.2962 25.0041 13.3155 24.9972 13.3317C24.9937 13.3398 24.9907 13.3471 24.988 13.3536L24.9873 13.3556C24.9863 13.3581 24.9853 13.3605 24.9844 13.3628C24.9841 13.3636 24.9838 13.3643 24.9835 13.3651V13.3653C24.9832 13.3658 24.983 13.3664 24.9828 13.3669C24.9827 13.3672 24.9826 13.3675 24.9825 13.3679V13.368C24.9823 13.3682 24.9822 13.3685 24.9822 13.3688C24.9822 13.3688 24.982 13.3691 24.982 13.3693L24.9818 13.3697C24.9816 13.3702 24.9815 13.3707 24.9815 13.3707ZM26.2633 13.8658L26.2622 13.8685C26.2639 13.8642 26.2656 13.8598 26.2673 13.8554L26.2669 13.8567C26.2664 13.8578 26.266 13.8589 26.2656 13.86C26.2651 13.8613 26.2646 13.8625 26.2642 13.8637L26.2633 13.8658ZM26.2566 13.8814C26.2564 13.8819 26.2562 13.8823 26.2562 13.8823C26.256 13.8825 26.2562 13.8822 26.2566 13.8814ZM42.9882 14.389C42.9887 14.3898 42.9888 14.39 42.9884 14.3893L42.9882 14.389Z" fill="#E65C28"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M24.9815 16.676C24.8482 17.0313 25.0282 17.4274 25.3835 17.5606C25.7301 17.6906 26.1154 17.5225 26.2578 17.1846C26.2594 17.1817 26.2621 17.177 26.2662 17.1708C26.281 17.1482 26.3119 17.1072 26.3659 17.0632C26.4609 16.9856 26.687 16.8491 27.1689 16.8677C27.4676 16.8791 27.5895 17.0006 27.8682 17.3581C27.874 17.3655 27.8798 17.373 27.8858 17.3807C27.8906 17.3869 27.8956 17.3933 27.9005 17.3997C28.1707 17.7484 28.6296 18.3406 29.5512 18.3406C30.3764 18.3406 30.8634 17.9307 31.1917 17.6545C31.2073 17.6414 31.2225 17.6285 31.2374 17.6161C31.5468 17.3573 31.7425 17.2117 32.1524 17.2117C32.3778 17.2117 32.5172 17.2577 32.6197 17.3109C32.7351 17.3707 32.8363 17.4553 32.9878 17.5947C33.0035 17.6091 33.0197 17.6241 33.0363 17.6396L33.0367 17.6399C33.3324 17.9146 33.791 18.3405 34.6064 18.3405C35.3839 18.3405 35.9552 17.9531 36.3501 17.6853C36.3636 17.6761 36.377 17.667 36.3902 17.6581C36.8285 17.3616 37.0793 17.2117 37.4039 17.2117C37.689 17.2117 37.8497 17.3262 38.1524 17.5993C38.1694 17.6146 38.1872 17.6308 38.2058 17.6478L38.206 17.648C38.4917 17.9088 38.9646 18.3405 39.7108 18.3405C40.4768 18.3405 41.0011 17.8506 41.3119 17.5601C41.3272 17.5459 41.3419 17.5321 41.3561 17.5189C41.7391 17.1634 41.8887 17.0645 42.0665 17.0645C42.3153 17.0645 42.5344 17.1876 42.7214 17.3657C42.812 17.452 42.8825 17.5399 42.9298 17.6058C42.9531 17.6383 42.9697 17.664 42.9793 17.6794C42.9834 17.6861 42.9862 17.6908 42.9876 17.6932C43.1715 18.0234 43.5877 18.1433 43.9191 17.961C44.2516 17.7781 44.373 17.3603 44.19 17.0278C44.19 17.0278 44.1899 17.0276 44.1898 17.0274L44.1895 17.0269L44.1889 17.0258L44.1883 17.0246C44.1881 17.0242 44.1879 17.0238 44.1876 17.0234C44.1867 17.0218 44.1856 17.0198 44.1843 17.0176C44.1819 17.0133 44.1788 17.0079 44.1752 17.0017C44.1679 16.9893 44.1584 16.9732 44.1465 16.9541C44.1228 16.9159 44.0895 16.8649 44.0468 16.8053C43.9622 16.6872 43.8363 16.5297 43.6693 16.3706C43.3409 16.0579 42.7994 15.6902 42.0665 15.6902C41.3003 15.6902 40.776 16.1803 40.4651 16.4708L40.4647 16.4712C40.4496 16.4853 40.4351 16.4989 40.4211 16.5119C40.0382 16.8674 39.8887 16.9663 39.7108 16.9663C39.5241 16.9663 39.4198 16.8918 39.0728 16.5788C38.7497 16.2874 38.2477 15.8375 37.4039 15.8375C36.6266 15.8375 36.0555 16.2247 35.6605 16.4925C35.6469 16.5018 35.6334 16.5109 35.6202 16.5199C35.1819 16.8164 34.931 16.9663 34.6064 16.9663C34.3393 16.9663 34.2381 16.8776 33.9182 16.5833C33.763 16.4405 33.5452 16.2429 33.2526 16.0911C32.9471 15.9326 32.5896 15.8375 32.1524 15.8375C31.2372 15.8375 30.7212 16.2563 30.3558 16.5619C30.0094 16.8516 29.8647 16.9663 29.5512 16.9663C29.3327 16.9663 29.2507 16.8964 28.9519 16.5132L28.9412 16.4994C28.6546 16.1316 28.187 15.5316 27.2218 15.4944C26.4276 15.4639 25.8684 15.6955 25.4972 15.9983C25.3181 16.1445 25.1956 16.2967 25.1154 16.4198C25.0752 16.4813 25.0453 16.5359 25.0237 16.5796C25.0129 16.6015 25.0041 16.6208 24.9972 16.637C24.9937 16.6451 24.9907 16.6524 24.988 16.6589L24.9866 16.6627C24.9858 16.6646 24.9851 16.6664 24.9844 16.6681C24.9841 16.6689 24.9838 16.6698 24.9835 16.6706L24.9828 16.6722C24.9828 16.6724 24.9827 16.6727 24.9826 16.6729L24.9825 16.6732C24.9824 16.6735 24.9822 16.6738 24.9822 16.6741L24.982 16.6746L24.9818 16.6751L24.9815 16.676ZM26.2633 17.1711L26.2622 17.1738C26.2639 17.1695 26.2657 17.1651 26.2673 17.1607L26.2669 17.162C26.2664 17.1631 26.266 17.1642 26.2656 17.1653C26.2651 17.1666 26.2646 17.1678 26.2642 17.1689L26.2633 17.1711ZM26.2566 17.1868C26.2564 17.1872 26.2562 17.1876 26.2562 17.1876C26.256 17.1878 26.2562 17.1875 26.2566 17.1868ZM42.9886 17.6949C42.9887 17.6951 42.9887 17.695 42.9884 17.6947L42.9886 17.6949Z" fill="#E65C28"/>
<path d="M6 18.0614C6 14.0497 9.25211 10.7976 13.2638 10.7976H46.7362C50.7479 10.7976 54 14.0497 54 18.0614V43.9755C54 44.7887 53.3408 45.4479 52.5276 45.4479H7.27607C6.57132 45.4479 6 44.8766 6 44.1718V18.0614Z" fill="#B4B4B4"/>
<path d="M22 18.0614C22 14.0497 25.2521 10.7976 29.2638 10.7976H46.7362C50.7479 10.7976 54 14.0497 54 18.0614V43.9755C54 44.7887 53.3408 45.4479 52.5276 45.4479H22V18.0614Z" fill="#C4C4C4"/>
<path d="M6 43.7793H22V45.448H6.83436C6.37355 45.448 6 45.0744 6 44.6137V43.7793Z" fill="#C4C4C4"/>
<path d="M13.2637 36.6135H15.1288C15.6709 36.6135 16.1104 36.1741 16.1104 35.6319V20.5154C16.1104 19.9732 15.6709 19.5338 15.1288 19.5338H13.2637C12.7216 19.5338 12.2821 19.9732 12.2821 20.5154V35.6319C12.2821 36.1741 12.7216 36.6135 13.2637 36.6135Z" fill="#2F2F2F"/>
<path d="M15.5217 23.2668C16.3891 23.2668 17.0923 22.5637 17.0923 21.6963C17.0923 20.8289 16.3891 20.1257 15.5217 20.1257H9.14138C8.27398 20.1257 7.57082 20.8289 7.57082 21.6963C7.57082 22.5637 8.27398 23.2668 9.14138 23.2668H15.5217Z" fill="#4A4A4A"/>
<path d="M12.4782 23.2668C13.3455 23.2668 14.0487 22.5637 14.0487 21.6963C14.0487 20.8289 13.3455 20.1257 12.4782 20.1257H9.14073C8.27334 20.1257 7.57018 20.8289 7.57018 21.6963C7.57018 22.5637 8.27334 23.2668 9.14073 23.2668H12.4782Z" fill="#808080"/>
<path d="M39.4829 35.0918C32.8878 35.0918 29.1261 29.915 28.9694 21.3005H32.2729C32.3815 27.6233 34.8169 30.3015 36.746 30.8537V21.3005H39.8568V26.7536C41.7618 26.5189 43.7631 24.034 44.4382 21.3005H47.5489C47.0305 24.669 44.8603 27.1539 43.317 28.1755C44.8603 29.0038 47.3321 31.1713 48.2724 35.0918H44.8482C44.1127 32.4689 42.2802 30.4395 39.8568 30.1635V35.0918H39.4829Z" fill="#2F2F2F"/>
<path d="M280.512 16.7987V14.5839H273.476V2.60403H271V16.7987H280.512Z" fill="black"/>
<path d="M283.458 4.83893C284.304 4.83893 284.923 4.25503 284.923 3.42953C284.923 2.60403 284.304 2 283.458 2C282.591 2 281.972 2.60403 281.972 3.42953C281.972 4.25503 282.591 4.83893 283.458 4.83893ZM284.634 16.7987V6.32886H282.261V16.7987H284.634Z" fill="black"/>
<path d="M291.606 14.7852C290.801 14.7852 290.409 14.4027 290.409 13.6174V8.34228H293.607V6.32886H290.409V3.30872H288.635L288.036 6.32886H286.282V8.34228H288.036V13.6174C288.036 15.6711 289.254 16.7987 291.606 16.7987H293.607L293.813 14.7852H291.606Z" fill="black"/>
<path d="M306 11.443C306 8.42282 303.689 6.12752 300.429 6.12752C297.169 6.12752 294.858 8.40268 294.858 11.5638C294.858 14.7248 297.169 17 300.429 17C302.657 17 304.762 15.9732 305.567 13.9799L303.338 13.6174C302.822 14.3624 301.832 14.8859 300.573 14.8859C298.758 14.8859 297.561 13.7987 297.334 12.1879H305.959C305.979 11.9664 306 11.7248 306 11.443ZM300.429 8.14094C301.915 8.14094 303.029 9.06711 303.421 10.3758H297.478C297.87 9.02684 298.985 8.14094 300.429 8.14094Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 819 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

+25 -9
View File
@@ -21,33 +21,49 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Set up JDK 11
uses: actions/setup-java@v2
- name: Checkout
uses: actions/checkout@v3
- name: Set up NDK
uses: nttld/setup-ndk@v1
with:
java-version: '11'
ndk-version: r25c
add-to-path: false
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
- uses: actions/checkout@v2
- name: Download tools
run: |
sudo apt update
sudo apt install default-jre
sudo apt install python3
sudo apt install zipalign
chmod +x scripts/apktool.jar
chmod +x scripts/apksigner.jar
rustup target add armv7-linux-androideabi
rustup target add aarch64-linux-android
- name: Build VTLite
run: |
bash scripts/buildworkflow.sh
gradle generateBuildTasks
gradle prepareDexForMergeDev
java -jar scripts/apktool.jar b smali -o smali/VTLite.apk --use-aapt2 -p scripts/framework/
zipalign -p -f 4 smali/VTLite.apk smali/VTLite.apk_aligned
mv smali/VTLite.apk_aligned smali/VTLite.apk
env:
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
- name: Sign and verify the apk
run: |
java -jar scripts/apksigner.jar sign --ks scripts/debug.keystore --ks-key-alias androiddebugkey --ks-pass pass:android smali/VTLite.apk
java -jar scripts/apksigner.jar verify smali/VTLite.apk
- name: Upload apk to artifact
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: VTLite.apk
path: smali/VTLite.apk
+3
View File
@@ -30,3 +30,6 @@ smali/build/resources.zip
smali/assets/version.properties
*.keystore
gradle.properties
scripts/build.sh
smali/lib/arm64-v8a/libnative_effects.so
smali/lib/armeabi-v7a/libnative_effects.so
+28
View File
@@ -0,0 +1,28 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="RClass Regeneration" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value="$PROJECT_DIR$/scripts/rclass_regenerator.sh" />
<option name="SCRIPT_OPTIONS" value="" />
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
<option name="INTERPRETER_PATH" value="/bin/zsh" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="EXECUTE_IN_TERMINAL" value="true" />
<option name="EXECUTE_SCRIPT_FILE" value="true" />
<envs />
<method v="2" />
</configuration>
<configuration default="false" name="RClass Regeneration" type="BatchConfigurationType" factoryName="Batch">
<option name="INTERPRETER_OPTIONS" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="PARENT_ENVS" value="true" />
<module name="" />
<option name="SCRIPT_NAME" value="./scripts/rclass_regenerator.bat" />
<option name="PARAMETERS" value="" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
+17
View File
@@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Update APKs Jars (MacOS)" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value="$PROJECT_DIR$/scripts/update_jars_brew.sh" />
<option name="SCRIPT_OPTIONS" value="" />
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
<option name="INTERPRETER_PATH" value="/bin/zsh" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="EXECUTE_IN_TERMINAL" value="true" />
<option name="EXECUTE_SCRIPT_FILE" value="true" />
<envs />
<method v="2" />
</configuration>
</component>
+17
View File
@@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Update APKs Jars" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value="$PROJECT_DIR$/scripts/update_jars.sh" />
<option name="SCRIPT_OPTIONS" value="" />
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
<option name="INTERPRETER_PATH" value="/bin/zsh" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="EXECUTE_IN_TERMINAL" value="true" />
<option name="EXECUTE_SCRIPT_FILE" value="true" />
<envs />
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:buildAndInstallVTLBeta]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:buildAndInstallVTLBeta" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:buildAndInstallVTLDev]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:buildAndInstallVTLDev" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:buildAndInstallVTLRelease]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:buildAndInstallVTLRelease" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:buildAndLaunchVTLBeta]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:buildAndLaunchVTLBeta" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:buildAndLaunchVTLDev]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:buildAndLaunchVTLDev" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:buildAndLaunchVTLRelease]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:buildAndLaunchVTLRelease" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:buildVTLBeta]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:buildVTLBeta" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:buildVTLDev]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:buildVTLDev" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:buildVTLRelease]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:buildVTLRelease" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:exportDexBeta]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:exportDexBeta" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:exportDexDev]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:exportDexDev" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:exportDexRelease]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:exportDexRelease" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:prepareDexForMergeDev]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:prepareDexForMergeDev" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:prepareDexForMergeRelease]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:prepareDexForMergeRelease" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+43 -97
View File
@@ -1,8 +1,8 @@
<p align="center">
<a href="https://vtosters.app/">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://cdn.discordapp.com/attachments/918864618116481029/1002916719595106344/VT_Fill_Logo_Dark.svg">
<img src="https://cdn.discordapp.com/attachments/918864618116481029/1002916719381201036/VT_Fill_Logo_Light.svg">
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/vtosters/lite/main/.github/images/VT_Fill_Logo_Dark.svg">
<img src="https://raw.githubusercontent.com/vtosters/lite/main/.github/images/VT_Fill_Logo_Light.svg">
</picture>
</a>
<br>
@@ -37,99 +37,34 @@
* Стабильные сборки находятся в [Releases](https://github.com/vtosters/lite/releases)
Зеркало на нашем [<img src="https://git.maki.su/assets/img/logo.svg" align="center" width="20" height="20"/> Git](https://git.maki.su/gdlbo/lite)
Зеркало на нашем [<img src="https://gitea.com/assets/img/logo.svg" align="center" width="20" height="20"/> Git](https://git.maki.su/vtosters/lite)
### Быстрая навигация
* [Функционал](#функционал)
* [Отладка приложения](#отладка-приложения)
* [Разработка](#разработка)
* [Всё необходимое для сборки и компиляции](#всё-необходимое-для-сборки-и-компиляции)
* [Необходимые зависимости](#необходимые-зависимости)
* [Linux/macOS](#linuxmacos)
* [Windows](#windows)
- [Функциональность](#функциональность)
- [Отладка приложения](#отладка-приложения)
- [Разработка](#разработка)
- [Всё необходимое для сборки и компиляции](#всё-необходимое-для-сборки-и-компиляции)
- [Необходимые зависимости](#необходимые-зависимости)
- [Linux/MacOS/Windows](#LinuxmacOSWindows)
## Функционал
## Функциональность
* Лента
* Блокировка рекламы в ленте
* Блокировка постов через фильтры
* Возможность добавлять в вайтлист фильтров группы, чтобы в них не удалялись посты
* Возможность отключить рекомендации от ВК
* Редактор докбара
* Редактор элементов Superapp
* Медиа контент
* Округление дат
* 1 января в 4:20
* 1 января в 4:20:00
* 1 января 2000 в 4:20:00
* Округление чисел
* Сокращение постов **(Показать полностью)**
* Результаты опросов без участия
* Возможность указывать папку для загрузки фото/видео/музыки/всего
* Интеграция с <a href="https://www.last.fm/">LAST.FM</a> (а также возможность скробблинга)
* Новый раздел музыки
* Возможность скачивать видео, очищать историю просмотра видео
* Возможность найти фотографию через поисковые системы
* Интеграция с <a href="https://vkx.app/">VK X</a>
* Сообщения
* ~Обои в сообщениях~ (временно недоступно из-за проблем с производительностью)
* Возможность выключения кнопки записи голосовых сообщений
* Возможность скрыть блок рекомендаций в сообщениях
* Режим **VK Me**
* Возможность вернуть вкладку уведомлений для режима VK Me
* Встроенный переводчик текста для сообщений
* Возможность выбрать язык перевода
* Автоматический перевод ваших сообщений на выбранный язык
* Альтернативный дизайн эмодзи меню
* Возможность использовать системные эмодзи
* Возможнсть использовать Enter с аппаратной клавиатуры
* Активность
* Возможность видеть удаленные сообщения
* Функционал, позволяющий оставаться в «оффлайне» (принудительный оффлайн/не отправлять статус онлайна и т.п.)
* Нечиталка/неписалка для ЛС/бесед/ботов/групп
* Возможность отключить информацию о том, что вы просмотрели историю/прослушали голосовое сообщение
* Возможность видеть онлайн пользователей, если у вас скрыт онлайн через VK Messenger
* Возможность сохранять настройки бесшумных сообщений/сообщений-бомбочек
* Отключить уведомление о том, что вы сделали скриншот в беседе
* Отключение редиректа через away.php
* Отключение отправки метрики
* Внешний вид
* **Milkshake** тема (дизайн новых версий ВК)
* Название заголовков в докбаре
* Возможность использовать акцент для иконок
* Возможность отключить счётчики в докбаре
* Смена иконки приложения (содержит много уникальных иконок для донатеров)
* Возможность покрасить панель навигации, веб-страницы
* Telegram Стикеры
* Возможность загружать свои стикерпаки из Telegram во ВКонтакте
* Интерфейс
* Возможность отключить блок историй наверху ленты
* Возможность отключить боковую камеру в разделе «Новости»
* Возможность отключить блок «Что у вас нового?» в разделе «Новости»
* Возможность показывать лайки у постов справа
* Возможность менять стартовый раздел при запуске приложения
* Анимации фрагментов
* Возможность изменять размер закругления картинок (аватарок и прочего)
* Возможность отключить редизайн видеопостов
* Возможность отключить блок миниаппов/VK Pay/Superapp
* Возможность отключить сокращение названий разделов в меню
* Возможность скрыть блок рекомендаций друзей в разделе «Друзья»
* Возможность скрыть подписи в настройках
* Прокси
* Поддержка сторонних прокси, таких как: Zaborona, VikaMobile, рандомные прокси и прочие
* Возможность использовать **HTTP/HTTPS/SOCKS** прокси, менять домены **API/OAuth/Static**
* Другое
* Очистка кеша приложения (**всё/стикеры/изображения/видео/сообщения/WebView**)
* Автоочистка кеша при достижении указанного вами значения (**100/500 MB, 1/2/5 GB**)
* Функционал для **дебага приложения/бэкап возможности/верификации VTosters**
* Возможность вернуть старый дизайн ВКонтакте
* Нет рекламы и ограничений музыки
* Интеграция с <a href="https://vkx.app/">VKX</a> и <a href="https://www.last.fm/">Last.FM</a>
* Самая большая кастомизация и фильтрация ленты новостей
* Кеширование и скачивание треков
* Редактор нижней панели
* Скрытие активности в сообщениях и офлайн-режим
* Возможность отправлять стикеры из Telegram
* Отключение редиректа через away.php
* Поддержка сторонних прокси для пользователей из Украины
* Эксклюзивные функции и галочки для тех кто поддержал разработку. <a href="https://vtosters.app/donate">Подробнее</a>
* Глобальная оптимизация приложения VK (Удалены сторонние библиотеки рекламы, аналитики и метрики, заглушки для рекламных запросов)
А также:
* Галочки, которые видны только пользователям приложения **ВТостерс Lite** (подробнее тут: [vtosters.app](https://vtosters.app) ➝ Пожертвования)
* Оптимизация приложения VK (удаление ненужных библиотек, которые встроены в оригинальный VK)
И многое другое!
Все функции модификации описаны [здесь](https://github.com/vtosters/lite/blob/main/.github/features.md)
## Отладка приложения
@@ -157,7 +92,7 @@
При нахождении решения каких-либо проблем ждем вас в [Pull Requests](https://github.com/vtosters/lite/pulls)
* Рекомендуется установка **ADB** в систему ([гайд](https://technastic.com/system-wide-adb-fastboot-windows-10))
* Рекомендуется установка **ADB** в систему ([Как это сделать](https://technastic.com/system-wide-adb-fastboot-windows-10))
* Для индексации декомпилированного кода в Studio используется [dex2jar](https://github.com/pxb1988/dex2jar)
@@ -182,16 +117,27 @@
* Все необходимые скрипты/.jar файлы для компиляции APK, его подписывании и не только находятся в `/scripts`
### Необходимые зависимости
<a href="https://www.oracle.com/java/technologies/downloads/"><img src="https://i.imgur.com/z8ZN19a.png" align="center" width="20" height="23"/> **JDK**</a> >11 версии
<img src="https://i.imgur.com/z8ZN19a.png" align="center" width="20" height="23"/> [**JDK**](https://adoptium.net/temurin/releases/) >14 версии
<a href="https://developer.android.com/studio"><img src="https://i.imgur.com/cPvvFDP.png" align="center" width="20" height="23"/> **Android Studio**</a>
<img src="https://www.rust-lang.org/logos/rust-logo-32x32.png" align="center" width="20" height="20"/> [**Rust**](https://www.rust-lang.org/learn/get-started) с Android ARM тулчейнами: `rustup target add aarch64-linux-android armv7-linux-androideabi`
### Linux/macOS
Для сборки используется файл `./build.sh`
<img src="https://developer.android.com/static/images/logos/android.svg" align="center" width="20" height="20"/> Android SDK и NDK (устанавливаются через
[sdkmanager](https://developer.android.com/studio/command-line/sdkmanager) или [Android Studio](https://developer.android.com/studio))
<img src="https://i.imgur.com/8BMX8lG.png" width="550" height="368"/>
### Windows
Для сборки используется файл `build.bat`
### Linux/macOS/Windows
<img src="https://i.imgur.com/iZSUKJ6.png" width="550" height="368"/>
Для сборки необходимо вызвать одну из следующих gradle tasks:
+ `./gradlew buildVTL + <Build Type>` - соберет и подпишет APK
+ `./gradlew buildAndInstallVTL + <Build Type>` - соберет, подпишет и попытается установить через ADB
+ `./gradlew buildAndLaunchVTL + <Build Type>` - соберет, подпишет, попытается установить через ADB и запустит на устройстве
+ [FOR DEVS] `./gradlew prepareDexForMerge + <Build Type>` - соберет все необходимое для сборки в `smali/`
+ [FOR DEVS] `./gradlew exportDex + <Build Type>` - экспортирование дексов из собранного приложения для переноса в `smali/`
```
Build types:
Dev
Beta
Release
```
+176 -65
View File
@@ -1,75 +1,46 @@
import java.util.zip.ZipEntry
import org.apache.tools.ant.taskdefs.condition.Os
import java.util.zip.ZipFile
import java.util.zip.ZipInputStream
plugins {
id 'com.android.application'
id 'net.nemerosa.versioning' version '2.15.1'
id 'org.mozilla.rust-android-gradle.rust-android'
}
cargo {
profile = 'release'
module = '../native-effects'
libname = 'native-effects'
targets = ["arm", "arm64"]
prebuiltToolchains = true
pythonCommand = "python3"
}
def smaliFolder = projectDir.toPath().resolve("../smali").normalize()
def scriptsFolder = projectDir.toPath().resolve("../scripts").normalize()
//you can add own folders with decompiled smali code
def dexes = smaliFolder.toFile()
.listFiles({ f -> f.isDirectory() && f.name.startsWith("smali") } as FileFilter)
.size()
versionFile {
File moduleDir = projectDir
file = new File(moduleDir.getAbsolutePath() + "/src/main/assets/version.properties")
file = projectDir.toPath().resolve("src/main/assets/version.properties").toFile()
}
task exportDex {
doLast {
try {
File moduleDir = projectDir
ZipInputStream inputStream = new ZipInputStream(new FileInputStream(moduleDir.getAbsolutePath() + "/build/outputs/apk/release/app-release-unsigned.apk"))
ZipFile file = new ZipFile(moduleDir.getAbsolutePath() + "/build/outputs/apk/release/app-release-unsigned.apk");
ZipEntry entry
while ((entry = inputStream.nextEntry) != null) {
if (entry.getName().equals("classes.dex")) {
print('classes.dex found!')
FileOutputStream output = new FileOutputStream(new File(moduleDir.getAbsoluteFile(), "classes6.dex"))
byte[] buffer = new byte[1024]
int len = 0
while ((len = inputStream.read(buffer)) > 0) {
output.write(buffer, 0, len)
}
output.close()
}
if (entry.getName().equals("classes2.dex")) {
print('\nclasses2.dex found!')
FileOutputStream output = new FileOutputStream(new File(moduleDir.getAbsoluteFile(), "classes7.dex"))
byte[] buffer = new byte[1024]
int len = 0
while ((len = inputStream.read(buffer)) > 0) {
output.write(buffer, 0, len)
}
output.close()
}
}
for (ZipEntry e : Collections.list(file.entries())) {
if (e.getName().endsWith("assets/version.properties")) {
var is = file.getInputStream(e)
FileOutputStream output = new FileOutputStream(new File(moduleDir.getAbsoluteFile(), "version.properties"))
byte[] buffer = new byte[1024]
int len = 0
while ((len = is.read(buffer)) > 0) {
output.write(buffer, 0, len)
}
output.close()
print('\nversion.properties found!')
}
}
} catch (Exception e) {
e.printStackTrace()
}
}
task cleanVersionFile {
projectDir.toPath().resolve("src/main/assets/version.properties").toFile().delete()
}
android {
compileSdkVersion 32
buildToolsVersion '33.0.0'
buildToolsVersion '32.0.0'
sourceSets {
main {
java.srcDirs += 'build/generated/aidl_source_output_dir/release/out'
}
}
defaultConfig {
applicationId "ru.vtosters.lite.utils.lite"
@@ -77,20 +48,160 @@ android {
targetSdkVersion 32
versionCode 1
versionName "1.0"
multiDexEnabled false
multiDexEnabled true
}
buildTypes {
release {
minifyEnabled true
buildConfigField 'String', 'APPCENTER_KEY', '""'
proguardFile 'proguard-rules.pro'
}
rc {
minifyEnabled true
buildConfigField 'String', 'APPCENTER_KEY', '""'
proguardFile 'proguard-rules.pro'
}
dev {
minifyEnabled false
buildConfigField 'String', 'APPCENTER_KEY', '""'
}
beta {
minifyEnabled false
buildConfigField 'String', 'APPCENTER_KEY', '""'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_14
targetCompatibility JavaVersion.VERSION_14
}
namespace 'ru.vtosters.lite'
ndkVersion '25.2.9519653'
buildFeatures {
aidl true
}
}
task testClasses {
doLast {
println 'This is a dummy testClasses task'
}
}
dependencies {
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.exifinterface:exifinterface:1.3.3'
implementation 'androidx.preference:preference:1.2.0'
implementation 'com.microsoft.appcenter:appcenter-analytics:5.0.4'
implementation 'com.microsoft.appcenter:appcenter-crashes:5.0.4'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
implementation 'net.sourceforge.streamsupport:streamsupport-minifuture:1.7.4'
implementation 'com.google.guava:guava:32.0.0-android'
implementation fileTree(dir: 'libs', include: ['*.aar'])
compileOnly fileTree(dir: 'libs', include: ['*.jar'])
}
}
task generateBuildTasks() {
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
def buildType = output.name.toString().capitalize()
if (buildType == "Base") return
task "exportDex$buildType"() {
dependsOn('assemble' + buildType)
doLast {
try {
def suffix = buildType.toLowerCase()
String apkPath = projectDir.getAbsolutePath() + "/build/outputs/apk/$suffix/app-$suffix"
def apk = new File(apkPath + "-unsigned.apk")
if (!apk.exists()) apk = new File(apkPath + ".apk")
def zip = new ZipFile(apk)
def dexCounter = dexes
zip.stream()
.filter(entry -> entry.name.matches("^classes(?:(?=\\d)2|)\\.dex\$") || entry.name == "assets/version.properties")
.forEach(entry -> {
String filename
if (entry.name.matches("^classes(?:(?=\\d)2|)\\.dex\$")) filename = "classes${++dexCounter}.dex"
else filename = "version.properties"
println("Exporting " + entry.name)
def tmpFile = new File(projectDir, filename)
try (def is = zip.getInputStream(entry); def fos = new FileOutputStream(tmpFile)) {
def buff = new byte[0x800]
int len
while ((len = is.read(buff)) > 0) fos.write(buff, 0, len)
}
});
} catch (Exception e) {
e.printStackTrace()
}
}
}
task "prepareDexForMerge$buildType"(type: Copy) {
dependsOn('exportDex' + buildType)
// Remove comment for native lib build
//dependsOn('cargoBuild')
into smaliFolder.toString()
from(projectDir) {
into '../smali'
include "classes*.dex"
}
from(projectDir) {
include 'version.properties'
into 'assets'
}
from('../native-effects/target/aarch64-linux-android/release') {
include 'libnative_effects.so'
into 'lib/arm64-v8a'
}
from('../native-effects/target/armv7-linux-androideabi/release') {
include 'libnative_effects.so'
into 'lib/armeabi-v7a'
}
}
task "cleanTemporaryFiles$buildType"(type: Delete)
{
delete fileTree(dir: projectDir, include: ["*.dex", "version.properties"])
delete fileTree(dir: smaliFolder, include: ['*.dex', "assets/version.properties"])
}
task "buildVTL$buildType"(type: Exec) {
dependsOn('prepareDexForMerge' + buildType)
workingDir(projectDir.parentFile)
finalizedBy "cleanTemporaryFiles$buildType"
if (Os.isFamily("unix") || Os.isFamily("mac")) {
commandLine 'bash', '-c', './scripts/build.sh'
} else {
commandLine 'cmd', '/C', '.\\scripts\\build.bat'
}
}
task "buildAndInstallVTL$buildType"(type: Exec) {
dependsOn('buildVTL' + buildType)
workingDir(scriptsFolder.toString())
ignoreExitValue true
if (Os.isFamily("unix") || Os.isFamily("mac")) {
commandLine 'bash', '-c', 'adb install VTLite.apk'
} else {
commandLine 'adb', 'install', 'VTLite.apk'
}
}
task "buildAndLaunchVTL$buildType"(type: Exec) {
dependsOn('buildAndInstallVTL' + buildType)
if (Os.isFamily("unix") || Os.isFamily("mac"))
commandLine 'bash', '-c', 'adb shell monkey -p com.vtosters.lite -c android.intent.category.LAUNCHER 1'
else
commandLine 'adb', 'shell', 'monkey', '-p', 'com.vtosters.lite', '-c', 'android.intent.category.LAUNCHER', '1'
}
}
}
}
task generateRjava(type: Exec) {
workingDir(projectDir.parentFile)
if (Os.isFamily("unix") || Os.isFamily("mac"))
commandLine "bash", "-c", "./scripts/rclass_regenerator.sh"
else
commandLine "cmd", "/C", ".\\scripts\\rclass_regenerator.sh"
}
clean.dependsOn('cleanVersionFile')
versionFile.dependsOn('cleanVersionFile')
preBuild.dependsOn('versionFile')
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+26 -1
View File
@@ -18,4 +18,29 @@
## If you keep the line number information, uncomment this to
## hide the original source file name.
##-renamesourcefileattribute SourceFile
#-keepclassmembers class fq
#-keepclassmembers class fq
-assumenosideeffects class android.util.Log {
public static boolean isLoggable(java.lang.String, int);
public static int v(...);
public static int i(...);
public static int w(...);
public static int d(...);
public static int e(...);
}
-repackageclasses
-allowaccessmodification
-optimizations
-optimizationpasses 5
-keepattributes SourceFile, LineNumberTable
-keep,allowoptimization class ru.vtosters.hooks.**, ru.vtosters.sponsorpost.internal.Native, ru.vtosters.lite.utils.AndroidUtils, ru.vtosters.lite.utils.NetworkUtils, ru.vtosters.lite.utils.CrashReporter, ru.vtosters.lite.ui.activities.**, ru.vtosters.lite.services.**, ru.vtosters.lite.ui.fragments.**, ru.vtosters.lite.themes.**, ru.vtosters.lite.music.hook.**, ru.vtosters.lite.music.cache.injectors.**, ru.vtosters.lite.ui.wallpapers.NativeEffects, com.aefyr.tsg.g2.TelegramStickersService {
public <fields>;
public <methods>;
public <init>(...);
}
-keep class com.vtosters.lite.** { *; }
-keep class com.vk.** { *; }
-keep class bruhcollective.itaysonlab.libvkx.client.** { *; }
+11 -9
View File
@@ -1,15 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" android:maxSdkVersion="22"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS" android:maxSdkVersion="22"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"></application>
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"></application>
</manifest>
@@ -0,0 +1,33 @@
// IVKExternalMusic.aidl
package bruhcollective.itaysonlab.libvkx;
interface ILibVkxService {
// Starts playback. playbackContext can be "other" if you don't sure what it is
void play(in List<String> audio_ids, in int index, in String playbackContext) = 1;
// A UserID. CHECK FOR THIS TO BE EQUAL BEFORE SENDING ANYTHING TO SERVICE!
int getUserId() = 2;
// Cache add/remove
void addTrackToCache(in int track_id, in int owner_id, in String access_key) = 3;
void deleteTrackFromCache(in int track_id, in int owner_id) = 4;
boolean isTrackCached(in int track_id, in int owner_id) = 5;
// Get a list of cached tracks. The response is close to VK's original response (an audio list)
// Also, the items in the list are JSON ones.
List<String> getCache() = 6;
// [ver 1.1]
void downloadTrack(in int track_id, in int owner_id, in String access_key) = 7;
void downloadPlaylist(in int playlist_id, in int owner_id, in String access_key) = 8;
void addPlaylistToCache(in int playlist_id, in int owner_id, in String access_key) = 9;
void deletePlaylistFromCache(in int playlist_id, in int owner_id) = 10;
// [ver 1.2]
String getCacheCatalog() = 11;
List<String> getTracksInPlaylist(in String playlist_id, in String owner_id) = 12;
String getPlaylistDefJson(in String playlist_id, in String owner_id) = 13;
// [ver 1.3]
boolean isPlaylistCached(in int playlist_id, in int owner_id) = 14;
}
@@ -1,340 +0,0 @@
/*
* This file is auto-generated. DO NOT MODIFY.
*/
package bruhcollective.itaysonlab.libvkx;
// Works only with original signature of VT
public interface ILibVkxService extends android.os.IInterface {
void play(java.util.List<String> audio_ids, int index, String playbackContext) throws android.os.RemoteException;
int getUserId() throws android.os.RemoteException;
// Starts playback. playbackContext can be "other" if you don't sure what it is
void addTrackToCache(int track_id, int owner_id, String access_key) throws android.os.RemoteException;
// A UserID. CHECK FOR THIS TO BE EQUAL BEFORE SENDING ANYTHING TO SERVICE!
void deleteTrackFromCache(int track_id, int owner_id) throws android.os.RemoteException;
// Cache add/remove
boolean isTrackCached(int track_id, int owner_id) throws android.os.RemoteException;
java.util.List<String> getCache() throws android.os.RemoteException;
/**
* Default implementation for ILibVkxService.
*/
class Default implements ILibVkxService {
// Starts playback. playbackContext can be "other" if you don't sure what it is
@Override
public void play(java.util.List<String> audio_ids, int index, String playbackContext) throws android.os.RemoteException {
}
// A UserID. CHECK FOR THIS TO BE EQUAL BEFORE SENDING ANYTHING TO SERVICE!
@Override
public int getUserId() throws android.os.RemoteException {
return 0;
}
// Cache add/remove
@Override
public void addTrackToCache(int track_id, int owner_id, String access_key) throws android.os.RemoteException {
}
@Override
public void deleteTrackFromCache(int track_id, int owner_id) throws android.os.RemoteException {
}
@Override
public boolean isTrackCached(int track_id, int owner_id) throws android.os.RemoteException {
return false;
}
// Get a list of cached tracks. The response is close to VK's original response (an audio list)
// Also, the items in the list are JSON ones.
@Override
public java.util.List<String> getCache() throws android.os.RemoteException {
return null;
}
@Override
public android.os.IBinder asBinder() {
return null;
}
}
// Get a list of cached tracks. The response is close to VK's original response (an audio list)
// Also, the items in the list are JSON ones.
/**
* Local-side IPC implementation stub class.
*/
abstract class Stub extends android.os.Binder implements ILibVkxService {
static final int TRANSACTION_play = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_getUserId = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
static final int TRANSACTION_addTrackToCache = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
static final int TRANSACTION_deleteTrackFromCache = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
static final int TRANSACTION_isTrackCached = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
static final int TRANSACTION_getCache = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
private static final String DESCRIPTOR = "bruhcollective.itaysonlab.libvkx.ILibVkxService";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an bruhcollective.itaysonlab.libvkx.ILibVkxService interface,
* generating a proxy if needed.
*/
public static ILibVkxService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof ILibVkxService))) {
return ((ILibVkxService) iin);
}
return new Proxy(obj);
}
public static boolean setDefaultImpl(ILibVkxService impl) {
if (Proxy.sDefaultImpl == null && impl != null) {
Proxy.sDefaultImpl = impl;
return true;
}
return false;
}
public static ILibVkxService getDefaultImpl() {
return Proxy.sDefaultImpl;
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
String descriptor = DESCRIPTOR;
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_play: {
data.enforceInterface(descriptor);
java.util.List<String> _arg0;
_arg0 = data.createStringArrayList();
int _arg1;
_arg1 = data.readInt();
String _arg2;
_arg2 = data.readString();
this.play(_arg0, _arg1, _arg2);
reply.writeNoException();
return true;
}
case TRANSACTION_getUserId: {
data.enforceInterface(descriptor);
int _result = this.getUserId();
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_addTrackToCache: {
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
String _arg2;
_arg2 = data.readString();
this.addTrackToCache(_arg0, _arg1, _arg2);
reply.writeNoException();
return true;
}
case TRANSACTION_deleteTrackFromCache: {
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
this.deleteTrackFromCache(_arg0, _arg1);
reply.writeNoException();
return true;
}
case TRANSACTION_isTrackCached: {
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
boolean _result = this.isTrackCached(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(((_result) ? (1) : (0)));
return true;
}
case TRANSACTION_getCache: {
data.enforceInterface(descriptor);
java.util.List<String> _result = this.getCache();
reply.writeNoException();
reply.writeStringList(_result);
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements ILibVkxService {
public static ILibVkxService sDefaultImpl;
private final android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
// Starts playback. playbackContext can be "other" if you don't sure what it is
public String getInterfaceDescriptor() {
return DESCRIPTOR;
}
// A UserID. CHECK FOR THIS TO BE EQUAL BEFORE SENDING ANYTHING TO SERVICE!
@Override
public void play(java.util.List<String> audio_ids, int index, String playbackContext) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStringList(audio_ids);
_data.writeInt(index);
_data.writeString(playbackContext);
boolean _status = mRemote.transact(Stub.TRANSACTION_play, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().play(audio_ids, index, playbackContext);
return;
}
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
// Cache add/remove
@Override
public int getUserId() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_getUserId, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().getUserId();
}
_reply.readException();
_result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
public void addTrackToCache(int track_id, int owner_id, String access_key) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(track_id);
_data.writeInt(owner_id);
_data.writeString(access_key);
boolean _status = mRemote.transact(Stub.TRANSACTION_addTrackToCache, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().addTrackToCache(track_id, owner_id, access_key);
return;
}
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public void deleteTrackFromCache(int track_id, int owner_id) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(track_id);
_data.writeInt(owner_id);
boolean _status = mRemote.transact(Stub.TRANSACTION_deleteTrackFromCache, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().deleteTrackFromCache(track_id, owner_id);
return;
}
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
// Get a list of cached tracks. The response is close to VK's original response (an audio list)
// Also, the items in the list are JSON ones.
@Override
public boolean isTrackCached(int track_id, int owner_id) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(track_id);
_data.writeInt(owner_id);
boolean _status = mRemote.transact(Stub.TRANSACTION_isTrackCached, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().isTrackCached(track_id, owner_id);
}
_reply.readException();
_result = (0 != _reply.readInt());
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
public java.util.List<String> getCache() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<String> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_getCache, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().getCache();
}
_reply.readException();
_result = _reply.createStringArrayList();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
}
}
@@ -1,19 +1,19 @@
package bruhcollective.itaysonlab.libvkx.client;
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.RemoteException;
import bruhcollective.itaysonlab.libvkx.ILibVkxService;
import com.vk.dto.music.MusicTrack;
import com.vk.music.common.MusicPlaybackLaunchContext;
import ru.vtosters.hooks.other.Preferences;
import java.util.ArrayList;
import java.util.List;
import bruhcollective.itaysonlab.libvkx.ILibVkxService;
import static ru.vtosters.hooks.other.Preferences.getBoolValue;
import static ru.vtosters.hooks.other.Preferences.isValidSignature;
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
public class LibVKXClient {
@SuppressLint("StaticFieldLeak")
@@ -34,7 +34,7 @@ public class LibVKXClient {
public static boolean isVkxInstalled() {
try {
getGlobalContext().getPackageManager().getPackageInfo("ua.itaysonlab.vkx", 0);
return true;
return isValidSignature() && !Preferences.serverFeaturesDisable();
} catch (Exception unused) {
return false;
}
@@ -54,28 +54,34 @@ public class LibVKXClient {
return getInstance().runOnService(action);
}
public static void lambdaplay(List<MusicTrack> list, MusicTrack musicTrack, ILibVkxService iLibVkxService) {
int indexOf = list.indexOf(musicTrack);
var ids = new ArrayList<String>();
for (var track : list) {
ids.add(asId(track));
}
if (indexOf == -1) {
indexOf = 0;
}
public static void lambdaplay(List<MusicTrack> list, MusicTrack musicTrack, ILibVkxService iLibVkxService, MusicPlaybackLaunchContext playerRefer) {
try {
iLibVkxService.play(ids, indexOf, "");
var playbackContext = "";
if (playerRefer != null) {
playbackContext = playerRefer.v0();
}
int indexOf = list.indexOf(musicTrack);
var ids = new ArrayList<String>();
for (var track : list) {
ids.add(asId(track));
}
if (indexOf == -1) {
indexOf = 0;
}
iLibVkxService.play(ids, indexOf, playbackContext);
} catch (RemoteException e) {
e.printStackTrace();
}
}
private static String asId(MusicTrack musicTrack) {
String str = musicTrack.e + "_" + musicTrack.d;
if (musicTrack.O == null || musicTrack.O.equals("")) {
return str;
}
return str + "_" + musicTrack.O;
public static void lambdaplay(List<MusicTrack> list, MusicTrack musicTrack, ILibVkxService iLibVkxService) {
lambdaplay(list, musicTrack, iLibVkxService, null);
}
public static String asId(MusicTrack musicTrack) {
return musicTrack.y1();
}
}
@@ -1,7 +1,5 @@
package bruhcollective.itaysonlab.libvkx.client;
import static ru.vtosters.lite.utils.AccountManagerUtils.getUserId;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -10,10 +8,11 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.IBinder;
import android.os.RemoteException;
import bruhcollective.itaysonlab.libvkx.ILibVkxService;
import java.util.List;
import bruhcollective.itaysonlab.libvkx.ILibVkxService;
import static ru.vtosters.lite.utils.AccountManagerUtils.getUserId;
public class LibVKXClientImpl {
private ILibVkxService serviceInstance;
@@ -1,90 +1,89 @@
package com.aefyr.tsg.g2;
import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationManagerCompat;
import com.aefyr.tsg.g2.stickersgrabber.TelegramStickersGrabber;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicLong;
import com.vtosters.lite.R;
import ru.vtosters.lite.utils.AndroidUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
/**
* Created by Aefyr on 20.05.2018.
*/
public class NotificationsHelper {
private static final int NOTIFICATION_ID_BASE = 3921337;
// private static final int NOTIFICATION_ID_BASE = 3921337;
private static final String NOTIFICATION_CHANNEL_ID = "tgss_chan_v5";
private static final int MAX_UPDATE_NOTIFICATIONS_PER_SECOND = 3;
private static final int MIN_TIME_BETWEEN_UPDATE_NOTIFICATIONS = 1000 / MAX_UPDATE_NOTIFICATIONS_PER_SECOND;
private final HashMap<TelegramStickersPack, Integer> downloadingPacksNotificationsIds;
private final List<Integer> downloadingPacksNotificationsIds;
private final Context c;
private final NotificationManagerCompat manager;
private final AtomicLong lastNotificationTime = new AtomicLong(0);
private int currentNotificationN = 0;
// private int currentNotificationN = 0;
public NotificationsHelper(Context c) {
this.c = c;
manager = NotificationManagerCompat.from(c);
downloadingPacksNotificationsIds = new HashMap<>();
downloadingPacksNotificationsIds = new ArrayList<>();
if (oreo()) {
NotificationChannel notificationChan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, AndroidUtils.getString("telegram_stickers_service"), NotificationManager.IMPORTANCE_HIGH);
NotificationChannel notificationChan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, AndroidUtils.getString(R.string.telegram_stickers_service), NotificationManager.IMPORTANCE_HIGH);
((NotificationManager) c.getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(notificationChan);
}
}
public void packStartedDownloading(TelegramStickersPack pack) {
int notificationId = NOTIFICATION_ID_BASE + currentNotificationN++;
downloadingPacksNotificationsIds.put(pack, notificationId);
downloadingPacksNotificationsIds.add(pack.hash);
Notification.Builder builder = commonBuilder();
builder.setContentTitle(pack.state == TelegramStickersPack.DOWNLOADING ? pack.title + AndroidUtils.getString("telegram_stickers_downloading") : pack.title + AndroidUtils.getString("telegram_stickers_updating"));
builder.setContentText(AndroidUtils.getString("telegram_stickers_gettinginfo"));
builder.setContentTitle(pack.state == TelegramStickersPack.DOWNLOADING ? pack.title + AndroidUtils.getString(R.string.telegram_stickers_downloading) : pack.title + AndroidUtils.getString(R.string.telegram_stickers_updating));
builder.setContentText(AndroidUtils.getString(R.string.telegram_stickers_gettinginfo));
builder.setOngoing(true);
manager.notify(notificationId, builder.build());
manager.notify(pack.hash, builder.build());
}
public void packDownloadUpdated(TelegramStickersPack pack, int downloadProgress) {
if (System.currentTimeMillis() - lastNotificationTime.get() < MIN_TIME_BETWEEN_UPDATE_NOTIFICATIONS)
if (System.currentTimeMillis() - lastNotificationTime.get() < MIN_TIME_BETWEEN_UPDATE_NOTIFICATIONS
|| !downloadingPacksNotificationsIds.contains(pack.hash))
return;
lastNotificationTime.set(System.currentTimeMillis());
Notification.Builder builder = commonBuilder();
builder.setContentTitle(pack.state == TelegramStickersPack.DOWNLOADING ? pack.title + AndroidUtils.getString("telegram_stickers_downloading") : pack.title + AndroidUtils.getString("telegram_stickers_updating"));
builder.setContentTitle(pack.state == TelegramStickersPack.DOWNLOADING ? pack.title + AndroidUtils.getString(R.string.telegram_stickers_downloading) : pack.title + AndroidUtils.getString(R.string.telegram_stickers_updating));
builder.setContentText(downloadProgress + "/" + pack.stickersCount);
builder.setProgress(pack.stickersCount, downloadProgress, false);
builder.setOngoing(true);
builder.setOnlyAlertOnce(true);
if (downloadingPacksNotificationsIds.containsKey(pack))
manager.notify(downloadingPacksNotificationsIds.get(pack), builder.build());
manager.notify(pack.hash, builder.build());
}
public void packDoneDownloading(TelegramStickersPack pack, boolean success, boolean wasUpdate, @Nullable Exception e) {
if (!downloadingPacksNotificationsIds.remove(pack.hash))
return;
Notification.Builder builder = commonBuilder();
builder.setProgress(0, 0, false);
builder.setOngoing(false);
builder.setContentTitle(AndroidUtils.getString("telegram_stickers_service"));
builder.setContentTitle(AndroidUtils.getString(R.string.telegram_stickers_service));
String text;
if (success)
text = wasUpdate ? pack.title + AndroidUtils.getString("telegram_stickers_updated") : pack.title + AndroidUtils.getString("telegram_stickers_downloaded");
text = pack.title + " " + AndroidUtils.getString(wasUpdate ? R.string.telegram_stickers_updated : R.string.telegram_stickers_downloaded);
else
text = wasUpdate ? pack.title + AndroidUtils.getString("telegram_stickers_error_update") : pack.title + AndroidUtils.getString("telegram_stickers_error_download");
text = pack.title + " " + AndroidUtils.getString(wasUpdate ? R.string.telegram_stickers_error_update : R.string.telegram_stickers_error_download);
if (e instanceof TelegramStickersGrabber.TSGException) {
text = pack.title + ": " + e.getMessage();
@@ -92,15 +91,16 @@ public class NotificationsHelper {
builder.setContentText(String.format(text, pack.title));
manager.notify(downloadingPacksNotificationsIds.remove(pack), builder.build());
manager.notify(pack.hash, builder.build());
}
public void removePackNotification(TelegramStickersPack pack) {
manager.cancel(downloadingPacksNotificationsIds.remove(pack));
if (downloadingPacksNotificationsIds.remove(pack.hash))
manager.cancel(pack.hash);
}
private Notification.Builder commonBuilder() {
var builder = new Notification.Builder(c).setPriority(Notification.PRIORITY_MAX).setSmallIcon(getIdentifier("ic_download_24", "drawable"));
var builder = new Notification.Builder(c).setPriority(Notification.PRIORITY_MAX).setSmallIcon(R.drawable.ic_download_24);
if (oreo()) {
builder.setChannelId(NOTIFICATION_CHANNEL_ID);
}
@@ -3,7 +3,6 @@ package com.aefyr.tsg.g2;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -32,12 +31,13 @@ public class TelegramStickersPack extends CustomStickersPack {
public int stickersCount = -1;
public String version;
public int index = -1;
public Integer hash;
public HashMap<String, List<Integer>> emojis = new HashMap<>();
public TelegramStickersPack(String id) {
this.id = id.toLowerCase();
title = id;
this.id = this.title = id;
this.hash = id.hashCode();
}
public JSONObject encodeEmojis() throws JSONException {
@@ -101,12 +101,12 @@ public class TelegramStickersPack extends CustomStickersPack {
@Override
public boolean equals(Object obj) {
return obj instanceof TelegramStickersPack && ((TelegramStickersPack) obj).id.equalsIgnoreCase(id);
return obj instanceof TelegramStickersPack && ((TelegramStickersPack) obj).id.equals(id);
}
@Override
public int hashCode() {
return id.toLowerCase().hashCode();
return hash;
}
@Override
@@ -1,16 +1,15 @@
package com.aefyr.tsg.g2;
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.aefyr.tsg.g2.sql.TelegramStickersDbHelper;
import com.aefyr.tsg.g2.stickersgrabber.TelegramStickersGrabber;
import com.aefyr.tsg.g2.stickersgrabber.TelegramStickersPackInfo;
import ru.vtosters.lite.ui.fragments.VTSettings;
import ru.vtosters.lite.ui.fragments.tgstickers.StickersFragment;
import java.io.File;
import java.util.ArrayList;
@@ -19,7 +18,7 @@ import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import ru.vtosters.lite.ui.fragments.tgstickers.StickersFragment;
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
/**
* Created by Aefyr on 19.05.2018.
@@ -27,19 +26,13 @@ import ru.vtosters.lite.ui.fragments.tgstickers.StickersFragment;
public class TelegramStickersService {
private static final String TAG = "TGStickersService";
private static TelegramStickersService instance;
private final Context c;
private final ArrayList<TelegramStickersPack> packs;
private final ArrayList<TelegramStickersPack> activePacks;
private final ArrayList<TelegramStickersPack> inactivePacks;
private final ArrayList<StickersEventsListener> listeners;
private final HashSet<String> currentlyDownloading;
private final Handler uiThreadHandler;
private final TelegramStickersGrabber grabber;
private final TelegramStickersDbHelper dbHelper;
private final ArrayList<Runnable> queuedTasks;
private final ThreadPoolExecutor executor;
@@ -49,16 +42,14 @@ public class TelegramStickersService {
private TelegramStickersService(Context context) {
instance = this;
this.c = context.getApplicationContext();
listeners = new ArrayList<>();
currentlyDownloading = new HashSet<>();
uiThreadHandler = new Handler(Looper.getMainLooper());
grabber = new TelegramStickersGrabber(null);
dbHelper = new TelegramStickersDbHelper(c);
dbHelper = new TelegramStickersDbHelper(context);
queuedTasks = new ArrayList<>();
executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
notificationsHelper = new NotificationsHelper(c);
notificationsHelper = new NotificationsHelper(context);
packs = new ArrayList<>();
activePacks = new ArrayList<>();
@@ -71,11 +62,11 @@ public class TelegramStickersService {
return instance == null ? new TelegramStickersService(c) : instance;
}
private void updatePacks(final boolean notify) {
private void updatePacks(boolean notify) {
packs.clear();
dbHelper.getAllPacks(new TelegramStickersDbHelper.PacksLoadingListener() {
@Override
public void onPackLoaded(final TelegramStickersPack pack) {
public void onPackLoaded(TelegramStickersPack pack) {
runOnUiThread(() -> {
packs.add(pack);
@@ -104,14 +95,6 @@ public class TelegramStickersService {
});
}
public void addStickersEventsListener(StickersEventsListener listener) {
listeners.add(listener);
}
public void removeStickersEventsListener(StickersEventsListener listener) {
listeners.remove(listener);
}
private void notifyPackAdded(TelegramStickersPack pack, int atIndex) {
getGlobalContext().sendBroadcast(new Intent(StickersFragment.ACTION_RELOAD));
if (listeners.isEmpty())
@@ -154,6 +137,7 @@ public class TelegramStickersService {
private void notifyActivePacksListChanged() {
getGlobalContext().sendBroadcast(new Intent(StickersFragment.ACTION_RELOAD));
getGlobalContext().sendBroadcast(new Intent(VTSettings.ACTION_INVALIDATE_TGS_COUNT));
if (listeners.isEmpty())
return;
@@ -188,20 +172,16 @@ public class TelegramStickersService {
return inactivePacks;
}
public boolean isDoneLoading() {
return ready;
}
public boolean requestPackDownload(final String id, File packFolder) {
public void requestPackDownload(String id, File packFolder) {
if (currentlyDownloading.contains(id)) {
Log.e(TAG, String.format("Got request to download pack %s which is already downloading", id));
return false;
return;
}
if (!ready) {
final File folder = packFolder;
File folder = packFolder;
queuedTasks.add(() -> requestPackDownload(id, folder));
return true;
return;
}
TelegramStickersPack pack = new TelegramStickersPack(id);
@@ -221,84 +201,86 @@ public class TelegramStickersService {
notifyPackAdded(pack, packs.size() - 1);
}
final TelegramStickersPack newPack = pack;
final boolean isUpdate = update;
TelegramStickersPack newPack = pack;
boolean isUpdate = update;
currentlyDownloading.add(id.toLowerCase());
currentlyDownloading.add(id);
notificationsHelper.packStartedDownloading(newPack);
grabber.enableProxy();
grabber.grabPack(id, packFolder, pack.version, new TelegramStickersGrabber.PackDownloadListener() {
@Override
public void onPackDownloaded(TelegramStickersPackInfo packInfo, boolean newVersionFound) {
runOnUiThread(() -> {
newPack.state = TelegramStickersPack.DOWNLOADED;
notifyPackChanged(newPack, packs.indexOf(newPack));
currentlyDownloading.remove(newPack.id.toLowerCase());
syncPack(newPack);
if (isUpdate) {
if (newPack.enabled)
notifyActivePacksListChanged();
} else {
activePacks.add(newPack);
notifyActivePacksListChanged();
}
});
notificationsHelper.packDoneDownloading(newPack, true, isUpdate, null);
}
@Override
public void onPackDownloadError(final Exception e) {
runOnUiThread(() -> {
Log.e(TAG, "Error while downloading pack " + newPack.id);
e.printStackTrace();
if (!isUpdate) {
int index = packs.indexOf(newPack);
packs.remove(index);
notifyPackRemoved(newPack, index);
} else {
// try-catch block to handle possible timeout exception
try {
grabber.grabPack(id, packFolder, pack.version, new TelegramStickersGrabber.PackDownloadListener() {
@Override
public void onPackDownloaded(TelegramStickersPackInfo packInfo, boolean newVersionFound) {
runOnUiThread(() -> {
newPack.state = TelegramStickersPack.DOWNLOADED;
notifyPackChanged(newPack, packs.indexOf(newPack));
}
currentlyDownloading.remove(newPack.id);
syncPack(newPack);
notifyPackDownloadError(newPack, e);
currentlyDownloading.remove(newPack.id);
});
notificationsHelper.packDoneDownloading(newPack, false, isUpdate, e);
}
if (isUpdate) {
if (newPack.enabled)
notifyActivePacksListChanged();
} else {
activePacks.add(newPack);
notifyActivePacksListChanged();
}
});
notificationsHelper.packDoneDownloading(newPack, true, isUpdate, null);
}
@Override
public void onGotPackInfo(final TelegramStickersPackInfo packInfo) {
runOnUiThread(() -> {
newPack.title = packInfo.title;
newPack.stickersCount = packInfo.stickersCount;
newPack.version = packInfo.version;
notifyPackChanged(newPack, packs.indexOf(newPack));
});
@Override
public void onPackDownloadError(Exception e) {
runOnUiThread(() -> {
Log.e(TAG, "Error while downloading pack " + newPack.id);
e.printStackTrace();
notificationsHelper.packDownloadUpdated(newPack, 0);
}
if (!isUpdate) {
int index = packs.indexOf(newPack);
packs.remove(index);
notifyPackRemoved(newPack, index);
} else {
newPack.state = TelegramStickersPack.DOWNLOADED;
notifyPackChanged(newPack, packs.indexOf(newPack));
}
@Override
public void onStickerDownloaded(String pack, File sticker, String boundEmoji, int stickerIndex, int downloadedStickersCount, int totalStickersCount) {
stickerIndex--;
notifyPackDownloadError(newPack, e);
currentlyDownloading.remove(newPack.id);
});
notificationsHelper.packDoneDownloading(newPack, false, isUpdate, e);
}
List<Integer> list = newPack.emojis.get(boundEmoji);
if (list == null) list = new ArrayList<>();
list.add(stickerIndex);
newPack.emojis.put(boundEmoji, list);
@Override
public void onGotPackInfo(TelegramStickersPackInfo packInfo) {
runOnUiThread(() -> {
newPack.title = packInfo.title;
newPack.stickersCount = packInfo.stickersCount;
newPack.version = packInfo.version;
notifyPackChanged(newPack, packs.indexOf(newPack));
});
notificationsHelper.packDownloadUpdated(newPack, downloadedStickersCount);
}
});
notificationsHelper.packDownloadUpdated(newPack, 0);
}
return true;
@Override
public void onStickerDownloaded(String pack, File sticker, String boundEmoji, int stickerIndex, int downloadedStickersCount, int totalStickersCount) {
stickerIndex--;
List<Integer> list = newPack.emojis.get(boundEmoji);
if (list == null) list = new ArrayList<>();
list.add(stickerIndex);
newPack.emojis.put(boundEmoji, list);
notificationsHelper.packDownloadUpdated(newPack, downloadedStickersCount);
}
});
} catch (Exception e) {
// handle other possible exceptions
e.printStackTrace();
}
}
public void setPackEnabled(final TelegramStickersPack pack, final boolean enabled, final boolean notify) {
public void setPackEnabled(TelegramStickersPack pack, boolean enabled, boolean notify) {
if (!ready) {
queuedTasks.add(() -> setPackEnabled(pack, enabled, notify));
return;
@@ -324,7 +306,7 @@ public class TelegramStickersService {
}
}
public void deletePack(final TelegramStickersPack pack) {
public void deletePack(TelegramStickersPack pack) {
if (!ready) {
queuedTasks.add(() -> deletePack(pack));
return;
@@ -333,7 +315,6 @@ public class TelegramStickersService {
boolean d = dbHelper.deletePack(pack);
Log.d(TAG, "Delete from DB=" + d);
int index = packs.indexOf(pack);
packs.remove(index);
notifyPackRemoved(pack, index);
@@ -354,7 +335,7 @@ public class TelegramStickersService {
uiThreadHandler.post(r);
}
private void syncPack(final TelegramStickersPack pack) {
private void syncPack(TelegramStickersPack pack) {
if (!ready) {
queuedTasks.add(() -> syncPack(pack));
return;
@@ -383,7 +364,7 @@ public class TelegramStickersService {
getPacksListReference().set(li1, p2);
}
interface StickersEventsListener {
public interface StickersEventsListener {
void onPackAdded(TelegramStickersPack pack, int atIndex);
void onPackRemoved(TelegramStickersPack pack, int atIndex);
@@ -396,6 +377,4 @@ public class TelegramStickersService {
void onInactivePacksListChanged();
}
}
@@ -8,9 +8,7 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.AsyncTask;
import android.util.Log;
import com.aefyr.tsg.g2.TelegramStickersPack;
import org.json.JSONException;
import org.json.JSONObject;
@@ -5,47 +5,42 @@ import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.aefyr.tsg.g2.stickersgrabber.util.Flag;
import com.aefyr.tsg.g2.stickersgrabber.util.GoalCounter;
import okhttp3.*;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import ru.vtosters.lite.di.singleton.VtOkHttpClient;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import ru.vtosters.lite.net.NetCall;
import ru.vtosters.lite.net.NetCallback;
import ru.vtosters.lite.net.NetClient;
import ru.vtosters.lite.net.NetRequest;
import ru.vtosters.lite.net.NetResponse;
/**
* Created by Aefyr on 11.05.2018.
*/
public class TelegramStickersGrabber {
private static final String TAG = "TSG";
public static String REAL_TG_IP = null;
public static String PROXY_IP = null;
public static int PROXY_PORT = -1;
public static String PROXY_USER = null;
public static String PROXY_PASS = null;
public static boolean PROXY_SOCKS = true;
public static boolean HAS_PASS = false;
public static boolean USE_PROXY = false;
private static final OkHttpClient sClient = VtOkHttpClient.getInstance();
private static final int MAX_RETRIES = 2;
private static final AtomicInteger retryCount = new AtomicInteger();
private static final int STICKER_QUALITY = 100;
private static final String STICKER_FILE_NAME_FORMAT = "%03d.png";
private static final String STICKERS_KEY = "stickers";
private static final String FILE_ID_KEY = "file_id";
private static final String EMOJI_KEY = "emoji";
private static final String IS_ANIMATED_KEY = "is_animated";
private static final String IS_VIDEO_KEY = "is_video";
private static final String THUMB_KEY = "thumb";
private static final String NAME_KEY = "name";
private static final String TITLE_KEY = "title";
private static String BOT_API_BASE_URL;
private static String GET_STICKER_SET_URL;
private static String GET_FILE_URL;
@@ -57,17 +52,15 @@ public class TelegramStickersGrabber {
private final MessageDigest sha256;
private final Handler uiThreadHandler;
private String botApiKey = "";
private NetClient httpClient;
private String botApiKey;
public TelegramStickersGrabber(String botApiKey) {
this.botApiKey = botApiKey;
httpClient = new NetClient.Builder().connectTimeout(5, TimeUnit.SECONDS).build();
uiThreadHandler = new Handler(Looper.getMainLooper());
try {
sha256 = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
Log.wtf(TAG, "No support for SHA-256");
Log.d(TAG, "No support for SHA-256");
e.printStackTrace();
throw new RuntimeException(e);
}
@@ -76,81 +69,12 @@ public class TelegramStickersGrabber {
public static void updateURLs() {
BOT_API_BASE_FILE_URL = "https://api.telegram.org/file/bot%s/%s";
BOT_API_BASE_URL = REAL_TG_IP != null ? "https://" + REAL_TG_IP + "/bot%s/" : "https://api.telegram.org/bot%s/";
BOT_API_BASE_URL = "https://api.telegram.org/bot%s/";
GET_STICKER_SET_URL = BOT_API_BASE_URL + "getStickerSet?name=%s";
GET_FILE_URL = BOT_API_BASE_URL + "getFile?file_id=%s";
}
public static boolean isTelegramBlocked() {
NetClient client = new NetClient.Builder().connectTimeout(5, TimeUnit.SECONDS).build();
try {
if (PROXY_IP != null) {
Socket socket = new Socket(PROXY_IP, PROXY_PORT);
Proxy proxy = new Proxy(Proxy.Type.SOCKS, socket.getRemoteSocketAddress());
NetClient.Builder b = new NetClient.Builder().proxy(proxy);
if (PROXY_USER != null) {
b = b.proxyAuthenticator(new PasswordAuthentication(PROXY_USER, PROXY_PASS.toCharArray()));
}
client = b.build();
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
NetRequest req = new NetRequest.Builder().url(REAL_TG_IP != null ? "https://" + REAL_TG_IP + "/test/" : "https://api.telegram.org/test/").build();
try {
NetResponse res = client.newCall(req).execute();
String s = res.getDataString();
if (!s.equals("{\"ok\":false,\"error_code\":404,\"description\":\"Not Found\"}"))
return true;
} catch (Exception e) {
return true;
}
return false;
}
public void resetProxy() {
httpClient = new NetClient.Builder().connectTimeout(5, TimeUnit.SECONDS).build();
}
public void enableProxy() {
Thread kostil = new Thread() {
@Override
public void run() {
try {
if (PROXY_IP != null) {
Socket socket = new Socket(PROXY_IP, PROXY_PORT);
Proxy proxy = new Proxy(Proxy.Type.SOCKS, socket.getRemoteSocketAddress());
NetClient.Builder b = httpClient.newBuilder().proxy(proxy);
if (PROXY_USER != null) {
httpClient = b.proxyAuthenticator(new PasswordAuthentication(PROXY_USER, PROXY_PASS.toCharArray())).build();
}
httpClient = b.build();
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
};
kostil.start();
try {
kostil.join();
Log.d(TAG, "Proxy set");
} catch (InterruptedException e) {
Log.e(TAG, "Unable to set proxy:");
e.printStackTrace();
}
}
public void grabPack(String id, File packFolder, String installedVersion, final PackDownloadListener listener) {
public void grabPack(String id, File packFolder, String installedVersion, PackDownloadListener listener) {
getPackInfo(id, packFolder, installedVersion, listener);
}
@@ -158,261 +82,247 @@ public class TelegramStickersGrabber {
botApiKey = key;
}
public void checkKey(final KeyCheckListener listener) {
public void checkKey(KeyCheckListener listener) {
Log.d(TAG, "Checking key: " + botApiKey);
NetRequest request = new NetRequest.Builder().get().url(String.format(BOT_API_BASE_URL + "getMe", botApiKey)).build();
httpClient.newCall(request).enqueue(new NetCallback() {
// Create a request object with the URL and bot API key
Request request = new Request.a()
.b(String.format(BOT_API_BASE_URL + "getMe", botApiKey))
.a();
// Create a new call object and enqueue it to run asynchronously
sClient.a(request).a(new Callback() {
@Override
public void onFailure(NetCall call, IOException e) {
e.printStackTrace();
public void a(Call call, IOException e) {
// Handle the failure case
Log.d(TAG, e.getMessage());
runOnUiThread(listener::onNetError);
}
@Override
public void onResponse(NetCall call, final NetResponse response) throws IOException {
runOnUiThread(() -> listener.onKeyChecked(response.code() == 200));
public void a(Call call, Response response) {
Log.d(TAG, response.toString());
runOnUiThread(() -> listener.onKeyChecked(response.h()));
}
});
}
private void getPackInfo(final String packName, final File packFolder, final String installedVersion, final PackDownloadListener listener) {
NetRequest packInfoRequest = new NetRequest.Builder().get().url(String.format(GET_STICKER_SET_URL, botApiKey, packName)).build();
httpClient.newCall(packInfoRequest).enqueue(new NetCallback() {
private void getPack(StickerSet set, File packFolder, TelegramStickersPackInfo packInfo, PackDownloadListener listener) {
GoalCounter downloadedStickers = new GoalCounter(set.stickers.size(), () -> {
Log.d(TAG, String.format("Pack %s has been downloaded to %s", set.id, packFolder.getAbsolutePath()));
listener.onPackDownloaded(packInfo, true);
});
Flag deathFlag = new Flag();
for (int i = 0; i < set.stickers.size(); i++) {
Sticker sticker = set.stickers.get(i);
String getFileUrl = String.format(GET_FILE_URL, botApiKey, sticker.fileId);
Request fileInfoRequest = new Request.a()
.b(getFileUrl)
.a();
int stickerIndex = i + 1;
sClient.a(fileInfoRequest).a(new Callback() {
@Override
public void a(Call call, IOException e) {
handleFailure(deathFlag, listener, e, downloadedStickers, call, fileInfoRequest, this);
}
@Override
public void a(Call call, Response response) {
if (deathFlag.up())
return;
if (!response.h()) {
retryRequest(call, fileInfoRequest, this);
return;
}
try (ResponseBody responseBody = response.a()) {
JSONObject fileInfoResponse = new JSONObject(responseBody.g()).getJSONObject("result");
String filePath = fileInfoResponse.getString("file_path");
if (botApiKey == null) botApiKey = "";
String fileDownloadUrl = String.format(BOT_API_BASE_FILE_URL, botApiKey, filePath);
Request fileDownloadRequest = new Request.a()
.b(fileDownloadUrl)
.a();
sClient.a(fileDownloadRequest).a(new Callback() {
@Override
public void a(Call call, IOException e) {
handleFailure(deathFlag, listener, e, downloadedStickers, call, fileDownloadRequest, this);
}
@Override
public void a(Call call, Response response) {
if (deathFlag.up())
return;
if (!response.h()) {
retryRequest(call, fileDownloadRequest, this);
return;
}
try (ResponseBody responseBody = response.a()) {
if (responseBody == null) {
handleFailure(deathFlag, listener, new TSGException("Response body for a sticker is null :/"), downloadedStickers, call, fileDownloadRequest, this);
return;
}
InputStream stickerInputStream = responseBody.a();
Bitmap stickerImage = BitmapFactory.decodeStream(stickerInputStream);
if (stickerImage == null) {
handleFailure(deathFlag, listener, new TSGException("Unable to decode sticker image"), downloadedStickers, call, fileDownloadRequest, this);
return;
}
File stickerFile = new File(packFolder, String.format(STICKER_FILE_NAME_FORMAT, stickerIndex));
try {
saveStickerImage(stickerImage, stickerFile);
} catch (TSGException e) {
throw new RuntimeException(e);
}
listener.onStickerDownloaded(set.name, stickerFile, sticker.emoji, stickerIndex,
downloadedStickers.value() + 1, set.stickers.size());
downloadedStickers.increase();
}
}
});
} catch (Exception e) {
handleFailure(deathFlag, listener, e, downloadedStickers, call, fileInfoRequest, this);
}
}
});
}
}
private void handleFailure(Flag deathFlag, PackDownloadListener listener, Exception e, GoalCounter downloadedStickers, Call call, Request request, Callback callback) {
if ((e instanceof IOException || e instanceof TSGException) && retryCount.get() > MAX_RETRIES) {
Log.e(TAG, "Unable to download sticker: " + e.getMessage());
downloadedStickers.increase();
return;
} else if (retryCount.get() < MAX_RETRIES) {
retryRequest(call, request, callback);
return;
}
if (deathFlag.up()) {
return;
}
deathFlag.raise();
listener.onPackDownloadError(e);
}
private void retryRequest(Call call, Request request, Callback callback) {
retryCount.incrementAndGet();
if (retryCount.get() > MAX_RETRIES) {
Log.e(TAG, "retryRequest: max retries");
callback.a(call, new IOException());
} else {
Log.e(TAG, "retryRequest");
sClient.a(request).a(callback);
}
}
private void saveStickerImage(Bitmap image, File file) throws TSGException {
try (FileOutputStream fos = new FileOutputStream(file)) {
image.compress(Bitmap.CompressFormat.PNG, 100, fos);
} catch (IOException e) {
throw new TSGException("Unable to save sticker image");
}
}
private void getPackInfo(String packName, File packFolder, String installedVersion, PackDownloadListener listener) {
String getStickerSetUrl = String.format(GET_STICKER_SET_URL, botApiKey, packName);
Request packInfoRequest = new Request.a()
.b(getStickerSetUrl)
.a();
sClient.a(packInfoRequest).a(new Callback() {
@Override
public void onFailure(NetCall call, IOException e) {
public void a(Call call, IOException e) {
Log.d(TAG, e.getMessage());
listener.onPackDownloadError(e);
}
@Override
public void onResponse(NetCall call, NetResponse response) throws IOException {
if (!response.isSuccessful()) {
if (response.getData() != null)
listener.onPackDownloadError(new TSGException(response.getDataString() + "\nURL: " + call.request().url()));
else
listener.onPackDownloadError(new TSGException("Unknown Exception, no response body"));
public void a(Call call, Response response) throws IOException {
Log.d(TAG, response.toString());
if (!response.h()) {
String errorMessage = response.a() != null ? response.a().g() + "\nURL: " + call.m0().g() : "Unknown Exception, no response body";
listener.onPackDownloadError(new TSGException(errorMessage));
return;
}
StickerSet set;
try {
JSONObject jPackInfo = new JSONObject(response.getDataString()).getJSONObject("result");
String packVersion = new String(sha256.digest(jPackInfo.toString().getBytes(StandardCharsets.UTF_8)));
try (ResponseBody responseBody = response.a()) {
JSONObject packInfoResponse = new JSONObject(responseBody.g()).getJSONObject("result");
String packVersion = new String(sha256.digest(packInfoResponse.toString().getBytes(StandardCharsets.UTF_8)));
if (packVersion.equals(installedVersion)) {
listener.onPackDownloaded(null, false);
return;
}
JSONArray jStickers = jPackInfo.getJSONArray("stickers");
JSONArray stickersArray = packInfoResponse.getJSONArray(STICKERS_KEY);
if (jStickers.length() == 0) {
if (stickersArray.length() == 0) {
listener.onPackDownloadError(new TSGException("No stickers in pack"));
return;
}
if (jPackInfo.optBoolean("is_animated")) {
listener.onPackDownloadError(new TSGException("Animated stickerpacks are not supported!"));
ArrayList<Sticker> stickers = parseStickers(stickersArray);
StickerSet set = new StickerSet(packInfoResponse.getString(NAME_KEY), packInfoResponse.getString(TITLE_KEY), packVersion, stickers);
if (!packFolder.exists() && !packFolder.mkdirs()) {
// Handle the folder creation failure case
listener.onPackDownloadError(new IOException("Can't create folder for the pack!"));
return;
}
ArrayList<Sticker> stickers = new ArrayList<>(jStickers.length());
Log.d(TAG, String.format("Got info for pack %s, now downloading stickers to %s", packName, packFolder.getAbsolutePath()));
Log.d(TAG, String.format("Parsing stickers in pack %s", packName));
TelegramStickersPackInfo packInfo = new TelegramStickersPackInfo(packName, set.name, set.stickers.size(), set.version);
for (int i = 0; i < jStickers.length(); i++) {
JSONObject jSticker = jStickers.getJSONObject(i);
stickers.add(new Sticker(jSticker.getString("file_id"), jSticker.getString("emoji")));
}
listener.onGotPackInfo(packInfo);
set = new StickerSet(jPackInfo.getString("name"), jPackInfo.getString("title"), packVersion, stickers);
getPack(set, packFolder, packInfo, listener);
} catch (Exception e) {
listener.onPackDownloadError(e);
return;
}
if (!packFolder.exists() && !packFolder.mkdirs()) {
listener.onPackDownloadError(new IOException("Can't create folder for the pack!"));
return;
}
Log.d(TAG, String.format("Got info for pack %s, now downloading stickers to %s", packName, packFolder.getAbsolutePath()));
TelegramStickersPackInfo packInfo = new TelegramStickersPackInfo(packName, set.name, set.stickers.size(), set.version);
listener.onGotPackInfo(packInfo);
getPack(set, packFolder, packInfo, listener);
}
});
}
private void getPack(final StickerSet set, final File packFolder, final TelegramStickersPackInfo packInfo, final PackDownloadListener listener) {
final GoalCounter downloadedStickers = new GoalCounter(set.stickers.size(), () -> {
Log.d(TAG, String.format("Pack %s has been downloaded to %s", set.id, packFolder.getAbsolutePath()));
private ArrayList<Sticker> parseStickers(JSONArray stickersArray) throws JSONException, TSGException {
ArrayList<Sticker> stickers = new ArrayList<>(stickersArray.length());
listener.onPackDownloaded(packInfo, true);
});
final Flag deathFlag = new Flag();
for (int i = 0; i < stickersArray.length(); i++) {
JSONObject stickerObject = stickersArray.getJSONObject(i);
boolean isAnimated = stickerObject.optBoolean(IS_ANIMATED_KEY);
boolean isVideo = stickerObject.optBoolean(IS_VIDEO_KEY);
String fileId = stickerObject.getString(FILE_ID_KEY);
String emoji = stickerObject.getString(EMOJI_KEY);
AtomicInteger retryed = new AtomicInteger();
for (int i = 0; i < set.stickers.size(); i++) {
final Sticker sticker = set.stickers.get(i);
NetRequest fileInfoRequest = new NetRequest.Builder().get().url(String.format(GET_FILE_URL, botApiKey, sticker.fileId)).build();
final int stickerIndex = i + 1;
AtomicBoolean sync = new AtomicBoolean();
httpClient.newCall(fileInfoRequest).enqueue(new NetCallback() {
@Override
public void onFailure(NetCall call, IOException e) {
if (deathFlag.up())
return;
deathFlag.raise();
listener.onPackDownloadError(e);
sync.set(true);
if (isAnimated || isVideo) {
if (stickerObject.has(THUMB_KEY)) {
fileId = stickerObject.getJSONObject(THUMB_KEY).getString(FILE_ID_KEY);
} else {
throw new TSGException("Animated and video stickerpacks without thumbs are not supported!");
}
}
@Override
public void onResponse(NetCall call, NetResponse response) throws IOException {
if (deathFlag.up())
return;
if (response.code() != 200) {
retryed.incrementAndGet();
if (retryed.get() > 5)
onFailure(call, new IOException());
else httpClient.newCall(fileInfoRequest)
.enqueue(this);
return;
}
String filePath;
try {
JSONObject jFileInfo = new JSONObject(response.getDataString()).getJSONObject("result");
filePath = jFileInfo.getString("file_path");
} catch (Exception e) {
deathFlag.raise();
listener.onPackDownloadError(e);
sync.set(true);
return;
}
if (botApiKey == null) botApiKey = "";
NetRequest fileDownloadRequest = new NetRequest.Builder().get().url(String.format(BOT_API_BASE_FILE_URL, botApiKey, filePath)).build();
httpClient.newCall(fileDownloadRequest).enqueue(new NetCallback() {
@Override
public void onFailure(NetCall call, IOException e) {
if (deathFlag.up())
return;
deathFlag.raise();
listener.onPackDownloadError(e);
sync.set(true);
}
@Override
public void onResponse(NetCall call, NetResponse response) throws IOException {
if (deathFlag.up())
return;
if (response.code() != 200) {
retryed.incrementAndGet();
if (retryed.get() > 5)
onFailure(call, new IOException());
else httpClient.newCall(fileDownloadRequest)
.enqueue(this);
return;
}
if (response.getData() == null) {
deathFlag.raise();
listener.onPackDownloadError(new TSGException("Response body for a sticker is null :/"));
sync.set(true);
return;
}
InputStream stickerInputStream = response.getDataStream();
Bitmap stickerImage = BitmapFactory.decodeStream(stickerInputStream);
try {
stickerInputStream.close();
} catch (IOException e) {
e.printStackTrace();
deathFlag.raise();
listener.onPackDownloadError(e);
sync.set(true);
return;
}
if (stickerImage == null) {
deathFlag.raise();
listener.onPackDownloadError(new TSGException("Unable to decode sticker image"));
sync.set(true);
return;
}
File stickerFile = new File(packFolder, String.format("%03d.png", stickerIndex));
FileOutputStream fileOutputStream;
try {
fileOutputStream = new FileOutputStream(stickerFile);
} catch (Exception e) {
e.printStackTrace();
deathFlag.raise();
listener.onPackDownloadError(e);
sync.set(true);
return;
}
if (!stickerImage.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream)) {
stickerImage.recycle();
deathFlag.raise();
listener.onPackDownloadError(new TSGException("Unable to compress sticker to a png file at path: " + stickerFile.getAbsolutePath()));
sync.set(true);
return;
}
stickerImage.recycle();
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
deathFlag.raise();
listener.onPackDownloadError(e);
sync.set(true);
return;
}
listener.onStickerDownloaded(set.name, stickerFile, sticker.emoji, stickerIndex, downloadedStickers.value() + 1, set.stickers.size());
downloadedStickers.increase();
sync.set(true);
}
});
}
});
while (!sync.get())
try {
Thread.sleep(100);
} catch (InterruptedException e1) {
}
stickers.add(new Sticker(fileId, emoji));
}
return stickers;
}
private void runOnUiThread(Runnable r) {
@@ -435,15 +345,13 @@ public class TelegramStickersGrabber {
void onNetError();
}
public class TSGException extends Exception {
private static final long serialVersionUID = 7866915509988422944L;
public static class TSGException extends Exception {
private TSGException(String message) {
super(message);
}
}
private class StickerSet {
private static class StickerSet {
String id;
String name;
String version;
@@ -457,7 +365,7 @@ public class TelegramStickersGrabber {
}
}
private class Sticker {
private static class Sticker {
String emoji;
String fileId;
@@ -2,35 +2,29 @@ package com.arthenica.ffmpegkit;
import android.os.Build;
import android.util.Log;
import com.arthenica.smartexception.java.Exceptions;
import java.util.Collections;
import java.util.List;
import ru.vtosters.lite.utils.AndroidUtils;
public class NativeLoader {
static final String[] FFMPEG_LIBRARIES = {"avutil", "swscale", "swresample", "avcodec", "avformat", "avfilter", "avdevice"};
static final String[] FFMPEG_LIBRARIES = {"avutil", "swresample", "avcodec", "avformat", "avfilter", "avdevice"};
private static void loadLibrary(String libraryName) {
String path = AndroidUtils.getGlobalContext().getFilesDir() + "/lib" + libraryName + ".so";
System.load(path);
System.loadLibrary(libraryName);
}
private static List<String> loadExternalLibraries() {
// return Packages.getExternalLibraries();
//return Packages.getExternalLibraries();
return Collections.emptyList();
}
private static String loadNativeAbi() {
// return AbiDetect.getNativeAbi();
return Abi.ABI_ARMV7A_NEON.getName();
return AbiDetect.getNativeAbi();
}
static String loadAbi() {
// return AbiDetect.getAbi();
return Abi.ABI_ARMV7A_NEON.getName();
return AbiDetect.getAbi();
}
static String loadPackageName() {
@@ -0,0 +1,323 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import java.util.*;
import java.util.Map.Entry;
/**
* Analyzes an APK to:
*
* <ul>
* <li>Blame resource configurations on their entry count (entries keeping the config around).
* <li>Blame strings in resources.arsc that have no base configuration.
* <li>Blame resources on their different configurations.
* </ul>
*/
public class ArscBlamer {
/**
* Maps package key pool indices to blamed resources.
*/
private final Map<PackageChunk, List<ResourceEntry>[]> keyToBlame = new HashMap<>();
/**
* Maps types to blamed resources.
*/
private final Map<PackageChunk, List<ResourceEntry>[]> typeToBlame = new HashMap<>();
/**
* Maps package to blamed resources.
*/
private final Multimap<PackageChunk, ResourceEntry> packageToBlame = HashMultimap.create();
/**
* Maps string indices to blamed resources.
*/
private final List<ResourceEntry>[] stringToBlame;
/**
* Maps type chunk entries to blamed resources.
*/
private final Multimap<TypeChunk.Entry, ResourceEntry> typeEntryToBlame = HashMultimap.create();
/**
* This is the {@link ResourceTableChunk} inside of the resources.arsc file in the APK.
*/
private final ResourceTableChunk resourceTable;
/**
* Maps resources to the type chunk entries they reference.
*/
private Multimap<ResourceEntry, TypeChunk.Entry> resourceEntries;
/**
* Maps resources which have no base config to the type chunk entries they reference.
*/
private Multimap<ResourceEntry, TypeChunk.Entry> baselessKeys;
/**
* Contains all of the type chunks in {@link #resourceTable}.
*/
private List<TypeChunk> typeChunks;
/**
* Creates a new {@link ArscBlamer}.
*
* @param resourceTable The resources.arsc resource table to blame.
*/
public ArscBlamer(ResourceTableChunk resourceTable) {
this.resourceTable = resourceTable;
this.stringToBlame = createEntryListArray(resourceTable.getStringPool().getStringCount());
}
private static List<ResourceEntry>[] createEntryListArray(int size) {
ArrayListResourceEntry[] result = new ArrayListResourceEntry[size];
for (int i = 0; i < size; ++i) {
result[i] = new ArrayListResourceEntry();
}
return result;
}
/**
* Generates blame mappings.
*/
public void blame() {
Multimap<ResourceEntry, TypeChunk.Entry> entries = getResourceEntries();
for (Entry<ResourceEntry, Collection<TypeChunk.Entry>> entry : entries.asMap().entrySet()) {
ResourceEntry resourceEntry = entry.getKey();
PackageChunk packageChunk = Preconditions.checkNotNull(
resourceTable.getPackage(resourceEntry.packageName()));
int keyCount = packageChunk.getKeyStringPool().getStringCount();
int typeCount = packageChunk.getTypeStringPool().getStringCount();
for (TypeChunk.Entry chunkEntry : entry.getValue()) {
blameKeyOrType(keyToBlame, packageChunk, chunkEntry.keyIndex(), resourceEntry, keyCount);
blameKeyOrType(typeToBlame, packageChunk, chunkEntry.parent().getId() - 1, resourceEntry,
typeCount);
blameFromTypeChunkEntry(chunkEntry);
}
blamePackage(packageChunk, resourceEntry);
}
Multimaps.invertFrom(entries, typeEntryToBlame);
for (TypeChunk.Entry entry : typeEntryToBlame.keySet()) {
blameFromTypeChunkEntry(entry);
}
}
private void blameKeyOrType(Map<PackageChunk, List<ResourceEntry>[]> keyOrType,
PackageChunk packageChunk, int keyIndex, ResourceEntry entry, int entryCount) {
if (!keyOrType.containsKey(packageChunk)) {
keyOrType.put(packageChunk, createEntryListArray(entryCount));
}
keyOrType.get(packageChunk)[keyIndex].add(entry);
}
private void blamePackage(PackageChunk packageChunk, ResourceEntry entry) {
packageToBlame.put(packageChunk, entry);
}
private void blameFromTypeChunkEntry(TypeChunk.Entry chunkEntry) {
for (BinaryResourceValue value : getAllResourceValues(chunkEntry)) {
for (ResourceEntry entry : typeEntryToBlame.get(chunkEntry)) {
switch (value.type()) {
case STRING:
blameString(value.data(), entry);
break;
default:
break;
}
}
}
}
/**
* Returns all {@link BinaryResourceValue} for a single {@code entry}.
*/
private Collection<BinaryResourceValue> getAllResourceValues(TypeChunk.Entry entry) {
Set<BinaryResourceValue> values = new HashSet<BinaryResourceValue>();
BinaryResourceValue binaryResourceValue = entry.value();
if (binaryResourceValue != null) {
values.add(binaryResourceValue);
}
for (BinaryResourceValue value : entry.values().values()) {
values.add(value);
}
return values;
}
private void blameString(int stringIndex, ResourceEntry entry) {
stringToBlame[stringIndex].add(entry);
}
/**
* Must first call {@link #blame}.
*/
public Map<PackageChunk, List<ResourceEntry>[]> getKeyToBlamedResources() {
return Collections.unmodifiableMap(keyToBlame);
}
/**
* Must first call {@link #blame}.
*/
public Map<PackageChunk, List<ResourceEntry>[]> getTypeToBlamedResources() {
return Collections.unmodifiableMap(typeToBlame);
}
/**
* Must first call {@link #blame}.
*/
public Multimap<PackageChunk, ResourceEntry> getPackageToBlamedResources() {
return Multimaps.unmodifiableMultimap(packageToBlame);
}
/**
* Must first call {@link #blame}.
*/
public List<ResourceEntry>[] getStringToBlamedResources() {
return stringToBlame;
}
/**
* Must first call {@link #blame}.
*/
public Multimap<TypeChunk.Entry, ResourceEntry> getTypeEntryToBlamedResources() {
return Multimaps.unmodifiableMultimap(typeEntryToBlame);
}
/**
* Returns a multimap of keys for which there is no default resource.
*/
public Multimap<ResourceEntry, TypeChunk.Entry> getBaselessKeys() {
if (baselessKeys != null) {
return baselessKeys;
}
Multimap<ResourceEntry, TypeChunk.Entry> result = HashMultimap.create();
for (Entry<ResourceEntry, Collection<TypeChunk.Entry>> entry
: getResourceEntries().asMap().entrySet()) {
Collection<TypeChunk.Entry> chunkEntries = entry.getValue();
if (!hasBaseConfiguration(chunkEntries)) {
result.putAll(entry.getKey(), chunkEntries);
}
}
baselessKeys = result;
return result;
}
/**
* Returns a multimap of resource entries to the chunk entries they reference in this APK.
*/
public Multimap<ResourceEntry, TypeChunk.Entry> getResourceEntries() {
if (resourceEntries != null) {
return resourceEntries;
}
Multimap<ResourceEntry, TypeChunk.Entry> result = HashMultimap.create();
for (TypeChunk typeChunk : getTypeChunks()) {
for (TypeChunk.Entry entry : typeChunk.getEntries().values()) {
result.put(ResourceEntry.create(entry), entry);
}
}
resourceEntries = result;
return result;
}
/**
* Returns all {@link TypeChunk} in resources.arsc.
*/
public List<TypeChunk> getTypeChunks() {
if (typeChunks != null) {
return typeChunks;
}
List<TypeChunk> result = new ArrayList<>();
for (PackageChunk packageChunk : resourceTable.getPackages()) {
for (TypeChunk typeChunk : packageChunk.getTypeChunks()) {
result.add(typeChunk);
}
}
typeChunks = result;
return result;
}
private boolean hasBaseConfiguration(Collection<TypeChunk.Entry> entries) {
for (TypeChunk.Entry entry : entries) {
if (entry.parent().getConfiguration().isDefault()) {
return true;
}
}
return false;
}
/**
* Allows creation of concrete parameterized type arr {@link ArscBlamer#createEntryListArray}.
*/
private static class ArrayListResourceEntry extends ArrayList<ResourceEntry> {
private ArrayListResourceEntry() {
super(2); // ~90-95% of these lists end up with only 1 or 2 elements.
}
}
/**
* Describes a single resource entry.
*/
public static class ResourceEntry {
private final String packageName;
private final String typeName;
private final String entryName;
private ResourceEntry(String packageName, String typeName, String entryName) {
this.packageName = packageName;
this.typeName = typeName;
this.entryName = entryName;
}
static ResourceEntry create(TypeChunk.Entry entry) {
PackageChunk packageChunk = Preconditions.checkNotNull(entry.parent().getPackageChunk());
String packageName = packageChunk.getPackageName();
String typeName = entry.typeName();
String entryName = entry.key();
return new ResourceEntry(packageName, typeName, entryName);
}
public String packageName() {
return packageName;
}
public String typeName() {
return typeName;
}
public String entryName() {
return entryName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ResourceEntry that = (ResourceEntry) o;
return Objects.equals(packageName, that.packageName) &&
Objects.equals(typeName, that.typeName) &&
Objects.equals(entryName, that.entryName);
}
@Override
public int hashCode() {
return Objects.hash(packageName, typeName, entryName);
}
}
}
@@ -0,0 +1,726 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.primitives.UnsignedBytes;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.*;
import static java.nio.charset.StandardCharsets.US_ASCII;
/**
* Describes a particular resource configuration.
*/
public class BinaryResourceConfiguration implements SerializableResource {
/**
* The below constants are from android.content.res.Configuration.
*/
private static final int DENSITY_DPI_UNDEFINED = 0;
private static final int DENSITY_DPI_LDPI = 120;
private static final int DENSITY_DPI_MDPI = 160;
private static final int DENSITY_DPI_TVDPI = 213;
private static final int DENSITY_DPI_HDPI = 240;
private static final int DENSITY_DPI_XHDPI = 320;
private static final int DENSITY_DPI_XXHDPI = 480;
private static final int DENSITY_DPI_XXXHDPI = 640;
private static final int DENSITY_DPI_ANY = 0xFFFE;
private static final int DENSITY_DPI_NONE = 0xFFFF;
private static final Map<Integer, String> DENSITY_DPI_VALUES =
ImmutableMap.<Integer, String>builder()
.put(DENSITY_DPI_UNDEFINED, "")
.put(DENSITY_DPI_LDPI, "ldpi")
.put(DENSITY_DPI_MDPI, "mdpi")
.put(DENSITY_DPI_TVDPI, "tvdpi")
.put(DENSITY_DPI_HDPI, "hdpi")
.put(DENSITY_DPI_XHDPI, "xhdpi")
.put(DENSITY_DPI_XXHDPI, "xxhdpi")
.put(DENSITY_DPI_XXXHDPI, "xxxhdpi")
.put(DENSITY_DPI_ANY, "anydpi")
.put(DENSITY_DPI_NONE, "nodpi")
.build();
private static final int KEYBOARD_NOKEYS = 1;
private static final int KEYBOARD_QWERTY = 2;
private static final int KEYBOARD_12KEY = 3;
private static final Map<Integer, String> KEYBOARD_VALUES = ImmutableMap.of(
KEYBOARD_NOKEYS, "nokeys",
KEYBOARD_QWERTY, "qwerty",
KEYBOARD_12KEY, "12key");
private static final int KEYBOARDHIDDEN_MASK = 0x03;
private static final int KEYBOARDHIDDEN_NO = 1;
private static final int KEYBOARDHIDDEN_YES = 2;
private static final int KEYBOARDHIDDEN_SOFT = 3;
private static final Map<Integer, String> KEYBOARDHIDDEN_VALUES = ImmutableMap.of(
KEYBOARDHIDDEN_NO, "keysexposed",
KEYBOARDHIDDEN_YES, "keyshidden",
KEYBOARDHIDDEN_SOFT, "keyssoft");
private static final int NAVIGATION_NONAV = 1;
private static final int NAVIGATION_DPAD = 2;
private static final int NAVIGATION_TRACKBALL = 3;
private static final int NAVIGATION_WHEEL = 4;
private static final Map<Integer, String> NAVIGATION_VALUES = ImmutableMap.of(
NAVIGATION_NONAV, "nonav",
NAVIGATION_DPAD, "dpad",
NAVIGATION_TRACKBALL, "trackball",
NAVIGATION_WHEEL, "wheel");
private static final int NAVIGATIONHIDDEN_MASK = 0x0C;
private static final int NAVIGATIONHIDDEN_NO = 0x04;
private static final int NAVIGATIONHIDDEN_YES = 0x08;
private static final Map<Integer, String> NAVIGATIONHIDDEN_VALUES = ImmutableMap.of(
NAVIGATIONHIDDEN_NO, "navexposed",
NAVIGATIONHIDDEN_YES, "navhidden");
private static final int ORIENTATION_PORTRAIT = 0x01;
private static final int ORIENTATION_LANDSCAPE = 0x02;
private static final Map<Integer, String> ORIENTATION_VALUES = ImmutableMap.of(
ORIENTATION_PORTRAIT, "port",
ORIENTATION_LANDSCAPE, "land");
private static final int SCREENLAYOUT_LAYOUTDIR_MASK = 0xC0;
private static final int SCREENLAYOUT_LAYOUTDIR_LTR = 0x40;
private static final int SCREENLAYOUT_LAYOUTDIR_RTL = 0x80;
private static final Map<Integer, String> SCREENLAYOUT_LAYOUTDIR_VALUES = ImmutableMap.of(
SCREENLAYOUT_LAYOUTDIR_LTR, "ldltr",
SCREENLAYOUT_LAYOUTDIR_RTL, "ldrtl");
private static final int SCREENLAYOUT_LONG_MASK = 0x30;
private static final int SCREENLAYOUT_LONG_NO = 0x10;
private static final int SCREENLAYOUT_LONG_YES = 0x20;
private static final Map<Integer, String> SCREENLAYOUT_LONG_VALUES = ImmutableMap.of(
SCREENLAYOUT_LONG_NO, "notlong",
SCREENLAYOUT_LONG_YES, "long");
private static final int SCREENLAYOUT_ROUND_MASK = 0x03;
private static final int SCREENLAYOUT_ROUND_NO = 0x01;
private static final int SCREENLAYOUT_ROUND_YES = 0x02;
private static final Map<Integer, String> SCREENLAYOUT_ROUND_VALUES = ImmutableMap.of(
SCREENLAYOUT_ROUND_NO, "notround",
SCREENLAYOUT_ROUND_YES, "round");
private static final int SCREENLAYOUT_SIZE_MASK = 0x0F;
private static final int SCREENLAYOUT_SIZE_SMALL = 0x01;
private static final int SCREENLAYOUT_SIZE_NORMAL = 0x02;
private static final int SCREENLAYOUT_SIZE_LARGE = 0x03;
private static final int SCREENLAYOUT_SIZE_XLARGE = 0x04;
private static final Map<Integer, String> SCREENLAYOUT_SIZE_VALUES = ImmutableMap.of(
SCREENLAYOUT_SIZE_SMALL, "small",
SCREENLAYOUT_SIZE_NORMAL, "normal",
SCREENLAYOUT_SIZE_LARGE, "large",
SCREENLAYOUT_SIZE_XLARGE, "xlarge");
private static final int TOUCHSCREEN_NOTOUCH = 1;
private static final int TOUCHSCREEN_FINGER = 3;
private static final Map<Integer, String> TOUCHSCREEN_VALUES = ImmutableMap.of(
TOUCHSCREEN_NOTOUCH, "notouch",
TOUCHSCREEN_FINGER, "finger");
private static final int UI_MODE_NIGHT_MASK = 0x30;
private static final int UI_MODE_NIGHT_NO = 0x10;
private static final int UI_MODE_NIGHT_YES = 0x20;
private static final Map<Integer, String> UI_MODE_NIGHT_VALUES = ImmutableMap.of(
UI_MODE_NIGHT_NO, "notnight",
UI_MODE_NIGHT_YES, "night");
private static final int UI_MODE_TYPE_MASK = 0x0F;
private static final int UI_MODE_TYPE_DESK = 0x02;
private static final int UI_MODE_TYPE_CAR = 0x03;
private static final int UI_MODE_TYPE_TELEVISION = 0x04;
private static final int UI_MODE_TYPE_APPLIANCE = 0x05;
private static final int UI_MODE_TYPE_WATCH = 0x06;
private static final int UI_MODE_TYPE_VR_HEADSET = 0x07;
// start - miui
private static final int UI_MODE_TYPE_GODZILLAUI = 0x0b;
private static final int UI_MODE_TYPE_SMALLUI = 0x0c;
private static final int UI_MODE_TYPE_MEDIUMUI = 0x0d;
private static final int UI_MODE_TYPE_LARGEUI = 0x0e;
private static final int UI_MODE_TYPE_HUGEUI = 0x0f;
private static final Map<Integer, String> UI_MODE_TYPE_VALUES =
ImmutableMap.<Integer, String>builder()
.put(UI_MODE_TYPE_DESK, "desk")
.put(UI_MODE_TYPE_CAR, "car")
.put(UI_MODE_TYPE_TELEVISION, "television")
.put(UI_MODE_TYPE_APPLIANCE, "appliance")
.put(UI_MODE_TYPE_WATCH, "watch")
.put(UI_MODE_TYPE_VR_HEADSET, "vrheadset")
.put(UI_MODE_TYPE_GODZILLAUI, "godzillaui")
.put(UI_MODE_TYPE_SMALLUI, "smallui")
.put(UI_MODE_TYPE_MEDIUMUI, "mediumui")
.put(UI_MODE_TYPE_LARGEUI, "largeui")
.put(UI_MODE_TYPE_HUGEUI, "hugeui").build();
/**
* The minimum size in bytes that this configuration must be to contain screen config info.
*/
private static final int SCREEN_CONFIG_MIN_SIZE = 32;
/**
* The minimum size in bytes that this configuration must be to contain screen dp info.
*/
private static final int SCREEN_DP_MIN_SIZE = 36;
/**
* The minimum size in bytes that this configuration must be to contain locale info.
*/
private static final int LOCALE_MIN_SIZE = 48;
/**
* The minimum size in bytes that this config must be to contain the screenConfig extension.
*/
private static final int SCREEN_CONFIG_EXTENSION_MIN_SIZE = 52;
private final int size;
private final int mcc;
private final int mnc;
private final byte[] language;
private final byte[] region;
private final int orientation;
private final int touchscreen;
private final int density;
private final int keyboard;
private final int navigation;
private final int inputFlags;
private final int screenWidth;
private final int screenHeight;
private final int sdkVersion;
private final int minorVersion;
private final int screenLayout;
private final int uiMode;
private final int smallestScreenWidthDp;
private final int screenWidthDp;
private final int screenHeightDp;
private final byte[] localeScript;
private final byte[] localeVariant;
// end - miui
private final int screenLayout2;
private final byte[] unknown;
private BinaryResourceConfiguration(int size,
int mcc,
int mnc,
byte[] language,
byte[] region,
int orientation,
int touchscreen,
int density,
int keyboard,
int navigation,
int inputFlags,
int screenWidth,
int screenHeight,
int sdkVersion,
int minorVersion,
int screenLayout,
int uiMode,
int smallestScreenWidthDp,
int screenWidthDp,
int screenHeightDp,
byte[] localeScript,
byte[] localeVariant,
int screenLayout2,
byte[] unknown) {
this.size = size;
this.mcc = mcc;
this.mnc = mnc;
this.language = language;
this.region = region;
this.orientation = orientation;
this.touchscreen = touchscreen;
this.density = density;
this.keyboard = keyboard;
this.navigation = navigation;
this.inputFlags = inputFlags;
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
this.sdkVersion = sdkVersion;
this.minorVersion = minorVersion;
this.screenLayout = screenLayout;
this.uiMode = uiMode;
this.smallestScreenWidthDp = smallestScreenWidthDp;
this.screenWidthDp = screenWidthDp;
this.screenHeightDp = screenHeightDp;
this.localeScript = localeScript;
this.localeVariant = localeVariant;
this.screenLayout2 = screenLayout2;
this.unknown = unknown;
}
static BinaryResourceConfiguration create(ByteBuffer buffer) {
int startPosition = buffer.position(); // The starting buffer position to calculate bytes read.
int size = buffer.getInt();
int mcc = buffer.getShort() & 0xFFFF;
int mnc = buffer.getShort() & 0xFFFF;
byte[] language = new byte[2];
buffer.get(language);
byte[] region = new byte[2];
buffer.get(region);
int orientation = UnsignedBytes.toInt(buffer.get());
int touchscreen = UnsignedBytes.toInt(buffer.get());
int density = buffer.getShort() & 0xFFFF;
int keyboard = UnsignedBytes.toInt(buffer.get());
int navigation = UnsignedBytes.toInt(buffer.get());
int inputFlags = UnsignedBytes.toInt(buffer.get());
buffer.get(); // 1 byte of padding
int screenWidth = buffer.getShort() & 0xFFFF;
int screenHeight = buffer.getShort() & 0xFFFF;
int sdkVersion = buffer.getShort() & 0xFFFF;
int minorVersion = buffer.getShort() & 0xFFFF;
// At this point, the configuration's size needs to be taken into account as not all
// configurations have all values.
int screenLayout = 0;
int uiMode = 0;
int smallestScreenWidthDp = 0;
int screenWidthDp = 0;
int screenHeightDp = 0;
byte[] localeScript = new byte[4];
byte[] localeVariant = new byte[8];
int screenLayout2 = 0;
if (size >= SCREEN_CONFIG_MIN_SIZE) {
screenLayout = UnsignedBytes.toInt(buffer.get());
uiMode = UnsignedBytes.toInt(buffer.get());
smallestScreenWidthDp = buffer.getShort() & 0xFFFF;
}
if (size >= SCREEN_DP_MIN_SIZE) {
screenWidthDp = buffer.getShort() & 0xFFFF;
screenHeightDp = buffer.getShort() & 0xFFFF;
}
if (size >= LOCALE_MIN_SIZE) {
buffer.get(localeScript);
buffer.get(localeVariant);
}
if (size >= SCREEN_CONFIG_EXTENSION_MIN_SIZE) {
screenLayout2 = UnsignedBytes.toInt(buffer.get());
buffer.get(); // Reserved padding
buffer.getShort(); // More reserved padding
}
// After parsing everything that's known, account for anything that's unknown.
int bytesRead = buffer.position() - startPosition;
byte[] unknown = new byte[size - bytesRead];
buffer.get(unknown);
return new BinaryResourceConfiguration(size, mcc, mnc, language, region, orientation,
touchscreen, density, keyboard, navigation, inputFlags, screenWidth, screenHeight,
sdkVersion, minorVersion, screenLayout, uiMode, smallestScreenWidthDp, screenWidthDp,
screenHeightDp, localeScript, localeVariant, screenLayout2, unknown);
}
/**
* The number of bytes that this resource configuration takes up.
*/
public int size() {
return size;
}
public int mcc() {
return mcc;
}
public int mnc() {
return mnc;
}
/**
* Returns a packed 2-byte language code.
*/
@SuppressWarnings("mutable")
public byte[] language() {
return language;
}
/**
* Returns {@link #language} as an unpacked string representation.
*/
public final String languageString() {
return unpackLanguage();
}
/**
* Returns a packed 2-byte region code.
*/
@SuppressWarnings("mutable")
public byte[] region() {
return region;
}
/**
* Returns {@link #region} as an unpacked string representation.
*/
public final String regionString() {
return unpackRegion();
}
public int orientation() {
return orientation;
}
public int touchscreen() {
return touchscreen;
}
public int density() {
return density;
}
public int keyboard() {
return keyboard;
}
public int navigation() {
return navigation;
}
public int inputFlags() {
return inputFlags;
}
public final int keyboardHidden() {
return inputFlags() & KEYBOARDHIDDEN_MASK;
}
public final int navigationHidden() {
return inputFlags() & NAVIGATIONHIDDEN_MASK;
}
public int screenWidth() {
return screenWidth;
}
public int screenHeight() {
return screenHeight;
}
public int sdkVersion() {
return sdkVersion;
}
/**
* Returns a copy of this resource configuration with a different {@link #sdkVersion}, or this
* configuration if the {@code sdkVersion} is the same.
*
* @param sdkVersion The SDK version of the returned configuration.
* @return A copy of this configuration with the only difference being #sdkVersion.
*/
public final BinaryResourceConfiguration withSdkVersion(int sdkVersion) {
if (sdkVersion == sdkVersion()) {
return this;
}
return new BinaryResourceConfiguration(size(), mcc(), mnc(), language(), region(),
orientation(), touchscreen(), density(), keyboard(), navigation(), inputFlags(),
screenWidth(), screenHeight(), sdkVersion, minorVersion(), screenLayout(), uiMode(),
smallestScreenWidthDp(), screenWidthDp(), screenHeightDp(), localeScript(), localeVariant(),
screenLayout2(), unknown());
}
public int minorVersion() {
return minorVersion;
}
public int screenLayout() {
return screenLayout;
}
public final int screenLayoutDirection() {
return screenLayout() & SCREENLAYOUT_LAYOUTDIR_MASK;
}
public final int screenLayoutSize() {
return screenLayout() & SCREENLAYOUT_SIZE_MASK;
}
public final int screenLayoutLong() {
return screenLayout() & SCREENLAYOUT_LONG_MASK;
}
public final int screenLayoutRound() {
return screenLayout2() & SCREENLAYOUT_ROUND_MASK;
}
public int uiMode() {
return uiMode;
}
public final int uiModeType() {
return uiMode() & UI_MODE_TYPE_MASK;
}
public final int uiModeNight() {
return uiMode() & UI_MODE_NIGHT_MASK;
}
public int smallestScreenWidthDp() {
return smallestScreenWidthDp;
}
public int screenWidthDp() {
return screenWidthDp;
}
public int screenHeightDp() {
return screenHeightDp;
}
/**
* The ISO-15924 short name for the script corresponding to this configuration.
*/
@SuppressWarnings("mutable")
public byte[] localeScript() {
return localeScript;
}
/**
* A single BCP-47 variant subtag.
*/
@SuppressWarnings("mutable")
public byte[] localeVariant() {
return localeVariant;
}
/**
* An extension to {@link #screenLayout}. Contains round/notround qualifier.
*/
public int screenLayout2() {
return screenLayout2;
}
/**
* Any remaining bytes in this resource configuration that are unaccounted for.
*/
@SuppressWarnings("mutable")
public byte[] unknown() {
return unknown;
}
private String unpackLanguage() {
return unpackLanguageOrRegion(language(), 0x61);
}
private String unpackRegion() {
return unpackLanguageOrRegion(region(), 0x30);
}
private String unpackLanguageOrRegion(byte[] value, int base) {
Preconditions.checkState(value.length == 2, "Language or region value must be 2 bytes.");
if (value[0] == 0 && value[1] == 0) {
return "";
}
if ((UnsignedBytes.toInt(value[0]) & 0x80) != 0) {
byte[] result = new byte[3];
result[0] = (byte) (base + (value[1] & 0x1F));
result[1] = (byte) (base + ((value[1] & 0xE0) >>> 5) + ((value[0] & 0x03) << 3));
result[2] = (byte) (base + ((value[0] & 0x7C) >>> 2));
return new String(result, US_ASCII);
}
return new String(value, US_ASCII);
}
/**
* Returns true if this is the default "any" configuration.
*/
public final boolean isDefault() {
return mcc() == 0
&& mnc() == 0
&& Arrays.equals(language(), new byte[2])
&& Arrays.equals(region(), new byte[2])
&& orientation() == 0
&& touchscreen() == 0
&& density() == 0
&& keyboard() == 0
&& navigation() == 0
&& inputFlags() == 0
&& screenWidth() == 0
&& screenHeight() == 0
&& sdkVersion() == 0
&& minorVersion() == 0
&& screenLayout() == 0
&& uiMode() == 0
&& smallestScreenWidthDp() == 0
&& screenWidthDp() == 0
&& screenHeightDp() == 0
&& Arrays.equals(localeScript(), new byte[4])
&& Arrays.equals(localeVariant(), new byte[8])
&& screenLayout2() == 0;
}
@Override
public final byte[] toByteArray() {
return toByteArray(false);
}
@Override
public final byte[] toByteArray(boolean shrink) {
ByteBuffer buffer = ByteBuffer.allocate(size()).order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(size());
buffer.putShort((short) mcc());
buffer.putShort((short) mnc());
buffer.put(language());
buffer.put(region());
buffer.put((byte) orientation());
buffer.put((byte) touchscreen());
buffer.putShort((short) density());
buffer.put((byte) keyboard());
buffer.put((byte) navigation());
buffer.put((byte) inputFlags());
buffer.put((byte) 0); // Padding
buffer.putShort((short) screenWidth());
buffer.putShort((short) screenHeight());
buffer.putShort((short) sdkVersion());
buffer.putShort((short) minorVersion());
if (size() >= SCREEN_CONFIG_MIN_SIZE) {
buffer.put((byte) screenLayout());
buffer.put((byte) uiMode());
buffer.putShort((short) smallestScreenWidthDp());
}
if (size() >= SCREEN_DP_MIN_SIZE) {
buffer.putShort((short) screenWidthDp());
buffer.putShort((short) screenHeightDp());
}
if (size() >= LOCALE_MIN_SIZE) {
buffer.put(localeScript());
buffer.put(localeVariant());
}
if (size() >= SCREEN_CONFIG_EXTENSION_MIN_SIZE) {
buffer.putInt(screenLayout2()); // Writing an unsigned byte + 3 padding
}
buffer.put(unknown());
return buffer.array();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BinaryResourceConfiguration that = (BinaryResourceConfiguration) o;
return size == that.size &&
mcc == that.mcc &&
mnc == that.mnc &&
orientation == that.orientation &&
touchscreen == that.touchscreen &&
density == that.density &&
keyboard == that.keyboard &&
navigation == that.navigation &&
inputFlags == that.inputFlags &&
screenWidth == that.screenWidth &&
screenHeight == that.screenHeight &&
sdkVersion == that.sdkVersion &&
minorVersion == that.minorVersion &&
screenLayout == that.screenLayout &&
uiMode == that.uiMode &&
smallestScreenWidthDp == that.smallestScreenWidthDp &&
screenWidthDp == that.screenWidthDp &&
screenHeightDp == that.screenHeightDp &&
screenLayout2 == that.screenLayout2 &&
Arrays.equals(language, that.language) &&
Arrays.equals(region, that.region) &&
Arrays.equals(localeScript, that.localeScript) &&
Arrays.equals(localeVariant, that.localeVariant) &&
Arrays.equals(unknown, that.unknown);
}
@Override
public int hashCode() {
return Objects
.hash(size, mcc, mnc, Arrays.hashCode(language), Arrays.hashCode(region), orientation, touchscreen, density, keyboard, navigation, inputFlags, screenWidth,
screenHeight,
sdkVersion, minorVersion, screenLayout, uiMode, smallestScreenWidthDp, screenWidthDp, screenHeightDp, Arrays.hashCode(localeScript),
Arrays.hashCode(localeVariant),
screenLayout2, Arrays.hashCode(unknown));
}
@Override
public final String toString() {
if (isDefault()) { // Prevent the default configuration from returning the empty string
return "default";
}
Collection<String> parts = toStringParts().values();
parts.removeAll(Collections.singleton(""));
return Joiner.on('-').join(parts);
}
/**
* Returns a map of the configuration parts for {@link #toString}.
*
* <p>If a configuration part is not defined for this {@link BinaryResourceConfiguration}, its value
* will be the empty string.
*/
public final Map<Type, String> toStringParts() {
Map<Type, String> result = new LinkedHashMap<>(); // Preserve order for #toString().
result.put(Type.MCC, mcc() != 0 ? "mcc" + mcc() : "");
result.put(Type.MNC, mnc() != 0 ? "mnc" + mnc() : "");
result.put(Type.LANGUAGE_STRING, !languageString().isEmpty() ? languageString() : "");
result.put(Type.REGION_STRING, !regionString().isEmpty() ? "r" + regionString() : "");
result.put(Type.SCREEN_LAYOUT_DIRECTION,
getOrDefault(SCREENLAYOUT_LAYOUTDIR_VALUES, screenLayoutDirection(), ""));
result.put(Type.SMALLEST_SCREEN_WIDTH_DP,
smallestScreenWidthDp() != 0 ? "sw" + smallestScreenWidthDp() + "dp" : "");
result.put(Type.SCREEN_WIDTH_DP, screenWidthDp() != 0 ? "w" + screenWidthDp() + "dp" : "");
result.put(Type.SCREEN_HEIGHT_DP, screenHeightDp() != 0 ? "h" + screenHeightDp() + "dp" : "");
result.put(Type.SCREEN_LAYOUT_SIZE,
getOrDefault(SCREENLAYOUT_SIZE_VALUES, screenLayoutSize(), ""));
result.put(Type.SCREEN_LAYOUT_LONG,
getOrDefault(SCREENLAYOUT_LONG_VALUES, screenLayoutLong(), ""));
result.put(Type.SCREEN_LAYOUT_ROUND,
getOrDefault(SCREENLAYOUT_ROUND_VALUES, screenLayoutRound(), ""));
result.put(Type.ORIENTATION, getOrDefault(ORIENTATION_VALUES, orientation(), ""));
result.put(Type.UI_MODE_TYPE, getOrDefault(UI_MODE_TYPE_VALUES, uiModeType(), ""));
result.put(Type.UI_MODE_NIGHT, getOrDefault(UI_MODE_NIGHT_VALUES, uiModeNight(), ""));
result.put(Type.DENSITY_DPI, getOrDefault(DENSITY_DPI_VALUES, density(), density() + "dpi"));
result.put(Type.TOUCHSCREEN, getOrDefault(TOUCHSCREEN_VALUES, touchscreen(), ""));
result.put(Type.KEYBOARD_HIDDEN, getOrDefault(KEYBOARDHIDDEN_VALUES, keyboardHidden(), ""));
result.put(Type.KEYBOARD, getOrDefault(KEYBOARD_VALUES, keyboard(), ""));
result.put(Type.NAVIGATION_HIDDEN,
getOrDefault(NAVIGATIONHIDDEN_VALUES, navigationHidden(), ""));
result.put(Type.NAVIGATION, getOrDefault(NAVIGATION_VALUES, navigation(), ""));
result.put(Type.SDK_VERSION, sdkVersion() != 0 ? "v" + sdkVersion() : "");
return result;
}
private <K, V> V getOrDefault(Map<K, V> map, K key, V defaultValue) {
// TODO(acornwall): Remove this when Java 8's Map#getOrDefault is available.
// Null is not returned, even if the map contains a key whose value is null. This is intended.
V value = map.get(key);
return value != null ? value : defaultValue;
}
/**
* The different types of configs that can be present in a {@link BinaryResourceConfiguration}.
*/
public enum Type {
MCC,
MNC,
LANGUAGE_STRING,
REGION_STRING,
SCREEN_LAYOUT_DIRECTION,
SMALLEST_SCREEN_WIDTH_DP,
SCREEN_WIDTH_DP,
SCREEN_HEIGHT_DP,
SCREEN_LAYOUT_SIZE,
SCREEN_LAYOUT_LONG,
SCREEN_LAYOUT_ROUND,
ORIENTATION,
UI_MODE_TYPE,
UI_MODE_NIGHT,
DENSITY_DPI,
TOUCHSCREEN,
KEYBOARD_HIDDEN,
KEYBOARD,
NAVIGATION_HIDDEN,
NAVIGATION,
SDK_VERSION
}
}
@@ -0,0 +1,80 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Given an arsc file, maps the contents of the file.
*/
public final class BinaryResourceFile implements SerializableResource {
/**
* The chunks contained in this resource file.
*/
private final List<Chunk> chunks = new ArrayList<>();
public BinaryResourceFile(byte[] buf) {
ByteBuffer buffer = ByteBuffer.wrap(buf).order(ByteOrder.LITTLE_ENDIAN);
while (buffer.remaining() > 0) {
chunks.add(Chunk.newInstance(buffer));
}
}
/**
* Given an input stream, reads the stream until the end and returns a {@link BinaryResourceFile}
* representing the contents of the stream.
*
* @param is The input stream to read from.
* @return BinaryResourceFile represented by the @{link InputStream}.
* @throws IOException
*/
public static BinaryResourceFile fromInputStream(InputStream is) throws IOException {
byte[] buf = ByteStreams.toByteArray(is);
return new BinaryResourceFile(buf);
}
/**
* Returns the chunks in this resource file.
*/
public List<Chunk> getChunks() {
return Collections.unmodifiableList(chunks);
}
@Override
public byte[] toByteArray() throws IOException {
return toByteArray(false);
}
@Override
public byte[] toByteArray(boolean shrink) throws IOException {
ByteArrayDataOutput output = ByteStreams.newDataOutput();
for (Chunk chunk : chunks) {
output.write(chunk.toByteArray(shrink));
}
return output.toByteArray();
}
}
@@ -0,0 +1,123 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import com.google.common.base.Preconditions;
import java.util.Objects;
/**
* Resources in a {@link ResourceTableChunk} are identified by an integer of the form 0xpptteeee,
* where pp is the {@link PackageChunk} id, tt is the {@link TypeChunk} id, and eeee is the index of
* the entry in the {@link TypeChunk}.
*/
public class BinaryResourceIdentifier {
/**
* The {@link PackageChunk} id mask for a packed resource id of the form 0xpptteeee.
*/
private static final int PACKAGE_ID_MASK = 0xFF000000;
private static final int PACKAGE_ID_SHIFT = 24;
/**
* The {@link TypeChunk} id mask for a packed resource id of the form 0xpptteeee.
*/
private static final int TYPE_ID_MASK = 0x00FF0000;
private static final int TYPE_ID_SHIFT = 16;
/**
* The {@link TypeChunk.Entry} id mask for a packed resource id of the form 0xpptteeee.
*/
private static final int ENTRY_ID_MASK = 0xFFFF;
private static final int ENTRY_ID_SHIFT = 0;
private final int packageId;
private final int typeId;
private final int entryId;
private BinaryResourceIdentifier(int packageId, int typeId, int entryId) {
this.packageId = packageId;
this.typeId = typeId;
this.entryId = entryId;
}
/**
* Returns a {@link BinaryResourceIdentifier} from a {@code resourceId} of the form 0xpptteeee.
*/
public static BinaryResourceIdentifier create(int resourceId) {
int packageId = (resourceId & PACKAGE_ID_MASK) >>> PACKAGE_ID_SHIFT;
int typeId = (resourceId & TYPE_ID_MASK) >>> TYPE_ID_SHIFT;
int entryId = (resourceId & ENTRY_ID_MASK) >>> ENTRY_ID_SHIFT;
return create(packageId, typeId, entryId);
}
/**
* Returns a {@link BinaryResourceIdentifier} with the given identifiers.
*/
public static BinaryResourceIdentifier create(int packageId, int typeId, int entryId) {
Preconditions.checkState((packageId & 0xFF) == packageId, "packageId must be <= 0xFF.");
Preconditions.checkState((typeId & 0xFF) == typeId, "typeId must be <= 0xFF.");
Preconditions.checkState((entryId & 0xFFFF) == entryId, "entryId must be <= 0xFFFF.");
return new BinaryResourceIdentifier(packageId, typeId, entryId);
}
/**
* The (1-based) id of the {@link PackageChunk} containing this resource.
*/
public int packageId() {
return packageId;
}
/**
* The (1-based) id of the {@link TypeChunk} containing this resource.
*/
public int typeId() {
return typeId;
}
/**
* The (0-based) index of the entry in a {@link TypeChunk} containing this resource.
*/
public int entryId() {
return entryId;
}
public int resId() {
return packageId << PACKAGE_ID_SHIFT | typeId << TYPE_ID_SHIFT | entryId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BinaryResourceIdentifier that = (BinaryResourceIdentifier) o;
return packageId == that.packageId &&
typeId == that.typeId &&
entryId == that.entryId;
}
@Override
public int hashCode() {
return Objects.hash(packageId, typeId, entryId);
}
@Override
public String toString() {
int v = packageId << PACKAGE_ID_SHIFT | typeId << TYPE_ID_SHIFT | entryId;
return String.format("0x%1$08x", v);
}
}
@@ -0,0 +1,169 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import com.google.common.primitives.UnsignedBytes;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import static java.nio.charset.StandardCharsets.UTF_16LE;
import static java.nio.charset.StandardCharsets.UTF_8;
/**
* Provides utilities to decode/encode a String packed in an arsc resource file.
*/
public final class BinaryResourceString {
private BinaryResourceString() {
} // Private constructor
/**
* Given a buffer and an offset into the buffer, returns a String. The {@code offset} is the
* 0-based byte offset from the start of the buffer where the string resides. This should be the
* location in memory where the string's character count, followed by its byte count, and then
* followed by the actual string is located.
*
* <p>Here's an example UTF-8-encoded string of ab©:
* <pre>
* 03 04 61 62 C2 A9 00
* ^ Offset should be here
* </pre>
*
* @param buffer The buffer containing the string to decode.
* @param offset Offset into the buffer where the string resides.
* @param type The encoding type that the {@link BinaryResourceString} is encoded in.
* @return The decoded string.
*/
public static String decodeString(ByteBuffer buffer, int offset, Type type) {
int length;
int characterCount = decodeLength(buffer, offset, type);
offset += computeLengthOffset(characterCount, type);
// UTF-8 strings have 2 lengths: the number of characters, and then the encoding length.
// UTF-16 strings, however, only have 1 length: the number of characters.
if (type == Type.UTF8) {
length = decodeLength(buffer, offset, type);
offset += computeLengthOffset(length, type);
} else {
length = characterCount * 2;
}
return new String(buffer.array(), offset, length, type.charset());
}
/**
* Encodes a string in either UTF-8 or UTF-16 and returns the bytes of the encoded string.
* Strings are prefixed by 2 values. The first is the number of characters in the string.
* The second is the encoding length (number of bytes in the string).
*
* <p>Here's an example UTF-8-encoded string of ab©:
* <pre>03 04 61 62 C2 A9 00</pre>
*
* @param str The string to be encoded.
* @param type The encoding type that the {@link BinaryResourceString} should be encoded in.
* @return The encoded string.
*/
public static byte[] encodeString(String str, Type type) {
byte[] bytes = str.getBytes(type.charset());
// The extra 5 bytes is for metadata (character count + byte count) and the NULL terminator.
ByteArrayDataOutput output = ByteStreams.newDataOutput(bytes.length + 5);
encodeLength(output, str.length(), type);
if (type == Type.UTF8) { // Only UTF-8 strings have the encoding length.
encodeLength(output, bytes.length, type);
}
output.write(bytes);
// NULL-terminate the string
if (type == Type.UTF8) {
output.write(0);
} else {
output.writeShort(0);
}
return output.toByteArray();
}
private static void encodeLength(ByteArrayDataOutput output, int length, Type type) {
if (length < 0) {
output.write(0);
return;
}
if (type == Type.UTF8) {
if (length > 0x7F) {
output.write(((length & 0x7F00) >> 8) | 0x80);
}
output.write(length & 0xFF);
} else { // UTF-16
// TODO(acornwall): Replace output with a little-endian output.
if (length > 0x7FFF) {
int highBytes = ((length & 0x7FFF0000) >> 16) | 0x8000;
output.write(highBytes & 0xFF);
output.write((highBytes & 0xFF00) >> 8);
}
int lowBytes = length & 0xFFFF;
output.write(lowBytes & 0xFF);
output.write((lowBytes & 0xFF00) >> 8);
}
}
private static int computeLengthOffset(int length, Type type) {
return (type == Type.UTF8 ? 1 : 2) * (length >= (type == Type.UTF8 ? 0x80 : 0x8000) ? 2 : 1);
}
private static int decodeLength(ByteBuffer buffer, int offset, Type type) {
return type == Type.UTF8 ? decodeLengthUTF8(buffer, offset) : decodeLengthUTF16(buffer, offset);
}
private static int decodeLengthUTF8(ByteBuffer buffer, int offset) {
// UTF-8 strings use a clever variant of the 7-bit integer for packing the string length.
// If the first byte is >= 0x80, then a second byte follows. For these values, the length
// is WORD-length in big-endian & 0x7FFF.
int length = UnsignedBytes.toInt(buffer.get(offset));
if ((length & 0x80) != 0) {
length = ((length & 0x7F) << 8) | UnsignedBytes.toInt(buffer.get(offset + 1));
}
return length;
}
private static int decodeLengthUTF16(ByteBuffer buffer, int offset) {
// UTF-16 strings use a clever variant of the 7-bit integer for packing the string length.
// If the first word is >= 0x8000, then a second word follows. For these values, the length
// is DWORD-length in big-endian & 0x7FFFFFFF.
int length = (buffer.getShort(offset) & 0xFFFF);
if ((length & 0x8000) != 0) {
length = ((length & 0x7FFF) << 16) | (buffer.getShort(offset + 2) & 0xFFFF);
}
return length;
}
/**
* Type of {@link BinaryResourceString} to encode / decode.
*/
public enum Type {
UTF8(UTF_8),
UTF16(UTF_16LE);
private final Charset charset;
Type(Charset charset) {
this.charset = charset;
}
public Charset charset() {
return charset;
}
}
}
@@ -0,0 +1,199 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.primitives.UnsignedBytes;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Map;
import java.util.Objects;
/**
* Represents a single typed resource value.
*/
public class BinaryResourceValue implements SerializableResource {
/**
* The serialized size in bytes of a {@link BinaryResourceValue}.
*/
public static final int SIZE = 8;
public int size;
public Type type;
public int data;
public BinaryResourceValue(int size, Type type, int data) {
this.size = size;
this.type = type;
this.data = data;
}
public static BinaryResourceValue create(ByteBuffer buffer) {
int size = (buffer.getShort() & 0xFFFF);
buffer.get(); // Unused
Type type = Type.fromCode(buffer.get());
int data = buffer.getInt();
return new BinaryResourceValue(size, type, data);
}
/**
* The length in bytes of this value.
*/
public int size() {
return size;
}
/**
* The raw data type of this value.
*/
public Type type() {
return type;
}
/**
* The actual 4-byte value; interpretation of the value depends on {@code dataType}.
*/
public int data() {
return data;
}
@Override
public byte[] toByteArray() {
return toByteArray(false);
}
@Override
public byte[] toByteArray(boolean shrink) {
ByteBuffer buffer = ByteBuffer.allocate(SIZE).order(ByteOrder.LITTLE_ENDIAN);
buffer.putShort((short) size());
buffer.put((byte) 0); // Unused
buffer.put(type().code());
buffer.putInt(data());
return buffer.array();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BinaryResourceValue that = (BinaryResourceValue) o;
return size == that.size &&
data == that.data &&
type == that.type;
}
@Override
public int hashCode() {
return Objects.hash(size, type, data);
}
/**
* Resource type codes.
*/
public enum Type {
/**
* {@code data} is either 0 (undefined) or 1 (empty).
*/
NULL(0x00),
/**
* {@code data} holds a {@link ResourceTableChunk} entry reference.
*/
REFERENCE(0x01),
/**
* {@code data} holds an attribute resource identifier.
*/
ATTRIBUTE(0x02),
/**
* {@code data} holds an index into the containing resource table's string pool.
*/
STRING(0x03),
/**
* {@code data} holds a single-precision floating point number.
*/
FLOAT(0x04),
/**
* {@code data} holds a complex number encoding a dimension value, such as "100in".
*/
DIMENSION(0x05),
/**
* {@code data} holds a complex number encoding a fraction of a container.
*/
FRACTION(0x06),
/**
* {@code data} holds a dynamic {@link ResourceTableChunk} entry reference.
*/
DYNAMIC_REFERENCE(0x07),
/**
* {@code data} holds a dynamic attribute resource identifier.
*/
DYNAMIC_ATTRIBUTE(0x08),
/**
* {@code data} is a raw integer value of the form n..n.
*/
INT_DEC(0x10),
/**
* {@code data} is a raw integer value of the form 0xn..n.
*/
INT_HEX(0x11),
/**
* {@code data} is either 0 (false) or 1 (true).
*/
INT_BOOLEAN(0x12),
/**
* {@code data} is a raw integer value of the form #aarrggbb.
*/
INT_COLOR_ARGB8(0x1c),
/**
* {@code data} is a raw integer value of the form #rrggbb.
*/
INT_COLOR_RGB8(0x1d),
/**
* {@code data} is a raw integer value of the form #argb.
*/
INT_COLOR_ARGB4(0x1e),
/**
* {@code data} is a raw integer value of the form #rgb.
*/
INT_COLOR_RGB4(0x1f);
private static final Map<Byte, Type> FROM_BYTE;
static {
Builder<Byte, Type> builder = ImmutableMap.builder();
for (Type type : values()) {
builder.put(type.code(), type);
}
FROM_BYTE = builder.build();
}
private final byte code;
Type(int code) {
this.code = UnsignedBytes.checkedCast(code);
}
public static Type fromCode(byte code) {
return Preconditions.checkNotNull(FROM_BYTE.get(code), "Unknown resource type: %s", code);
}
public byte code() {
return code;
}
}
}
@@ -0,0 +1,319 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import androidx.annotation.Nullable;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.io.LittleEndianDataOutputStream;
import com.google.common.primitives.Shorts;
import java.io.ByteArrayOutputStream;
import java.io.DataOutput;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Map;
/**
* Represents a generic chunk.
*/
public abstract class Chunk implements SerializableResource {
/**
* The byte boundary to pad chunks on.
*/
public static final int PAD_BOUNDARY = 4;
/**
* The number of bytes in every chunk that describes chunk type, header size, and chunk size.
*/
public static final int METADATA_SIZE = 8;
/**
* The offset in bytes, from the start of the chunk, where the chunk size can be found.
*/
private static final int CHUNK_SIZE_OFFSET = 4;
/**
* Size of the chunk header in bytes.
*/
protected final int headerSize;
/**
* headerSize + dataSize. The total size of this chunk.
*/
protected final int chunkSize;
/**
* Offset of this chunk from the start of the file.
*/
protected final int offset;
/**
* The parent to this chunk, if any.
*/
@Nullable
private final Chunk parent;
protected Chunk(ByteBuffer buffer, @Nullable Chunk parent) {
this.parent = parent;
offset = buffer.position() - 2;
headerSize = (buffer.getShort() & 0xFFFF);
chunkSize = buffer.getInt();
}
/**
* Creates a new chunk whose contents start at {@code buffer}'s current position.
*
* @param buffer A buffer positioned at the start of a chunk.
* @return new chunk
*/
public static Chunk newInstance(ByteBuffer buffer) {
return newInstance(buffer, null);
}
/**
* Creates a new chunk whose contents start at {@code buffer}'s current position.
*
* @param buffer A buffer positioned at the start of a chunk.
* @param parent The parent to this chunk (or null if there's no parent).
* @return new chunk
*/
public static Chunk newInstance(ByteBuffer buffer, @Nullable Chunk parent) {
Chunk result;
Type type = Type.fromCode(buffer.getShort());
switch (type) {
case STRING_POOL:
result = new StringPoolChunk(buffer, parent);
break;
case TABLE:
result = new ResourceTableChunk(buffer, parent);
break;
case XML:
result = new XmlChunk(buffer, parent);
break;
case XML_START_NAMESPACE:
result = new XmlNamespaceStartChunk(buffer, parent);
break;
case XML_END_NAMESPACE:
result = new XmlNamespaceEndChunk(buffer, parent);
break;
case XML_START_ELEMENT:
result = new XmlStartElementChunk(buffer, parent);
break;
case XML_END_ELEMENT:
result = new XmlEndElementChunk(buffer, parent);
break;
case XML_CDATA:
result = new XmlCdataChunk(buffer, parent);
break;
case XML_RESOURCE_MAP:
result = new XmlResourceMapChunk(buffer, parent);
break;
case TABLE_PACKAGE:
result = new PackageChunk(buffer, parent);
break;
case TABLE_TYPE:
result = new TypeChunk(buffer, parent);
break;
case TABLE_TYPE_SPEC:
result = new TypeSpecChunk(buffer, parent);
break;
case TABLE_LIBRARY:
result = new LibraryChunk(buffer, parent);
break;
default:
result = new UnknownChunk(buffer, parent);
}
result.init(buffer);
result.seekToEndOfChunk(buffer);
return result;
}
/**
* Finishes initialization of a chunk. This should be called immediately after the constructor.
* This is separate from the constructor so that the header of a chunk can be fully initialized
* before the payload of that chunk is initialized for chunks that require such behavior.
*
* @param buffer The buffer that the payload will be initialized from.
*/
protected void init(ByteBuffer buffer) {
}
/**
* Returns the parent to this chunk, if any. A parent is a chunk whose payload contains this
* chunk. If there's no parent, null is returned.
*/
@Nullable
public Chunk getParent() {
return parent;
}
protected abstract Type getType();
/**
* Returns the size of this chunk's header.
*/
public final int getHeaderSize() {
return headerSize;
}
/**
* Returns the size of this chunk when it was first read from a buffer. A chunk's size can deviate
* from this value when its data is modified (e.g. adding an entry, changing a string).
*
* <p>A chunk's current size can be determined from the length of the byte array returned from
* {@link #toByteArray}.
*/
public final int getOriginalChunkSize() {
return chunkSize;
}
/**
* Reposition the buffer after this chunk. Use this at the end of a Chunk constructor.
*
* @param buffer The buffer to be repositioned.
*/
private final void seekToEndOfChunk(ByteBuffer buffer) {
buffer.position(offset + chunkSize);
}
/**
* Writes the type and header size. We don't know how big this chunk will be (it could be
* different since the last time we checked), so this needs to be passed in.
*
* @param output The buffer that will be written to.
* @param chunkSize The total size of this chunk in bytes, including the header.
*/
protected final void writeHeader(ByteBuffer output, int chunkSize) {
int start = output.position();
output.putShort(getType().code());
output.putShort((short) headerSize);
output.putInt(chunkSize);
writeHeader(output);
int headerBytes = output.position() - start;
Preconditions.checkState(headerBytes == getHeaderSize(),
"Written header is wrong size. Got %s, want %s", headerBytes, getHeaderSize());
}
/**
* Writes the remaining header (after the type, {@code headerSize}, and {@code chunkSize}).
*
* @param output The buffer that the header will be written to.
*/
protected void writeHeader(ByteBuffer output) {
}
/**
* Writes the chunk payload. The payload is data in a chunk which is not in
* the first {@code headerSize} bytes of the chunk.
*
* @param output The stream that the payload will be written to.
* @param header The already-written header. This can be modified to fix payload offsets.
* @param shrink True if this payload should be optimized for size.
* @throws IOException Thrown if {@code output} could not be written to (out of memory).
*/
protected void writePayload(DataOutput output, ByteBuffer header, boolean shrink)
throws IOException {
}
/**
* Pads {@code output} until {@code currentLength} is on a 4-byte boundary.
*
* @param output The {@link DataOutput} that will be padded.
* @param currentLength The current length, in bytes, of {@code output}
* @return The new length of {@code output}
* @throws IOException Thrown if {@code output} could not be written to.
*/
protected int writePad(DataOutput output, int currentLength) throws IOException {
while (currentLength % PAD_BOUNDARY != 0) {
output.write(0);
++currentLength;
}
return currentLength;
}
@Override
public final byte[] toByteArray() throws IOException {
return toByteArray(false);
}
/**
* Converts this chunk into an array of bytes representation. Normally you will not need to
* override this method unless your header changes based on the contents / size of the payload.
*/
@Override
public final byte[] toByteArray(boolean shrink) throws IOException {
ByteBuffer header = ByteBuffer.allocate(getHeaderSize()).order(ByteOrder.LITTLE_ENDIAN);
writeHeader(header, 0); // The chunk size isn't known yet. This will be filled in later.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (LittleEndianDataOutputStream payload = new LittleEndianDataOutputStream(baos)) {
writePayload(payload, header, shrink);
}
byte[] payloadBytes = baos.toByteArray();
int chunkSize = getHeaderSize() + payloadBytes.length;
header.putInt(CHUNK_SIZE_OFFSET, chunkSize);
// Combine results
ByteBuffer result = ByteBuffer.allocate(chunkSize).order(ByteOrder.LITTLE_ENDIAN);
result.put(header.array());
result.put(payloadBytes);
return result.array();
}
/**
* Types of chunks that can exist.
*/
public enum Type {
NULL(0x0000),
STRING_POOL(0x0001),
TABLE(0x0002),
XML(0x0003),
XML_START_NAMESPACE(0x0100),
XML_END_NAMESPACE(0x0101),
XML_START_ELEMENT(0x0102),
XML_END_ELEMENT(0x0103),
XML_CDATA(0x0104),
XML_RESOURCE_MAP(0x0180),
TABLE_PACKAGE(0x0200),
TABLE_TYPE(0x0201),
TABLE_TYPE_SPEC(0x0202),
TABLE_LIBRARY(0x0203);
private static final Map<Short, Type> FROM_SHORT;
static {
Builder<Short, Type> builder = ImmutableMap.builder();
for (Type type : values()) {
builder.put(type.code(), type);
}
FROM_SHORT = builder.build();
}
private final short code;
Type(int code) {
this.code = Shorts.checkedCast(code);
}
public static Type fromCode(short code) {
return Preconditions.checkNotNull(FROM_SHORT.get(code), "Unknown chunk type: %s", code);
}
public short code() {
return code;
}
}
}
@@ -0,0 +1,75 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import androidx.annotation.Nullable;
import java.io.DataOutput;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Represents a chunk whose payload is a list of sub-chunks.
*/
public abstract class ChunkWithChunks extends Chunk {
private final Map<Integer, Chunk> chunks = new LinkedHashMap<>();
protected ChunkWithChunks(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
}
@Override
protected void init(ByteBuffer buffer) {
super.init(buffer);
chunks.clear();
int start = this.offset + getHeaderSize();
int offset = start;
int end = this.offset + getOriginalChunkSize();
int position = buffer.position();
buffer.position(start);
while (offset < end) {
Chunk chunk = Chunk.newInstance(buffer, this);
chunks.put(offset, chunk);
offset += chunk.getOriginalChunkSize();
}
buffer.position(position);
}
/**
* Retrieves the @{code chunks} contained in this chunk.
*
* @return map of buffer offset -> chunk contained in this chunk.
*/
public final Map<Integer, Chunk> getChunks() {
return chunks;
}
@Override
protected void writePayload(DataOutput output, ByteBuffer header, boolean shrink)
throws IOException {
for (Chunk chunk : getChunks().values()) {
byte[] chunkBytes = chunk.toByteArray(shrink);
output.write(chunkBytes);
writePad(output, chunkBytes.length);
}
}
}
@@ -0,0 +1,153 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import androidx.annotation.Nullable;
import java.io.DataOutput;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Contains a list of package-id to package name mappings for any shared libraries used in this
* {@link ResourceTableChunk}. The package-id's encoded in this resource table may be different
* than the id's assigned at runtime
*/
public final class LibraryChunk extends Chunk {
/**
* The number of resources of this type at creation time.
*/
private final int entryCount;
/**
* The libraries used in this chunk (package id + name).
*/
private final List<Entry> entries = new ArrayList<>();
LibraryChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
entryCount = buffer.getInt();
}
@Override
protected void init(ByteBuffer buffer) {
super.init(buffer);
entries.addAll(enumerateEntries(buffer));
}
private List<Entry> enumerateEntries(ByteBuffer buffer) {
List<Entry> result = new ArrayList<>(entryCount);
int offset = this.offset + getHeaderSize();
int endOffset = offset + Entry.SIZE * entryCount;
while (offset < endOffset) {
result.add(Entry.create(buffer, offset));
offset += Entry.SIZE;
}
return result;
}
@Override
protected Type getType() {
return Type.TABLE_LIBRARY;
}
@Override
protected void writeHeader(ByteBuffer output) {
super.writeHeader(output);
output.putInt(entries.size());
}
@Override
protected void writePayload(DataOutput output, ByteBuffer header, boolean shrink)
throws IOException {
for (Entry entry : entries) {
output.write(entry.toByteArray(shrink));
}
}
/**
* A shared library package-id to package name entry.
*/
protected static class Entry implements SerializableResource {
/**
* Library entries only contain a package ID (4 bytes) and a package name.
*/
private static final int SIZE = 4 + PackageUtils.PACKAGE_NAME_SIZE;
private final int packageId;
private final String packageName;
private Entry(int packageId, String packageName) {
this.packageId = packageId;
this.packageName = packageName;
}
static Entry create(ByteBuffer buffer, int offset) {
int packageId = buffer.getInt(offset);
String packageName = PackageUtils.readPackageName(buffer, offset + 4);
return new Entry(packageId, packageName);
}
/**
* The id assigned to the shared library at build time.
*/
public int packageId() {
return packageId;
}
/**
* The package name of the shared library.
*/
public String packageName() {
return packageName;
}
@Override
public byte[] toByteArray() throws IOException {
return toByteArray(false);
}
@Override
public byte[] toByteArray(boolean shrink) throws IOException {
ByteBuffer buffer = ByteBuffer.allocate(SIZE).order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(packageId());
PackageUtils.writePackageName(buffer, packageName());
return buffer.array();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Entry entry = (Entry) o;
return packageId == entry.packageId &&
Objects.equals(packageName, entry.packageName);
}
@Override
public int hashCode() {
return Objects.hash(packageId, packageName);
}
}
}
@@ -0,0 +1,269 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import androidx.annotation.Nullable;
import com.google.common.base.Preconditions;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import java.io.DataOutput;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
/**
* A package chunk is a collection of resource data types within a package.
*/
public final class PackageChunk extends ChunkWithChunks {
/**
* Offset in bytes, from the start of the chunk, where {@code typeStringsOffset} can be found.
*/
private static final int TYPE_OFFSET_OFFSET = 268;
/**
* Offset in bytes, from the start of the chunk, where {@code keyStringsOffset} can be found.
*/
private static final int KEY_OFFSET_OFFSET = 276;
/**
* The offset (from {@code offset}) in the original buffer where type strings start.
*/
private final int typeStringsOffset;
/**
* The index into the type string pool of the last public type.
*/
private final int lastPublicType;
/**
* An offset to the string pool that contains the key strings for this package.
*/
private final int keyStringsOffset;
/**
* The index into the key string pool of the last public key.
*/
private final int lastPublicKey;
/**
* An offset to the type ID(s). This is undocumented in the original code.
*/
private final int typeIdOffset;
/**
* Contains a mapping of a type index to its {@link TypeSpecChunk}.
*/
private final Map<Integer, TypeSpecChunk> typeSpecs = new HashMap<>();
/**
* Contains a mapping of a type index to all of the {@link TypeChunk} with that index.
*/
private final Multimap<Integer, TypeChunk> types = ArrayListMultimap.create();
/**
* The package id if this is a base package, or 0 if not a base package.
*/
private int id;
/**
* The name of the package.
*/
private String packageName;
/**
* May contain a library chunk for mapping dynamic references to resolved references.
*/
private Optional<LibraryChunk> libraryChunk = Optional.empty();
PackageChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
id = buffer.getInt();
packageName = PackageUtils.readPackageName(buffer, buffer.position());
typeStringsOffset = buffer.getInt();
lastPublicType = buffer.getInt();
keyStringsOffset = buffer.getInt();
lastPublicKey = buffer.getInt();
typeIdOffset = buffer.getInt();
}
@Override
protected void init(ByteBuffer buffer) {
super.init(buffer);
for (Chunk chunk : getChunks().values()) {
if (chunk instanceof TypeChunk) {
TypeChunk typeChunk = (TypeChunk) chunk;
types.put(typeChunk.getId(), typeChunk);
} else if (chunk instanceof TypeSpecChunk) {
TypeSpecChunk typeSpecChunk = (TypeSpecChunk) chunk;
typeSpecs.put(typeSpecChunk.getId(), typeSpecChunk);
} else if (chunk instanceof LibraryChunk) {
if (libraryChunk.isPresent()) {
throw new IllegalStateException(
"Multiple library chunks present in package chunk.");
}
libraryChunk = Optional.of((LibraryChunk) chunk);
} else if (!(chunk instanceof StringPoolChunk)) {
throw new IllegalStateException(
String.format("PackageChunk contains an unexpected chunk: %s", chunk.getClass()));
}
}
}
/**
* Returns the package id if this is a base package, or 0 if not a base package.
*/
public int getId() {
return id;
}
/**
* Sets the package id
*/
public void setId(int id) {
this.id = id;
}
/**
* Returns the string pool that contains the names of the resources in this package.
*/
public StringPoolChunk getKeyStringPool() {
Chunk chunk = Preconditions.checkNotNull(getChunks().get(keyStringsOffset + offset));
Preconditions.checkState(chunk instanceof StringPoolChunk, "Key string pool not found.");
return (StringPoolChunk) chunk;
}
/**
* Get the type string for a specific id, e.g., (e.g. string, attr, id).
*
* @param id The id to get the type for.
* @return The type string.
*/
public String getTypeString(int id) {
StringPoolChunk typePool = getTypeStringPool();
Preconditions.checkNotNull(typePool, "Package has no type pool.");
Preconditions.checkState(typePool.getStyleCount() >= id, "No type for id: " + id);
return typePool.getString(id - 1); // - 1 here to convert to 0-based index
}
/**
* Returns the string pool that contains the type strings for this package, such as "layout",
* "string", "color".
*/
public StringPoolChunk getTypeStringPool() {
Chunk chunk = Preconditions.checkNotNull(getChunks().get(typeStringsOffset + offset));
Preconditions.checkState(chunk instanceof StringPoolChunk, "Type string pool not found.");
return (StringPoolChunk) chunk;
}
/**
* Returns all {@link TypeChunk} in this package.
*/
public Collection<TypeChunk> getTypeChunks() {
return types.values();
}
/**
* For a given type id, returns the {@link TypeChunk} objects that match that id. The type id is
* the 1-based index of the type in the type string pool (returned by {@link #getTypeStringPool}).
*
* @param id The 1-based type id to return {@link TypeChunk} objects for.
* @return The matching {@link TypeChunk} objects, or an empty collection if there are none.
*/
public Collection<TypeChunk> getTypeChunks(int id) {
return types.get(id);
}
/**
* For a given type, returns the {@link TypeChunk} objects that match that type
* (e.g. "attr", "id", "string", ...).
*
* @param type The type to return {@link TypeChunk} objects for.
* @return The matching {@link TypeChunk} objects, or an empty collection if there are none.
*/
public Collection<TypeChunk> getTypeChunks(String type) {
StringPoolChunk typeStringPool = Preconditions.checkNotNull(getTypeStringPool());
return getTypeChunks(typeStringPool.indexOf(type) + 1); // Convert 0-based index to 1-based
}
/**
* Returns all {@link TypeSpecChunk} in this package.
*/
public Collection<TypeSpecChunk> getTypeSpecChunks() {
return typeSpecs.values();
}
/**
* For a given (1-based) type id, returns the {@link TypeSpecChunk} matching it.
*/
public TypeSpecChunk getTypeSpecChunk(int id) {
return Preconditions.checkNotNull(typeSpecs.get(id));
}
/**
* For a given {@code type}, returns the {@link TypeSpecChunk} that matches it
* (e.g. "attr", "id", "string", ...).
*/
public TypeSpecChunk getTypeSpecChunk(String type) {
StringPoolChunk typeStringPool = Preconditions.checkNotNull(getTypeStringPool());
return getTypeSpecChunk(typeStringPool.indexOf(type) + 1); // Convert 0-based index to 1-based
}
/**
* Returns the name of this package.
*/
public String getPackageName() {
return packageName;
}
/**
* Set the package name
*/
public void setPackageName(String packageName) {
this.packageName = packageName;
}
@Override
protected Type getType() {
return Type.TABLE_PACKAGE;
}
@Override
protected void writeHeader(ByteBuffer output) {
output.putInt(id);
PackageUtils.writePackageName(output, packageName);
output.putInt(0); // typeStringsOffset. This value can't be computed here.
output.putInt(lastPublicType);
output.putInt(0); // keyStringsOffset. This value can't be computed here.
output.putInt(lastPublicKey);
output.putInt(typeIdOffset);
}
@Override
protected void writePayload(DataOutput output, ByteBuffer header, boolean shrink)
throws IOException {
int typeOffset = typeStringsOffset;
int keyOffset = keyStringsOffset;
int payloadOffset = 0;
for (Chunk chunk : getChunks().values()) {
if (chunk == getTypeStringPool()) {
typeOffset = payloadOffset + getHeaderSize();
} else if (chunk == getKeyStringPool()) {
keyOffset = payloadOffset + getHeaderSize();
}
byte[] chunkBytes = chunk.toByteArray(shrink);
output.write(chunkBytes);
payloadOffset = writePad(output, chunkBytes.length);
}
header.putInt(TYPE_OFFSET_OFFSET, typeOffset);
header.putInt(KEY_OFFSET_OFFSET, keyOffset);
}
}
@@ -0,0 +1,72 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/**
* Provides utility methods for package names.
*/
public final class PackageUtils {
public static final int PACKAGE_NAME_SIZE = 256;
private PackageUtils() {
} // Prevent instantiation
/**
* Reads the package name from the buffer and repositions the buffer to point directly after
* the package name.
*
* @param buffer The buffer containing the package name.
* @param offset The offset in the buffer to read from.
* @return The package name.
*/
public static String readPackageName(ByteBuffer buffer, int offset) {
byte[] data = buffer.array();
int length = 0;
// Look for the null terminator for the string instead of using the entire buffer.
// It's UTF-16 so check 2 bytes at a time to see if its double 0.
for (int i = offset; i < data.length && i < PACKAGE_NAME_SIZE + offset; i += 2) {
if (data[i] == 0 && data[i + 1] == 0) {
length = i - offset;
break;
}
}
Charset utf16 = StandardCharsets.UTF_16LE;
String str = new String(data, offset, length, utf16);
buffer.position(offset + PACKAGE_NAME_SIZE);
return str;
}
/**
* Writes the provided package name to the buffer in UTF-16.
*
* @param buffer The buffer that will be written to.
* @param packageName The package name that will be written to the buffer.
*/
public static void writePackageName(ByteBuffer buffer, String packageName) {
byte[] nameBytes = packageName.getBytes(StandardCharsets.UTF_16LE);
buffer.put(nameBytes, 0, Math.min(nameBytes.length, PACKAGE_NAME_SIZE));
if (nameBytes.length < PACKAGE_NAME_SIZE) {
// pad out the remaining space with an empty array.
buffer.put(new byte[PACKAGE_NAME_SIZE - nameBytes.length]);
}
}
}
@@ -0,0 +1,301 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import com.google.common.base.Preconditions;
import com.google.devrel.gmscore.tools.apk.arsc.ArscBlamer.ResourceEntry;
import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
/**
* Calculates extra information about an {@link ResourceEntry}, such as the total
* APK size the entry is responsible for.
* <p>
* This class is not thread-safe.
*/
public class ResourceEntryStatsCollector {
/**
* The size in bytes of an offset in a chunk.
*/
private static final int OFFSET_SIZE = 4;
/**
* The size in bytes of overhead for styles, if present, in {@link StringPoolChunk}.
*/
private static final int STYLE_OVERHEAD = 8;
/**
* The number of bytes, in addition to the header, that the {@link PackageChunk} has in overhead
* excluding the chunks it contains.
*/
private static final int PACKAGE_CHUNK_OVERHEAD = 8;
private final Map<ResourceEntry, ResourceStatistics> stats = new HashMap<>();
private final ArscBlamer blamer;
private final ResourceTableChunk resourceTable;
/**
* Creates a new {@link ResourceEntryStatsCollector}.
*
* @param blamer The blamer that maps resource entries to what they use.
* @param resourceTable The resource table that {@code blamer} is blamed on.
*/
public ResourceEntryStatsCollector(ArscBlamer blamer, ResourceTableChunk resourceTable) {
this.resourceTable = resourceTable;
this.blamer = blamer;
}
public void compute() throws IOException {
Preconditions.checkState(stats.isEmpty(), "Must only call #compute once.");
blamer.blame();
computeStringPoolSizes();
computePackageSizes();
}
/**
* Returns entries for which there are computed stats. Must first call {@link #compute}.
*/
public Map<ResourceEntry, ResourceStatistics> getStats() {
Preconditions.checkState(!stats.isEmpty(), "Must call #compute() first.");
return Collections.unmodifiableMap(stats);
}
/**
* Returns computed stats for a given entry. Must first call {@link #compute}.
*/
public ResourceStatistics getStats(ResourceEntry entry) {
Preconditions.checkState(!stats.isEmpty(), "Must call #compute() first.");
return stats.containsKey(entry) ? stats.get(entry) : ResourceStatistics.EMPTY;
}
private void computeStringPoolSizes() throws IOException {
computePoolSizes(resourceTable.getStringPool(), blamer.getStringToBlamedResources());
}
private void computePackageSizes() throws IOException {
computeTypePoolSizes();
computeKeyPoolSizes();
computeTypeSpecSizes();
computeTypeChunkSizes();
computePackageChunkSizes();
}
private void computeTypePoolSizes() throws IOException {
for (Entry<PackageChunk, List<ResourceEntry>[]> entry
: blamer.getTypeToBlamedResources().entrySet()) {
computePoolSizes(entry.getKey().getTypeStringPool(), entry.getValue());
}
}
private void computeKeyPoolSizes() throws IOException {
for (Entry<PackageChunk, List<ResourceEntry>[]> entry
: blamer.getKeyToBlamedResources().entrySet()) {
computePoolSizes(entry.getKey().getKeyStringPool(), entry.getValue());
}
}
private void computeTypeSpecSizes() {
for (Entry<PackageChunk, List<ResourceEntry>[]> entry
: blamer.getTypeToBlamedResources().entrySet()) {
computeTypeSpecSizes(entry.getKey(), entry.getValue());
}
}
private void computeTypeChunkSizes() {
for (Entry<TypeChunk.Entry, Collection<ResourceEntry>> entry
: blamer.getTypeEntryToBlamedResources().asMap().entrySet()) {
TypeChunk.Entry chunkEntry = entry.getKey();
TypeChunk typeChunk = chunkEntry.parent();
int size = chunkEntry.size() + OFFSET_SIZE;
int count = typeChunk.getEntries().size();
int nullEntries = typeChunk.getTotalEntryCount() - typeChunk.getEntries().size();
int overhead = typeChunk.getHeaderSize() + nullEntries * OFFSET_SIZE;
addSizes(entry.getValue(), overhead, size, count);
}
}
private void computePackageChunkSizes() {
for (Entry<PackageChunk, Collection<ResourceEntry>> entry
: blamer.getPackageToBlamedResources().asMap().entrySet()) {
int overhead = entry.getKey().getHeaderSize() + PACKAGE_CHUNK_OVERHEAD;
addSizes(entry.getValue(), overhead, 0, 1);
}
}
private void computePoolSizes(StringPoolChunk stringPool,
List<ResourceEntry>[] usages) throws IOException {
int overhead = stringPool.getHeaderSize();
if (stringPool.getStyleCount() > 0) {
overhead += STYLE_OVERHEAD;
}
// We have to iterate over the indices of the string pool, because it is possible that there are
// indices which have *no* associated resource entry (i.e. references from XML files without an
// entry in R).
int count = 0;
for (int i = 0; i < usages.length; ++i) {
if (usages[i].isEmpty()) {
overhead += computeStringAndStyleSize(stringPool, i);
} else {
++count;
}
}
// Now that we know the number of actual entries, we can compute the size.
for (int i = 0; i < usages.length; ++i) {
if (usages[i].isEmpty()) {
continue;
}
int size = computeStringAndStyleSize(stringPool, i);
addSizes(usages[i], overhead, size, count);
}
}
private void computeTypeSpecSizes(PackageChunk packageChunk,
List<ResourceEntry>[] usages) {
for (int i = 0; i < usages.length; ++i) {
// The 1 here is to convert back to a 1-based index.
TypeSpecChunk typeSpec = packageChunk.getTypeSpecChunk(i + 1);
// TypeSpecChunk entries share everything equally.
addSizes(usages[i], typeSpec.getOriginalChunkSize(), 0, 1);
}
}
/**
* Given an {@code index} into a {@code stringPool}, return string's total size in bytes plus its
* style, if any.
*
* @param stringPool The string pool containing the {@code index}.
* @param index The (0-based) index of the string and (optional) style.
* @throws IOException Thrown if the style's length could not be computed.
*/
private int computeStringAndStyleSize(StringPoolChunk stringPool, int index)
throws IOException {
return computeStringSize(stringPool, index) + computeStyleSize(stringPool, index);
}
/**
* Given an {@code index} into a {@code stringPool}, return string's total size in bytes.
*/
private int computeStringSize(StringPoolChunk stringPool, int index) {
String string = stringPool.getString(index);
int result = BinaryResourceString.encodeString(string, stringPool.getStringType()).length;
result += OFFSET_SIZE;
return result;
}
/**
* Given an {@code index} into a {@code stringPool}, return style's total size in bytes or 0 if
* there's no style at that index.
*
* @throws IOException Thrown if the style's length could not be computed.
*/
private int computeStyleSize(StringPoolChunk stringPool, int index) throws IOException {
if (index >= stringPool.getStyleCount()) { // No style at index
return 0;
}
return stringPool.getStyle(index).toByteArray().length + OFFSET_SIZE;
}
/**
* Adds to the {@link #stats} of {@code entries} that reference a value in a chunk the bytes it's
* responsible for. This should only be called once per chunk-value pair.
*
* @param entries The resource entries referencing a single value in a chunk.
* @param overhead The number of bytes of overhead of a chunk. Typically the header size.
* @param size The size in bytes of a value in a chunk that {@code entries} reference.
* @param count The total number of values in the chunk.
*/
private void addSizes(Collection<ResourceEntry> entries, int overhead, int size, int count) {
int usageCount = entries.size();
for (ResourceEntry resourceEntry : entries) {
// TODO(acornwall): Replace with Java 8's #getOrDefault when possible.
if (!stats.containsKey(resourceEntry)) {
stats.put(resourceEntry, new ResourceStatistics());
}
ResourceStatistics resourceStats = stats.get(resourceEntry);
if (usageCount == 1) {
resourceStats.addPrivateSize(size);
} else {
resourceStats.addSharedSize(size);
}
// Special case: If the chunk only has one relevant value, removing this entry will remove the
// entire chunk.
if (usageCount == 1 && count == 1) {
resourceStats.addPrivateSize(overhead);
}
resourceStats.addProportionalSize(size, usageCount);
resourceStats.addProportionalSize(overhead, usageCount * count);
}
}
/**
* Stats for an individual {@link ResourceEntry}.
*/
public static class ResourceStatistics {
/**
* The empty, immutable instance of ResourceStatistics which contains 0 for all values.
*/
public static final ResourceStatistics EMPTY = new ResourceStatistics();
private int privateSize = 0;
private int sharedSize = 0;
private double proportionalSize = 0;
private ResourceStatistics() {
}
/**
* The number of bytes that would be freed if this resource was removed.
*/
public int getPrivateSize() {
return privateSize;
}
/**
* The number of bytes taken up by this resource that are also shared with other resources.
*/
public int getSharedSize() {
return sharedSize;
}
/**
* The total size this resource is responsible for.
*/
public double getProportionalSize() {
return proportionalSize;
}
private void addPrivateSize(int privateSize) {
this.privateSize += privateSize;
}
private void addSharedSize(int sharedSize) {
this.sharedSize += sharedSize;
}
private void addProportionalSize(int numerator, int denominator) {
this.proportionalSize += 1.0 * numerator / denominator;
}
}
}
@@ -0,0 +1,101 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import androidx.annotation.Nullable;
import com.google.common.base.Preconditions;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* Represents a resource table structure. Its sub-chunks contain:
*
* <ul>
* <li>A {@link StringPoolChunk} containing all string values in the entire resource table. It does
* not, however, contain the names of entries or type identifiers.
* <li>One or more {@link PackageChunk}.
* </ul>
*/
public final class ResourceTableChunk extends ChunkWithChunks {
/**
* The packages contained in this resource table.
*/
private final Map<String, PackageChunk> packages = new HashMap<>();
/**
* A string pool containing all string resource values in the entire resource table.
*/
private StringPoolChunk stringPool;
ResourceTableChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
// packageCount. We ignore this, because we already know how many chunks we have.
Preconditions.checkState(buffer.getInt() >= 1, "ResourceTableChunk package count was < 1.");
}
@Override
protected void init(ByteBuffer buffer) {
super.init(buffer);
packages.clear();
for (Chunk chunk : getChunks().values()) {
if (chunk instanceof PackageChunk) {
PackageChunk packageChunk = (PackageChunk) chunk;
packages.put(packageChunk.getPackageName(), packageChunk);
} else if (chunk instanceof StringPoolChunk) {
stringPool = (StringPoolChunk) chunk;
}
}
Preconditions.checkNotNull(stringPool, "ResourceTableChunk must have a string pool.");
}
/**
* Returns the string pool containing all string resource values in the resource table.
*/
public StringPoolChunk getStringPool() {
return stringPool;
}
/**
* Returns the package with the given {@code packageName}. Else, returns null.
*/
@Nullable
public PackageChunk getPackage(String packageName) {
return packages.get(packageName);
}
/**
* Returns the packages contained in this resource table.
*/
public Collection<PackageChunk> getPackages() {
return Collections.unmodifiableCollection(packages.values());
}
@Override
protected Type getType() {
return Type.TABLE;
}
@Override
protected void writeHeader(ByteBuffer output) {
super.writeHeader(output);
output.putInt(packages.size());
}
}
@@ -0,0 +1,43 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import java.io.IOException;
/**
* A resource, typically a @{link Chunk}, that can be converted to an array of bytes.
*/
public interface SerializableResource {
/**
* Converts this resource into an array of bytes representation.
*
* @return An array of bytes representing this resource.
* @throws IOException
*/
byte[] toByteArray() throws IOException;
/**
* Converts this resource into an array of bytes representation.
*
* @param shrink True if, when converting to a byte array, this resource can modify the returned
* bytes in an effort to reduce the size.
* @return An array of bytes representing this resource.
* @throws IOException
*/
byte[] toByteArray(boolean shrink) throws IOException;
}
@@ -0,0 +1,443 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import androidx.annotation.Nullable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.io.LittleEndianDataOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutput;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.*;
/**
* Represents a string pool structure.
*/
public final class StringPoolChunk extends Chunk {
// These are the defined flags for the "flags" field of ResourceStringPoolHeader
private static final int SORTED_FLAG = 1 << 0;
private static final int UTF8_FLAG = 1 << 8;
/**
* The offset from the start of the header that the stylesStart field is at.
*/
private static final int STYLE_START_OFFSET = 24;
/**
* Flags.
*/
private final int flags;
/**
* Index from header of the string data.
*/
private final int stringsStart;
/**
* Index from header of the style data.
*/
private final int stylesStart;
/**
* Number of strings in the original buffer. This is not necessarily the number of strings in
* {@code strings}.
*/
private final int stringCount;
/**
* Number of styles in the original buffer. This is not necessarily the number of styles in
* {@code styles}.
*/
private final int styleCount;
/**
* The strings ordered as they appear in the arsc file. e.g. strings.get(1234) gets the 1235th
* string in the arsc file.
*/
private final List<String> strings = new ArrayList<>();
/**
* These styles have a 1:1 relationship with the strings. For example, styles.get(3) refers to
* the string at location strings.get(3). There are never more styles than strings (though there
* may be less). Inside of that are all of the styles referenced by that string.
*/
private final List<StringPoolStyle> styles = new ArrayList<>();
/**
* True if the original {@link StringPoolChunk} shows signs of being deduped. Specifically, this
* is set to true if there exists a string whose offset is <= the previous offset. This is used to
* preserve the deduping of strings for pools that have been deduped.
*/
private boolean isOriginalDeduped = false;
StringPoolChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
stringCount = buffer.getInt();
styleCount = buffer.getInt();
flags = buffer.getInt();
stringsStart = buffer.getInt();
stylesStart = buffer.getInt();
}
@Override
protected void init(ByteBuffer buffer) {
super.init(buffer);
strings.addAll(readStrings(buffer, offset + stringsStart, stringCount));
styles.addAll(readStyles(buffer, offset + stylesStart, styleCount));
}
/**
* Returns the 0-based index of the first occurrence of the given string, or -1 if the string is
* not in the pool. This runs in O(n) time.
*
* @param string The string to check the pool for.
* @return Index of the string, or -1 if not found.
*/
public int indexOf(String string) {
return strings.indexOf(string);
}
/**
* Returns a string at the given (0-based) index.
*
* @param index The (0-based) index of the string to return.
* @throws IndexOutOfBoundsException If the index is out of range (index < 0 || index >= size()).
*/
public String getString(int index) {
return strings.get(index);
}
public void updateString(int index, String value) {
strings.set(index, value);
}
/**
* Returns the number of strings in this pool.
*/
public int getStringCount() {
return strings.size();
}
/**
* Returns a style at the given (0-based) index.
*
* @param index The (0-based) index of the style to return.
* @throws IndexOutOfBoundsException If the index is out of range (index < 0 || index >= size()).
*/
public StringPoolStyle getStyle(int index) {
return styles.get(index);
}
/**
* Returns the number of styles in this pool.
*/
public int getStyleCount() {
return styles.size();
}
/**
* Returns the type of strings in this pool.
*/
public BinaryResourceString.Type getStringType() {
return isUTF8() ? BinaryResourceString.Type.UTF8 : BinaryResourceString.Type.UTF16;
}
@Override
protected Type getType() {
return Type.STRING_POOL;
}
/**
* Returns the number of bytes needed for offsets based on {@code strings} and {@code styles}.
*/
private int getOffsetSize() {
return (strings.size() + styles.size()) * 4;
}
/**
* True if this string pool contains strings in UTF-8 format. Otherwise, strings are in UTF-16.
*
* @return true if @{code strings} are in UTF-8; false if they're in UTF-16.
*/
public boolean isUTF8() {
return (flags & UTF8_FLAG) != 0;
}
/**
* True if this string pool contains already-sorted strings.
*
* @return true if @{code strings} are sorted.
*/
public boolean isSorted() {
return (flags & SORTED_FLAG) != 0;
}
private List<String> readStrings(ByteBuffer buffer, int offset, int count) {
List<String> result = new ArrayList<>();
int previousOffset = -1;
// After the header, we now have an array of offsets for the strings in this pool.
for (int i = 0; i < count; ++i) {
int stringOffset = offset + buffer.getInt();
result.add(BinaryResourceString.decodeString(buffer, stringOffset, getStringType()));
if (stringOffset <= previousOffset) {
isOriginalDeduped = true;
}
previousOffset = stringOffset;
}
return result;
}
private List<StringPoolStyle> readStyles(ByteBuffer buffer, int offset, int count) {
List<StringPoolStyle> result = new ArrayList<>();
// After the array of offsets for the strings in the pool, we have an offset for the styles
// in this pool.
for (int i = 0; i < count; ++i) {
int styleOffset = offset + buffer.getInt();
result.add(StringPoolStyle.create(buffer, styleOffset, this));
}
return result;
}
private int writeStrings(DataOutput payload, ByteBuffer offsets, boolean shrink)
throws IOException {
int stringOffset = 0;
Map<String, Integer> used = new HashMap<>(); // Keeps track of strings already written
for (String string : strings) {
// Dedupe everything except stylized strings, unless shrink is true (then dedupe everything)
if (used.containsKey(string) && (shrink || isOriginalDeduped)) {
Integer offset = used.get(string);
offsets.putInt(offset == null ? 0 : offset);
} else {
byte[] encodedString = BinaryResourceString.encodeString(string, getStringType());
payload.write(encodedString);
used.put(string, stringOffset);
offsets.putInt(stringOffset);
stringOffset += encodedString.length;
}
}
// ARSC files pad to a 4-byte boundary. We should do so too.
stringOffset = writePad(payload, stringOffset);
return stringOffset;
}
private int writeStyles(DataOutput payload, ByteBuffer offsets, boolean shrink)
throws IOException {
int styleOffset = 0;
if (!styles.isEmpty()) {
Map<StringPoolStyle, Integer> used = new HashMap<>(); // Keeps track of bytes already written
for (StringPoolStyle style : styles) {
if (!used.containsKey(style) || !shrink) {
byte[] encodedStyle = style.toByteArray(shrink);
payload.write(encodedStyle);
used.put(style, styleOffset);
offsets.putInt(styleOffset);
styleOffset += encodedStyle.length;
} else { // contains key and shrink is true
Integer offset = used.get(style);
offsets.putInt(offset == null ? 0 : offset);
}
}
// The end of the spans are terminated with another sentinel value
payload.writeInt(StringPoolStyle.RES_STRING_POOL_SPAN_END);
styleOffset += 4;
// TODO(acornwall): There appears to be an extra SPAN_END here... why?
payload.writeInt(StringPoolStyle.RES_STRING_POOL_SPAN_END);
styleOffset += 4;
styleOffset = writePad(payload, styleOffset);
}
return styleOffset;
}
@Override
protected void writeHeader(ByteBuffer output) {
int stringsStart = getHeaderSize() + getOffsetSize();
output.putInt(strings.size());
output.putInt(styles.size());
output.putInt(flags);
output.putInt(strings.isEmpty() ? 0 : stringsStart);
output.putInt(0); // Placeholder. The styles starting offset cannot be computed at this point.
}
@Override
protected void writePayload(DataOutput output, ByteBuffer header, boolean shrink)
throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int stringOffset = 0;
ByteBuffer offsets = ByteBuffer.allocate(getOffsetSize());
offsets.order(ByteOrder.LITTLE_ENDIAN);
// Write to a temporary payload so we can rearrange this and put the offsets first
try (LittleEndianDataOutputStream payload = new LittleEndianDataOutputStream(baos)) {
stringOffset = writeStrings(payload, offsets, shrink);
writeStyles(payload, offsets, shrink);
}
output.write(offsets.array());
output.write(baos.toByteArray());
if (!styles.isEmpty()) {
header.putInt(STYLE_START_OFFSET, getHeaderSize() + getOffsetSize() + stringOffset);
}
}
/**
* Represents all of the styles for a particular string. The string is determined by its index
* in {@link StringPoolChunk}.
*/
public static class StringPoolStyle implements SerializableResource {
// Styles are a list of integers with 0xFFFFFFFF serving as a sentinel value.
static final int RES_STRING_POOL_SPAN_END = 0xFFFFFFFF;
private final List<StringPoolSpan> spans;
private StringPoolStyle(List<StringPoolSpan> spans) {
this.spans = spans;
}
static StringPoolStyle create(ByteBuffer buffer, int offset, StringPoolChunk parent) {
Builder<StringPoolSpan> spans = ImmutableList.builder();
int nameIndex = buffer.getInt(offset);
while (nameIndex != RES_STRING_POOL_SPAN_END) {
spans.add(StringPoolSpan.create(buffer, offset, parent));
offset += StringPoolSpan.SPAN_LENGTH;
nameIndex = buffer.getInt(offset);
}
return new StringPoolStyle(spans.build());
}
@Override
public byte[] toByteArray() throws IOException {
return toByteArray(false);
}
@Override
public byte[] toByteArray(boolean shrink) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (LittleEndianDataOutputStream payload = new LittleEndianDataOutputStream(baos)) {
for (StringPoolSpan span : spans) {
byte[] encodedSpan = span.toByteArray(shrink);
if (encodedSpan.length != StringPoolSpan.SPAN_LENGTH) {
throw new IllegalStateException("Encountered a span of invalid length.");
}
payload.write(encodedSpan);
}
payload.writeInt(RES_STRING_POOL_SPAN_END);
}
return baos.toByteArray();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
StringPoolStyle that = (StringPoolStyle) o;
return Objects.equals(spans, that.spans);
}
@Override
public int hashCode() {
return Objects.hash(spans);
}
/**
* Returns a brief description of the contents of this style. The representation of this
* information is subject to change, but below is a typical example:
*
* <pre>"StringPoolStyle{spans=[StringPoolSpan{foo, start=0, stop=5}, ...]}"</pre>
*/
@Override
public String toString() {
return String.format("StringPoolStyle{spans=%s}", spans);
}
}
/**
* Represents a styled span associated with a specific string.
*/
private static class StringPoolSpan implements SerializableResource {
static final int SPAN_LENGTH = 12;
private final int nameIndex;
private final int start;
private final int stop;
private final StringPoolChunk parent;
private StringPoolSpan(int nameIndex, int start, int stop, StringPoolChunk parent) {
this.nameIndex = nameIndex;
this.start = start;
this.stop = stop;
this.parent = parent;
}
static StringPoolSpan create(ByteBuffer buffer, int offset, StringPoolChunk parent) {
int nameIndex = buffer.getInt(offset);
int start = buffer.getInt(offset + 4);
int stop = buffer.getInt(offset + 8);
return new StringPoolSpan(nameIndex, start, stop, parent);
}
@Override
public final byte[] toByteArray() {
return toByteArray(false);
}
@Override
public final byte[] toByteArray(boolean shrink) {
ByteBuffer buffer = ByteBuffer.allocate(SPAN_LENGTH).order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(nameIndex);
buffer.putInt(start);
buffer.putInt(stop);
return buffer.array();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
StringPoolSpan that = (StringPoolSpan) o;
return nameIndex == that.nameIndex &&
start == that.start &&
stop == that.stop &&
Objects.equals(parent, that.parent);
}
@Override
public int hashCode() {
return Objects.hash(nameIndex, start, stop, parent);
}
/**
* Returns a brief description of this span. The representation of this information is subject
* to change, but below is a typical example:
*
* <pre>"StringPoolSpan{foo, start=0, stop=5}"</pre>
*/
@Override
public String toString() {
return String.format("StringPoolSpan{%s, start=%d, stop=%d}",
parent.getString(nameIndex), start, stop);
}
}
}
@@ -0,0 +1,520 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import androidx.annotation.Nullable;
import com.google.common.base.Preconditions;
import com.google.common.io.LittleEndianDataOutputStream;
import com.google.common.primitives.UnsignedBytes;
import java.io.ByteArrayOutputStream;
import java.io.DataOutput;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.*;
/**
* Represents a type chunk, which contains the resource values for a specific resource type and
* configuration in a {@link PackageChunk}. The resource values in this chunk correspond to
* the array of type strings in the enclosing {@link PackageChunk}.
*
* <p>A {@link PackageChunk} can have multiple of these chunks for different
* (configuration, resource type) combinations.
*/
public final class TypeChunk extends Chunk {
/**
* The type identifier of the resource type this chunk is holding.
*/
private final int id;
/**
* The number of resources of this type at creation time.
*/
private final int entryCount;
/**
* The offset (from {@code offset}) in the original buffer where {@code entries} start.
*/
private final int entriesStart;
/**
* A sparse list of resource entries defined by this chunk.
*/
private final Map<Integer, Entry> entries = new TreeMap<>();
/**
* The resource configuration that these resource entries correspond to.
*/
private BinaryResourceConfiguration configuration;
TypeChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
id = UnsignedBytes.toInt(buffer.get());
buffer.position(buffer.position() + 3); // Skip 3 bytes for packing
entryCount = buffer.getInt();
entriesStart = buffer.getInt();
configuration = BinaryResourceConfiguration.create(buffer);
}
@Override
protected void init(ByteBuffer buffer) {
int offset = this.offset + entriesStart;
for (int i = 0; i < entryCount; ++i) {
Entry entry = Entry.create(buffer, offset, this);
if (entry != null) {
entries.put(i, entry);
}
}
}
/**
* Returns the (1-based) type id of the resource types that this {@link TypeChunk} is holding.
*/
public int getId() {
return id;
}
/**
* Returns the name of the type this chunk represents (e.g. string, attr, id).
*/
public String getTypeName() {
PackageChunk packageChunk = getPackageChunk();
Preconditions.checkNotNull(packageChunk, "%s has no parent package.", getClass());
StringPoolChunk typePool = packageChunk.getTypeStringPool();
Preconditions.checkNotNull(typePool, "%s's parent package has no type pool.", getClass());
return typePool.getString(getId() - 1); // - 1 here to convert to 0-based index
}
/**
* Returns the resource configuration that these resource entries correspond to.
*/
public BinaryResourceConfiguration getConfiguration() {
return configuration;
}
/**
* Sets the resource configuration that this chunk's entries correspond to.
*
* @param configuration The new configuration.
*/
public void setConfiguration(BinaryResourceConfiguration configuration) {
this.configuration = configuration;
}
/**
* Returns the total number of entries for this type + configuration, including null entries.
*/
public int getTotalEntryCount() {
return entryCount;
}
/**
* Returns a sparse list of 0-based indices to resource entries defined by this chunk.
*/
public Map<Integer, Entry> getEntries() {
return Collections.unmodifiableMap(entries);
}
/**
* Returns true if this chunk contains an entry for {@code resourceId}.
*/
public boolean containsResource(BinaryResourceIdentifier resourceId) {
PackageChunk packageChunk = Preconditions.checkNotNull(getPackageChunk());
int packageId = packageChunk.getId();
int typeId = getId();
return resourceId.packageId() == packageId
&& resourceId.typeId() == typeId
&& entries.containsKey(resourceId.entryId());
}
/**
* Overrides the entries in this chunk at the given index:entry pairs in {@code entries}.
* For example, if the current list of entries is {0: foo, 1: bar, 2: baz}, and {@code entries}
* is {1: qux, 3: quux}, then the entries will be changed to {0: foo, 1: qux, 2: baz}. If an entry
* has an index that does not exist in the dense entry list, then it is considered a no-op for
* that single entry.
*
* @param entries A sparse list containing index:entry pairs to override.
*/
public void overrideEntries(Map<Integer, Entry> entries) {
for (Map.Entry<Integer, Entry> entry : entries.entrySet()) {
int index = entry.getKey() != null ? entry.getKey() : -1;
overrideEntry(index, entry.getValue());
}
}
/**
* Overrides an entry at the given index. Passing null for the {@code entry} will remove that
* entry from {@code entries}. Indices < 0 or >= {@link #getTotalEntryCount()} are a no-op.
*
* @param index The 0-based index for the entry to override.
* @param entry The entry to override, or null if the entry should be removed at this location.
*/
public void overrideEntry(int index, @Nullable Entry entry) {
if (index >= 0 && index < entryCount) {
if (entry != null) {
entries.put(index, entry);
} else {
entries.remove(index);
}
}
}
private String getString(int index) {
ResourceTableChunk resourceTable = getResourceTableChunk();
Preconditions.checkNotNull(resourceTable, "%s has no resource table.", getClass());
return resourceTable.getStringPool().getString(index);
}
private String getKeyName(int index) {
PackageChunk packageChunk = getPackageChunk();
Preconditions.checkNotNull(packageChunk, "%s has no parent package.", getClass());
StringPoolChunk keyPool = packageChunk.getKeyStringPool();
Preconditions.checkNotNull(keyPool, "%s's parent package has no key pool.", getClass());
return keyPool.getString(index);
}
private void updateKey(int index, String value) {
PackageChunk packageChunk = getPackageChunk();
Preconditions.checkNotNull(packageChunk, "%s has no parent package.", getClass());
StringPoolChunk keyPool = packageChunk.getKeyStringPool();
Preconditions.checkNotNull(keyPool, "%s's parent package has no key pool.", getClass());
keyPool.updateString(index, value);
}
@Nullable
private ResourceTableChunk getResourceTableChunk() {
Chunk chunk = getParent();
while (chunk != null && !(chunk instanceof ResourceTableChunk)) {
chunk = chunk.getParent();
}
return chunk != null ? (ResourceTableChunk) chunk : null;
}
/**
* Returns the package enclosing this chunk, if any. Else, returns null.
*/
@Nullable
public PackageChunk getPackageChunk() {
Chunk chunk = getParent();
while (chunk != null && !(chunk instanceof PackageChunk)) {
chunk = chunk.getParent();
}
return chunk != null ? (PackageChunk) chunk : null;
}
@Override
protected Type getType() {
return Type.TABLE_TYPE;
}
/**
* Returns the number of bytes needed for offsets based on {@code entries}.
*/
private int getOffsetSize() {
return entryCount * 4;
}
private int writeEntries(DataOutput payload, ByteBuffer offsets, boolean shrink)
throws IOException {
int entryOffset = 0;
for (int i = 0; i < entryCount; ++i) {
Entry entry = entries.get(i);
if (entry == null) {
offsets.putInt(Entry.NO_ENTRY);
} else {
byte[] encodedEntry = entry.toByteArray(shrink);
payload.write(encodedEntry);
offsets.putInt(entryOffset);
entryOffset += encodedEntry.length;
}
}
entryOffset = writePad(payload, entryOffset);
return entryOffset;
}
@Override
protected void writeHeader(ByteBuffer output) {
int entriesStart = getHeaderSize() + getOffsetSize();
output.putInt(id); // Write an unsigned byte with 3 bytes padding
output.putInt(entryCount);
output.putInt(entriesStart);
output.put(configuration.toByteArray(false));
}
@Override
protected void writePayload(DataOutput output, ByteBuffer header, boolean shrink)
throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ByteBuffer offsets = ByteBuffer.allocate(getOffsetSize()).order(ByteOrder.LITTLE_ENDIAN);
try (LittleEndianDataOutputStream payload = new LittleEndianDataOutputStream(baos)) {
writeEntries(payload, offsets, shrink);
}
output.write(offsets.array());
output.write(baos.toByteArray());
}
/**
* An {@link Entry} in a {@link TypeChunk}. Contains one or more {@link BinaryResourceValue}.
*/
public static class Entry implements SerializableResource {
/**
* An entry offset that indicates that a given resource is not present.
*/
public static final int NO_ENTRY = 0xFFFFFFFF;
/**
* Set if this is a complex resource. Otherwise, it's a simple resource.
*/
private static final int FLAG_COMPLEX = 0x0001;
/**
* Size of a single resource id + value mapping entry.
*/
private static final int MAPPING_SIZE = 4 + BinaryResourceValue.SIZE;
private final int headerSize;
private final int flags;
private final int keyIndex;
private final int parentEntry;
private final TypeChunk parent;
private BinaryResourceValue value;
private final Map<Integer, BinaryResourceValue> values;
private Entry(int headerSize,
int flags,
int keyIndex,
BinaryResourceValue value,
Map<Integer, BinaryResourceValue> values,
int parentEntry,
TypeChunk parent) {
this.headerSize = headerSize;
this.flags = flags;
this.keyIndex = keyIndex;
this.value = value;
this.values = values;
this.parentEntry = parentEntry;
this.parent = parent;
}
/**
* Creates a new {@link Entry} whose contents start at the 0-based position in
* {@code buffer} given by a 4-byte value read from {@code buffer} and then added to
* {@code baseOffset}. If the value read from {@code buffer} is equal to {@link #NO_ENTRY}, then
* null is returned as there is no resource at that position.
*
* <p>Otherwise, this position is parsed and returned as an {@link Entry}.
*
* @param buffer A buffer positioned at an offset to an {@link Entry}.
* @param baseOffset Offset that must be added to the value at {@code buffer}'s position.
* @param parent The {@link TypeChunk} that this resource entry belongs to.
* @return New {@link Entry} or null if there is no resource at this location.
*/
@Nullable
public static Entry create(ByteBuffer buffer, int baseOffset, TypeChunk parent) {
int offset = buffer.getInt();
if (offset == NO_ENTRY) {
return null;
}
int position = buffer.position();
buffer.position(baseOffset + offset); // Set buffer position to resource entry start
Entry result = newInstance(buffer, parent);
buffer.position(position); // Restore buffer position
return result;
}
@Nullable
private static Entry newInstance(ByteBuffer buffer, TypeChunk parent) {
int headerSize = buffer.getShort() & 0xFFFF;
int flags = buffer.getShort() & 0xFFFF;
int keyIndex = buffer.getInt();
BinaryResourceValue value = null;
Map<Integer, BinaryResourceValue> values = new LinkedHashMap<>();
int parentEntry = 0;
if ((flags & FLAG_COMPLEX) != 0) {
parentEntry = buffer.getInt();
int valueCount = buffer.getInt();
for (int i = 0; i < valueCount; ++i) {
values.put(buffer.getInt(), BinaryResourceValue.create(buffer));
}
} else {
value = BinaryResourceValue.create(buffer);
}
return new Entry(headerSize, flags, keyIndex, value, values, parentEntry, parent);
}
/**
* Number of bytes in the header of the {@link Entry}.
*/
public int headerSize() {
return headerSize;
}
/**
* Resource entry flags.
*/
public int flags() {
return flags;
}
/**
* Index into {@link PackageChunk#getKeyStringPool} identifying this entry.
*/
public int keyIndex() {
return keyIndex;
}
/**
* The value of this resource entry, if this is not a complex entry. Else, null.
*/
@Nullable
public BinaryResourceValue value() {
return value;
}
/**
* Update the value of this resource entry
*
* @param value
*/
public void updateValue(@Nullable BinaryResourceValue value) {
this.value = value;
}
/**
* The extra values in this resource entry if this {@link #isComplex}.
*/
public Map<Integer, BinaryResourceValue> values() {
return values;
}
/**
* Update the value in this resource entry if this {@link #isComplex}.
*/
public void updateValue(int index, BinaryResourceValue value) {
if (index >= 0) {
if (value != null) {
values.put(index, value);
} else {
values.remove(index);
}
}
}
/**
* Entry into {@link PackageChunk} that is the parent {@link Entry} to this entry.
* This value only makes sense when this is complex ({@link #isComplex} returns true).
*/
public int parentEntry() {
return parentEntry;
}
/**
* The {@link TypeChunk} that this resource entry belongs to.
*/
public TypeChunk parent() {
return parent;
}
/**
* Returns the name of the type this chunk represents (e.g. string, attr, id).
*/
public final String typeName() {
return parent().getTypeName();
}
/**
* The total number of bytes that this {@link Entry} takes up.
*/
public final int size() {
return headerSize() + (isComplex() ? values().size() * MAPPING_SIZE : BinaryResourceValue.SIZE);
}
/**
* Returns the key name identifying this resource entry.
*/
public final String key() {
return parent().getKeyName(keyIndex());
}
/**
* Update the key name in this resource entry.
*/
public final void updateKey(int keyIndex, String value) {
parent().updateKey(keyIndex, value);
}
/**
* Returns true if this is a complex resource.
*/
public final boolean isComplex() {
return (flags() & FLAG_COMPLEX) != 0;
}
@Override
public final byte[] toByteArray() {
return toByteArray(false);
}
@Override
public final byte[] toByteArray(boolean shrink) {
ByteBuffer buffer = ByteBuffer.allocate(size());
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putShort((short) headerSize());
buffer.putShort((short) flags());
buffer.putInt(keyIndex());
if (isComplex()) {
buffer.putInt(parentEntry());
buffer.putInt(values().size());
for (Map.Entry<Integer, BinaryResourceValue> entry : values().entrySet()) {
buffer.putInt(entry.getKey());
buffer.put(entry.getValue().toByteArray(shrink));
}
} else {
BinaryResourceValue value = value();
Preconditions.checkNotNull(value, "A non-complex TypeChunk entry must have a value.");
buffer.put(value.toByteArray());
}
return buffer.array();
}
@Override
public final String toString() {
return String.format("Entry{key=%s}", key());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Entry entry = (Entry) o;
return headerSize == entry.headerSize &&
flags == entry.flags &&
keyIndex == entry.keyIndex &&
parentEntry == entry.parentEntry &&
Objects.equals(value, entry.value) &&
Objects.equals(values, entry.values) &&
Objects.equals(parent, entry.parent);
}
@Override
public int hashCode() {
return Objects.hash(headerSize, flags, keyIndex, value, values, parentEntry, parent);
}
}
}
@@ -0,0 +1,113 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import androidx.annotation.Nullable;
import com.google.common.base.Preconditions;
import com.google.common.primitives.UnsignedBytes;
import java.io.DataOutput;
import java.io.IOException;
import java.nio.ByteBuffer;
/**
* A chunk that contains a collection of resource entries for a particular resource data type.
*/
public final class TypeSpecChunk extends Chunk {
/**
* The id of the resource type that this type spec refers to.
*/
private final int id;
/**
* Resource configuration masks.
*/
private final int[] resources;
TypeSpecChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
id = UnsignedBytes.toInt(buffer.get());
buffer.position(buffer.position() + 3); // Skip 3 bytes for packing
int resourceCount = buffer.getInt();
resources = new int[resourceCount];
for (int i = 0; i < resourceCount; ++i) {
resources[i] = buffer.getInt();
}
}
/**
* Returns the (1-based) type id of the resources that this {@link TypeSpecChunk} has
* configuration masks for.
*/
public int getId() {
return id;
}
/**
* Returns the number of resource entries that this chunk has configuration masks for.
*/
public int getResourceCount() {
return resources.length;
}
@Override
protected Type getType() {
return Type.TABLE_TYPE_SPEC;
}
/**
* Returns the name of the type this chunk represents (e.g. string, attr, id).
*/
public String getTypeName() {
PackageChunk packageChunk = getPackageChunk();
Preconditions.checkNotNull(packageChunk, "%s has no parent package.", getClass());
StringPoolChunk typePool = packageChunk.getTypeStringPool();
Preconditions.checkNotNull(typePool, "%s's parent package has no type pool.", getClass());
return typePool.getString(getId() - 1); // - 1 here to convert to 0-based index
}
/**
* Returns the package enclosing this chunk, if any. Else, returns null.
*/
@Nullable
private PackageChunk getPackageChunk() {
Chunk chunk = getParent();
while (chunk != null && !(chunk instanceof PackageChunk)) {
chunk = chunk.getParent();
}
return chunk != null ? (PackageChunk) chunk : null;
}
@Override
protected void writeHeader(ByteBuffer output) {
super.writeHeader(output);
// id is an unsigned byte in the range [0-255]. It is guaranteed to be non-negative.
// Because our output is in little-endian, we are making use of the 4 byte packing here
output.putInt(id);
output.putInt(resources.length);
}
@Override
protected void writePayload(DataOutput output, ByteBuffer header, boolean shrink)
throws IOException {
for (int resource : resources) {
output.writeInt(resource);
}
}
}
@@ -0,0 +1,62 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import androidx.annotation.Nullable;
import java.io.DataOutput;
import java.io.IOException;
import java.nio.ByteBuffer;
/**
* A chunk whose contents are unknown. This is a placeholder until we add a proper chunk for the
* unknown type.
*/
public final class UnknownChunk extends Chunk {
private final Type type;
private final byte[] header;
private final byte[] payload;
UnknownChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
type = Type.fromCode(buffer.getShort(offset));
header = new byte[headerSize - Chunk.METADATA_SIZE];
payload = new byte[chunkSize - headerSize];
buffer.get(header);
buffer.get(payload);
}
@Override
protected void writeHeader(ByteBuffer output) {
output.put(header);
}
@Override
protected void writePayload(DataOutput output, ByteBuffer header, boolean shrink)
throws IOException {
output.write(payload);
}
@Override
protected Type getType() {
return type;
}
}
@@ -0,0 +1,168 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Objects;
/**
* Represents an XML attribute and value.
*/
public class XmlAttribute implements SerializableResource {
/**
* The serialized size in bytes of an {@link XmlAttribute}.
*/
public static final int SIZE = 12 + BinaryResourceValue.SIZE;
private final int namespaceIndex;
private final int nameIndex;
private final int rawValueIndex;
private final BinaryResourceValue typedValue;
private final XmlNodeChunk parent;
private XmlAttribute(int namespaceIndex,
int nameIndex,
int rawValueIndex,
BinaryResourceValue typedValue,
XmlNodeChunk parent) {
this.namespaceIndex = namespaceIndex;
this.nameIndex = nameIndex;
this.rawValueIndex = rawValueIndex;
this.typedValue = typedValue;
this.parent = parent;
}
/**
* Creates a new {@link XmlAttribute} based on the bytes at the current {@code buffer} position.
*
* @param buffer A buffer whose position is at the start of a {@link XmlAttribute}.
* @param parent The parent chunk that contains this attribute; used for string lookups.
*/
public static XmlAttribute create(ByteBuffer buffer, XmlNodeChunk parent) {
int namespace = buffer.getInt();
int name = buffer.getInt();
int rawValue = buffer.getInt();
BinaryResourceValue typedValue = BinaryResourceValue.create(buffer);
return new XmlAttribute(namespace, name, rawValue, typedValue, parent);
}
/**
* A string reference to the namespace URI, or -1 if not present.
*/
public int namespaceIndex() {
return namespaceIndex;
}
/**
* A string reference to the attribute name.
*/
public int nameIndex() {
return nameIndex;
}
/**
* A string reference to a string containing the character value.
*/
public int rawValueIndex() {
return rawValueIndex;
}
/**
* A {@link BinaryResourceValue} instance containing the parsed value.
*/
public BinaryResourceValue typedValue() {
return typedValue;
}
/**
* The parent of this XML attribute; used for dereferencing the namespace and name.
*/
public XmlNodeChunk parent() {
return parent;
}
/**
* The namespace URI, or the empty string if not present.
*/
public final String namespace() {
return getString(namespaceIndex());
}
/**
* The attribute name, or the empty string if not present.
*/
public final String name() {
return getString(nameIndex());
}
/**
* The raw character value.
*/
public final String rawValue() {
return getString(rawValueIndex());
}
private String getString(int index) {
return parent().getString(index);
}
@Override
public byte[] toByteArray() {
return toByteArray(false);
}
@Override
public byte[] toByteArray(boolean shrink) {
ByteBuffer buffer = ByteBuffer.allocate(SIZE).order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(namespaceIndex());
buffer.putInt(nameIndex());
buffer.putInt(rawValueIndex());
buffer.put(typedValue().toByteArray(shrink));
return buffer.array();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
XmlAttribute that = (XmlAttribute) o;
return namespaceIndex == that.namespaceIndex &&
nameIndex == that.nameIndex &&
rawValueIndex == that.rawValueIndex &&
Objects.equals(typedValue, that.typedValue) &&
Objects.equals(parent, that.parent);
}
@Override
public int hashCode() {
return Objects.hash(namespaceIndex, nameIndex, rawValueIndex, typedValue, parent);
}
/**
* Returns a brief description of this XML attribute. The representation of this information is
* subject to change, but below is a typical example:
*
* <pre>"XmlAttribute{namespace=foo, name=bar, value=1234}"</pre>
*/
@Override
public String toString() {
return String.format("XmlAttribute{namespace=%s, name=%s, value=%s}",
namespace(), name(), rawValue());
}
}
@@ -0,0 +1,84 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import androidx.annotation.Nullable;
import java.io.DataOutput;
import java.io.IOException;
import java.nio.ByteBuffer;
/**
* Represents an XML cdata node.
*/
public final class XmlCdataChunk extends XmlNodeChunk {
/**
* A string reference to a string containing the raw character data.
*/
private final int rawValue;
/**
* A {@link BinaryResourceValue} instance containing the parsed value.
*/
private final BinaryResourceValue binaryResourceValue;
XmlCdataChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
rawValue = buffer.getInt();
binaryResourceValue = BinaryResourceValue.create(buffer);
}
/**
* Returns a string containing the raw character data of this chunk.
*/
public String getRawValue() {
return getString(rawValue);
}
/**
* Returns a {@link BinaryResourceValue} instance containing the parsed cdata value.
*/
public BinaryResourceValue getResourceValue() {
return binaryResourceValue;
}
@Override
protected Type getType() {
return Type.XML_CDATA;
}
@Override
protected void writePayload(DataOutput output, ByteBuffer header, boolean shrink)
throws IOException {
super.writePayload(output, header, shrink);
output.writeInt(rawValue);
output.write(binaryResourceValue.toByteArray());
}
/**
* Returns a brief description of this XML node. The representation of this information is
* subject to change, but below is a typical example:
*
* <pre>"XmlCdataChunk{line=1234, comment=My awesome comment., value=1234}"</pre>
*/
@Override
public String toString() {
return String.format("XmlCdataChunk{line=%d, comment=%s, value=%s}",
getLineNumber(), getComment(), getRawValue());
}
}
@@ -0,0 +1,51 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import androidx.annotation.Nullable;
import java.nio.ByteBuffer;
/**
* Represents an XML chunk structure.
*
* <p>An XML chunk can contain many nodes as well as a string pool which contains all of the strings
* referenced by the nodes.
*/
public final class XmlChunk extends ChunkWithChunks {
XmlChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
}
@Override
protected Type getType() {
return Type.XML;
}
/**
* Returns a string at the provided (0-based) index if the index exists in the string pool.
*/
public String getString(int index) {
for (Chunk chunk : getChunks().values()) {
if (chunk instanceof StringPoolChunk) {
return ((StringPoolChunk) chunk).getString(index);
}
}
throw new IllegalStateException("XmlChunk did not contain a string pool.");
}
}
@@ -0,0 +1,86 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import androidx.annotation.Nullable;
import java.io.DataOutput;
import java.io.IOException;
import java.nio.ByteBuffer;
/**
* Represents the end of an XML node.
*/
public final class XmlEndElementChunk extends XmlNodeChunk {
/**
* A string reference to the namespace URI, or -1 if not present.
*/
private final int namespace;
/**
* A string reference to the attribute name.
*/
private final int name;
XmlEndElementChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
namespace = buffer.getInt();
name = buffer.getInt();
}
/**
* Returns the namespace URI, or the empty string if no namespace is present.
*/
public String getNamespace() {
return getString(namespace);
}
/**
* Returns the attribute name.
*/
public String getName() {
return getString(name);
}
@Override
protected Type getType() {
return Type.XML_END_ELEMENT;
}
@Override
protected void writePayload(DataOutput output, ByteBuffer header, boolean shrink)
throws IOException {
super.writePayload(output, header, shrink);
output.writeInt(namespace);
output.writeInt(name);
}
/**
* Returns a brief description of this XML node. The representation of this information is
* subject to change, but below is a typical example:
*
* <pre>
* "XmlEndElementChunk{line=1234, comment=My awesome comment., namespace=foo, name=bar}"
* </pre>
*/
@Override
public String toString() {
return String.format("XmlEndElementChunk{line=%d, comment=%s, namespace=%s, name=%s}",
getLineNumber(), getComment(), getNamespace(), getName());
}
}
@@ -0,0 +1,81 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import androidx.annotation.Nullable;
import java.io.DataOutput;
import java.io.IOException;
import java.nio.ByteBuffer;
/**
* Represents the start/end of a namespace in an XML document.
*/
public abstract class XmlNamespaceChunk extends XmlNodeChunk {
/**
* A string reference to the namespace prefix.
*/
private final int prefix;
/**
* A string reference to the namespace URI.
*/
private final int uri;
protected XmlNamespaceChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
prefix = buffer.getInt();
uri = buffer.getInt();
}
/**
* Returns the namespace prefix.
*/
public String getPrefix() {
return getString(prefix);
}
/**
* Returns the namespace URI.
*/
public String getUri() {
return getString(uri);
}
@Override
protected void writePayload(DataOutput output, ByteBuffer header, boolean shrink)
throws IOException {
super.writePayload(output, header, shrink);
output.writeInt(prefix);
output.writeInt(uri);
}
/**
* Returns a brief description of this namespace chunk. The representation of this information is
* subject to change, but below is a typical example:
*
* <pre>
* "XmlNamespaceChunk{line=1234, comment=My awesome comment., prefix=foo, uri=com.google.foo}"
* </pre>
*/
@Override
public String toString() {
return String.format("XmlNamespaceChunk{line=%d, comment=%s, prefix=%s, uri=%s}",
getLineNumber(), getComment(), getPrefix(), getUri());
}
}
@@ -0,0 +1,36 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import androidx.annotation.Nullable;
import java.nio.ByteBuffer;
/**
* Represents the ending tag of a namespace in an XML document.
*/
public final class XmlNamespaceEndChunk extends XmlNamespaceChunk {
XmlNamespaceEndChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
}
@Override
protected Type getType() {
return Type.XML_END_NAMESPACE;
}
}
@@ -0,0 +1,36 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import androidx.annotation.Nullable;
import java.nio.ByteBuffer;
/**
* Represents the starting tag of a namespace in an XML document.
*/
public final class XmlNamespaceStartChunk extends XmlNamespaceChunk {
XmlNamespaceStartChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
}
@Override
protected Type getType() {
return Type.XML_START_NAMESPACE;
}
}
@@ -0,0 +1,109 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import androidx.annotation.Nullable;
import java.nio.ByteBuffer;
/**
* The common superclass for the various types of XML nodes.
*/
public abstract class XmlNodeChunk extends Chunk {
/**
* The line number in the original source at which this node appeared.
*/
private final int lineNumber;
/**
* A string reference of this node's comment. If this is -1, then there is no comment.
*/
private final int comment;
protected XmlNodeChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
lineNumber = buffer.getInt();
comment = buffer.getInt();
}
/**
* Returns true if this XML node contains a comment. Else, returns false.
*/
public boolean hasComment() {
return comment != -1;
}
/**
* Returns the line number in the original source at which this node appeared.
*/
public int getLineNumber() {
return lineNumber;
}
/**
* Returns the comment associated with this node, if any. Else, returns the empty string.
*/
public String getComment() {
return getString(comment);
}
/**
* An {@link XmlNodeChunk} does not know by itself what strings its indices reference. In order
* to get the actual string, the first {@link XmlChunk} ancestor is found. The
* {@link XmlChunk} ancestor should have a string pool which {@code index} references.
*
* @param index The index of the string.
* @return String that the given {@code index} references, or empty string if {@code index} is -1.
*/
protected String getString(int index) {
if (index == -1) { // Special case. Packed XML files use -1 for "no string entry"
return "";
}
Chunk parent = getParent();
while (parent != null) {
if (parent instanceof XmlChunk) {
return ((XmlChunk) parent).getString(index);
}
parent = parent.getParent();
}
throw new IllegalStateException("XmlNodeChunk did not have an XmlChunk parent.");
}
/**
* An {@link XmlNodeChunk} and anything that is itself an {@link XmlNodeChunk} has a header size
* of 16. Anything else is, interestingly, considered to be a payload. For that reason, this
* method is final.
*/
@Override
protected final void writeHeader(ByteBuffer output) {
super.writeHeader(output);
output.putInt(lineNumber);
output.putInt(comment);
}
/**
* Returns a brief description of this XML node. The representation of this information is
* subject to change, but below is a typical example:
*
* <pre>"XmlNodeChunk{line=1234, comment=My awesome comment.}"</pre>
*/
@Override
public String toString() {
return String.format("XmlNodeChunk{line=%d, comment=%s}", getLineNumber(), getComment());
}
}
@@ -0,0 +1,91 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import androidx.annotation.Nullable;
import java.io.DataOutput;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
/**
* Represents an XML resource map chunk.
*
* <p>This chunk maps attribute ids to the resource ids of the attribute resource that defines the
* attribute (e.g. type, enum values, etc.).
*/
public class XmlResourceMapChunk extends Chunk {
/**
* The size of a resource reference for {@code resources} in bytes.
*/
private static final int RESOURCE_SIZE = 4;
/**
* Contains a mapping of attributeID to resourceID. For example, the attributeID 2 refers to the
* resourceID returned by {@code resources.get(2)}.
*/
private final List<Integer> resources = new ArrayList<>();
protected XmlResourceMapChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
}
@Override
protected void init(ByteBuffer buffer) {
super.init(buffer);
resources.addAll(enumerateResources(buffer));
}
private List<Integer> enumerateResources(ByteBuffer buffer) {
int resourceCount = (getOriginalChunkSize() - getHeaderSize()) / RESOURCE_SIZE;
List<Integer> result = new ArrayList<>(resourceCount);
int offset = this.offset + getHeaderSize();
buffer.mark();
buffer.position(offset);
for (int i = 0; i < resourceCount; ++i) {
result.add(buffer.getInt());
}
buffer.reset();
return result;
}
/**
* Returns the resource ID that this {@code attributeId} maps to.
*/
public BinaryResourceIdentifier getResourceId(int attributeId) {
return BinaryResourceIdentifier.create(resources.get(attributeId));
}
@Override
protected Type getType() {
return Type.XML_RESOURCE_MAP;
}
@Override
protected void writePayload(DataOutput output, ByteBuffer header, boolean shrink)
throws IOException {
super.writePayload(output, header, shrink);
for (Integer resource : resources) {
output.writeInt(resource);
}
}
}
@@ -0,0 +1,169 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devrel.gmscore.tools.apk.arsc;
import androidx.annotation.Nullable;
import com.google.common.base.Preconditions;
import java.io.DataOutput;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Represents the beginning of an XML node.
*/
public final class XmlStartElementChunk extends XmlNodeChunk {
/**
* A string reference to the namespace URI, or -1 if not present.
*/
private final int namespace;
/**
* A string reference to the element name that this chunk represents.
*/
private final int name;
/**
* The offset to the start of the attributes payload.
*/
private final int attributeStart;
/**
* The number of attributes in the original buffer.
*/
private final int attributeCount;
/**
* The (0-based) index of the id attribute, or -1 if not present.
*/
private final int idIndex;
/**
* The (0-based) index of the class attribute, or -1 if not present.
*/
private final int classIndex;
/**
* The (0-based) index of the style attribute, or -1 if not present.
*/
private final int styleIndex;
/**
* The XML attributes associated with this element.
*/
private final List<XmlAttribute> attributes = new ArrayList<>();
XmlStartElementChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
namespace = buffer.getInt();
name = buffer.getInt();
attributeStart = (buffer.getShort() & 0xFFFF);
int attributeSize = (buffer.getShort() & 0xFFFF);
Preconditions.checkState(attributeSize == XmlAttribute.SIZE,
"attributeSize is wrong size. Got %s, want %s", attributeSize, XmlAttribute.SIZE);
attributeCount = (buffer.getShort() & 0xFFFF);
// The following indices are 1-based and need to be adjusted.
idIndex = (buffer.getShort() & 0xFFFF) - 1;
classIndex = (buffer.getShort() & 0xFFFF) - 1;
styleIndex = (buffer.getShort() & 0xFFFF) - 1;
}
@Override
protected void init(ByteBuffer buffer) {
super.init(buffer);
attributes.addAll(enumerateAttributes(buffer));
}
private List<XmlAttribute> enumerateAttributes(ByteBuffer buffer) {
List<XmlAttribute> result = new ArrayList<>(attributeCount);
int offset = this.offset + getHeaderSize() + attributeStart;
int endOffset = offset + XmlAttribute.SIZE * attributeCount;
buffer.mark();
buffer.position(offset);
while (offset < endOffset) {
result.add(XmlAttribute.create(buffer, this));
offset += XmlAttribute.SIZE;
}
buffer.reset();
return result;
}
/**
* Returns the namespace URI, or the empty string if not present.
*/
public String getNamespace() {
return getString(namespace);
}
/**
* Returns the element name that this chunk represents.
*/
public String getName() {
return getString(name);
}
/**
* Returns an unmodifiable list of this XML element's attributes.
*/
public List<XmlAttribute> getAttributes() {
return Collections.unmodifiableList(attributes);
}
@Override
protected Type getType() {
return Type.XML_START_ELEMENT;
}
@Override
protected void writePayload(DataOutput output, ByteBuffer header, boolean shrink)
throws IOException {
super.writePayload(output, header, shrink);
output.writeInt(namespace);
output.writeInt(name);
output.writeShort((short) XmlAttribute.SIZE); // attribute start
output.writeShort((short) XmlAttribute.SIZE);
output.writeShort((short) attributes.size());
output.writeShort((short) (idIndex + 1));
output.writeShort((short) (classIndex + 1));
output.writeShort((short) (styleIndex + 1));
for (XmlAttribute attribute : attributes) {
output.write(attribute.toByteArray(shrink));
}
}
/**
* Returns a brief description of this XML node. The representation of this information is
* subject to change, but below is a typical example:
*
* <pre>
* "XmlStartElementChunk{line=1234, comment=My awesome comment., namespace=foo, name=bar, ...}"
* </pre>
*/
@Override
public String toString() {
return String.format(
"XmlStartElementChunk{line=%d, comment=%s, namespace=%s, name=%s, attributes=%s}",
getLineNumber(), getComment(), getNamespace(), getName(), attributes.toString());
}
}
@@ -0,0 +1,77 @@
package com.vk.api.audio;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import com.vk.api.base.ApiRequest;
import com.vk.dto.music.MusicTrack;
import com.vk.log.L;
import org.json.JSONObject;
import ru.vtosters.hooks.other.Preferences;
import ru.vtosters.lite.music.Genius;
import ru.vtosters.lite.utils.AndroidUtils;
import java.util.ArrayList;
public class AudioGetLyrics extends ApiRequest<AudioGetLyrics.a> {
private final MusicTrack musicTrack;
public AudioGetLyrics(int lyrics_id, String audio_id, MusicTrack mt) {
super("audio.getLyrics");
c("audio_id", audio_id);
musicTrack = mt;
}
/* renamed from: a */
public a a(@NonNull JSONObject jSONObject) {
var aVar = new a();
if (Preferences.getBoolValue("useGenius", false) && !Preferences.serverFeaturesDisable()) {
aVar.a = Genius.getTextMusic(musicTrack);
return aVar;
}
try {
var lines = new ArrayList<>();
var lyrics = jSONObject.getJSONObject("response").getJSONObject("lyrics");
if (lyrics.has("timestamps")) {
var timestamps = lyrics.getJSONArray("timestamps");
for (int i = 0; i < timestamps.length(); i++) {
var timestamp = timestamps.getJSONObject(i);
if (timestamp.has("line")) {
lines.add(timestamp.getString("line"));
}
if (timestamp.optString("interlude").length() > 0) {
lines.add("♪");
}
}
aVar.a = TextUtils.join("\n", lines);
} else if (lyrics.has("text")) {
var text = lyrics.getJSONArray("text");
for (int i = 0; i < text.length(); i++) {
lines.add(text.getString(i));
}
aVar.a = TextUtils.join("\n", lines);
} else {
L.e("vk", "No text found");
aVar.a = "No text found";
}
return aVar;
} catch (Exception e) {
L.e("vk", e);
aVar.a = AndroidUtils.getString("failed_to_get_text") + "\n\n" + AndroidUtils.getString("error") + ": \n" + e.getLocalizedMessage();
return aVar;
}
}
public static class a {
public String a;
}
}
@@ -1,24 +1,12 @@
package com.vk.api.gifts;
import android.content.Context;
import com.vk.api.base.ApiRequest;
import com.vk.dto.gift.CatalogedGift;
import org.json.JSONException;
import org.json.JSONObject;
public class GiftGetByStickerId extends ApiRequest<GiftGetByStickerId.a> {
public static class a {
public final int a;
public final CatalogedGift b;
public a(int i, CatalogedGift catalogedGift) {
this.a = i;
this.b = catalogedGift;
}
}
public GiftGetByStickerId(Context context, int i) {
super("execute.getGiftByStickerId");
b("sticker_id", i);
@@ -29,7 +17,17 @@ public class GiftGetByStickerId extends ApiRequest<GiftGetByStickerId.a> {
@Override // com.vk.api.sdk.o.VKRequest
public GiftGetByStickerId.a a(JSONObject jSONObject) throws JSONException {
JSONObject jSONObject2 = jSONObject.getJSONObject("response");
return new a(jSONObject2.optInt("balance"),
return new a(jSONObject2.optInt("balance"),
new CatalogedGift(jSONObject2.getJSONObject("gift")));
}
public static class a {
public final int a;
public final CatalogedGift b;
public a(int i, CatalogedGift catalogedGift) {
this.a = i;
this.b = catalogedGift;
}
}
}
@@ -0,0 +1,200 @@
package com.vk.contacts;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.ContextThemeWrapper;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.RadioButton;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import com.vk.core.dialogs.alert.VkAlertDialog;
import com.vk.core.ui.themes.VKThemeHelper;
import com.vk.core.util.ContextExtKt;
import com.vk.navigation.NavigatorKeys;
import com.vk.permission.PermissionHelper;
import com.vtosters.lite.R;
import com.vtosters.lite.VKActivity;
import com.vtosters.lite.activities.LogoutReceiver;
import java.util.List;
import kotlin.Unit;
import kotlin.jvm.b.Functions;
import kotlin.jvm.b.Functions2;
public class ContactsSyncAcitvity extends VKActivity implements View.OnClickListener {
private boolean I;
private View J;
private RadioButton K;
private RadioButton L;
private RadioButton M;
@Nullable
private String G = null;
private int H = 2;
private LogoutReceiver N = null;
public static void a(Context context) {
b(context, ContactsSyncUtils.b());
}
public static void b(Context context, int i) {
a(context, i, null);
}
private void f(int i) {
this.H = i;
this.K.setChecked(i == 0);
this.L.setChecked(i == 1);
this.M.setChecked(i == 2);
CheckBox checkBox = this.J.findViewById(R.id.sync_big_pictures);
checkBox.setEnabled(i != 2);
if (i == 2) {
checkBox.setChecked(false);
}
}
private void onDismiss() {
ContactsSyncReporter.a.a(ContactsSyncUtils.b(), this.G);
finish();
}
private void x1() {
this.H = getIntent().getIntExtra("force_select_sync_contacts", ContactsSyncUtils.b());
this.I = ContactsSyncUtils.d();
this.K = this.J.findViewById(R.id.welcome_sync_opt1);
this.L = this.J.findViewById(R.id.welcome_sync_opt2);
this.M = this.J.findViewById(R.id.welcome_sync_opt3);
this.K.setChecked(this.H == 0);
this.L.setChecked(this.H == 1);
this.M.setChecked(this.H == 2);
this.J.findViewById(R.id.welcome_sync1).setOnClickListener(this);
this.J.findViewById(R.id.welcome_sync2).setOnClickListener(this);
this.J.findViewById(R.id.welcome_sync3).setOnClickListener(this);
CheckBox checkBox = this.J.findViewById(R.id.sync_big_pictures);
checkBox.setChecked(this.I);
checkBox.setEnabled(this.H != 2);
checkBox.setOnCheckedChangeListener(ContactsSyncAcitvity.this::a);
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(this);
builder.setTitle(R.string.sett_sync);
builder.setView(this.J);
builder.setCancelable(false);
builder.setPositiveButton(R.string.save, ContactsSyncAcitvity.this::a);
builder.setNegativeButton(R.string.cancel, ContactsSyncAcitvity.this::b);
builder.show();
}
public Unit c(List list) {
ContactsSyncReporter.a.a(this.G);
finish();
return Unit.a;
}
@SuppressLint("NonConstantResourceId")
@Override // android.view.View.OnClickListener
public void onClick(View view) {
switch (view.getId()) {
case R.id.welcome_sync1 /* 2131365835 */:
f(0);
return;
case R.id.welcome_sync2 /* 2131365836 */:
f(1);
return;
case R.id.welcome_sync3 /* 2131365837 */:
f(2);
return;
default:
}
}
@Override // com.vtosters.lite.VKActivity, com.vk.core.ui.themes.ThemableActivity, androidx.appcompat.app.AppCompatActivity, androidx.fragment.app.FragmentActivity, androidx.core.app.ComponentActivity, android.app.Activity
public void onCreate(Bundle bundle) {
setTheme(VKThemeHelper.n());
super.onCreate(bundle);
this.G = getIntent().getStringExtra(NavigatorKeys.l0);
this.N = LogoutReceiver.a(this);
overridePendingTransition(0, 0);
getWindow().setBackgroundDrawableResource(R.drawable.transparent);
setContentView(new View(this));
this.J = View.inflate(new ContextThemeWrapper(this, VKThemeHelper.n()), R.layout.welcome, null);
VKThemeHelper.d(this);
PermissionHelper permissionHelper = PermissionHelper.r;
permissionHelper.a(this, permissionHelper.e(), R.string.permissions_contacts_sync, R.string.permissions_contacts_sync_settings, new Functions() { // from class: com.vk.contacts.c
@Override // kotlin.jvm.b.Functions
public Object invoke() {
return ContactsSyncAcitvity.this.w1();
}
}, new Functions2() { // from class: com.vk.contacts.a
@Override // kotlin.jvm.b.Functions2
public Object invoke(Object obj) {
return ContactsSyncAcitvity.this.c((List) obj);
}
});
}
@Override // com.vtosters.lite.VKActivity, androidx.appcompat.app.AppCompatActivity, androidx.fragment.app.FragmentActivity, android.app.Activity
public void onDestroy() {
this.N.a();
super.onDestroy();
}
@Override // android.app.Activity
protected void onRestoreInstanceState(Bundle bundle) {
super.onRestoreInstanceState(bundle);
this.H = bundle.getInt("state_option", 2);
this.I = bundle.getBoolean("state_sync_hq_photo", false);
f(this.H);
}
@Override // androidx.appcompat.app.AppCompatActivity, androidx.fragment.app.FragmentActivity, androidx.core.app.ComponentActivity, android.app.Activity
public void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(bundle);
bundle.putInt("state_option", this.H);
bundle.putBoolean("state_sync_hq_photo", this.I);
}
public Unit w1() {
x1();
return Unit.a;
}
public static void a(Context context, int i, @Nullable String str) {
Intent intent = new Intent(context, ContactsSyncAcitvity.class);
intent.setAction("syncsettings");
intent.putExtra("force_select_sync_contacts", i);
intent.putExtra(NavigatorKeys.l0, str);
if (ContextExtKt.e(context) == null) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent);
}
public void b(DialogInterface dialogInterface, int i) {
onDismiss();
}
public void a(CompoundButton compoundButton, boolean z) {
this.I = z;
}
public void a(DialogInterface dialogInterface, int i) {
ContactsSyncUtils.b(this.H);
ContactsSyncUtils.a(this.I);
Intent intent = new Intent();
intent.putExtra("option", this.H);
setResult(-1, intent);
onDismiss();
}
public void a(DialogInterface dialogInterface) {
onDismiss();
}
}
@@ -0,0 +1,45 @@
package com.vk.contacts;
import com.vk.metrics.eventtracking.Event;
import com.vk.metrics.eventtracking.VkTracker;
import com.vk.navigation.NavigatorKeys;
public final class ContactsSyncReporter {
public static final ContactsSyncReporter a = new ContactsSyncReporter();
private static final String EVENT_NAME = "LoggingTracker";
private static final String ENABLE_CONTACTS_SYNC = "enable_contacts_sync";
private static final String HAS_CONTACTS_PERMISSION = "has_contacts_permission";
private static final String SELECTED_SYNC_OPTION = "selected_sync_option";
private static final String NAVIGATOR_KEYS_L0 = NavigatorKeys.l0;
private ContactsSyncReporter() {
}
private static Event createEvent(boolean z, int i, String str) {
Event.a a2 = Event.b.a();
a2.a(EVENT_NAME);
a2.a(ENABLE_CONTACTS_SYNC);
a2.a(HAS_CONTACTS_PERMISSION, z);
a2.a(SELECTED_SYNC_OPTION, i != 0 ? (i != 1 ? "disabled" : "contacts") : "all");
if (str == null) {
str = "";
}
a2.a(NAVIGATOR_KEYS_L0, str);
return a2.a();
}
public void a(String str) {
a(false, 2, str);
}
public void a(int i, String str) {
a(true, i, str);
}
private void a(boolean z, int i, String str) {
VkTracker vkTracker = VkTracker.k;
Event event = createEvent(z, i, str);
vkTracker.a(event);
}
}
@@ -0,0 +1,112 @@
package com.vk.contacts;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.ContentResolver;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import com.vk.auth.VKAuthUtils;
import com.vk.core.concurrent.VkExecutors;
import com.vk.core.preference.Preference;
import com.vk.core.util.AppContextHolder;
import com.vk.metrics.eventtracking.VkTracker;
import com.vtosters.lite.auth.VKAccountManager;
public final class ContactsSyncUtils {
private static final SharedPreferences prefs;
static {
prefs = Preference.b();
}
public static void a(boolean z) { // setSyncHqPhotos
try {
prefs.edit().putBoolean("sync_hq_photos", z).apply();
Log.d("Contacts", "setSyncHqPhotos");
} catch (Exception e) {
VkTracker.k.b(e);
e.fillInStackTrace();
}
}
public static void b(int i) { // setSyncOption
try {
prefs.edit().putInt("key_sync_option", i).apply();
syncAccount(i);
Log.d("Contacts", "setSyncOption");
} catch (Exception e) {
VkTracker.k.b(e);
e.fillInStackTrace();
}
}
public static boolean d() { // getSyncHqPhotos
return prefs.getBoolean("sync_hq_photos", false);
}
public static void e() { // syncAccount
syncAccount(b());
Log.d("Contacts", "syncAccount");
}
public static int b() { // getSyncOption
Account[] accounts;
try {
AccountManager accountManager = AccountManager.get(AppContextHolder.a);
accounts = accountManager.getAccountsByType("com.vkontakte.account");
if (accounts.length == 0) {
Account account = new Account(VKAccountManager.d().Z(), "com.vkontakte.account");
try {
accountManager.addAccountExplicitly(account, null, null);
} catch (Exception e) {
VkTracker.k.a(e);
e.fillInStackTrace();
}
accounts = new Account[]{account};
}
if (ContentResolver.getSyncAutomatically(accounts[0], "com.android.contacts")) {
if (prefs.contains("key_sync_option")) {
return prefs.getInt("key_sync_option", 2);
}
if (prefs.contains("sync_all")) {
return prefs.getBoolean("sync_all", false) ? 0 : 1;
}
return 2;
}
return 2;
} catch (Exception e2) {
VkTracker.k.b(e2);
e2.fillInStackTrace();
return 2;
}
}
private static void syncAccount(int i) {
Log.d("Contacts", String.valueOf(i));
if (!VKAccountManager.d().b1()) {
syncAllAccounts();
Log.d("Contacts", "VKAccountManager.d().b1() is not false");
return;
}
Account account = VKAuthUtils.a.a(VKAccountManager.d().Z());
if (i != 2 && account != null) {
syncSingleAccount(account);
Log.d("Contacts", "sync single account, account is " + account);
} else {
syncAllAccounts();
Log.d("Contacts", "sync all accounts, account is " + account);
}
}
private static void syncSingleAccount(Account account) {
Bundle bundle = new Bundle();
bundle.putBoolean("com.vtosters.lite.EXTRA_FORCE_KEY", true);
ContentResolver.requestSync(account, "com.android.contacts", bundle);
VkExecutors.x.l().submit(() -> ContactsSyncAdapterService.a(AppContextHolder.a, account, new Bundle()));
}
private static void syncAllAccounts() {
VkExecutors.x.l().submit(() -> ContactsSyncAdapterService.a(AppContextHolder.a.getContentResolver()));
}
}
@@ -0,0 +1,132 @@
package com.vk.core.drawable;
import android.content.res.ColorStateList;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import ru.vtosters.lite.themes.utils.RecolorUtils;
public class RecoloredDrawable extends Drawable implements Drawable.Callback {
private Drawable drawable;
private ColorStateList colorStateList;
private int c;
private int d;
public RecoloredDrawable(Drawable drawable, ColorStateList colorStateList) {
this.c = 255;
this.d = 255;
try {
this.drawable = drawable.mutate();
} catch (Exception e) {
e.printStackTrace();
}
this.drawable.setCallback(this);
this.colorStateList = RecolorUtils.themeCSL(colorStateList);
onStateChange(new int[0]);
}
public RecoloredDrawable(Drawable drawable, int i) {
this(drawable, new ColorStateList(new int[][]{new int[0]}, new int[]{i}));
}
public RecoloredDrawable() {
this.c = 255;
this.d = 255;
}
public void a(int i) {
a(new ColorStateList(new int[][]{new int[0]}, new int[]{i}));
}
@Override
public void draw(@NonNull Canvas canvas) {
this.drawable.draw(canvas);
}
@Override
public int getIntrinsicHeight() {
return this.drawable.getIntrinsicHeight();
}
@Override
public int getIntrinsicWidth() {
return this.drawable.getIntrinsicWidth();
}
@Override
public int getOpacity() {
return this.drawable.getOpacity();
}
@Override
public void invalidateDrawable(@NonNull Drawable drawable) {
invalidateSelf();
}
@Override
public boolean isStateful() {
return this.colorStateList.isStateful();
}
@Override
protected boolean onStateChange(int[] iArr) {
super.onStateChange(iArr);
ColorStateList colorStateList = this.colorStateList;
this.drawable.setColorFilter(colorStateList.getColorForState(iArr, colorStateList.getDefaultColor()), PorterDuff.Mode.SRC_IN);
int length = iArr.length;
boolean z = false;
int i = 0;
while (true) {
if (i >= length) {
break;
} else if (iArr[i] == 0x010100a1) {
z = true;
break;
} else {
i++;
}
}
this.drawable.setState(iArr);
this.drawable.setAlpha(z ? this.c : this.d);
return true;
}
@Override
public void scheduleDrawable(@NonNull Drawable drawable, @NonNull Runnable runnable, long j) {
scheduleSelf(runnable, j);
}
@Override
public void setAlpha(int i) {
this.c = i;
this.d = i;
this.drawable.setAlpha(i);
}
@Override
public void setBounds(int i, int i2, int i3, int i4) {
super.setBounds(i, i2, i3, i4);
this.drawable.setBounds(i, i2, i3, i4);
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
}
@Override
public void unscheduleDrawable(@NonNull Drawable drawable, @NonNull Runnable runnable) {
unscheduleSelf(runnable);
}
public void a(ColorStateList colorStateList) {
this.colorStateList = colorStateList;
onStateChange(getState());
invalidateSelf();
}
public Drawable a() {
return this.drawable;
}
}
@@ -0,0 +1,128 @@
package com.vk.core.extensions;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.AttrRes;
import androidx.annotation.ColorRes;
import androidx.annotation.DrawableRes;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.drawable.DrawableCompat;
import b.h.v.InitialValueObservable;
import b.h.v.TextViewTextChangeEvent;
import b.h.v.TextViewTextChangeEventObservable;
import com.vk.core.util.ContextExtKt;
import ru.vtosters.hooks.other.ThemesUtils;
public final class TextViewExt {
public static void a(TextView textView, Drawable drawable) {
a(textView, null, drawable);
}
public static boolean b(TextView textView) {
return textView == null || TextUtils.isEmpty(textView.getEditableText());
}
public static InitialValueObservable<TextViewTextChangeEvent> c(TextView textView) {
return new TextViewTextChangeEventObservable(textView);
}
public static void d(TextView textView, @DrawableRes int i, @AttrRes int i2) {
b(textView, ThemesUtils.recolorDrawable(ContextExtKt.a(textView.getContext(), i, ContextExtKt.h(textView.getContext(), i2))));
}
public static void a(TextView textView, Drawable drawable, ColorStateList colorStateList) {
a(textView, null, a(drawable, colorStateList));
}
public static void b(TextView textView, Drawable drawable) {
a(textView, drawable, (Drawable) null);
}
public static void c(TextView textView, @DrawableRes int i, @ColorRes int i2) {
if (i == 0) {
b(textView, null);
} else if (i2 == 0) {
b(textView, ContextCompat.getDrawable(textView.getContext(), i));
} else {
b(textView, ContextCompat.getDrawable(textView.getContext(), i), ContextCompat.getColorStateList(textView.getContext(), i2));
}
}
public static void d(TextView textView, int i) {
textView.setTextSize(0, i);
}
public static void a(TextView textView, @DrawableRes int i) {
a(textView, i, 0);
}
public static void b(TextView textView, Drawable drawable, ColorStateList colorStateList) {
a(textView, a(drawable, colorStateList), (Drawable) null);
}
public static void a(TextView textView, @DrawableRes int i, @ColorRes int i2) {
if (i == 0) {
a(textView, (Drawable) null);
} else if (i2 == 0) {
a(textView, ContextCompat.getDrawable(textView.getContext(), i));
} else {
a(textView, ContextCompat.getDrawable(textView.getContext(), i), ContextCompat.getColorStateList(textView.getContext(), i2));
}
}
public static void b(TextView textView, @DrawableRes int i) {
c(textView, i, 0);
}
public static void b(TextView textView, @DrawableRes int i, @AttrRes int i2) {
if (i == 0) {
a(textView, (Drawable) null);
} else if (i2 == 0) {
a(textView, ContextCompat.getDrawable(textView.getContext(), i));
} else {
Drawable drawable = ContextCompat.getDrawable(textView.getContext(), i);
a(textView, drawable, ColorStateList.valueOf(ContextExtKt.h(textView.getContext(), i2)));
}
}
public static void c(TextView textView, @ColorRes int i) {
textView.setTextColor(ContextExtKt.a(textView.getContext(), i));
}
private static void a(TextView textView, Drawable drawable, Drawable drawable2) {
textView.setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, drawable2, null);
}
public static void a(TextView textView) {
textView.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, null, null);
}
public static Drawable a(Drawable drawable, ColorStateList colorStateList) {
if (colorStateList == null) return drawable;
if (drawable != null) {
Drawable wrap = DrawableCompat.wrap(drawable.mutate());
DrawableCompat.setTintList(wrap, colorStateList);
return wrap;
}
return null;
}
public static void a(TextView textView, CharSequence charSequence) {
if (TextUtils.isEmpty(charSequence)) {
textView.setVisibility(View.GONE);
return;
}
textView.setVisibility(View.VISIBLE);
textView.setText(charSequence);
}
public static void a(TextView textView, float f) {
textView.setTextSize(0, f);
}
}
@@ -11,14 +11,15 @@ import android.net.Uri;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import b.h.g.m.CameraUtils;
import b.h.g.m.FileUtils;
import com.facebook.common.i.MediaUtils;
import com.facebook.x.g.EncodedImage;
import com.vk.core.concurrent.VkExecutors;
import com.vk.imageloader.VKImageLoader;
import com.vk.log.L;
import com.vk.metrics.eventtracking.VkTracker;
import com.vtosters.lite.R;
import ru.vtosters.lite.concurrent.VTExecutors;
import java.io.File;
import java.io.FileOutputStream;
@@ -27,9 +28,6 @@ import java.io.InputStream;
import java.net.URI;
import java.util.HashSet;
import b.h.g.m.CameraUtils;
import b.h.g.m.FileUtils;
public class DownloadUtils {
public static final HashSet<Long> a = new HashSet<>();
@@ -49,7 +47,7 @@ public class DownloadUtils {
ToastUtils.a(context.getString(R.string.error) + " [" + e2.getMessage() + "]");
}
}
private static void b(final Context context, String str, String uri, boolean z) {
if (TextUtils.isEmpty(uri)) {
return;
@@ -81,7 +79,7 @@ public class DownloadUtils {
file.createNewFile();
}
if (file.exists()) {
VkExecutors.x.e().execute(() -> {
VTExecutors.getIoExecutor().execute(() -> {
try {
FileUtils.b.a(h, new FileOutputStream(file), h.available(), null);
ToastUtils.a(context.getString(R.string.file_saved, file.getAbsoluteFile()));
@@ -191,7 +189,7 @@ public class DownloadUtils {
if (!file.exists()) {
return false;
}
Intent intent = new Intent("android.intent.action.VIEW");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
var mimeType = FileUtils.f(file);
var uri = FileUtils.uriFromFile(file);
@@ -222,7 +220,7 @@ public class DownloadUtils {
var mimeType = FileUtils.f(file);
var uri = FileUtils.uriFromFile(file);
Intent intent = new Intent("android.intent.action.VIEW");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, mimeType);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Log.d("DownloadUtils", "openFile: " + file.getAbsolutePath() + "| mimetype " + mimeType + "| uri " + uri);
@@ -0,0 +1,268 @@
package com.vk.core.utils;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.core.content.ContextCompat;
import b.h.z.e;
import com.vk.core.drawable.RecoloredDrawable;
import com.vk.core.extensions.TextViewExt;
import com.vk.core.ui.themes.MilkshakeHelper;
import com.vk.core.ui.themes.VKThemeHelper;
import com.vk.dto.common.VerifyInfo;
import com.vk.extensions.ViewExtKt;
import com.vtosters.lite.R;
import ru.vtosters.hooks.other.ThemesUtils;
public final class VerifyInfoHelper {
public static final VerifyInfoHelper h;
public static int devIcon = R.drawable.ic_favorite_16;
static {
h = new VerifyInfoHelper();
}
private VerifyInfoHelper() {
}
public static Integer enumSwitchMapping(VerifyInfoHelper.ColorTheme color) {
return switch (color) {
case normal -> 1;
case light -> 2;
case ultraLight -> 3;
case white -> 4;
};
}
public static Drawable b(VerifyInfoHelper verifyInfoHelper, boolean z, boolean z2, boolean dev, Context context, ColorTheme colorTheme, int i, Object obj) {
if ((i & 8) != 0) {
colorTheme = ColorTheme.normal;
}
return verifyInfoHelper.b(z, z2, dev, context, colorTheme);
}
public static Drawable b(VerifyInfoHelper verifyInfoHelper, VerifyInfo verifyInfo, Context context, ColorTheme colorTheme, int i, Object obj) {
return b(verifyInfoHelper, verifyInfo.u1(), verifyInfo.t1(), verifyInfo.dev(), context, colorTheme, i, obj);
}
public static Drawable b(VerifyInfoHelper verifyInfoHelper, boolean z, boolean z2, Context context, ColorTheme colorTheme, int i, Object obj) {
return b(verifyInfoHelper, z, z2, false, context, colorTheme, i, obj);
}
public static Drawable a(VerifyInfoHelper verifyInfoHelper, VerifyInfo verifyInfo, Context context, ColorTheme colorTheme, int i, Object obj) {
if ((i & 4) != 0) {
colorTheme = ColorTheme.normal;
}
return verifyInfoHelper.b(verifyInfo, context, colorTheme);
}
public static Drawable a(VerifyInfoHelper verifyInfoHelper, boolean z, boolean z2, boolean dev, Context context, ColorTheme colorTheme, int i, Object obj) {
if ((i & 8) != 0) {
colorTheme = ColorTheme.normal;
}
return verifyInfoHelper.a(z, z2, dev, context, colorTheme);
}
public static Drawable a(VerifyInfoHelper verifyInfoHelper, boolean z, boolean z2, Context context, ColorTheme colorTheme, int i, Object obj) {
return a(verifyInfoHelper, z, z2, false, context, colorTheme, i, obj);
}
public static void a(VerifyInfoHelper verifyInfoHelper, TextView textView, VerifyInfo verifyInfo, boolean z, ColorTheme colorTheme, int i, Object obj) {
if ((i & 4) != 0) {
z = false;
}
if ((i & 8) != 0) {
colorTheme = ColorTheme.normal;
}
verifyInfoHelper.a(textView, verifyInfo, z, colorTheme);
}
private int a() {
return ThemesUtils.getAccentColor();
}
private int b() {
return ThemesUtils.getAccentColor();
}
private int c() {
return ThemesUtils.getColor(R.color.fire_orange);
}
private int d() {
return ThemesUtils.getColor(R.color.light_blue);
}
private int e() {
return ThemesUtils.getColor(R.color.white_alpha60);
}
private int f() {
return ThemesUtils.getColor(R.color.white);
}
public int a(ColorTheme colorTheme) {
return switch (enumSwitchMapping(colorTheme)) {
case 1, 2 -> c();
case 3 -> e();
case 4 -> d();
default -> 0;
};
}
public Drawable a(VerifyInfo verifyInfo, Context context) {
return a(this, verifyInfo, context, null, 4, null);
}
public Drawable a(boolean z, boolean z2, boolean dev, Context context) {
return b(this, z, z2, dev, context, null, 8, null);
}
public Drawable a(boolean z, boolean z2, Context context) {
return b(this, z, z2, false, context, null, 8, null);
}
public int b(ColorTheme colorTheme) {
return a(colorTheme);
}
public int c(ColorTheme colorTheme) {
return switch (enumSwitchMapping(colorTheme)) {
case 1 -> MilkshakeHelper.e() ? b() : a();
case 2 -> d();
case 3 -> e();
case 4 -> f();
default -> 0;
};
}
public Drawable b(Context context, VerifyInfo verifyInfo) {
if (verifyInfo.dev()) {
return new RecoloredDrawable(ContextCompat.getDrawable(context, devIcon), c(ColorTheme.normal));
} else if (verifyInfo.t1() && verifyInfo.u1()) {
return ContextCompat.getDrawable(context, e.ic_fire_verified_border_composite_20_xml);
} else if (verifyInfo.t1()) {
return ContextCompat.getDrawable(context, e.ic_fire_border_composite_20_xml);
} else if (verifyInfo.u1()) {
return new RecoloredDrawable(ContextCompat.getDrawable(context, e.verified_16), c(ColorTheme.normal));
}
return null;
}
public Drawable b(VerifyInfo verifyInfo, Context context, ColorTheme colorTheme) {
return b(verifyInfo.u1(), verifyInfo.t1(), verifyInfo.dev(), context, colorTheme);
}
public Drawable a(Context context, VerifyInfo verifyInfo) {
if (verifyInfo.dev()) {
return new RecoloredDrawable(ContextCompat.getDrawable(context, devIcon), c(ColorTheme.normal));
} else if (verifyInfo.t1() && verifyInfo.u1()) {
return ContextCompat.getDrawable(context, e.ic_fire_verified_border_composite_20_xml);
} else if (verifyInfo.t1()) {
return ContextCompat.getDrawable(context, e.ic_fire_border_composite_20_xml);
} else if (verifyInfo.u1() && VKThemeHelper.s()) {
return ContextCompat.getDrawable(context, e.verified_badge_light_24);
} else if (verifyInfo.u1() && VKThemeHelper.r()) {
return ContextCompat.getDrawable(context, e.verified_badge_dark_24);
}
return null;
}
public Drawable b(boolean z, boolean z2, Context context, ColorTheme colorTheme) {
return b(z, z2, false, context, colorTheme);
}
public Drawable b(boolean z, boolean z2, boolean dev, Context context, ColorTheme colorTheme) {
int i = 0;
int c2 = 0;
if (dev) {
i = devIcon;
c2 = c(colorTheme);
} else if (z2 && z) {
i = e.ic_fire_verified_16;
c2 = b(colorTheme);
} else if (z2) {
i = e.ic_fire_16;
c2 = a(colorTheme);
} else if (z) {
i = e.verified_16;
c2 = c(colorTheme);
} else {
Log.d("VerifyInfoHelper", "Use VerifyInfo.has()");
}
return new RecoloredDrawable(ContextCompat.getDrawable(context, i), c2);
}
public Drawable a(VerifyInfo verifyInfo, Context context, ColorTheme colorTheme) {
return a(verifyInfo.u1(), verifyInfo.t1(), verifyInfo.dev(), context, colorTheme);
}
public Drawable a(boolean z, boolean z2, Context context, ColorTheme colorTheme) {
return a(z, z2, false, context, colorTheme);
}
public Drawable a(boolean z, boolean z2, boolean dev, Context context, ColorTheme colorTheme) {
int i = 0;
int c2 = 0;
if (dev) {
i = devIcon;
c2 = c(colorTheme);
} else if (z2 && z) {
i = e.ic_fire_verified_12;
c2 = b(colorTheme);
} else if (z2) {
i = e.ic_fire_12;
c2 = a(colorTheme);
} else if (z) {
i = e.verified_12;
c2 = c(colorTheme);
} else {
Log.d("VerifyInfoHelper", "Use VerifyInfo.has()");
}
return new RecoloredDrawable(ContextCompat.getDrawable(context, i), c2);
}
public void a(TextView textView, VerifyInfo verifyInfo, boolean z, ColorTheme colorTheme) {
Drawable drawable;
Context context = textView.getContext();
if (verifyInfo == null || !verifyInfo.v1() || context == null) {
drawable = null;
} else {
drawable = z ? a(verifyInfo, context, colorTheme) : b(verifyInfo, context, colorTheme);
}
TextViewExt.a(textView, drawable);
}
public void a(ImageView imageView, boolean z, VerifyInfo verifyInfo) {
Drawable b2;
if (verifyInfo != null && verifyInfo.v1()) {
if (z) {
Context context = imageView.getContext();
b2 = a(context, verifyInfo);
} else {
Context context2 = imageView.getContext();
b2 = b(context2, verifyInfo);
}
imageView.setImageDrawable(b2);
ViewExtKt.r(imageView);
return;
}
ViewExtKt.p(imageView);
}
public enum ColorTheme {
white,
normal,
light,
ultraLight
}
}
@@ -0,0 +1,11 @@
package com.vk.extensions;
import android.widget.TextView;
import androidx.annotation.AttrRes;
import com.vk.core.ui.themes.VKThemeHelper;
public final class TextViewExt {
public static void a(TextView textView, @AttrRes int i) {
VKThemeHelper.a(textView, i);
}
}
@@ -0,0 +1,238 @@
package com.vk.im.engine.commands.dialogs;
import androidx.collection.ArraySet;
import b.h.g.p.Transliteration;
import com.vk.auth.y.a.BuildConfig;
import com.vk.im.engine.ImEnvironment;
import com.vk.im.engine.commands.etc.ProfilesGetCmd;
import com.vk.im.engine.commands.etc.ProfilesInfoGetArgs;
import com.vk.im.engine.i.BaseImEngineCmd;
import com.vk.im.engine.internal.storage.utils.StringMatchStrategy;
import com.vk.im.engine.models.*;
import com.vk.im.engine.models.dialogs.DialogMember;
import com.vk.im.engine.utils.ImDialogsUtils;
import kotlin.NoWhenBranchMatchedException;
import kotlin.collections.l;
import kotlin.jvm.b.Functions2;
import kotlin.jvm.internal.Intrinsics;
import kotlin.sequences.m;
import kotlin.text.Regex;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
public final class DialogGetMentionSuggestionCmd extends BaseImEngineCmd<Suggestion> {
private final int f2365b;
private final String c;
private final Source d;
private final boolean e;
private final Object f;
public DialogGetMentionSuggestionCmd(int i, String str, Source source, boolean z, Object obj) {
this.f2365b = i;
this.c = str;
this.d = source;
this.e = z;
this.f = obj;
}
private ProfilesInfo a(ImEnvironment imEnvironment, Collection<Member> collection, Source source, boolean z, Object obj) {
ProfilesInfoGetArgs.a aVar = new ProfilesInfoGetArgs.a();
aVar.a(collection);
aVar.a(source);
aVar.a(z);
aVar.a(obj);
Object a2 = null;
try {
a2 = imEnvironment.a(this, new ProfilesGetCmd(aVar.a()));
} catch (Exception ex) {
throw new RuntimeException(ex);
}
Intrinsics.a(a2, "env.submitCommandDirect(this, cmd)");
return (ProfilesInfo) a2;
}
private String a(String str) {
String a2 = new Regex("\\W*").a(str, BuildConfig.g);
int length = a2.length() - 1;
int i = 0;
boolean z = false;
while (i <= length) {
boolean z2 = a2.charAt(!z ? i : length) <= ' ';
if (z) {
if (!z2) {
break;
}
length--;
} else if (z2) {
i++;
} else {
z = true;
}
}
return a2.subSequence(i, length + 1).toString();
}
private Collection<Member> a(ImEnvironment imEnvironment, int i) {
var d = imEnvironment.a0().f().b().d(i);
var arrayList = new ArrayList(l.a(d, 10));
for (DialogMember dialogMember : d) {
arrayList.add(dialogMember.Z());
}
// changed
var fakeMember = new Member();
fakeMember.b(MemberType.CUSTOM_BOT);
arrayList.add(fakeMember);
return arrayList;
}
private Collection<Member> a(ImEnvironment imEnvironment, int i, String str) {
if (a(str).length() == 0) {
return l.a();
}
List<String> c = l.c(Transliteration.a.a(str), Transliteration.a.b(str));
ArraySet arraySet = new ArraySet();
for (String str2 : c) {
arraySet.addAll(imEnvironment.a0().m().a(i, str2, StringMatchStrategy.STARTING_WITH));
}
// changed
var fakeMember = new Member();
fakeMember.b(MemberType.CUSTOM_BOT);
arraySet.add(fakeMember);
return arraySet;
}
private Comparator<Member> a(List<Member> list) {
return new a(list);
}
private void a(ImEnvironment imEnvironment, int i, Source source, boolean z, Object obj) {
try {
imEnvironment.a(this, new DialogGetMembersCmd(i, source, z, obj));
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
private List<Member> b(ImEnvironment imEnvironment, int i) {
return imEnvironment.a0().j().a(i, Weight.d.c(), Direction.BEFORE, 100);
}
@Override // com.vk.im.engine.i.ImEngineCmd
public Suggestion a(ImEnvironment imEnvironment) {
Collection<Member> a2;
Source source;
if (ImDialogsUtils.d(this.f2365b) != PeerType.CHAT) {
return new Suggestion(null, null);
}
Member Z = imEnvironment.Z();
int d = imEnvironment.a0().n().d();
Integer e = imEnvironment.a0().f().b().e(this.f2365b);
boolean z = false;
boolean z2 = e == null;
boolean z3 = e == null || e.intValue() != d;
boolean z4 = z2 || z3;
Source source2 = this.d;
boolean z5 = source2 == Source.NETWORK || (z4 && source2 == Source.ACTUAL);
if (z5) {
a(imEnvironment, this.f2365b, this.d, this.e, this.f);
z3 = false;
z2 = false;
}
List<Member> b2 = b(imEnvironment, this.f2365b);
if (this.c.length() == 0) {
z = true;
}
if (z) {
a2 = a(imEnvironment, this.f2365b);
} else if (z) {
throw new NoWhenBranchMatchedException();
} else {
a2 = a(imEnvironment, this.f2365b, this.c);
}
var sequense = l.d(a2);
var l = m.l(m.a(m.b(sequense, new Functions2<Member, Boolean>() {
@Override
public Boolean invoke(Member member) {
return member.e(Z) && (member.a(MemberType.USER) || member.a(MemberType.GROUP));
}
}), a(b2)));
EntityValue entityValue = new EntityValue(z2 ? null : l, z3);
switch (this.d) {
case CACHE:
source = Source.CACHE;
break;
case ACTUAL:
source = Source.ACTUAL;
break;
case NETWORK:
source = Source.NETWORK;
break;
default:
throw new NoWhenBranchMatchedException();
}
return new Suggestion(entityValue, a(imEnvironment, l, source, this.e, this.f));
}
public boolean equals(Object obj) {
if (this != obj) {
if (obj instanceof DialogGetMentionSuggestionCmd) {
DialogGetMentionSuggestionCmd dialogGetMentionSuggestionCmd = (DialogGetMentionSuggestionCmd) obj;
return this.f2365b == dialogGetMentionSuggestionCmd.f2365b && this.e == dialogGetMentionSuggestionCmd.e;
}
return false;
}
return true;
}
public int hashCode() {
int i = this.f2365b;
String str = this.c;
int i2 = 0;
int hashCode = str != null ? str.hashCode() : 0;
Source source = this.d;
int hashCode2 = source != null ? source.hashCode() : 0;
boolean z = this.e;
int i3 = z ? 1 : 0;
if (z) {
i3 = 1;
}
Object obj = this.f;
if (obj != null) {
i2 = obj.hashCode();
}
return (((((((i * 31) + hashCode) * 31) + hashCode2) * 31) + i3) * 31) + i2;
}
public String toString() {
return "DialogGetMentionSuggestionCmd(dialogId=" + this.f2365b + ", query=" + this.c + ", source=" + this.d + ", isAwaitNetwork=" + this.e + ", changerTag=" + this.f + ")";
}
public static final class a<T> implements Comparator<Member> {
List a;
a(List list) {
this.a = list;
}
@Override // java.util.Comparator
/* renamed from: a */
public int compare(Member member, Member member2) {
int indexOf = this.a.indexOf(member);
int indexOf2 = this.a.indexOf(member2);
int i = indexOf;
if (indexOf < 0) {
i = Integer.MAX_VALUE;
}
int i2 = indexOf2;
if (indexOf2 < 0) {
i2 = Integer.MAX_VALUE;
}
return Intrinsics.a(i, i2);
}
}
}
@@ -0,0 +1,38 @@
package com.vk.im.engine.models;
public enum MemberType {
UNKNOWN(0),
USER(1),
GROUP(2),
EMAIL(3),
CONTACT(4),
CUSTOM_BOT(5);
private final int mTypeAsInt;
MemberType(int i) {
this.mTypeAsInt = i;
}
public static MemberType a(int i) {
switch (i) {
case 0:
return UNKNOWN;
case 1:
return USER;
case 2:
return GROUP;
case 3:
return EMAIL;
case 4:
return CONTACT;
case 5:
return CUSTOM_BOT;
}
throw new IllegalArgumentException("Unknown member type value: " + i);
}
public int a() {
return this.mTypeAsInt;
}
}
@@ -36,5 +36,6 @@ public enum DialogAction {
unpinmsg,
ENCRYPT_SETT,
ENCRYPT,
DOWNLOAD
DOWNLOAD,
STAT
}
@@ -11,16 +11,15 @@ import com.vk.im.engine.models.dialogs.Dialog;
import com.vk.im.engine.models.groups.Group;
import com.vk.im.engine.utils.DialogPermissionHelper;
import com.vk.im.ui.p.ImBridge7;
import ru.vtosters.hooks.DialogMenuInjectors;
import java.util.ArrayList;
import java.util.List;
import ru.vtosters.lite.dnr.DNRInjector;
public final class DialogActionsHelper {
public static final DialogActionsHelper a = new DialogActionsHelper();
public final List<DialogAction> a(ImConfig imConfig, Dialog dialog, ProfilesSimpleInfo profilesSimpleInfo) {
public List<DialogAction> a(ImConfig imConfig, Dialog dialog, ProfilesSimpleInfo profilesSimpleInfo) {
if (dialog != null && profilesSimpleInfo != null) {
long b2 = TimeProvider.f.b();
ChatSettings z1 = dialog.z1();
@@ -28,7 +27,7 @@ public final class DialogActionsHelper {
boolean I1 = z1 != null && z1.I1();
ArrayList<DialogAction> arrayList = new ArrayList<>();
DNRInjector.inject(dialog, arrayList);
DialogMenuInjectors.inject(dialog, arrayList);
arrayList.add(DialogAction.SEARCH);
@@ -85,7 +84,7 @@ public final class DialogActionsHelper {
return new ArrayList<>();
}
public final List<DialogAction> a(Dialog dialog, ProfilesSimpleInfo profilesSimpleInfo) {
public List<DialogAction> a(Dialog dialog, ProfilesSimpleInfo profilesSimpleInfo) {
long b2 = TimeProvider.f.b();
Profile profile = profilesSimpleInfo.get(dialog.getId());
@@ -97,7 +96,7 @@ public final class DialogActionsHelper {
ChatSettings z1 = dialog.z1();
ArrayList<DialogAction> arrayList = new ArrayList<>();
DNRInjector.inject(dialog, arrayList);
DialogMenuInjectors.inject(dialog, arrayList);
// if (dialog.hasUnread()) {
arrayList.add(DialogAction.MARK_AS_READ);
@@ -139,7 +138,7 @@ public final class DialogActionsHelper {
return arrayList;
}
public final boolean a(Dialog dialog) {
public boolean a(Dialog dialog) {
if (dialog.V1() || !dialog.y1()) {
return false;
}
@@ -11,5 +11,6 @@ public enum MsgAction {
PIN,
UNPIN,
TRANSLATE,
READTO
READTO,
KICK
}
@@ -3,9 +3,11 @@ package com.vk.im.ui.components.common;
import com.vk.core.extensions.CollectionExt;
import com.vk.im.engine.ImConfig;
import com.vk.im.engine.ImEngine;
import com.vk.im.engine.models.Member;
import com.vk.im.engine.models.dialogs.Dialog;
import com.vk.im.engine.models.messages.Msg;
import com.vk.im.engine.utils.MsgPermissionHelper;
import ru.vtosters.lite.utils.AccountManagerUtils;
import java.util.ArrayList;
import java.util.Collection;
@@ -14,11 +16,11 @@ import java.util.List;
public final class MsgActionHelper {
public static final MsgActionHelper a = new MsgActionHelper();
public final List<MsgAction> a(ImEngine imEngine, Dialog dialog, Collection<? extends Msg> collection) {
public List<MsgAction> a(ImEngine imEngine, Dialog dialog, Collection<? extends Msg> collection) {
return a(imEngine != null ? imEngine.g() : null, dialog, collection);
}
public final List<MsgAction> a(ImConfig imConfig, Dialog dialog, Collection<? extends Msg> collection) {
public List<MsgAction> a(ImConfig imConfig, Dialog dialog, Collection<? extends Msg> collection) {
if (imConfig != null && dialog != null && collection != null) {
MsgPermissionHelper.a aVar = new MsgPermissionHelper.a(imConfig, dialog, collection);
ArrayList<MsgAction> arrayList = new ArrayList<>();
@@ -35,6 +37,24 @@ public final class MsgActionHelper {
CollectionExt.a(arrayList, MsgAction.TRANSLATE, true);
CollectionExt.a(arrayList, MsgAction.READTO, true);
boolean isAdmin = false;
try {
if (aVar.a().z1().L0().t1() == AccountManagerUtils.getUserId()) { // is owner
isAdmin = true;
} else if (!aVar.a().z1().K1()) { // is you not kicked
for (Member admins : aVar.a().z1().t1()) { // admin list
if (admins.t1() == AccountManagerUtils.getUserId()) {
isAdmin = true;
break;
}
}
}
} catch (Exception ignored) {
}
CollectionExt.a(arrayList, MsgAction.KICK, isAdmin);
return arrayList;
}
@@ -0,0 +1,73 @@
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.vk.im.ui.components.viewcontrollers.msg_list.adapter;
import android.util.SparseIntArray;
import androidx.annotation.ColorInt;
import androidx.annotation.MainThread;
import androidx.annotation.Nullable;
import com.vk.im.engine.j.StickersAnimationLoader;
import com.vk.im.engine.models.ImExperimentsProvider;
import com.vk.im.engine.models.Member;
import com.vk.im.engine.models.ProfilesSimpleInfo;
import com.vk.im.engine.models.attaches.Attach;
import com.vk.im.engine.models.messages.Msg;
import com.vk.im.engine.models.messages.NestedMsg;
import com.vk.im.ui.media.audio.AudioTrack;
import com.vk.im.ui.q.h.VideoAutoPlayer;
import com.vk.im.ui.views.span.OnSpanClickListener;
import com.vk.im.ui.views.span.OnSpanLongPressListener;
import com.vk.im.ui.views.sticker.StickerAnimationState;
import java.util.List;
@MainThread
public class MsgPartHolderBindArgs {
public SparseIntArray A;
public AudioTrack B;
public AudioMsgInfo C;
public StickerAnimationState D;
public StickersAnimationLoader E;
@Nullable
public OnSpanClickListener F;
@Nullable
public OnSpanLongPressListener G;
@Nullable
public MsgListAdapterCallback H;
@Nullable
public VideoAutoPlayer I;
public Msg a;
public NestedMsg b;
public CharSequence c;
public Attach d;
public List<Attach> e;
public boolean f;
public int g;
public int h;
public int i;
public int j;
public int k;
@ColorInt
public int l;
public Member m;
public ProfilesSimpleInfo n;
public ImExperimentsProvider o;
public int p;
public int q;
public int r;
public boolean s;
public boolean t;
public boolean u;
public boolean v;
public boolean w;
public boolean x;
public boolean y;
public boolean isSelected;
public SparseIntArray z;
public MsgPartHolderBindArgs() {
}
}

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