Compare commits

...
14 Commits
3 changed files with 101 additions and 7 deletions

No files matched your search

+2 -2
View File
@@ -41,8 +41,8 @@ A private step tracking web app that syncs steps from your phone and lets you co
4. Select **Steps** → set Date Range to **Default** → set schedule to **Daily**
### Android
1. Download the **StepMates Sync** Android app from GitHub:
https://github.com/JustinOros/step-tracker/releases/latest
1. Download the **StepMates Sync** Android app:
[Download StepMates-Sync-Android.apk](https://github.com/JustinOros/stepmates-sync/releases/download/v1.1/StepMates-Sync-Android.apk)
2. Install it (allow unknown sources when prompted)
3. Sign in to StepMates in your browser → hamburger menu → **Setup & Sync** → copy your Webhook URL
4. Open the StepMates Sync app → paste your Webhook URL → tap **Sync My Steps**
+49 -5
View File
@@ -55,6 +55,8 @@
.btn-primary:hover:not(:disabled) { opacity: 0.9; }
.btn-ghost { background: transparent; color: var(--muted); border: 1.5px solid var(--border); }
.btn-ghost:hover { border-color: var(--teal); color: var(--teal); }
.btn-google { background: #fff; color: #3c4043; border: 1.5px solid #dadce0; font-family: var(--font-body); font-size: 15px; font-weight: 500; width: 100%; margin-bottom: 4px; gap: 10px; }
.btn-google:hover { background: #f8f9fa; border-color: #c6c6c6; }
.btn-danger { background: transparent; color: var(--danger); border: 1.5px solid var(--danger); }
.btn-danger:hover { background: rgba(255,107,107,0.1); }
.btn-sm { padding: 7px 14px; font-size: 13px; min-height: 38px; }
@@ -266,7 +268,16 @@
<p class="auth-tagline">Walk more. Compete with friends.</p>
<div class="auth-card" id="auth-card">
<h2>Welcome</h2>
<p>Enter your email to sign in or create an account — no password needed.</p>
<p>Sign in or create an account to get started.</p>
<button class="btn btn-google" id="google-signin-btn" onclick="signInWithGoogle()" style="display:none">
<svg width="18" height="18" viewBox="0 0 18 18" style="flex-shrink:0"><path fill="#4285F4" d="M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.875 2.684-6.615z"/><path fill="#34A853" d="M9 18c2.43 0 4.467-.806 5.956-2.184l-2.908-2.258c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711H.957v2.332C2.438 15.983 5.482 18 9 18z"/><path fill="#FBBC05" d="M3.964 10.707c-.18-.54-.282-1.117-.282-1.707s.102-1.167.282-1.707V4.961H.957C.347 6.175 0 7.55 0 9s.348 2.825.957 4.039l3.007-2.332z"/><path fill="#EA4335" d="M9 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.463.891 11.426 0 9 0 5.482 0 2.438 2.017.957 4.961L3.964 7.293C4.672 5.166 6.656 3.58 9 3.58z"/></svg>
Sign in with Google
</button>
<div id="google-divider" style="display:none;align-items:center;gap:12px;margin:16px 0">
<div style="flex:1;height:1px;background:var(--border)"></div>
<span style="font-size:12px;color:var(--muted)">or</span>
<div style="flex:1;height:1px;background:var(--border)"></div>
</div>
<label for="auth-email">Email address</label>
<input type="email" id="auth-email" placeholder="you@example.com" autocomplete="email">
<div class="error-msg" id="auth-error" style="display:none"></div>
@@ -332,7 +343,7 @@
<div class="bc-icon">🍎</div><div class="bc-name">Health Auto Export</div>
<div class="bc-platform">iPhone · iOS 16+</div><div class="bc-badge">Free tier</div>
</a>
<a href="https://github.com/JustinOros/step-tracker/releases/download/v1.0/StepMates-Sync-Android.apk" target="_blank" class="bridge-card">
<a href="https://github.com/JustinOros/stepmates-sync/releases/download/v1.1/StepMates-Sync-Android.apk" target="_blank" class="bridge-card">
<div class="bc-icon">🤖</div><div class="bc-name">StepMates Sync</div>
<div class="bc-platform">Android 9+</div><div class="bc-badge">Free & open source</div>
</a>
@@ -471,7 +482,7 @@
2. Automations → New Automation → Webhook → paste your URL above<br>
3. Select <em>Steps</em> → set Date Range to <em>Default</em> → set schedule to <em>Daily</em><br><br>
<strong style="color:var(--white)">Android — StepMates Sync App:</strong><br>
1. Download <a href="https://github.com/JustinOros/step-tracker/releases/download/v1.0/StepMates-Sync-Android.apk" target="_blank" style="color:var(--teal)">StepMates Sync Android App</a><br>
1. Download <a href="https://github.com/JustinOros/stepmates-sync/releases/download/v1.1/StepMates-Sync-Android.apk" target="_blank" style="color:var(--teal)">StepMates Sync Android App</a><br>
2. Install it (allow unknown sources when prompted)<br>
3. Paste your Webhook URL above into the app → tap Sync
</div>
@@ -480,7 +491,7 @@
<a href="https://apps.apple.com/us/app/health-auto-export-json-csv/id1115567069" target="_blank" class="bridge-card">
<div class="bc-icon">🍎</div><div class="bc-name">Health Auto Export</div><div class="bc-platform">iPhone · iOS 16+</div><div class="bc-badge">Free tier</div>
</a>
<a href="https://github.com/JustinOros/step-tracker/releases/download/v1.0/StepMates-Sync-Android.apk" target="_blank" class="bridge-card">
<a href="https://github.com/JustinOros/stepmates-sync/releases/download/v1.1/StepMates-Sync-Android.apk" target="_blank" class="bridge-card">
<div class="bc-icon">🤖</div><div class="bc-name">StepMates Sync</div><div class="bc-platform">Android 9+</div><div class="bc-badge">Free & open source</div>
</a>
</div>
@@ -622,7 +633,7 @@
<script src="config.js"></script>
<script type="module">
import { initializeApp } from 'https://www.gstatic.com/firebasejs/10.12.0/firebase-app.js';
import { getAuth, isSignInWithEmailLink, signInWithEmailLink, signOut as fbSignOut, onAuthStateChanged } from 'https://www.gstatic.com/firebasejs/10.12.0/firebase-auth.js';
import { getAuth, isSignInWithEmailLink, signInWithEmailLink, signInWithPopup, signInWithRedirect, getRedirectResult, GoogleAuthProvider, signOut as fbSignOut, onAuthStateChanged } from 'https://www.gstatic.com/firebasejs/10.12.0/firebase-auth.js';
import { getFirestore, doc, getDoc, setDoc, updateDoc, deleteField, collection, query, where, getDocs, addDoc, onSnapshot, serverTimestamp } from 'https://www.gstatic.com/firebasejs/10.12.0/firebase-firestore.js';
if (!window.STEPMATES_CONFIG) {
@@ -638,6 +649,12 @@ const fbApp = initializeApp(FIREBASE_CONFIG);
const auth = getAuth(fbApp);
const db = getFirestore(fbApp);
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
if (!isIOS) {
document.getElementById('google-signin-btn').style.display = 'flex';
document.getElementById('google-divider').style.display = 'flex';
}
let currentUser = null;
let currentUserData = null;
let currentProfileData = null;
@@ -713,8 +730,12 @@ function getFriendDisplayName(uid) {
return nick || displayName;
}
let _initializingUser = false;
// AUTH
onAuthStateChanged(auth, async (user) => {
if (_initializingUser) return;
if (isSignInWithEmailLink(auth, window.location.href)) {
const urlParams = new URLSearchParams(window.location.search);
const email = urlParams.get('email') || localStorage.getItem('emailForSignIn');
@@ -757,6 +778,7 @@ window.confirmEmailSignIn = async function() {
}
async function initUser(user) {
_initializingUser = true;
currentUser = user;
const userRef = doc(db, 'users', user.uid);
const snap = await getDoc(userRef);
@@ -1282,6 +1304,25 @@ window.sendMagicLink = async function() {
btn.disabled = false; btn.innerHTML = 'Continue with Email';
}
window.signInWithGoogle = async function() {
const btn = document.getElementById('google-signin-btn');
btn.disabled = true;
btn.innerHTML = '<span class="spinner" style="color:#4285F4"></span> Signing in…';
try {
const provider = new GoogleAuthProvider();
const result = await signInWithPopup(auth, provider);
_initializingUser = true;
await initUser(result.user);
} catch(e) {
btn.disabled = false;
btn.innerHTML = `<svg width="18" height="18" viewBox="0 0 18 18" style="flex-shrink:0"><path fill="#4285F4" d="M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.875 2.684-6.615z"/><path fill="#34A853" d="M9 18c2.43 0 4.467-.806 5.956-2.184l-2.908-2.258c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711H.957v2.332C2.438 15.983 5.482 18 9 18z"/><path fill="#FBBC05" d="M3.964 10.707c-.18-.54-.282-1.117-.282-1.707s.102-1.167.282-1.707V4.961H.957C.347 6.175 0 7.55 0 9s.348 2.825.957 4.039l3.007-2.332z"/><path fill="#EA4335" d="M9 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.463.891 11.426 0 9 0 5.482 0 2.438 2.017.957 4.961L3.964 7.293C4.672 5.166 6.656 3.58 9 3.58z"/></svg> Sign in with Google`;
if (e.code !== 'auth/popup-closed-by-user' && e.code !== 'auth/cancelled-popup-request') {
document.getElementById('auth-error').textContent = 'Google sign-in failed. Please try again or use email.';
document.getElementById('auth-error').style.display = 'block';
}
}
}
window.showAuthForm = function() {
document.getElementById('auth-card').style.display = 'block';
document.getElementById('magic-sent-card').style.display = 'none';
@@ -1388,8 +1429,11 @@ window.signOut = async function() {
if (!confirm('Sign out?')) return;
teardown();
await fbSignOut(auth);
_initializingUser = false;
currentUser = null; currentUserData = null; currentProfileData = null; currentStepsData = null;
friendsData = {}; friendProfiles = {}; friendSteps = {};
const btn = document.getElementById('google-signin-btn');
if (btn) { btn.disabled = false; btn.innerHTML = `<svg width="18" height="18" viewBox="0 0 18 18" style="flex-shrink:0"><path fill="#4285F4" d="M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.875 2.684-6.615z"/><path fill="#34A853" d="M9 18c2.43 0 4.467-.806 5.956-2.184l-2.908-2.258c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711H.957v2.332C2.438 15.983 5.482 18 9 18z"/><path fill="#FBBC05" d="M3.964 10.707c-.18-.54-.282-1.117-.282-1.707s.102-1.167.282-1.707V4.961H.957C.347 6.175 0 7.55 0 9s.348 2.825.957 4.039l3.007-2.332z"/><path fill="#EA4335" d="M9 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.463.891 11.426 0 9 0 5.482 0 2.438 2.017.957 4.961L3.964 7.293C4.672 5.166 6.656 3.58 9 3.58z"/></svg> Sign in with Google`; }
showScreen('auth'); showAuthForm();
}
+50
View File
@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>StepMates — Privacy Policy</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #0F1923; color: #F8F9FA; padding: 40px 20px; max-width: 720px; margin: 0 auto; line-height: 1.7; }
h1 { color: #00C9B1; font-size: 28px; margin-bottom: 8px; }
h2 { color: #F8F9FA; font-size: 18px; margin: 32px 0 10px; }
p { color: #8899A6; margin-bottom: 14px; }
a { color: #00C9B1; }
.updated { color: #8899A6; font-size: 13px; margin-bottom: 40px; }
</style>
</head>
<body>
<h1>StepMates Privacy Policy</h1>
<p class="updated">Last updated: June 27, 2026</p>
<p>StepMates ("we", "our", or "us") is a private step tracking app. This policy explains how we handle your data.</p>
<h2>Data We Collect</h2>
<p>We collect the following information when you use StepMates:</p>
<p><strong>Account information:</strong> Your email address and display name, provided via Google Sign-In.</p>
<p><strong>Step data:</strong> Daily step counts read from Google Health Connect (Android) or Apple Health via Health Auto Export (iPhone). We only read step count data — we do not access any other health information.</p>
<p><strong>Friend data:</strong> Display names and step counts of friends you choose to connect with inside the app.</p>
<h2>How We Use Your Data</h2>
<p>Your step data is stored in Firebase Firestore and used solely to display your personal step history and to show your ranking on the leaderboard shared with your approved friends.</p>
<p>We do not sell, share, or use your data for advertising or any purpose other than operating the StepMates app.</p>
<h2>Health Connect Data</h2>
<p>On Android, StepMates uses Google Health Connect to read your step count. We only request read access to Steps. We do not write any data to Health Connect. Step data is synced to our secure Firebase database and displayed only to you and your approved friends.</p>
<h2>Data Sharing</h2>
<p>Your step data is visible only to friends you have mutually approved within the app. No data is shared with third parties.</p>
<h2>Data Storage</h2>
<p>Your data is stored securely using Google Firebase, hosted in the United States. You can request deletion of your account and all associated data by contacting us.</p>
<h2>Account Access</h2>
<p>StepMates is a private app — new accounts require admin approval. Access can be revoked at any time.</p>
<h2>Contact</h2>
<p>For privacy questions or data deletion requests, contact us at <a href="mailto:justin@slothware.net">justin@slothware.net</a>.</p>
<p style="margin-top:40px"><a href="https://justinoros.github.io/step-tracker">← Back to StepMates</a></p>
</body>
</html>