├── .github
└── workflows
│ └── push.yml
├── LICENSE
├── README.md
├── docs
├── ikws4.adaptive_color_bar.md
├── ikws4.system_variable.md
└── ikws4.webview_custom_css.md
├── scope_config.lua
├── scripts
├── ikws4.adaptive_color_bar.lua
├── ikws4.example.lua
├── ikws4.system_variable.lua
└── ikws4.webview_custom_css.lua
└── stylua.toml
/.github/workflows/push.yml:
--------------------------------------------------------------------------------
1 | name: Format
2 |
3 | on: push
4 |
5 | jobs:
6 | postprocessing:
7 | runs-on: ubuntu-latest
8 |
9 | steps:
10 | - uses: actions/checkout@v3
11 |
12 | - uses: JohnnyMorganz/stylua-action@v1.1.2
13 | with:
14 | token: ${{ secrets.GITHUB_TOKEN }}
15 | args: .
16 |
17 | - uses: stefanzweifel/git-auto-commit-action@v4
18 | with:
19 | commit_message: "chore: format with stylua"
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Devin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WeiJu2-Scripts
2 |
3 | - [ikws4.adaptive_color_bar](./docs/ikws4.adaptive_color_bar.md)
4 | - [ikws4.system_variable](./docs/ikws4.system_variable.md)
5 | - [ikws4.webview_custom_css](./docs/ikws4.webview_custom_css.md)
6 |
--------------------------------------------------------------------------------
/docs/ikws4.adaptive_color_bar.md:
--------------------------------------------------------------------------------
1 | ### Usage
2 |
3 | ```lua
4 | require("ikws4.adaptive_color_bar").setup {
5 | status_bar = true,
6 | navigation_bar = true,
7 | samples = 10,
8 | refresh_rate = 125,
9 | }
10 | ```
11 |
12 | ### Change Log
13 |
14 | #### [1.0.1] - 2023-2-15
15 |
16 | ##### Fixed
17 |
18 | - A null pointer, this happens when the local variable canvas has been recycled by the GC.
19 |
20 | ### Preview
21 |
22 | https://user-images.githubusercontent.com/47056144/190885640-ea7525ff-2de3-4637-88dd-8f6fb1352127.mp4
23 |
24 |
--------------------------------------------------------------------------------
/docs/ikws4.system_variable.md:
--------------------------------------------------------------------------------
1 | ### Usage
2 |
3 | ```lua
4 | require("ikws4.system_variable").setup {
5 | build = {
6 | device = "coral",
7 | product = "coral",
8 | model = "Pixel 4 XL",
9 | brand = "google",
10 | android_version = "13",
11 | },
12 | location = {
13 | longitude = 31.921279,
14 | latitude = 620.157480,
15 | },
16 | display = {
17 | dpi = 320,
18 | language = "en-US",
19 | },
20 | }
21 | ```
22 |
--------------------------------------------------------------------------------
/docs/ikws4.webview_custom_css.md:
--------------------------------------------------------------------------------
1 | ### Usage
2 |
3 | ```lua
4 | require("ikws4.webview_custom_css").setup {
5 | css = [[
6 | * {
7 | color: white;
8 | background: black;
9 | }
10 | ]],
11 | }
12 | ```
13 |
14 | ### Preview
15 |
16 |
17 |

18 |

