[object Object]

← back to Homesonspec

snapshot before TK-11155 logo/PWA-banner sweep (pre-existing: tracker-policy extraction, debug-log cleanup, device capture evidence)

13331cf6f60b20d04adfe619c8119622478497fa · 2026-09-03 15:02:34 -0700 · Steve

Files touched

Diff

commit 13331cf6f60b20d04adfe619c8119622478497fa
Author: Steve <steve@designerwallcoverings.com>
Date:   Thu Sep 3 15:02:34 2026 -0700

    snapshot before TK-11155 logo/PWA-banner sweep (pre-existing: tracker-policy extraction, debug-log cleanup, device capture evidence)
---
 apps/mobile/app/(tabs)/_layout.tsx                 |   1 -
 apps/mobile/app/(tabs)/browse.tsx                  |  39 +++++----------------
 apps/mobile/app/_layout.tsx                        |   7 +---
 ...sonspec-DEVICE-journey-2026-09-03T21-10-10Z.mov | Bin 0 -> 1721476 bytes
 .../privacy-sweep-2026-09-03T21-10-10Z.jpg         | Bin 0 -> 211749 bytes
 .../stills-2026-09-03T21-10-10Z/1-browse.png       | Bin 0 -> 1855538 bytes
 .../stills-2026-09-03T21-10-10Z/2-saved.png        | Bin 0 -> 147320 bytes
 .../stills-2026-09-03T21-10-10Z/3-map.png          | Bin 0 -> 1664888 bytes
 .../stills-2026-09-03T21-10-10Z/4-alerts.png       | Bin 0 -> 309257 bytes
 .../5-browse-return.png                            | Bin 0 -> 1855562 bytes
 apps/mobile/lib/tracker-policy.test.mjs            |  31 ++++++++++++++++
 apps/mobile/lib/tracker-policy.ts                  |  28 +++++++++++++++
 12 files changed, 69 insertions(+), 37 deletions(-)

