diff --git a/gravity.lp b/gravity.lp
new file mode 100644
index 00000000..063125d8
--- /dev/null
+++ b/gravity.lp
@@ -0,0 +1,31 @@
+ --[[
+* Pi-hole: A black hole for Internet advertisements
+* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
+* Network-wide ad blocking via your own hardware.
+*
+* This file is copyright under the latest version of the EUPL.
+* Please see LICENSE file for your rights under this license.
+--]]
+
+mg.include('scripts/pi-hole/lua/header_authenticated.lp','r')
+?>
+
+
+
Update Gravity (list of blocked domains)
+
+
+
+
+
+ Updating... this may take a while. Please do not navigate away from or close this page.
+
+
+
+ Success!
+
+
+
+
+
+
+ mg.include('scripts/pi-hole/lua/footer.lp','r')?>
diff --git a/scripts/pi-hole/js/gravity.js b/scripts/pi-hole/js/gravity.js
new file mode 100644
index 00000000..3cf2ab85
--- /dev/null
+++ b/scripts/pi-hole/js/gravity.js
@@ -0,0 +1,83 @@
+/* Pi-hole: A black hole for Internet advertisements
+ * (c) 2017 Pi-hole, LLC (https://pi-hole.net)
+ * Network-wide ad blocking via your own hardware.
+ *
+ * This file is copyright under the latest version of the EUPL.
+ * Please see LICENSE file for your rights under this license. */
+
+function eventsource() {
+ var alInfo = $("#alInfo");
+ var alSuccess = $("#alSuccess");
+ var ta = $("#output");
+
+ // https://caniuse.com/fetch - everything except IE
+ // This is fine, as we dropped support for IE a while ago
+ if (typeof fetch !== "function") {
+ ta.show();
+ ta.html("Updating lists of ad-serving domains is not supported with this browser!");
+ return;
+ }
+
+ ta.html("");
+ ta.show();
+ alInfo.show();
+ alSuccess.hide();
+
+ fetch("/api/action/gravity", {
+ method: "POST",
+ })
+ // Retrieve its body as ReadableStream
+ .then((response) => {
+ const reader = response.body.getReader();
+ return new ReadableStream({
+ start(controller) {
+ return pump();
+ function pump() {
+ return reader.read().then(({ done, value }) => {
+ // When no more data needs to be consumed, close the stream
+ if (done) {
+ controller.close();
+ alInfo.hide();
+ $("#gravityBtn").prop("disabled", false);
+ return;
+ }
+ // Enqueue the next data chunk into our target stream
+ controller.enqueue(value);
+ var string = new TextDecoder().decode(value);
+ // Remove ${OVER} from the string
+ string = string.replaceAll("\r[K", "\n");
+ console.log(string);
+ ta.append(string);
+ if (string.indexOf("Pi-hole blocking is") !== -1) {
+ alSuccess.show();
+ }
+ return pump();
+ });
+ }
+ },
+ });
+ })
+ .catch((err) => console.error(err));
+}
+
+$("#gravityBtn").on("click", function () {
+ $("#gravityBtn").prop("disabled", true);
+ eventsource();
+});
+
+// Handle hiding of alerts
+$(function () {
+ $("[data-hide]").on("click", function () {
+ $(this)
+ .closest("." + $(this).attr("data-hide"))
+ .hide();
+ });
+
+ // Do we want to start updating immediately?
+ // gravity.php?go
+ var searchString = window.location.search.substring(1);
+ if (searchString.indexOf("go") !== -1) {
+ $("#gravityBtn").prop("disabled", true);
+ eventsource();
+ }
+});
diff --git a/scripts/pi-hole/lua/sidebar.lp b/scripts/pi-hole/lua/sidebar.lp
index 6412c37c..e1c8ce11 100644
--- a/scripts/pi-hole/lua/sidebar.lp
+++ b/scripts/pi-hole/lua/sidebar.lp
@@ -176,7 +176,7 @@
-