= 80 ? "rating-high" : rating.replace("%", "") >= 50 ? "" : "rating-low"}`}
+ className={`rating-value ${rating === "unrated" ? "" : rating.replace("%", "") >= 80 ? "rating-high" : rating.replace("%", "") >= 50 ? "rating-medium" : "rating-low"}`}
>
{rating}
diff --git a/src/pages/plugins/plugins.scss b/src/pages/plugins/plugins.scss
index d8b3635aa..37860ddbb 100644
--- a/src/pages/plugins/plugins.scss
+++ b/src/pages/plugins/plugins.scss
@@ -293,6 +293,15 @@
box-shadow 180ms ease;
}
+ @supports not (gap: 1px) {
+ .plugin-header > * + * { margin-left: 0.75rem; }
+ .plugin-info > * + * { margin-left: 0.75rem; }
+ .plugin-title > * + * { margin-left: 0.75rem; }
+ .plugin-meta > * + * { margin-left: 0.5rem; }
+ .plugin-stats > * + * { margin-left: 0.375rem; }
+ .plugin-price > * + * { margin-left: 0.25rem; }
+ }
+
.plugin-toggle-switch[data-enabled="true"] .plugin-toggle-thumb,
.plugin-toggle-track[data-enabled="true"] .plugin-toggle-thumb {
transform: translateX(1.12rem);
diff --git a/src/pages/quickTools/style.scss b/src/pages/quickTools/style.scss
index 674a19326..4503198c4 100644
--- a/src/pages/quickTools/style.scss
+++ b/src/pages/quickTools/style.scss
@@ -128,6 +128,10 @@
}
}
+ @supports not (gap: 1px) {
+ .quicktools-grid > * { margin-right: 8px; margin-bottom: 8px; }
+ }
+
.tool-ghost {
position: fixed;
top: 0;
diff --git a/src/pages/sponsor/style.scss b/src/pages/sponsor/style.scss
index b1e538c38..dc2c16f7d 100644
--- a/src/pages/sponsor/style.scss
+++ b/src/pages/sponsor/style.scss
@@ -106,6 +106,10 @@
line-height: 1.4;
}
+ @supports not (gap: 1px) {
+ .tier-header > * + * { margin-left: 0.5rem; }
+ }
+
.purchase-btn {
background: var(--button-background-color);
color: var(--button-text-color);
diff --git a/src/pages/sponsors/style.scss b/src/pages/sponsors/style.scss
index eb5f6ab89..60d778430 100644
--- a/src/pages/sponsors/style.scss
+++ b/src/pages/sponsors/style.scss
@@ -95,6 +95,10 @@
}
}
+ @supports not (gap: 1px) {
+ .sponsors > * { margin-right: 1rem; margin-bottom: 1rem; }
+ }
+
.sponsor-card {
flex-grow: 1;
min-width: 150px;
diff --git a/src/pages/themeSetting/themeSetting.scss b/src/pages/themeSetting/themeSetting.scss
index d89b7ad7e..789edbb5b 100644
--- a/src/pages/themeSetting/themeSetting.scss
+++ b/src/pages/themeSetting/themeSetting.scss
@@ -31,6 +31,7 @@
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 0.72fr);
grid-template-rows: repeat(2, minmax(0, 1fr));
+ gap: 1px;
width: 1.5rem;
min-width: 1.5rem;
height: 1.5rem;
@@ -52,4 +53,17 @@
.theme-swatch-main {
grid-row: 1 / 3;
}
+
+ @supports not (gap: 1px) {
+ .theme-swatch-main {
+ margin-right: 1px;
+ }
+ .theme-swatch:nth-child(2) {
+ margin-left: 1px;
+ margin-bottom: 1px;
+ }
+ .theme-swatch:nth-child(3) {
+ margin-left: 1px;
+ }
+ }
}
diff --git a/src/pages/welcome/welcome.scss b/src/pages/welcome/welcome.scss
index ae94a415d..5a1a95840 100644
--- a/src/pages/welcome/welcome.scss
+++ b/src/pages/welcome/welcome.scss
@@ -148,6 +148,14 @@
}
}
+ @supports not (gap: 1px) {
+ .welcome-header > * + * { margin-left: 16px; }
+ .action-list > * + * { margin-top: 2px; }
+ .action-row > * + * { margin-left: 12px; }
+ .link-row > * { margin-right: 8px; margin-bottom: 8px; }
+ .link-item > * + * { margin-left: 8px; }
+ }
+
// Responsive adjustments for smaller screens
@media (max-width: 360px) {
#welcome-tab {
diff --git a/src/plugins/admob/src/android/cordova/ads/Banner.kt b/src/plugins/admob/src/android/cordova/ads/Banner.kt
index aea50f96b..57460f2b8 100644
--- a/src/plugins/admob/src/android/cordova/ads/Banner.kt
+++ b/src/plugins/admob/src/android/cordova/ads/Banner.kt
@@ -4,7 +4,6 @@ import admob.plus.cordova.Events
import admob.plus.cordova.ExecuteContext
import admob.plus.core.buildAdSize
import admob.plus.core.pxToDp
-import android.annotation.SuppressLint
import android.content.res.Configuration
import android.util.Log
import android.view.Gravity
@@ -12,7 +11,6 @@ import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.widget.FrameLayout
-import android.widget.LinearLayout
import android.widget.RelativeLayout
import com.google.android.gms.ads.AdListener
import com.google.android.gms.ads.AdSize
@@ -24,6 +22,7 @@ enum class AdSizeType {
BANNER, LARGE_BANNER, MEDIUM_RECTANGLE, FULL_BANNER, LEADERBOARD, SMART_BANNER;
companion object {
+ @Suppress("DEPRECATION")
fun getAdSize(adSize: Int): AdSize? {
return when (values()[adSize]) {
BANNER -> AdSize.BANNER
@@ -32,7 +31,6 @@ enum class AdSizeType {
FULL_BANNER -> AdSize.FULL_BANNER
LEADERBOARD -> AdSize.LEADERBOARD
SMART_BANNER -> AdSize.SMART_BANNER
- else -> null
}
}
}
@@ -131,12 +129,9 @@ class Banner(ctx: ExecuteContext) : AdBase(ctx) {
} else if (mAdView!!.visibility == View.GONE) {
mAdView!!.resume()
mAdView!!.visibility = View.VISIBLE
- } else {
+ // Re-apply bottom margin in case it was reset by hide()
val wvParentView = getParentView(webView)
- if (rootLinearLayout !== wvParentView && webViewWrapper !== wvParentView) {
- removeFromParentView(rootLinearLayout)
- addBannerView()
- }
+ setBottomMargin(wvParentView)
}
ctx.resolve()
}
@@ -145,6 +140,8 @@ class Banner(ctx: ExecuteContext) : AdBase(ctx) {
if (mAdView != null) {
mAdView!!.pause()
mAdView!!.visibility = View.GONE
+ val wvParentView = getParentView(webView)
+ resetBottomMargin(wvParentView)
}
ctx.resolve()
}
@@ -215,63 +212,34 @@ class Banner(ctx: ExecuteContext) : AdBase(ctx) {
private fun addBannerView() {
if (mAdView == null) return
if (offset == null) {
- if (getParentView(mAdView) === rootLinearLayout && rootLinearLayout != null) return
+ if (getParentView(mAdView) === plugin.contentView && plugin.contentView != null) return
addBannerViewWithLinearLayout()
} else {
if (getParentView(mAdView) === mRelativeLayout && mRelativeLayout != null) return
addBannerViewWithRelativeLayout()
}
plugin.contentView?.let {
- it.bringToFront()
it.requestLayout()
- it.requestFocus()
}
}
private fun addBannerViewWithLinearLayout() {
val wvParentView = getParentView(webView)
- if (rootLinearLayout == null) {
- rootLinearLayout = LinearLayout(plugin.activity)
- }
- if (wvParentView != null && wvParentView !== rootLinearLayout && wvParentView !== webViewWrapper) {
- if (webViewWrapper == null) {
- webViewWrapper = FrameLayout(plugin.activity)
- } else {
- removeFromParentView(webViewWrapper)
- }
- wvParentView.removeView(webView)
- val content = rootLinearLayout as LinearLayout?
- content!!.orientation = LinearLayout.VERTICAL
- rootLinearLayout!!.layoutParams = LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT,
- 0.0f
- )
- webViewWrapper!!.layoutParams = LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
+ if (wvParentView == null) return
+ // Keep the WebView in its original parent. Add the banner to
+ // contentView as a bottom-aligned sibling and push the WebView's
+ // parent up via bottom margin — no removeView/reparent needed.
+ removeFromParentView(mAdView)
+ val content = plugin.contentView
+ if (content is FrameLayout) {
+ val bannerParams = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
- 1.0f
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ Gravity.BOTTOM
)
- webViewWrapper!!.addView(webView)
- rootLinearLayout!!.addView(webViewWrapper)
- val view = getParentView(rootLinearLayout)
- if (view !== wvParentView) {
- removeFromParentView(rootLinearLayout)
- wvParentView.addView(rootLinearLayout)
- }
- }
- removeFromParentView(mAdView)
- if (isPositionTop) {
- rootLinearLayout!!.addView(mAdView, 0)
- } else {
- rootLinearLayout!!.addView(mAdView)
- }
- plugin.contentView?.let {
- for (i in 0 until it.childCount) {
- val view = it.getChildAt(i)
- (view as? RelativeLayout)?.bringToFront()
- }
+ content.addView(mAdView, bannerParams)
}
+ setBottomMargin(wvParentView)
}
private fun addBannerViewWithRelativeLayout() {
@@ -302,24 +270,25 @@ class Banner(ctx: ExecuteContext) : AdBase(ctx) {
private val isPositionTop: Boolean
get() = gravity == Gravity.TOP
+ private fun setBottomMargin(view: View?) {
+ val lp = view?.layoutParams as? FrameLayout.LayoutParams ?: return
+ lp.bottomMargin = adSize.getHeightInPixels(plugin.activity)
+ view.layoutParams = lp
+ }
+
+ private fun resetBottomMargin(view: View?) {
+ val lp = view?.layoutParams as? FrameLayout.LayoutParams ?: return
+ if (lp.bottomMargin > 0) {
+ lp.bottomMargin = 0
+ view.layoutParams = lp
+ }
+ }
+
companion object {
private const val TAG = "AdMobPlus.Banner"
- @SuppressLint("StaticFieldLeak")
- private var rootLinearLayout: ViewGroup? = null
- @SuppressLint("StaticFieldLeak")
- private var webViewWrapper: FrameLayout? = null
private var screenWidth = 0
- fun destroyParentView() {
- try {
- webViewWrapper?.removeAllViews()
- webViewWrapper = null
- val vg = getParentView(rootLinearLayout)
- vg?.removeAllViews()
- } finally {
- rootLinearLayout = null
- }
- }
+ fun destroyParentView() {}
private fun runJustBeforeBeingDrawn(view: View, runnable: Runnable) {
val preDrawListener: ViewTreeObserver.OnPreDrawListener =
diff --git a/src/plugins/admob/src/android/core/util.kt b/src/plugins/admob/src/android/core/util.kt
index 10c616431..3b912dd7d 100644
--- a/src/plugins/admob/src/android/core/util.kt
+++ b/src/plugins/admob/src/android/core/util.kt
@@ -22,11 +22,11 @@ import kotlin.math.roundToInt
fun buildAdRequest(opts: JSONObject): AdRequest {
val builder = AdRequest.Builder()
- opts.optString("contentUrl", null)?.let {
+ opts.optString("contentUrl", null as String?)?.let {
builder.setContentUrl(it)
}
val extras = Bundle().apply {
- opts.optString("npa", null)?.let { npa ->
+ opts.optString("npa", null as String?)?.let { npa ->
putString("npa", npa)
}
}
@@ -36,11 +36,13 @@ fun buildAdRequest(opts: JSONObject): AdRequest {
fun buildAdSize(opts: JSONObject, activity: Activity): AdSize {
val name = "size"
if (!opts.has(name)) {
+ @Suppress("DEPRECATION")
return AdSize.SMART_BANNER
}
val adSizeObj = opts.optJSONObject(name)
val adSize = AdSizeType.getAdSize(opts.optInt(name))
if (adSizeObj == null) {
+ @Suppress("DEPRECATION")
return adSize ?: AdSize.SMART_BANNER
}
val adaptive = adSizeObj.optString("adaptive")
@@ -84,7 +86,7 @@ fun optFloat(opts: JSONObject, name: String): Float? {
fun buildRequestConfiguration(opts: JSONObject): RequestConfiguration {
val builder = RequestConfiguration.Builder()
- opts.optString("maxAdContentRating", null)?.let {
+ opts.optString("maxAdContentRating", null as String?)?.let {
builder.setMaxAdContentRating(it)
}
optBooleanToInt(
diff --git a/src/plugins/system/www/plugin.js b/src/plugins/system/www/plugin.js
index 519b4f988..e5b26da07 100644
--- a/src/plugins/system/www/plugin.js
+++ b/src/plugins/system/www/plugin.js
@@ -222,7 +222,7 @@ module.exports = {
onFail,
'System',
'set-native-context-menu-disabled',
- [String(!!disabled)],
+ [String(!!disabled)]
);
},
getGlobalSetting: function (key, onSuccess, onFail) {
diff --git a/src/sidebarApps/extensions/index.js b/src/sidebarApps/extensions/index.js
index c59d9063c..07e14cc8a 100644
--- a/src/sidebarApps/extensions/index.js
+++ b/src/sidebarApps/extensions/index.js
@@ -11,6 +11,7 @@ import config from "lib/config";
import InstallState from "lib/installState";
import loadPlugin from "lib/loadPlugin";
import settings from "lib/settings";
+import { interstitialAd } from "lib/startAd";
import FileBrowser from "pages/fileBrowser";
import plugin from "pages/plugin";
import helpers from "utils/helpers";
@@ -861,10 +862,10 @@ function ListItem({
async function loadAd(el) {
if (!helpers.canShowAds()) return;
try {
- if (!(await window.iad?.isLoaded())) {
+ if (!(await interstitialAd?.isLoaded())) {
const oldText = el.textContent;
el.textContent = strings["loading..."];
- await window.iad.load();
+ await interstitialAd?.load();
el.textContent = oldText;
}
} catch (error) {
diff --git a/src/sidebarApps/extensions/style.scss b/src/sidebarApps/extensions/style.scss
index 18d79cfde..c123b8dc1 100644
--- a/src/sidebarApps/extensions/style.scss
+++ b/src/sidebarApps/extensions/style.scss
@@ -1,7 +1,33 @@
@use "../../styles/mixins.scss";
.container.extensions {
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+
+ .list.collapsible {
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+
+ &:not(.hidden) {
+ flex: 1;
+ min-height: 0;
+ }
+
+ &.hidden {
+ flex-shrink: 0;
+ }
+
+ >ul {
+ flex: 1;
+ min-height: 0;
+ overflow-y: auto;
+ }
+ }
+
.header {
+ flex-shrink: 0;
padding: 10px;
display: flex;
flex-direction: column;
@@ -67,7 +93,12 @@
}
.list.search-result {
- min-height: 0;
+ flex-shrink: 0;
+ overflow-y: auto;
+
+ &:empty {
+ display: none
+ }
&.loading {
@include mixins.loader(20px);
diff --git a/src/sidebarApps/notification/style.scss b/src/sidebarApps/notification/style.scss
index 1ca2e0866..fa2a4db4b 100644
--- a/src/sidebarApps/notification/style.scss
+++ b/src/sidebarApps/notification/style.scss
@@ -154,6 +154,13 @@
}
+@supports not (gap: 1px) {
+ .title > * + * { margin-left: 4px; }
+ .notifications-container > * + * { margin-top: 8px; }
+ .notification-item > * + * { margin-left: 10px; }
+ .action-button > * + * { margin-left: 4px; }
+}
+
@keyframes slideIn {
from {
transform: translateX(100%);
diff --git a/src/styles/codemirror.scss b/src/styles/codemirror.scss
index 972b38cf9..f0321b160 100644
--- a/src/styles/codemirror.scss
+++ b/src/styles/codemirror.scss
@@ -92,6 +92,13 @@
overflow: auto;
}
+@supports not (gap: 1px) {
+ .cm-tooltip.cm-tooltip-autocomplete {
+ > * + * { margin-left: 0.4rem; }
+ > ul > li > * + * { margin-left: 0.12rem; }
+ }
+}
+
@media (max-width: 480px) {
.cm-tooltip {
font-size: 0.9rem;
diff --git a/src/styles/fileInfo.scss b/src/styles/fileInfo.scss
index 9b3bc2397..c03f9343e 100644
--- a/src/styles/fileInfo.scss
+++ b/src/styles/fileInfo.scss
@@ -83,6 +83,12 @@
}
}
+ @supports not (gap: 1px) {
+ .file-name > * + * { margin-left: 0.5rem; }
+ .info-grid > * { margin-right: 1.5rem; margin-bottom: 1.5rem; }
+ .info-item > * + * { margin-top: 0.5rem; }
+ }
+
@media (max-width: 480px) {
.file-card {
padding: 1.5rem;
diff --git a/src/styles/wideScreen.scss b/src/styles/wideScreen.scss
index ea12e7844..5d07be586 100644
--- a/src/styles/wideScreen.scss
+++ b/src/styles/wideScreen.scss
@@ -161,6 +161,15 @@
}
#plugin {
+ @supports not (gap: 1px) {
+ .plugin-header > * { margin-right: 1.25rem; margin-bottom: 1.25rem; }
+ .plugin-header > *:last-child { margin-right: 0; margin-bottom: 0; }
+ .plugin-info > * + * { margin-left: 1.25rem; }
+ .plugin-title > * + * { margin-left: 1rem; }
+ .plugin-meta > * + * { margin-left: 0.75rem; }
+ .plugin-stats > * + * { margin-left: 0.5rem; }
+ }
+
.list-item {
margin: 0 1rem 0.75rem 1rem;
padding: 1.25rem;
diff --git a/src/utils/helpers.js b/src/utils/helpers.js
index ddea27fb4..d3175b225 100644
--- a/src/utils/helpers.js
+++ b/src/utils/helpers.js
@@ -4,6 +4,7 @@ import alert from "dialogs/alert";
import escapeStringRegexp from "escape-string-regexp";
import adRewards from "lib/adRewards";
import config from "lib/config";
+import { bannerAd, interstitialAd } from "lib/startAd";
import path from "./Path";
import Uri from "./Uri";
import Url from "./Url";
@@ -293,11 +294,11 @@ export default {
async showInterstitialIfReady() {
if (!this.canShowAds()) return false;
if (
- typeof window.iad?.isLoaded === "function" &&
- typeof window.iad?.show === "function" &&
- (await window.iad.isLoaded())
+ typeof interstitialAd?.isLoaded === "function" &&
+ typeof interstitialAd?.show === "function" &&
+ (await interstitialAd?.isLoaded())
) {
- window.iad.show();
+ interstitialAd.show();
return true;
}
return false;
@@ -306,17 +307,14 @@ export default {
* Displays ad on the current page
*/
showAd() {
- const { ad } = window;
- if (
- this.canShowAds() &&
- innerHeight * devicePixelRatio > 600 &&
- typeof ad?.show === "function"
- ) {
- const $page = tag.getAll("wc-page:not(#root)").pop();
- if ($page) {
- ad.active = true;
- ad.show();
- }
+ if (!this.canShowAds()) return;
+ if (innerHeight * devicePixelRatio <= 600) return;
+ if (!bannerAd || typeof bannerAd.show !== "function") return;
+
+ const $page = tag.getAll("wc-page:not(#root)").pop();
+ if ($page) {
+ bannerAd.active = true;
+ bannerAd.show();
}
},
async toInternalUri(uri) {
diff --git a/www/index.html b/www/index.html
index 7802e3a00..07f170909 100644
--- a/www/index.html
+++ b/www/index.html
@@ -1,195 +1,207 @@
-
-
-
-
-
-
+
+
+
+ window.addEventListener("error", handleStartupError);
+ window.addEventListener("unhandledrejection", handleStartupRejection);
+ })();
+
-
-
+
+
-
+
-
Acode
-
+
Acode
+
-
-
+
+
-
+
-
-
+ });
+
+
+