diff --git a/src/plugins/browser/android/com/foxdebug/browser/Browser.java b/src/plugins/browser/android/com/foxdebug/browser/Browser.java index f12597159b..bd0d4ab93d 100644 --- a/src/plugins/browser/android/com/foxdebug/browser/Browser.java +++ b/src/plugins/browser/android/com/foxdebug/browser/Browser.java @@ -227,6 +227,7 @@ public void onDownloadStart(String url, String userAgent, createMenu(); addView(titleLayout); addView(webViewContainer); + restoreEmulator(); } private void createMenu() { @@ -236,6 +237,10 @@ private void createMenu() { menu.addItem(Ui.Icons.DEVICES, "Devices", false); menu.addItem(Ui.Icons.NO_CACHE, "Disable Cache", false); menu.addItem(Ui.Icons.TERMINAL, "Console", false); + menu.addItem(Ui.Icons.TUNE, "Set as Default"); + menu.addItem(Ui.Icons.REFRESH, "Clear Default"); + menu.setVisible("Set as Default", false); + menu.setVisible("Clear Default", false); menu.addItem(Ui.Icons.OPEN_IN_BROWSER, "Open in Browser"); menu.addItem(Ui.Icons.EXIT, "Exit"); @@ -250,6 +255,7 @@ public void onSelect(String action, Boolean checked) { } emulator = checked; + updateDefaultItems(checked); if (checked) { setDesktopMode(true); setConsoleVisible(false); @@ -284,6 +290,26 @@ public void onGlobalLayout() { case "Console": setConsoleVisible(checked); break; + case "Set as Default": + if (deviceEmulator != null) { + deviceEmulator.saveAsDefault(); + updateDefaultItems(emulator); + Toast + .makeText( + context, + "Saved as default preview", + Toast.LENGTH_SHORT + ) + .show(); + } + break; + case "Clear Default": + Emulator.clearDefault(context); + updateDefaultItems(emulator); + Toast + .makeText(context, "Default cleared", Toast.LENGTH_SHORT) + .show(); + break; case "Disable Cache": webView .getSettings() @@ -308,6 +334,75 @@ public void onGlobalLayout() { ); } + private void updateDefaultItems(boolean emulatorOn) { + menu.setVisible("Set as Default", emulatorOn); + menu.setVisible( + "Clear Default", + emulatorOn && Emulator.hasDefault(context) + ); + } + + private void reloadAfterLayout() { + // If no page was requested yet, the first load will already happen at + // the saved size, so there is nothing to reload. + if (url.isEmpty()) return; + + webView + .getViewTreeObserver() + .addOnGlobalLayoutListener( + new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + webView.getViewTreeObserver().removeOnGlobalLayoutListener(this); + webView.reload(); + } + } + ); + } + + private void restoreEmulator() { + if (onlyConsole) return; + if (!Emulator.hasDefault(context)) return; + + // Apply the saved mode before the first navigation so the page is not + // loaded with the wrong user agent and then reloaded. + setDesktopMode(true, false); + + webView + .getViewTreeObserver() + .addOnGlobalLayoutListener( + new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + if (webView.getMeasuredWidth() == 0) return; + webView.getViewTreeObserver().removeOnGlobalLayoutListener(this); + + if (deviceEmulator == null) { + createDeviceEmulatorLayout(); + deviceEmulator.setRestoredListener( + new Runnable() { + @Override + public void run() { + reloadAfterLayout(); + } + } + ); + } + + emulator = true; + menu.setChecked("Devices", true); + updateDefaultItems(true); + setConsoleVisible(false); + menu.setChecked("Console", false); + menu.setVisible("Console", false); + addView(deviceEmulator); + // The emulator sets up its sliders on a later layout pass and then + // applies the saved size itself, so the webview is not resized here. + } + } + ); + } + private void createDeviceEmulatorLayout() { Browser browser = this; deviceEmulator = new Emulator(context, theme); @@ -339,6 +434,10 @@ private void setTextViewProperties(TextView textView, int height) { } private void setDesktopMode(boolean enabled) { + setDesktopMode(enabled, true); + } + + private void setDesktopMode(boolean enabled, boolean reload) { int width = 0; int height = 0; WebSettings webSettings = webView.getSettings(); @@ -360,7 +459,9 @@ private void setDesktopMode(boolean enabled) { webSettings.setLoadWithOverviewMode(enabled); webSettings.setSupportZoom(enabled); webSettings.setBuiltInZoomControls(enabled); - webView.reload(); + if (reload) { + webView.reload(); + } } public void setDesktopMode() { diff --git a/src/plugins/browser/android/com/foxdebug/browser/Emulator.java b/src/plugins/browser/android/com/foxdebug/browser/Emulator.java index adb65f2b1f..25f0d70eae 100644 --- a/src/plugins/browser/android/com/foxdebug/browser/Emulator.java +++ b/src/plugins/browser/android/com/foxdebug/browser/Emulator.java @@ -163,6 +163,8 @@ public void onGlobalLayout() { if (listener != null) { listener.onChange(iWidth, correctedHeight, 1); } + + restoreDefaultDevice(); } } ); @@ -302,6 +304,108 @@ private void selectDevice(Device device) { listener.onChange(width, height, maxScale / 100f); } + public static boolean hasDefault(Context context) { + return context + .getSharedPreferences("acode_browser", Context.MODE_PRIVATE) + .getBoolean("default_set", false); + } + + public static void clearDefault(Context context) { + context + .getSharedPreferences("acode_browser", Context.MODE_PRIVATE) + .edit() + .putBoolean("default_set", false) + .apply(); + } + + public void saveAsDefault() { + context + .getSharedPreferences("acode_browser", Context.MODE_PRIVATE) + .edit() + .putBoolean("default_set", true) + .putInt("default_width", getWidthProgress()) + .putInt("default_height", getHeightProgress()) + .putInt("default_scale", seekBars.get("scale").getProgress()) + .putString( + "default_device", + selectedDevice != null ? selectedDevice.name : "Custom" + ) + .apply(); + } + + private Runnable restoredListener; + + public void setRestoredListener(Runnable listener) { + restoredListener = listener; + } + + private void restoreDefaultDevice() { + if (!hasDefault(context)) return; + + android.content.SharedPreferences prefs = context.getSharedPreferences( + "acode_browser", + Context.MODE_PRIVATE + ); + SeekBar widthSeekBar = seekBars.get("width"); + SeekBar heightSeekBar = seekBars.get("height"); + SeekBar scaleSeekBar = seekBars.get("scale"); + String name = prefs.getString("default_device", "Custom"); + + Device preset = null; + for (Device device : deviceListView.devices) { + if (device.id != customDevice.id && device.name.equals(name)) { + preset = device; + break; + } + } + + if (preset != null && listener != null) { + // A preset is re-fitted to the current screen, so it keeps its shape if + // the screen size changed since it was saved (rotation, split-screen, + // foldables). Only the scale is restored from the saved value. + if (deviceListView.selectedDeviceView != null) { + deviceListView.selectedDeviceView.deselect(); + } + deviceListView.select(preset); + selectDevice(preset); + + int scale = Math.min( + prefs.getInt("default_scale", scaleSeekBar.getMax()), + scaleSeekBar.getMax() + ); + scaleSeekBar.setProgress(scale); + listener.onChange(getWidthProgress(), getHeightProgress(), scale / 100f); + } else { + // Custom sizes are restored from the saved width/height. + int width = Math.min( + prefs.getInt("default_width", widthSeekBar.getMax()), + widthSeekBar.getMax() + ); + int height = Math.min( + prefs.getInt("default_height", heightSeekBar.getMax()), + heightSeekBar.getMax() + ); + + widthSeekBar.setProgress(width); + heightSeekBar.setProgress(height); + setMaxScale(width, height); + int scale = Math.min( + prefs.getInt("default_scale", 100), + scaleSeekBar.getMax() + ); + scaleSeekBar.setProgress(scale); + selectedDevice = customDevice; + + if (listener != null) { + listener.onChange(width, height, scale / 100f); + } + } + + if (restoredListener != null) { + restoredListener.run(); + } + } + private void setMaxScale(int width, int height) { SeekBar scaleSeekBar = seekBars.get("scale"); SeekBar widthSeekBar = seekBars.get("width"); @@ -367,6 +471,7 @@ public void deselect() { class DeviceListView extends ScrollView { DeviceView selectedDeviceView; + ArrayList devices = new ArrayList(); LinearLayout deviceListLayout; Callback callback; Context context; @@ -407,6 +512,7 @@ public void select(Device device) { } public void add(Device device) { + devices.add(device); DeviceView deviceView = new DeviceView(context, device, theme); deviceListLayout.addView(deviceView);