← 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
M apps/mobile/app/(tabs)/_layout.tsxM apps/mobile/app/(tabs)/browse.tsxM apps/mobile/app/_layout.tsxA apps/mobile/device-proof-evidence/homesonspec-DEVICE-journey-2026-09-03T21-10-10Z.movA apps/mobile/device-proof-evidence/privacy-sweep-2026-09-03T21-10-10Z.jpgA apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/1-browse.pngA apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/2-saved.pngA apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/3-map.pngA apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/4-alerts.pngA apps/mobile/device-proof-evidence/stills-2026-09-03T21-10-10Z/5-browse-return.pngA apps/mobile/lib/tracker-policy.test.mjsA apps/mobile/lib/tracker-policy.ts
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 →