19 |
20 |
--------------------------------------------------------------------------------
/scope_config.lua:
--------------------------------------------------------------------------------
1 | return {
2 | -- ["ikws4.example"] = ".*",
3 | ["ikws4.system_variable"] = ".*",
4 | ["ikws4.webview_custom_css"] = ".*",
5 | ["ikws4.adaptive_color_bar"] = ".*",
6 | }
7 |
--------------------------------------------------------------------------------
/scripts/ikws4.adaptive_color_bar.lua:
--------------------------------------------------------------------------------
1 | --[==[
2 | @metadata
3 | return {
4 | name = "adaptive_color_bar",
5 | author = "ikws4",
6 | version = "1.0.1",
7 | description = "Adaptive color for status and navigation bar",
8 | example = [=[
9 | require("ikws4.adaptive_color_bar").setup {
10 | status_bar = true,
11 | navigation_bar = true,
12 | samples = 10,
13 | refresh_rate = 125,
14 | }
15 | ]=]
16 | }
17 | @end
18 | --]==]
19 |
20 | local config = {
21 | status_bar = true,
22 | navigation_bar = true,
23 | samples = 10,
24 | refresh_rate = 125,
25 | }
26 |
27 | local M = {}
28 |
29 | M.setup = function(opts)
30 | config = table.extend(config, opts or {})
31 |
32 | local Activity = import("android.app.Activity")
33 | local Bundle = import("android.os.Bundle")
34 | local Canvas = import("android.graphics.Canvas")
35 | local Bitmap = import("android.graphics.Bitmap")
36 | local BitmapConfig = import("android.graphics.Bitmap.Config")
37 | local Runnable = import("java.lang.Runnable")
38 | local OnApplyWindowInsetsListener = import("android.view.View.OnApplyWindowInsetsListener")
39 | local Window = import("android.view.Window")
40 | local Rect = import("android.graphics.Rect")
41 | local ValueAnimator = import("android.animation.ValueAnimator")
42 | local ValueAnimatorAnimatorUpdateListener = import("android.animation.ValueAnimator.AnimatorUpdateListener")
43 | local AccelerateInterpolator = import("android.view.animation.AccelerateInterpolator")
44 |
45 | local decor_view_bitmap
46 |
47 | local function get_most_frequent_color(colors)
48 | local map = {}
49 | for _, color in ipairs(colors) do
50 | map[color] = map[color] and map[color] + 1 or 1
51 | end
52 |
53 | local max, res = 0, 0
54 | for k, v in pairs(map) do
55 | if v > max then
56 | max = v
57 | res = k
58 | end
59 | end
60 |
61 | return res
62 | end
63 |
64 | local function color_animator(old_color, new_color, duration, callback)
65 | local animator = ValueAnimator:ofArgb { old_color, new_color }
66 | animator:setDuration(duration)
67 | animator:addUpdateListener(object(ValueAnimatorAnimatorUpdateListener, {
68 | onAnimationUpdate = callback,
69 | }))
70 | animator:start()
71 | end
72 |
73 | hook {
74 | class = Activity,
75 | returns = void,
76 | method = "onCreate",
77 | params = {
78 | Bundle,
79 | },
80 | after = function(this, params)
81 | local window = this:getWindow()
82 | local decorView = window:getDecorView()
83 |
84 | local status_bar_height, navigation_bar_height
85 | local canvas
86 |
87 | decorView:post(object(Runnable, {
88 | run = function(this)
89 | if not status_bar_height or not navigation_bar_height then
90 | local visible_rect = Rect()
91 | decorView:getWindowVisibleDisplayFrame(visible_rect)
92 | status_bar_height = visible_rect.top
93 | navigation_bar_height = decorView:getHeight() - visible_rect.bottom
94 | end
95 |
96 | if not decor_view_bitmap or decor_view_bitmap:isRecycled() or not canvas then
97 | decor_view_bitmap = Bitmap:createBitmap(decorView:getWidth(), decorView:getHeight(), BitmapConfig.ARGB_8888)
98 | canvas = Canvas(decor_view_bitmap)
99 | end
100 |
101 | decorView:draw(canvas)
102 |
103 | local width = decorView:getWidth()
104 | local step = math.floor(width / config.samples)
105 |
106 | -- compute and set status bar color
107 | if config.status_bar then
108 | local colors = {}
109 | for x = 0, decorView:getWidth() - 1, step do
110 | colors[#colors + 1] = decor_view_bitmap:getPixel(x, status_bar_height + 1)
111 | end
112 | local old_color = window:getStatusBarColor()
113 | local new_color = get_most_frequent_color(colors)
114 | if old_color ~= new_color then
115 | color_animator(old_color, new_color, config.refresh_rate, function(this, animation)
116 | window:setStatusBarColor(animation:getAnimatedValue())
117 | end)
118 | end
119 | end
120 |
121 | -- compute and setnavigation bar color
122 | if config.navigation_bar then
123 | local colors = {}
124 | for x = 0, decorView:getWidth() - 1, step do
125 | colors[#colors + 1] = decor_view_bitmap:getPixel(x, decorView:getHeight() - (navigation_bar_height + 1))
126 | end
127 | local old_color = window:getNavigationBarColor()
128 | local new_color = get_most_frequent_color(colors)
129 | if old_color ~= new_color then
130 | color_animator(old_color, new_color, config.refresh_rate, function(this, animation)
131 | window:setNavigationBarColor(animation:getAnimatedValue())
132 | end)
133 | end
134 | end
135 |
136 | decorView:postDelayed(this, config.refresh_rate)
137 | end,
138 | }))
139 | end,
140 | }
141 |
142 | hook {
143 | class = Activity,
144 | returns = void,
145 | method = "onDestroy",
146 | after = function()
147 | if decor_view_bitmap and not decor_view_bitmap:isRecycled() then
148 | decor_view_bitmap:recycle()
149 | end
150 | end,
151 | }
152 | end
153 |
154 | return M
155 |
--------------------------------------------------------------------------------
/scripts/ikws4.example.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | @metadata
3 | return {
4 | name = "example",
5 | author = "ikws4",
6 | version = "1.0.0",
7 | description = "A complete example to show you how to write scripts."
8 | }
9 | @end
10 | --]]
11 |
12 | local config = {
13 | toast_msg = nil,
14 | text = nil,
15 | }
16 |
17 | local M = {}
18 |
19 | M.setup = function(opts)
20 | config = table.extend(config, opts or {})
21 |
22 | -- Easy to import any java class and support for private field, method and constructor access
23 | local Toast = import("android.widget.Toast")
24 | local Activity = import("android.app.Activity")
25 | local TextView = import("android.widget.TextView")
26 | local Bundle = import("android.os.Bundle")
27 | local CharSequence = import("java.lang.CharSequence")
28 | local BufferType = import("android.widget.TextView$BufferType")
29 |
30 | if config.toast_msg then
31 | -- Make a toast after activity created
32 | hook {
33 | class = Activity,
34 | returns = void,
35 | method = "onCreate",
36 | params = {
37 | Bundle,
38 | },
39 | after = function(this, params)
40 | Toast:makeText(this, config.toast_msg, Toast.LENGTH_SHORT):show()
41 | -- ^
42 | -- Note: `this` is the Activity instance
43 | end,
44 | }
45 | end
46 |
47 | if config.text then
48 | -- Change all the text to `config.text`
49 | hook {
50 | class = TextView,
51 | returns = void,
52 | method = "setText",
53 | params = {
54 | CharSequence, -- text
55 | BufferType, -- type
56 | boolean, -- nofityBefore
57 | int, -- oldLen
58 | },
59 | before = function(this, params)
60 | -- Reset `text` value
61 | params[1] = config.text
62 | -- ^
63 | -- Note: In lua, index is 1 based
64 | end,
65 | }
66 | end
67 | end
68 |
69 | return M
70 |
--------------------------------------------------------------------------------
/scripts/ikws4.system_variable.lua:
--------------------------------------------------------------------------------
1 | --[=[
2 | @metadata
3 | return {
4 | name = "system_variable",
5 | author = "ikws4",
6 | version = "1.1.1",
7 | description = "Configing the variables, like phone model, location, dpi etc...",
8 | example = [[
9 | require("ikws4.system_variable").setup {
10 | build = {
11 | device = "coral",
12 | product = "coral",
13 | model = "Pixel 4 XL",
14 | brand = "google",
15 | android_version = "13",
16 | },
17 | location = {
18 | longitude = 31.921279,
19 | latitude = 620.157480,
20 | },
21 | display = {
22 | dpi = 320,
23 | language = "en-US",
24 | },
25 | }
26 | ]]
27 | }
28 | @end
29 | --]=]
30 |
31 | local config = {
32 | build = {
33 | device = nil,
34 | product = nil,
35 | model = nil,
36 | brand = nil,
37 | android_version = nil,
38 | },
39 | location = {
40 | -- See https://www.latlong.net/
41 | longitude = nil,
42 | latitude = nil,
43 | },
44 | display = {
45 | dpi = nil,
46 | -- See https://www.fincher.org/Utilities/CountryLanguageList.shtml
47 | language = nil,
48 | },
49 | }
50 |
51 | local M = {}
52 |
53 | M.setup = function(opts)
54 | config = table.extend(config, opts or {})
55 |
56 | local Build = import("android.os.Build")
57 |
58 | Build.DEVICE = config.build.device or Build.DEVICE
59 | Build.PRODUCT = config.build.product or Build.PRODUCT
60 | Build.MODEL = config.build.model or Build.MODEL
61 | Build.BRAND = config.build.brand or Build.BRAND
62 | Build.MANUFACTURER = config.build.brand or Build.MANUFACTURER
63 | Build.VERSION.RELEASE = config.build.android_version or Build.VERSION.RELEASE
64 |
65 | local location_classes = {
66 | "android.location.Location", -- Android
67 | "com.baidu.location.BDLocation", -- Baidu
68 | }
69 |
70 | for _, class in ipairs(location_classes) do
71 | local ok, class = pcall(import, class)
72 |
73 | if ok then
74 | if config.location.longitude then
75 | hook {
76 | class = class,
77 | returns = double,
78 | method = "getLongitude",
79 | replace = function(this, params)
80 | return config.location.longitude
81 | end,
82 | }
83 | end
84 |
85 | if config.location.latitude then
86 | hook {
87 | class = class,
88 | returns = double,
89 | method = "getLatitude",
90 | replace = function(this, params)
91 | return config.location.latitude
92 | end,
93 | }
94 | end
95 | end
96 | end
97 |
98 | if config.display.dpi or config.display.language then
99 | local ContextWrapper = import("android.content.ContextWrapper")
100 | local Configuration = import("android.content.res.Configuration")
101 | local Context = import("android.content.Context")
102 |
103 | hook {
104 | class = ContextWrapper,
105 | returns = void,
106 | method = "attachBaseContext",
107 | params = {
108 | Context,
109 | },
110 | before = function(this, params)
111 | local context = params[1]
112 |
113 | -- Make a copy of the configuration, and then modify the dpi
114 | local new_configuration = Configuration(context:getResources():getConfiguration())
115 |
116 | if config.display.dpi then
117 | new_configuration.densityDpi = config.display.dpi
118 | end
119 |
120 | -- Change the language
121 | if config.display.language then
122 | local String = import("java.lang.String")
123 | local Locale = import("java.util.Locale")
124 |
125 | local country_city = config.display.language:split("-")
126 | local locale = Locale(country_city[1], country_city[2])
127 | Locale:setDefault(locale)
128 | new_configuration:setLocale(locale)
129 | end
130 |
131 | params[1] = context:createConfigurationContext(new_configuration)
132 | end,
133 | }
134 | end
135 | end
136 |
137 | return M
138 |
--------------------------------------------------------------------------------
/scripts/ikws4.webview_custom_css.lua:
--------------------------------------------------------------------------------
1 | --[==[
2 | @metadata
3 | return {
4 | name = "webview_custom_css",
5 | author = "ikws4",
6 | version = "1.0.1",
7 | description = "Inject custom css into WebView",
8 | example = [=[
9 | require("ikws4.webview_custom_css").setup {
10 | css = [[
11 | * {
12 | color: white;
13 | background: black;
14 | }
15 | ]],
16 | }
17 | ]=]
18 | }
19 | @end
20 | --]==]
21 |
22 | local config = {
23 | css = nil,
24 | }
25 |
26 | local M = {}
27 |
28 | M.setup = function(opts)
29 | config = table.extend(config, opts or {})
30 |
31 | local WebViewClient = import("android.webkit.WebViewClient")
32 | local WebView = import("android.webkit.WebView")
33 | local String = import("java.lang.String")
34 | local Bitmap = import("android.graphics.Bitmap")
35 |
36 | if config.css then
37 | hook {
38 | class = WebViewClient,
39 | returns = void,
40 | method = "onPageStarted",
41 | params = {
42 | WebView,
43 | String,
44 | Bitmap,
45 | },
46 | after = function(this, params)
47 | local view = params[1]
48 | local settings = view:getSettings()
49 |
50 | if not settings:getJavaScriptEnabled() then
51 | settings:setJavaScriptEnabled(true)
52 | end
53 | end,
54 | }
55 |
56 | hook {
57 | class = WebViewClient,
58 | returns = void,
59 | method = "onPageCommitVisible",
60 | params = {
61 | WebView,
62 | String,
63 | },
64 | after = function(this, params)
65 | local view = params[1]
66 | local css = string.gsub(config.css, "\n", "\\n")
67 |
68 | -- inject custom css
69 | local injection = string.format(
70 | [[
71 | (function() {
72 | var style = document.createElement('style');
73 | style.type = 'text/css';
74 | style.innerHTML = '%s';
75 | document.head.appendChild(style);
76 | })()
77 | ]],
78 | css
79 | )
80 |
81 | view:evaluateJavascript(injection, nil)
82 | end,
83 | }
84 | end
85 | end
86 |
87 | return M
88 |
--------------------------------------------------------------------------------
/stylua.toml:
--------------------------------------------------------------------------------
1 | column_width = 120
2 | line_endings = "Unix"
3 | indent_type = "Spaces"
4 | indent_width = 2
5 | quote_style = "AutoPreferDouble"
6 | call_parentheses = "NoSingleTable"
7 |
--------------------------------------------------------------------------------