diff --git a/apps/mobile/app/(tabs)/_layout.tsx b/apps/mobile/app/(tabs)/_layout.tsx
index 7b85c37e..c2b9ddbf 100644
--- a/apps/mobile/app/(tabs)/_layout.tsx
+++ b/apps/mobile/app/(tabs)/_layout.tsx
@@ -14,7 +14,6 @@ const BRAND = '#1a3a6e';
 const ACCENT = '#e07b39';
 
 export default function TabLayout() {
-  console.log('HOS_DEBUG: TabLayout render');
   return (
     <Tabs
       screenOptions={{
diff --git a/apps/mobile/app/(tabs)/browse.tsx b/apps/mobile/app/(tabs)/browse.tsx
index 9b7242f6..11c6dc2b 100644
--- a/apps/mobile/app/(tabs)/browse.tsx
+++ b/apps/mobile/app/(tabs)/browse.tsx
@@ -25,6 +25,7 @@ import {
 import { WebView, WebViewNavigation } from 'react-native-webview';
 import { saveHome } from '../../lib/storage';
 import { WEB_BASE_URL } from '../../lib/api';
+import { isTrackerUrl, TRACKER_HOSTS } from '../../lib/tracker-policy';
 
 const BRAND = '#1a3a6e';
 const ACCENT = '#e07b39';
@@ -34,23 +35,6 @@ const ACCENT = '#e07b39';
  * Kept in sync between the JS-level interceptor (below) and the native
  * onShouldStartLoadWithRequest filter.
  */
-const TRACKER_HOSTS = [
-  'googletagmanager.com',
-  'google-analytics.com',
-  'analytics.google.com',
-  'connect.facebook.net',
-  'facebook.com/tr',
-  'www.facebook.com/tr',
-  'googlesyndication.com',
-  'doubleclick.net',
-  'stats.g.doubleclick.net',
-];
-
-function isTrackerUrl(url: string): boolean {
-  const u = (url || '').toLowerCase();
-  return TRACKER_HOSTS.some((h) => u.includes(h));
-}
-
 /**
  * Runs BEFORE any page script. Neutralizes analytics/ad trackers two ways so
  * the app genuinely transmits nothing:
@@ -68,8 +52,12 @@ const TRACKER_BLOCK = `
   try {
     var HOSTS = ${JSON.stringify(TRACKER_HOSTS)};
     function blocked(u) {
-      try { u = String(u).toLowerCase(); } catch (e) { return false; }
-      for (var i = 0; i < HOSTS.length; i++) { if (u.indexOf(HOSTS[i]) !== -1) return true; }
+      try {
+        var hostname = new URL(String(u), window.location.href).hostname.toLowerCase();
+        for (var i = 0; i < HOSTS.length; i++) {
+          if (hostname === HOSTS[i] || hostname.slice(-(HOSTS[i].length + 1)) === '.' + HOSTS[i]) return true;
+        }
+      } catch (e) {}
       return false;
     }
 
@@ -228,7 +216,6 @@ interface PageInfo {
 }
 
 export default function BrowseTab() {
-  console.log('HOS_DEBUG: BrowseTab render, WEB_BASE_URL=', WEB_BASE_URL);
   const webViewRef = useRef<WebView>(null);
   const [loading, setLoading] = useState(true);
   const [error, setError] = useState<string | null>(null);
@@ -299,21 +286,13 @@ export default function BrowseTab() {
         ref={webViewRef}
         source={{ uri: WEB_BASE_URL }}
         style={styles.webview}
-        onLoadStart={() => {
-          console.log('HOS_DEBUG: WebView onLoadStart');
-          setLoading(true);
-        }}
-        onLoadEnd={() => {
-          console.log('HOS_DEBUG: WebView onLoadEnd');
-          setLoading(false);
-        }}
+        onLoadStart={() => setLoading(true)}
+        onLoadEnd={() => setLoading(false)}
         onError={(e) => {
-          console.log('HOS_DEBUG: WebView onError', JSON.stringify(e.nativeEvent));
           setLoading(false);
           setError(e.nativeEvent.description);
         }}
         onHttpError={(e) => {
-          console.log('HOS_DEBUG: WebView onHttpError', e.nativeEvent.statusCode);
           if (e.nativeEvent.statusCode >= 500) {
             setError(`Server error ${e.nativeEvent.statusCode}`);
           }
diff --git a/apps/mobile/app/_layout.tsx b/apps/mobile/app/_layout.tsx
index cbf0e0b3..bfbfded9 100644
--- a/apps/mobile/app/_layout.tsx
+++ b/apps/mobile/app/_layout.tsx
@@ -3,16 +3,11 @@ import { Stack } from 'expo-router';
 import { StatusBar } from 'expo-status-bar';
 import * as SplashScreen from 'expo-splash-screen';
 
-console.log('HOS_DEBUG: module _layout.tsx evaluated');
 SplashScreen.preventAutoHideAsync();
 
 export default function RootLayout() {
-  console.log('HOS_DEBUG: RootLayout render');
   useEffect(() => {
-    console.log('HOS_DEBUG: RootLayout useEffect - calling SplashScreen.hideAsync()');
-    SplashScreen.hideAsync()
-      .then(() => console.log('HOS_DEBUG: SplashScreen.hideAsync() resolved'))
-      .catch((e) => console.log('HOS_DEBUG: SplashScreen.hideAsync() REJECTED', e));
+    SplashScreen.hideAsync();
   }, []);
 
   return (
diff --git a/apps/mobile/device-proof-evidence/homesonspec-DEVICE-journey-2026-09-03T21-10-10Z.mov b/apps/mobile/device-proof-evidence/homesonspec-DEVICE-journey-2026-09-03T21-10-10Z.mov
new file mode 100644
index 00000000..f31f3759
Binary files /dev/null and b/apps/mobile/device-proof-evidence/homesonspec-DEVICE-journey-2026-09-03T21-10-10Z.mov differ
diff --git a/apps/mobile/device-proof-evidence/privacy-sweep-2026-09-03T21-10-10Z.jpg b/apps/mobile/device-proof-evidence/privacy-sweep-2026-09-03T21-10-10Z.jpg
new file mode 100644
index 00000000..bdd30f3a
Binary files /dev/null and b/apps/mobile/device-proof-evidence/privacy-sweep-2026-09-03T21-10-10Z.jpg differ
diff --git a/apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/1-browse.png b/apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/1-browse.png
new file mode 100644
index 00000000..acaf5548
Binary files /dev/null and b/apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/1-browse.png differ
diff --git a/apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/2-saved.png b/apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/2-saved.png
new file mode 100644
index 00000000..3c1ad884
Binary files /dev/null and b/apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/2-saved.png differ
diff --git a/apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/3-map.png b/apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/3-map.png
new file mode 100644
index 00000000..ce6f4a72
Binary files /dev/null and b/apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/3-map.png differ
diff --git a/apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/4-alerts.png b/apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/4-alerts.png
new file mode 100644
index 00000000..372d4cb0
Binary files /dev/null and b/apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/4-alerts.png differ
diff --git a/apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/5-browse-return.png b/apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/5-browse-return.png
new file mode 100644
index 00000000..aaef1530
Binary files /dev/null and b/apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/5-browse-return.png differ
diff --git a/apps/mobile/lib/tracker-policy.test.mjs b/apps/mobile/lib/tracker-policy.test.mjs
new file mode 100644
index 00000000..aa29fcbc
--- /dev/null
+++ b/apps/mobile/lib/tracker-policy.test.mjs
@@ -0,0 +1,31 @@
+import assert from 'node:assert/strict';
+import test from 'node:test';
+
+import { isTrackerUrl } from './tracker-policy.ts';
+
+test('blocks known analytics and advertising hosts and subdomains', () => {
+  const blocked = [
+    'https://www.googletagmanager.com/gtm.js?id=GTM-123',
+    'https://region1.google-analytics.com/g/collect',
+    'https://connect.facebook.net/en_US/fbevents.js',
+    'https://www.facebook.com/tr?id=123',
+    'https://stats.g.doubleclick.net/j/collect',
+    'HTTPS://GOOGLESYNDICATION.COM/pagead/id',
+  ];
+
+  for (const url of blocked) assert.equal(isTrackerUrl(url), true, url);
+});
+
+test('allows first-party, lookalike, relative, and malformed URLs', () => {
+  const allowed = [
+    'https://homesonspec.com/',
+    'https://homesonspec.com/homes/abc?next=google-analytics.com',
+    'https://google-analytics.com.example.org/collect',
+    'https://notfacebook.com/tr',
+    '/homes/abc',
+    '',
+    'not a URL',
+  ];
+
+  for (const url of allowed) assert.equal(isTrackerUrl(url), false, url);
+});
diff --git a/apps/mobile/lib/tracker-policy.ts b/apps/mobile/lib/tracker-policy.ts
new file mode 100644
index 00000000..4b1ea72d
--- /dev/null
+++ b/apps/mobile/lib/tracker-policy.ts
@@ -0,0 +1,28 @@
+/**
+ * Analytics and advertising hosts blocked inside the Browse WebView.
+ * Matching is hostname-aware: exact hosts and their subdomains are blocked,
+ * while lookalike domains and harmless query-string mentions remain allowed.
+ */
+export const TRACKER_HOSTS = [
+  'googletagmanager.com',
+  'google-analytics.com',
+  'analytics.google.com',
+  'connect.facebook.net',
+  'facebook.com',
+  'googlesyndication.com',
+  'doubleclick.net',
+] as const;
+
+export function isTrackerUrl(value: string): boolean {
+  if (!value) return false;
+
+  try {
+    const hostname = new URL(value).hostname.toLowerCase();
+    return TRACKER_HOSTS.some(
+      (blockedHost) =>
+        hostname === blockedHost || hostname.endsWith(`.${blockedHost}`),
+    );
+  } catch {
+    return false;
+  }
+}

← febf413e auto-data-snapshot: 2026-09-03T14:29:24 (1 data files) — app  ·  back to Homesonspec  ·  mobile: regenerate splash.png as a large full-screen brand l 9b533a90 →