5.1.0: Fitbit: привязки к задачам, цели из API
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m23s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m23s
This commit is contained in:
@@ -32,6 +32,22 @@ const FULL_STATISTICS_API_URL = '/d2dc349a-0d13-49b2-a8f0-1ab094bfba9b'
|
||||
const mainTabs = ['current', 'tasks', 'wishlist', 'profile']
|
||||
const deepTabs = ['add-words', 'test', 'task-form', 'wishlist-form', 'wishlist-detail', 'board-form', 'board-join', 'words', 'dictionaries', 'todoist-integration', 'telegram-integration', 'fitbit-integration', 'full', 'priorities', 'tracking', 'tracking-access', 'tracking-invite']
|
||||
|
||||
/**
|
||||
* Гарантирует базовую запись истории для главного экрана перед глубоким табом.
|
||||
* После долгого бездействия PWA может перезапуститься с одной записью в истории;
|
||||
* кнопка "назад" тогда закрывает приложение. Эта функция добавляет запись для
|
||||
* экрана 'current', чтобы "назад" возвращала на главный экран.
|
||||
*/
|
||||
function ensureBaseHistory(deepTab, params = {}, url) {
|
||||
if (typeof window === 'undefined' || !deepTabs.includes(deepTab)) return
|
||||
if (window.history.length <= 1) {
|
||||
window.history.replaceState({ tab: 'current' }, '', '/')
|
||||
window.history.pushState({ tab: deepTab, params, previousTab: 'current' }, '', url)
|
||||
} else {
|
||||
window.history.replaceState({ tab: deepTab, params, previousTab: 'current' }, '', url)
|
||||
}
|
||||
}
|
||||
|
||||
function AppContent() {
|
||||
const { authFetch, isAuthenticated, loading: authLoading } = useAuth()
|
||||
const prevIsAuthenticatedRef = useRef(null)
|
||||
@@ -179,12 +195,12 @@ function AppContent() {
|
||||
if (path.startsWith('/invite/')) {
|
||||
const token = path.replace('/invite/', '')
|
||||
if (token) {
|
||||
const url = '/?tab=board-join&inviteToken=' + token
|
||||
ensureBaseHistory('board-join', { inviteToken: token }, url)
|
||||
setActiveTab('board-join')
|
||||
setLoadedTabs(prev => ({ ...prev, 'board-join': true }))
|
||||
setTabParams({ inviteToken: token })
|
||||
setIsInitialized(true)
|
||||
// Очищаем путь, оставляем только параметры
|
||||
window.history.replaceState({}, '', '/?tab=board-join&inviteToken=' + token)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -193,11 +209,12 @@ function AppContent() {
|
||||
if (path.startsWith('/tracking/invite/')) {
|
||||
const token = path.replace('/tracking/invite/', '')
|
||||
if (token) {
|
||||
const url = '/?tab=tracking-invite&inviteToken=' + token
|
||||
ensureBaseHistory('tracking-invite', { inviteToken: token }, url)
|
||||
setActiveTab('tracking-invite')
|
||||
setLoadedTabs(prev => ({ ...prev, 'tracking-invite': true }))
|
||||
setTabParams({ inviteToken: token })
|
||||
setIsInitialized(true)
|
||||
window.history.replaceState({}, '', '/?tab=tracking-invite&inviteToken=' + token)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -206,16 +223,18 @@ function AppContent() {
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
const integration = urlParams.get('integration')
|
||||
if (integration === 'fitbit') {
|
||||
setActiveTab('fitbit-integration')
|
||||
setLoadedTabs(prev => ({ ...prev, 'fitbit-integration': true }))
|
||||
setIsInitialized(true)
|
||||
// Перезаписываем URL с tab параметром и сохраняем integration/status для компонента
|
||||
const status = urlParams.get('status')
|
||||
const message = urlParams.get('message')
|
||||
let newUrl = '/?tab=fitbit-integration&integration=fitbit'
|
||||
if (status) newUrl += `&status=${status}`
|
||||
if (message) newUrl += `&message=${message}`
|
||||
window.history.replaceState({}, '', newUrl)
|
||||
const fitbitParams = { integration: 'fitbit' }
|
||||
if (status) fitbitParams.status = status
|
||||
if (message) fitbitParams.message = message
|
||||
ensureBaseHistory('fitbit-integration', fitbitParams, newUrl)
|
||||
setActiveTab('fitbit-integration')
|
||||
setLoadedTabs(prev => ({ ...prev, 'fitbit-integration': true }))
|
||||
setIsInitialized(true)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -224,10 +243,6 @@ function AppContent() {
|
||||
const validTabs = ['current', 'priorities', 'full', 'words', 'add-words', 'dictionaries', 'test', 'tasks', 'task-form', 'wishlist', 'wishlist-form', 'wishlist-detail', 'board-form', 'board-join', 'profile', 'todoist-integration', 'telegram-integration', 'fitbit-integration', 'tracking', 'tracking-access', 'tracking-invite']
|
||||
|
||||
if (tabFromUrl && validTabs.includes(tabFromUrl) && deepTabs.includes(tabFromUrl)) {
|
||||
// Если в URL есть глубокий таб, восстанавливаем его
|
||||
setActiveTab(tabFromUrl)
|
||||
setLoadedTabs(prev => ({ ...prev, [tabFromUrl]: true }))
|
||||
|
||||
// Восстанавливаем параметры из URL
|
||||
const params = {}
|
||||
urlParams.forEach((value, key) => {
|
||||
@@ -239,6 +254,11 @@ function AppContent() {
|
||||
}
|
||||
}
|
||||
})
|
||||
const deepTabUrl = window.location.pathname + window.location.search
|
||||
ensureBaseHistory(tabFromUrl, params, deepTabUrl)
|
||||
// Если в URL есть глубокий таб, восстанавливаем его
|
||||
setActiveTab(tabFromUrl)
|
||||
setLoadedTabs(prev => ({ ...prev, [tabFromUrl]: true }))
|
||||
if (Object.keys(params).length > 0) {
|
||||
setTabParams(params)
|
||||
// Если это экран full с selectedProject, восстанавливаем его
|
||||
|
||||
Reference in New Issue
Block a user