Skip to content

Commit

Permalink
Merge pull request #431 from doubleangels/dev
Browse files Browse the repository at this point in the history
Bug fixes, introduce swipe to refresh
  • Loading branch information
doubleangels authored Feb 19, 2025
2 parents 77dd2cf + fa20470 commit 329d604
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 119 deletions.
5 changes: 3 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ android {
applicationId "com.doubleangels.nextdnsmanagement"
minSdkVersion 32
targetSdk = 35
versionCode 252
versionName "5.5.3"
versionCode 253
versionName "5.5.4"
resourceConfigurations += ["en", "zh", "nl", "fi", "fr", "de", "in", "it", "ja", "pl", "pt", "es", "sv", "tr"]
}

Expand Down Expand Up @@ -68,6 +68,7 @@ dependencies {
implementation 'androidx.preference:preference:1.2.1'
implementation 'androidx.webkit:webkit:1.12.1'
implementation 'com.google.android.material:material:1.12.0'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'

// Only include Firebase Messaging in the gms flavor:
gmsImplementation 'com.google.firebase:firebase-messaging:24.1.0'
Expand Down
122 changes: 69 additions & 53 deletions app/src/foss/java/com/doubleangels/nextdnsmanagement/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import android.annotation.SuppressLint;
import android.app.DownloadManager;
import android.content.ComponentCallbacks2;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
Expand All @@ -15,6 +14,7 @@
import android.view.MenuItem;
import android.view.Window;
import android.webkit.CookieManager;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
Expand All @@ -28,13 +28,15 @@
import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.LifecycleOwner;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import androidx.webkit.WebSettingsCompat;
import androidx.webkit.WebViewFeature;

import com.doubleangels.nextdnsmanagement.protocol.VisualIndicator;
import com.doubleangels.nextdnsmanagement.sentry.SentryInitializer;
import com.doubleangels.nextdnsmanagement.sentry.SentryManager;
import com.doubleangels.nextdnsmanagement.sharedpreferences.SharedPreferencesManager;
import com.doubleangels.nextdnsmanagement.webview.WebAppInterface;

import java.util.Locale;

Expand All @@ -47,6 +49,8 @@ public class MainActivity extends AppCompatActivity {

// Main WebView for displaying content
private WebView webView;
// SwipeRefreshLayout for handling pull-to-refresh
private SwipeRefreshLayout swipeRefreshLayout;
// Indicates whether dark mode is currently enabled
private Boolean darkModeEnabled = false;
// Indicates if the WebView is initialized to avoid re-initialization
Expand Down Expand Up @@ -121,6 +125,9 @@ protected void onCreate(Bundle savedInstanceState) {
// Set up any additional UI indicators
setupVisualIndicatorForActivity(sentryManager, this);

// Set up swipe to refresh
setupSwipeToRefreshForActivity();

// Initialize the WebView, load the main URL
setupWebViewForActivity(getString(R.string.main_url));
} catch (Exception e) {
Expand All @@ -135,35 +142,7 @@ protected void onCreate(Bundle savedInstanceState) {
@Override
protected void onDestroy() {
super.onDestroy();
cleanupWebView();
}

/**
* Called when the app is running low on memory. If the WebView is initialized,
* destroy it to free resources.
*/
@Override
public void onLowMemory() {
super.onLowMemory();
if (!isWebViewInitialized) {
return;
}
cleanupWebView();
}

/**
* Called when the app should trim memory. If the trim level is high enough,
* the WebView is destroyed to free up resources.
*/
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
if (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE) {
if (!isWebViewInitialized) {
return;
}
cleanupWebView();
}
webView.destroy();
}

/**
Expand Down Expand Up @@ -315,23 +294,6 @@ private void setupVisualIndicatorForActivity(SentryManager sentryManager, Lifecy
}
}

/**
* Cleans up the WebView by loading a blank page, removing all views, and destroying the WebView.
* This frees up memory and resources.
*/
private void cleanupWebView() {
if (webView != null) {
try {
webView.loadUrl("about:blank");
webView.removeAllViews();
webView.destroy();
} finally {
webView = null;
isWebViewInitialized = false;
}
}
}

/**
* Initializes and configures the WebView, including JavaScript, DOM storage,
* caching, and download handling. Optionally restores a previously saved WebView state.
Expand Down Expand Up @@ -369,8 +331,26 @@ public void onPageFinished(WebView webView, String url) {
CookieManager.getInstance().acceptCookie();
// Flush cookies to ensure persistence
CookieManager.getInstance().flush();
// Inject JavaScript to enable swipe-to-refresh
String js =
"setInterval(function() {" +
" var modal = document.querySelector('.modal-dialog.modal-lg.modal-dialog-scrollable');" +
" if (modal) {" +
" if (!modal.getAttribute('data-listeners-attached')) {" +
" modal.setAttribute('data-listeners-attached', 'true');" +
" modal.addEventListener('touchstart', function(){" +
" AndroidInterface.setSwipeRefreshEnabled(false);" +
" });" +
" modal.addEventListener('touchend', function(){" +
" AndroidInterface.setSwipeRefreshEnabled(true);" +
" });" +
" }" +
" }" +
"}, 500);";
webView.evaluateJavascript(js, null);
}
});
webView.setWebChromeClient(new WebChromeClient());

// Enable or disable algorithmic darkening for WebView if dark mode is active
if (Boolean.TRUE.equals(darkModeEnabled)) {
Expand All @@ -389,6 +369,27 @@ public void onPageFinished(WebView webView, String url) {
isWebViewInitialized = true;
}

/**
* Initializes and configures the SwipeRefreshLayout and WebView. This method enables JavaScript,
* attaches a JavaScript interface for native-to-JS communication, and sets up a refresh listener
* that reloads the WebView when a swipe-to-refresh gesture is detected.
*/
@SuppressLint("SetJavaScriptEnabled")
private void setupSwipeToRefreshForActivity() {
swipeRefreshLayout = findViewById(R.id.swipeRefreshLayout);
webView = findViewById(R.id.webView);

// Enable JavaScript and add our JS interface.
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new WebAppInterface(this, swipeRefreshLayout), "AndroidInterface");

// Setup refresh listener (if pull-to-refresh should work elsewhere)
swipeRefreshLayout.setOnRefreshListener(() -> {
webView.reload();
swipeRefreshLayout.setRefreshing(false);
});
}

/**
* Sets up a listener to handle file downloads from within the WebView using the system
* DownloadManager. It saves files to the app's external files directory by default.
Expand Down Expand Up @@ -448,20 +449,35 @@ public boolean onCreateOptionsMenu(@NonNull Menu menu) {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.back:
// Go back in the WebView history
webView.goBack();
if (webView == null) {
// Re-set up the WebView if it's null
setupWebViewForActivity(getString(R.string.main_url));
} else {
// Go back in the WebView history
webView.goBack();
}
break;
case R.id.refreshNextDNS:
// Reload the current WebView page
webView.reload();
if (webView == null) {
// Re-set up the WebView if it's null
setupWebViewForActivity(getString(R.string.main_url));
} else {
// Reload the current WebView page
webView.reload();
}
break;
case R.id.pingNextDNS:
// Start PingActivity
startIntent(PingActivity.class);
break;
case R.id.returnHome:
// Navigate to the main URL in the WebView
webView.loadUrl(getString(R.string.main_url));
if (webView == null) {
// Re-set up the WebView if it's null
setupWebViewForActivity(getString(R.string.main_url));
} else {
// Navigate to the main URL in the WebView
webView.loadUrl(getString(R.string.main_url));
}
break;
case R.id.privateDNS:
// Launch system settings for Private DNS
Expand Down
Loading

0 comments on commit 329d604

Please sign in to comment.