html2apk 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1027,17 +1027,26 @@ h2 {
1027
1027
 
1028
1028
  .log-console {
1029
1029
  height: min(620px, calc(100vh - 230px));
1030
+ min-height: 0;
1031
+ box-sizing: border-box;
1030
1032
  overflow: auto;
1031
1033
  border: 1px solid var(--line);
1032
1034
  border-radius: 8px;
1033
1035
  background: #0c1117;
1034
1036
  color: #d6e4f7;
1035
- padding: 18px;
1037
+ padding: 18px 18px 34px;
1038
+ scroll-padding-bottom: 34px;
1036
1039
  font-family: "Cascadia Mono", Consolas, monospace;
1037
1040
  font-size: 13px;
1038
1041
  line-height: 1.55;
1039
1042
  }
1040
1043
 
1044
+ .log-console::after {
1045
+ content: "";
1046
+ display: block;
1047
+ height: 12px;
1048
+ }
1049
+
1041
1050
  .log-line {
1042
1051
  padding: 4px 0;
1043
1052
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
@@ -1407,9 +1416,10 @@ body.logs-visible .bottom-log-bar {
1407
1416
  }
1408
1417
 
1409
1418
  .bottom-log-console {
1410
- height: auto;
1419
+ height: 100%;
1411
1420
  min-height: 0;
1412
- padding: 10px 12px;
1421
+ padding: 10px 12px 26px;
1422
+ scroll-padding-bottom: 26px;
1413
1423
  font-size: 12px;
1414
1424
  line-height: 1.4;
1415
1425
  }
@@ -55,29 +55,74 @@ function getAndroidSdkPath(env = process.env) {
55
55
  return defaultAndroidSdkCandidates(env).find(pathExists) || env.ANDROID_HOME || env.ANDROID_SDK_ROOT || null;
56
56
  }
57
57
 
58
- function getJavaHome(env = process.env) {
58
+ function getValidJavaHome(dir) {
59
+ if (!pathExists(dir)) {
60
+ return null;
61
+ }
62
+ const javaExe = process.platform === "win32" ? "java.exe" : "java";
63
+ if (pathExists(path.join(dir, "bin", javaExe))) {
64
+ return dir;
65
+ }
66
+ // Support macOS virtual machine package structures
67
+ const macHome = path.join(dir, "Contents", "Home");
68
+ if (pathExists(path.join(macHome, "bin", javaExe))) {
69
+ return macHome;
70
+ }
71
+ return null;
72
+ }
73
+
74
+ function getJavaHome(env = process.env, parentDirsOverride = null) {
59
75
  if (env.JAVA_HOME && pathExists(env.JAVA_HOME)) {
60
76
  return env.JAVA_HOME;
61
77
  }
62
78
 
63
- const candidates = [];
64
- if (process.platform === "win32") {
65
- candidates.push(
66
- latestSubdir(path.join(process.env.ProgramFiles || "C:\\Program Files", "Eclipse Adoptium")),
67
- latestSubdir(path.join(process.env.ProgramFiles || "C:\\Program Files", "Java"))
68
- );
69
- } else if (process.platform === "darwin") {
70
- candidates.push(
71
- latestSubdir("/Library/Java/JavaVirtualMachines")
72
- );
73
- } else {
74
- candidates.push(
75
- latestSubdir("/usr/lib/jvm"),
76
- latestSubdir("/usr/java")
77
- );
79
+ const parentDirs = parentDirsOverride || [];
80
+ if (!parentDirsOverride) {
81
+ if (process.platform === "win32") {
82
+ parentDirs.push(
83
+ path.join(process.env.ProgramFiles || "C:\\Program Files", "Eclipse Adoptium"),
84
+ path.join(process.env.ProgramFiles || "C:\\Program Files", "Java")
85
+ );
86
+ } else if (process.platform === "darwin") {
87
+ parentDirs.push(
88
+ "/Library/Java/JavaVirtualMachines"
89
+ );
90
+ } else {
91
+ parentDirs.push(
92
+ "/usr/lib/jvm",
93
+ "/usr/java"
94
+ );
95
+ }
96
+ }
97
+
98
+ for (const parent of parentDirs) {
99
+ if (!pathExists(parent)) {
100
+ continue;
101
+ }
102
+ try {
103
+ const entries = fs.readdirSync(parent)
104
+ .filter((name) => {
105
+ try {
106
+ return fs.statSync(path.join(parent, name)).isDirectory();
107
+ } catch {
108
+ return false;
109
+ }
110
+ })
111
+ .sort((a, b) => b.localeCompare(a, undefined, { numeric: true }));
112
+
113
+ for (const name of entries) {
114
+ const fullPath = path.join(parent, name);
115
+ const valid = getValidJavaHome(fullPath);
116
+ if (valid) {
117
+ return valid;
118
+ }
119
+ }
120
+ } catch {
121
+ // Ignore directory read errors and check next parent
122
+ }
78
123
  }
79
124
 
80
- return candidates.find(pathExists) || env.JAVA_HOME || null;
125
+ return env.JAVA_HOME || null;
81
126
  }
82
127
 
83
128
  function latestSubdir(parent) {
@@ -157,6 +202,23 @@ function getRuntimeEnvironment(env = process.env) {
157
202
  pathEntries.push(path.join(gradleHome, "bin"));
158
203
  }
159
204
 
205
+ // Ensure common system directories are present in PATH, since GUI/desktop
206
+ // launchers on Linux often inherit a minimal PATH that omits /usr/local/bin.
207
+ if (process.platform !== "win32") {
208
+ const systemDirs = [
209
+ "/usr/local/bin",
210
+ "/usr/local/sbin",
211
+ "/usr/bin",
212
+ "/usr/sbin"
213
+ ];
214
+ const currentPath = (nextEnv.PATH || "").split(pathDelimiter());
215
+ for (const dir of systemDirs) {
216
+ if (!currentPath.includes(dir) && pathExists(dir)) {
217
+ pathEntries.push(dir);
218
+ }
219
+ }
220
+ }
221
+
160
222
  prependToPath(nextEnv, pathEntries);
161
223
 
162
224
  return {
@@ -23,10 +23,21 @@
23
23
  <uses-permission android:name="android.permission.USE_BIOMETRIC" />
24
24
  <uses-permission android:name="android.permission.USE_FINGERPRINT" />
25
25
  <uses-permission android:name="android.permission.SET_WALLPAPER" />
26
+ <uses-permission android:name="android.permission.INTERNET" />
26
27
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
28
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
29
+ <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
30
+ <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
27
31
  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
32
+ <uses-permission android:name="android.permission.NFC" />
33
+ <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
34
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
35
+ <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
36
+ <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
28
37
  <uses-feature android:name="android.hardware.camera" android:required="false" />
29
38
  <uses-feature android:name="android.hardware.camera.flash" android:required="false" />
39
+ <uses-feature android:name="android.hardware.bluetooth" android:required="false" />
40
+ <uses-feature android:name="android.hardware.nfc" android:required="false" />
30
41
  <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
31
42
  <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
32
43
  </config-file>
@@ -52,6 +63,27 @@
52
63
  </receiver>
53
64
  </config-file>
54
65
 
66
+ <config-file target="AndroidManifest.xml" parent="/manifest/application/activity">
67
+ <intent-filter>
68
+ <action android:name="android.intent.action.SEND" />
69
+ <category android:name="android.intent.category.DEFAULT" />
70
+ <data android:mimeType="text/plain" />
71
+ <data android:mimeType="image/*" />
72
+ <data android:mimeType="video/*" />
73
+ <data android:mimeType="application/pdf" />
74
+ <data android:mimeType="*/*" />
75
+ </intent-filter>
76
+ <intent-filter>
77
+ <action android:name="android.intent.action.SEND_MULTIPLE" />
78
+ <category android:name="android.intent.category.DEFAULT" />
79
+ <data android:mimeType="text/plain" />
80
+ <data android:mimeType="image/*" />
81
+ <data android:mimeType="video/*" />
82
+ <data android:mimeType="application/pdf" />
83
+ <data android:mimeType="*/*" />
84
+ </intent-filter>
85
+ </config-file>
86
+
55
87
  <source-file src="src/android/Html2ApkBridge.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
56
88
  <source-file src="src/android/FloatingIconService.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
57
89
  <source-file src="src/android/NotificationReceiver.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
@@ -60,5 +92,6 @@
60
92
  <source-file src="src/android/NotificationStore.java" target-dir="app/src/main/java/dev/html2apk/bridge" />
61
93
  <resource-file src="src/android/xml/html2apk_file_paths.xml" target="res/xml/html2apk_file_paths.xml" />
62
94
  <framework src="androidx.core:core:1.12.0" />
95
+ <framework src="com.google.mlkit:text-recognition:16.0.1" />
63
96
  </platform>
64
97
  </plugin>
@@ -2,6 +2,7 @@ package dev.html2apk.bridge;
2
2
 
3
3
  import android.app.Service;
4
4
  import android.content.Intent;
5
+ import android.content.SharedPreferences;
5
6
  import android.graphics.PixelFormat;
6
7
  import android.graphics.drawable.GradientDrawable;
7
8
  import android.os.Build;
@@ -14,9 +15,14 @@ import android.view.WindowManager;
14
15
  import android.widget.ImageView;
15
16
 
16
17
  public class FloatingIconService extends Service {
18
+ private static final String PREFS_NAME = "html2apk_bridge";
19
+ private static final String OPACITY_KEY = "floating_icon_opacity";
20
+ private static final String EXTRA_OPACITY = "opacity";
21
+
17
22
  private WindowManager windowManager;
18
23
  private View floatingView;
19
24
  private WindowManager.LayoutParams params;
25
+ private float opacity = 1f;
20
26
  private int startX;
21
27
  private int startY;
22
28
  private float touchStartX;
@@ -29,6 +35,11 @@ public class FloatingIconService extends Service {
29
35
 
30
36
  @Override
31
37
  public int onStartCommand(Intent intent, int flags, int startId) {
38
+ applyOptions(intent);
39
+ if (floatingView != null) {
40
+ applyFloatingIconStyle();
41
+ return START_STICKY;
42
+ }
32
43
  showFloatingIcon();
33
44
  return START_STICKY;
34
45
  }
@@ -60,6 +71,7 @@ public class FloatingIconService extends Service {
60
71
  int padding = dp(8);
61
72
  icon.setImageDrawable(getApplicationInfo().loadIcon(getPackageManager()));
62
73
  icon.setPadding(padding, padding, padding, padding);
74
+ icon.setAlpha(opacity);
63
75
 
64
76
  GradientDrawable background = new GradientDrawable();
65
77
  background.setShape(GradientDrawable.OVAL);
@@ -125,6 +137,23 @@ public class FloatingIconService extends Service {
125
137
  floatingView = null;
126
138
  }
127
139
 
140
+ private void applyOptions(Intent intent) {
141
+ SharedPreferences preferences = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
142
+ float nextOpacity = preferences.getFloat(OPACITY_KEY, 1f);
143
+ if (intent != null && intent.hasExtra(EXTRA_OPACITY)) {
144
+ nextOpacity = intent.getFloatExtra(EXTRA_OPACITY, nextOpacity);
145
+ nextOpacity = clampOpacity(nextOpacity);
146
+ preferences.edit().putFloat(OPACITY_KEY, nextOpacity).apply();
147
+ }
148
+ opacity = clampOpacity(nextOpacity);
149
+ }
150
+
151
+ private void applyFloatingIconStyle() {
152
+ if (floatingView != null) {
153
+ floatingView.setAlpha(opacity);
154
+ }
155
+ }
156
+
128
157
  private void openApp() {
129
158
  Intent launchIntent = getPackageManager().getLaunchIntentForPackage(getPackageName());
130
159
  if (launchIntent == null) {
@@ -138,4 +167,8 @@ public class FloatingIconService extends Service {
138
167
  private int dp(int value) {
139
168
  return Math.round(value * getResources().getDisplayMetrics().density);
140
169
  }
170
+
171
+ private float clampOpacity(float value) {
172
+ return Math.max(0.1f, Math.min(1f, value));
173
+ }
141
174
  }