Merge branch 'dev'

This commit is contained in:
Mo Tarbin
2026-02-08 16:15:22 -05:00
8 changed files with 75 additions and 70 deletions

2
.env
View File

@@ -1,4 +1,4 @@
VITE_APP_API_URL=http://localhost:2021 VITE_APP_API_URL=http://localhost:2021
VITE_IS_LANDING_DEFAULT=false VITE_IS_LANDING_DEFAULT=true
VITE_OPENREPLAY_PROJECT_KEY= VITE_OPENREPLAY_PROJECT_KEY=
VITE_IS_SELF_HOSTED=false VITE_IS_SELF_HOSTED=false

View File

@@ -2,3 +2,4 @@ VITE_APP_API_URL=http://localhost:2021
VITE_APP_REDIRECT_URL=http://localhost:5173 VITE_APP_REDIRECT_URL=http://localhost:5173
VITE_APP_GOOGLE_CLIENT_ID=USE_YOUR_OWN_CLIENT_ID VITE_APP_GOOGLE_CLIENT_ID=USE_YOUR_OWN_CLIENT_ID
VITE_IS_SELF_HOSTED=true VITE_IS_SELF_HOSTED=true
VITE_IS_LANDING_DEFAULT=true

96
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "donetick", "name": "donetick",
"version": "0.1.110", "version": "0.1.145",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "donetick", "name": "donetick",
"version": "0.1.110", "version": "0.1.145",
"dependencies": { "dependencies": {
"@capacitor-community/sqlite": "^7.0.0", "@capacitor-community/sqlite": "^7.0.0",
"@capacitor/android": "^7.0.0", "@capacitor/android": "^7.0.0",
@@ -37,6 +37,7 @@
"@tanstack/react-query": "^5.17.0", "@tanstack/react-query": "^5.17.0",
"aos": "^2.3.4", "aos": "^2.3.4",
"browser-image-compression": "^2.0.2", "browser-image-compression": "^2.0.2",
"caniuse-lite": "^1.0.30001769",
"capacitor-plugin-safe-area": "^4.0.0", "capacitor-plugin-safe-area": "^4.0.0",
"chrono-node": "^2.7.7", "chrono-node": "^2.7.7",
"dotenv": "^16.4.5", "dotenv": "^16.4.5",
@@ -55,6 +56,7 @@
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-easy-crop": "^5.4.2", "react-easy-crop": "^5.4.2",
"react-router-dom": "^6.21.1", "react-router-dom": "^6.21.1",
"react-swipeable-list": "^1.10.0",
"react-transition-group": "^4.4.5", "react-transition-group": "^4.4.5",
"reactjs-social-login": "^2.6.3", "reactjs-social-login": "^2.6.3",
"recharts": "^2.15.0", "recharts": "^2.15.0",
@@ -64,14 +66,13 @@
"devDependencies": { "devDependencies": {
"@capacitor/assets": "^3.0.5", "@capacitor/assets": "^3.0.5",
"@capacitor/cli": "^7.0.0", "@capacitor/cli": "^7.0.0",
"@rollup/rollup-darwin-arm64": "^4.50.0",
"@swc/core-darwin-arm64": "^1.13.5",
"@tanstack/eslint-plugin-query": "^5.14.6", "@tanstack/eslint-plugin-query": "^5.14.6",
"@types/react": "^18.2.43", "@types/react": "^18.2.43",
"@types/react-dom": "^18.2.17", "@types/react-dom": "^18.2.17",
"@vite-pwa/assets-generator": "^0.2.4", "@vite-pwa/assets-generator": "^0.2.4",
"@vitejs/plugin-react-swc": "^3.5.0", "@vitejs/plugin-react-swc": "^3.5.0",
"autoprefixer": "^10.4.16", "autoprefixer": "^10.4.16",
"baseline-browser-mapping": "^2.9.19",
"eslint": "^8.56.0", "eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.2", "eslint-plugin-prettier": "^5.1.2",
@@ -92,12 +93,6 @@
"engines": { "engines": {
"node": ">=20.0.0", "node": ">=20.0.0",
"npm": ">=9.0.0" "npm": ">=9.0.0"
},
"optionalDependencies": {
"@rollup/rollup-darwin-arm64": "^4.46.1",
"@rollup/rollup-linux-x64-gnu": "^4.50.0",
"@swc/core-darwin-arm64": "^1.13.3",
"@swc/core-linux-x64-gnu": "^1.13.3"
} }
}, },
"node_modules/@alloc/quick-lru": { "node_modules/@alloc/quick-lru": {
@@ -3196,8 +3191,8 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"devOptional": true,
"license": "MIT", "license": "MIT",
"optional": true,
"os": [ "os": [
"darwin" "darwin"
] ]
@@ -3258,8 +3253,8 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"devOptional": true,
"license": "Apache-2.0 AND MIT", "license": "Apache-2.0 AND MIT",
"optional": true,
"os": [ "os": [
"darwin" "darwin"
], ],
@@ -4696,27 +4691,6 @@
"postcss": "^8.1.0" "postcss": "^8.1.0"
} }
}, },
"node_modules/autoprefixer/node_modules/caniuse-lite": {
"version": "1.0.30001739",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001739.tgz",
"integrity": "sha512-y+j60d6ulelrNSwpPyrHdl+9mJnQzHBr08xm48Qno0nSk4h3Qojh+ziv2qE6rXf4k3tadF4o1J/1tAbVm1NtnA==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "CC-BY-4.0"
},
"node_modules/available-typed-arrays": { "node_modules/available-typed-arrays": {
"version": "1.0.7", "version": "1.0.7",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
@@ -4813,6 +4787,16 @@
], ],
"license": "MIT" "license": "MIT"
}, },
"node_modules/baseline-browser-mapping": {
"version": "2.9.19",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz",
"integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"baseline-browser-mapping": "dist/cli.js"
}
},
"node_modules/big-integer": { "node_modules/big-integer": {
"version": "1.6.52", "version": "1.6.52",
"dev": true, "dev": true,
@@ -4938,26 +4922,6 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
} }
}, },
"node_modules/browserslist/node_modules/caniuse-lite": {
"version": "1.0.30001739",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001739.tgz",
"integrity": "sha512-y+j60d6ulelrNSwpPyrHdl+9mJnQzHBr08xm48Qno0nSk4h3Qojh+ziv2qE6rXf4k3tadF4o1J/1tAbVm1NtnA==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "CC-BY-4.0"
},
"node_modules/buffer": { "node_modules/buffer": {
"version": "5.7.1", "version": "5.7.1",
"devOptional": true, "devOptional": true,
@@ -5080,6 +5044,26 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/caniuse-lite": {
"version": "1.0.30001769",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001769.tgz",
"integrity": "sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "CC-BY-4.0"
},
"node_modules/capacitor-plugin-safe-area": { "node_modules/capacitor-plugin-safe-area": {
"version": "4.0.0", "version": "4.0.0",
"license": "MIT", "license": "MIT",
@@ -10830,6 +10814,12 @@
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
} }
}, },
"node_modules/react-swipeable-list": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/react-swipeable-list/-/react-swipeable-list-1.10.0.tgz",
"integrity": "sha512-Ap85a3c5sgvglZBlaansfT6VfwuMad5U4puxFW4sJbUU6alE7epzW39CHvs5AohUZi7wjlP1KFunpXoD+iUyGQ==",
"license": "MIT"
},
"node_modules/react-transition-group": { "node_modules/react-transition-group": {
"version": "4.4.5", "version": "4.4.5",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",

View File

@@ -2,13 +2,13 @@ import NavBar from '@/views/components/NavBar'
import { Button, Typography, useColorScheme } from '@mui/joy' import { Button, Typography, useColorScheme } from '@mui/joy'
import Tracker from '@openreplay/tracker' import Tracker from '@openreplay/tracker'
import { useCallback, useEffect } from 'react' import { useCallback, useEffect } from 'react'
import { Outlet, useNavigate } from 'react-router-dom' import { Outlet } from 'react-router-dom'
import { useRegisterSW } from 'virtual:pwa-register/react' import { useRegisterSW } from 'virtual:pwa-register/react'
import { registerCapacitorListeners } from './CapacitorListener' import { registerCapacitorListeners } from './CapacitorListener'
import PageTransition from './components/animations/PageTransition' import PageTransition from './components/animations/PageTransition'
import { AuthProvider } from './hooks/useAuth.jsx'
import { ImpersonateUserProvider } from './contexts/ImpersonateUserContext' import { ImpersonateUserProvider } from './contexts/ImpersonateUserContext'
import SSEProvider from './contexts/SSEContext' import SSEProvider from './contexts/SSEContext'
import { AuthProvider } from './hooks/useAuth.jsx'
import { useNotification } from './service/NotificationProvider' import { useNotification } from './service/NotificationProvider'
import NetworkBanner from './views/components/NetworkBanner' import NetworkBanner from './views/components/NetworkBanner'
@@ -32,7 +32,6 @@ const startOpenReplay = () => {
tracker.start() tracker.start()
} }
const AppContent = () => { const AppContent = () => {
const { showNotification } = useNotification() const { showNotification } = useNotification()

View File

@@ -18,9 +18,9 @@ const MAX_RECONNECT_ATTEMPTS = 10 // Circuit breaker limit
const CIRCUIT_BREAKER_RESET_TIME = 600000 // 10 minutes const CIRCUIT_BREAKER_RESET_TIME = 600000 // 10 minutes
export const useSSE = () => { export const useSSE = () => {
const { data: userProfile } = useUserProfile()
const { isAuthenticated, token } = useAuth() const { isAuthenticated, token } = useAuth()
// Only fetch user profile if authenticated - prevents unnecessary API calls on landing page
const { data: userProfile } = useUserProfile()
const [connectionState, setConnectionState] = useState(SSE_STATES.CLOSED) const [connectionState, setConnectionState] = useState(SSE_STATES.CLOSED)
const [lastEvent, setLastEvent] = useState(null) const [lastEvent, setLastEvent] = useState(null)
const [error, setError] = useState(null) const [error, setError] = useState(null)

View File

@@ -1,6 +1,17 @@
import { useQuery } from '@tanstack/react-query' import { useQuery } from '@tanstack/react-query'
import { GetResource } from '../utils/Fetcher' import { GetResource } from '../utils/Fetcher'
// Helper to check if we have a valid token
const isTokenValid = () => {
const token = localStorage.getItem('token')
if (!token) return false
const expiry = localStorage.getItem('token_expiry')
if (!expiry) return true // No expiry set, assume valid
return new Date() < new Date(expiry)
}
export const useResource = () => { export const useResource = () => {
const { data, isLoading, error } = useQuery({ const { data, isLoading, error } = useQuery({
queryKey: ['resource'], queryKey: ['resource'],
@@ -11,6 +22,7 @@ export const useResource = () => {
staleTime: 6 * 60 * 60 * 1000, // 6 hours in milliseconds staleTime: 6 * 60 * 60 * 1000, // 6 hours in milliseconds
refetchOnWindowFocus: false, refetchOnWindowFocus: false,
refetchOnReconnect: false, refetchOnReconnect: false,
enabled: isTokenValid(), // Only run query when we have a valid token
}) })
return { data, isLoading, error } return { data, isLoading, error }
} }

View File

@@ -54,6 +54,7 @@ export const useUserProfile = () => {
}, },
staleTime: 30 * 60 * 1000, // 30 minutes in milliseconds staleTime: 30 * 60 * 1000, // 30 minutes in milliseconds
gcTime: 30 * 60 * 1000, // 30 minutes in milliseconds gcTime: 30 * 60 * 1000, // 30 minutes in milliseconds
enabled: isTokenValid(), // Only run query when we have a valid token
}) })
return { return {
data, data,

View File

@@ -103,7 +103,18 @@ import Z_INDEX from '../../constants/zIndex'
import { useResource } from '../../queries/ResourceQueries' import { useResource } from '../../queries/ResourceQueries'
import { apiClient } from '../../utils/ApiClient' import { apiClient } from '../../utils/ApiClient'
const publicPages = ['/landing', '/privacy', '/terms'] const publicPages = [
'/landing',
'/privacy',
'/terms',
'login',
'/signup',
'/auth/oauth2',
'/forgot-password',
'/login/settings',
'/',
]
const NavBar = () => { const NavBar = () => {
const { data: resource } = useResource() const { data: resource } = useResource()
@@ -165,15 +176,7 @@ const NavBar = () => {
) )
} }
if ( if (publicPages.includes(location.pathname)) {
[
'/signup',
'/login',
'/auth/oauth2',
'/forgot-password',
'/login/settings',
].includes(location.pathname)
) {
return ( return (
// no navbar but show the safe area padding // no navbar but show the safe area padding
<div <div
@@ -320,5 +323,4 @@ const NavBar = () => {
</nav> </nav>
) )
} }
export default NavBar export default NavBar