From e2b41c85f66678b0083accdd34f69e7d4a928af3 Mon Sep 17 00:00:00 2001 From: Mo Tarbin Date: Thu, 13 Aug 2026 22:31:21 -0400 Subject: [PATCH] feat: add policy update notice and handling - Introduced a new policy update modal to inform users of changes to the Privacy Policy and Terms of Service. - Implemented a service to manage the state of policy updates, including versioning and acknowledgment tracking. - Added a prompt component that surfaces the policy update modal based on user profile and acknowledgment status. - Updated Privacy Policy and Terms of Service documents with new effective dates and content. - Enhanced developer settings to allow manual triggering of the policy update notice for testing purposes. --- public/locales/en/common.json | 7 + src/constants/policyUpdates.js | 13 + src/service/PolicyUpdateService.js | 90 ++++ src/views/Chores/MyChores.jsx | 2 + src/views/Modals/PolicyUpdateModal.jsx | 81 ++++ src/views/PrivacyPolicy/PrivacyPolicyView.jsx | 173 ++++--- src/views/Settings/DeveloperSettings.jsx | 55 ++- src/views/Terms/TermsView.jsx | 440 +++++++++--------- src/views/components/PolicyUpdatePrompt.jsx | 53 +++ 9 files changed, 625 insertions(+), 289 deletions(-) create mode 100644 src/constants/policyUpdates.js create mode 100644 src/service/PolicyUpdateService.js create mode 100644 src/views/Modals/PolicyUpdateModal.jsx create mode 100644 src/views/components/PolicyUpdatePrompt.jsx diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 1a1056e..15752a7 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -69,6 +69,13 @@ "typeToSearch": "Type to search" } }, + "policyUpdate": { + "title": "We've updated our Privacy Policy and Terms", + "subtitle": "Please take a moment to review them. By continuing to use Donetick, you accept the updated documents.", + "readPrivacy": "Privacy Policy", + "readTerms": "Terms", + "acknowledge": "Got it" + }, "feedback": { "later": "Maybe later", "sentiment": { diff --git a/src/constants/policyUpdates.js b/src/constants/policyUpdates.js new file mode 100644 index 0000000..53176a7 --- /dev/null +++ b/src/constants/policyUpdates.js @@ -0,0 +1,13 @@ +// The single source of truth for "have the legal documents changed since the +// user last saw them". Bump POLICY_VERSION whenever PrivacyPolicyView or +// TermsView change in a way users should be told about, and move +// POLICY_EFFECTIVE_DATE to the same date shown at the bottom of those pages. +// +// The notice always points at the documents, so a revision needs nothing here +// beyond these two values plus, optionally, a summary. + +export const POLICY_VERSION = 2 + +// ISO date. Accounts created on or after this date signed up under the current +// documents, so they are never shown the update notice. +export const POLICY_EFFECTIVE_DATE = '2026-08-12' diff --git a/src/service/PolicyUpdateService.js b/src/service/PolicyUpdateService.js new file mode 100644 index 0000000..0b18271 --- /dev/null +++ b/src/service/PolicyUpdateService.js @@ -0,0 +1,90 @@ +import { Preferences } from '@capacitor/preferences' + +import { + POLICY_EFFECTIVE_DATE, + POLICY_VERSION, +} from '../constants/policyUpdates' + +const STATE_KEY = 'policyUpdateState' + +const defaultState = { + // Highest POLICY_VERSION the user has dismissed. 0 = never acknowledged. + acknowledgedVersion: 0, + acknowledgedAt: null, + // Developer Settings escape hatch; never set in normal use. + devForced: false, +} + +let cachedState = null + +const readState = async () => { + if (cachedState) return cachedState + try { + const { value } = await Preferences.get({ key: STATE_KEY }) + cachedState = { ...defaultState, ...(value ? JSON.parse(value) : {}) } + } catch (error) { + console.warn('PolicyUpdateService: unable to read state', error) + cachedState = { ...defaultState } + } + return cachedState +} + +const writeState = async patch => { + const current = await readState() + cachedState = { ...current, ...patch } + try { + await Preferences.set({ + key: STATE_KEY, + value: JSON.stringify(cachedState), + }) + } catch (error) { + // Worst case the notice is shown once more on the next launch, which is + // strictly better than suppressing a legal notice we failed to record. + console.warn('PolicyUpdateService: unable to persist state', error) + } +} + +export const getPolicyUpdateState = readState + +// FeedbackService sees both spellings off the profile endpoint; match it. +const getSignupDate = userProfile => + userProfile?.createdAt || userProfile?.created_at || null + +/** + * The notice is for people who agreed to an *earlier* revision. Accounts + * created on or after the effective date already signed up under the current + * documents, so they are silently marked as acknowledged instead of being + * interrupted by a change they never experienced. + */ +export const shouldShowPolicyUpdate = async ({ userProfile } = {}) => { + const state = await readState() + if (state.devForced) return true + if (state.acknowledgedVersion >= POLICY_VERSION) return false + + // An unreadable signup date errs toward showing: a missed legal notice is + // worse than one extra dismissal. + const signupDate = getSignupDate(userProfile) + const signedUpAt = signupDate ? new Date(signupDate) : null + + if ( + signedUpAt && + !isNaN(signedUpAt.getTime()) && + signedUpAt >= new Date(`${POLICY_EFFECTIVE_DATE}T00:00:00Z`) + ) { + await acknowledgePolicyUpdate() + return false + } + + return true +} + +export const acknowledgePolicyUpdate = () => + writeState({ + acknowledgedVersion: POLICY_VERSION, + acknowledgedAt: new Date().toISOString(), + devForced: false, + }) + +/** Developer Settings only: replay the notice on the next eligible mount. */ +export const resetPolicyUpdate = () => + writeState({ acknowledgedVersion: 0, acknowledgedAt: null, devForced: true }) diff --git a/src/views/Chores/MyChores.jsx b/src/views/Chores/MyChores.jsx index a867de9..bcd5d19 100644 --- a/src/views/Chores/MyChores.jsx +++ b/src/views/Chores/MyChores.jsx @@ -45,6 +45,7 @@ import CalendarDual from '../components/CalendarDual' import CalendarMonthly from '../components/CalendarMonthly.jsx' import FeedbackPrompt from '../components/FeedbackPrompt.jsx' import LoadingComponent from '../components/Loading' +import PolicyUpdatePrompt from '../components/PolicyUpdatePrompt.jsx' import { useLabels } from '../Labels/LabelQueries' import AdvancedFilterBuilder from '../Modals/Inputs/AdvancedFilterBuilder' import ConfirmationModal from '../Modals/Inputs/ConfirmationModal' @@ -1514,6 +1515,7 @@ const MyChores = () => { /> + {addTaskModalOpen && ( { + const { t } = useTranslation() + const { ResponsiveModal } = useResponsiveModal() + const navigate = useNavigate() + + const handleClose = () => { + onAcknowledge?.() + onClose() + } + + const openDocument = path => { + handleClose() + navigate(path) + } + + const documentButtonSx = { + justifyContent: 'flex-start', + fontWeight: 500, + '--Button-gap': '12px', + '& .MuiButton-endDecorator': { ml: 'auto' }, + } + + return ( + + } + > + + + + + + ) +} + +export default PolicyUpdateModal diff --git a/src/views/PrivacyPolicy/PrivacyPolicyView.jsx b/src/views/PrivacyPolicy/PrivacyPolicyView.jsx index b818ee7..1724f18 100644 --- a/src/views/PrivacyPolicy/PrivacyPolicyView.jsx +++ b/src/views/PrivacyPolicy/PrivacyPolicyView.jsx @@ -1,97 +1,144 @@ const PrivacyPolicyView = () => { return ( -
+

Privacy Policy

- Favoro LLC ("we," "us," or "our") operates the Donetick application and - website (collectively, the "Service"). This Privacy Policy informs you - of our policies regarding the collection, use, and disclosure of - personal data when you use our Service and the choices you have - associated with that data. -

-

Information We Collect

-

- Personal Data: When you register for an account or use - the Service, we may collect certain personally identifiable information, - such as your name and email address. + How Donetick handles your data

- Usage Data: We collect information on how you use the - Service, such as your IP address, browser type, pages visited, and the - time and date of your visit. + Last updated August 12, 2026 +

+ +

+ Donetick is made by Favoro LLC ("we", "us", "our"). This policy covers + the Donetick Cloud Service and our website. If you run Donetick + yourself, your data lives on your own server and you control it. Only + the analytics section below applies, and only if you opt in. +

+ +

1. What we collect

+

+ • Account info: your email, your name, and the circle + (household or group) you belong to.

- Task Data: We store the tasks and chores you create - within the app, including their details and any assigned users. -

-

How We Use Your Information

-

- Provide and Maintain the Service: We use your - information to operate, maintain, and improve the Service. + • Your content: the tasks, chores, labels, notes, and + schedules you create.

- Communicate with You: We may use your email address to - send you notifications, updates, and promotional materials related to - the Service. + • Usage data: basic, privacy-respecting information + about how the app is used so we can keep it working and improve it.

- Analyze Usage: We analyze usage data to understand how - the Service is used and to make improvements. + • Billing: if you upgrade, payment is handled by + Stripe. We never see or store your full card details.

-

How We Share Your Information

+ +

2. How we use it

- With Your Consent: We will not share your personal data - with third parties without your consent, except as described in this - Privacy Policy. + To run the core product: store and sync your tasks across your devices, + remind you when things are due, share chores with your circle, and + provide support. We use your content to operate the Service for you, not + to build advertising profiles, and never to train AI models. +

+ +

3. Analytics and error reports

+

+ We use{' '} + + PostHog + {' '} + to see which features are used and to catch crashes. Every event is + checked against a fixed list of allowed properties before it is sent, so + only this can leave your device: feature usage (for example, that a task + was created and whether it had a due date), technical details about your + installation (platform, OS version, app version, Cloud or self-hosted), + whether your account is on a paid plan and how many people are in your + circle, and, for errors, status codes and stack traces.

- Service Providers: We may engage third-party companies - or individuals to perform services on our behalf (e.g., hosting, - analytics). These third parties have access to your personal data only - to perform these tasks and are obligated not to disclose or use it for - any other purpose. + We never send the content of your tasks, chores, notes, search queries, + circle names, or label names. We don't use session recording or + automatic click capture.

- Compliance with Law: We may disclose your personal data - if required to do so by law or in response to valid requests by public - authorities (e.g., a court or government agency). + For our public website we also use{' '} + + Plausible + + , a privacy-friendly analytics tool that counts page views without + cookies, without cross-site tracking, and without building a profile of + you.

-

Security

+ +

4. Your analytics choices

- We value your privacy and have implemented reasonable security measures - to protect your personal data from unauthorized access, disclosure, - alteration, or destruction. However, no method of transmission over the - Internet or electronic storage is 100% secure, and we cannot guarantee - absolute security. + Product analytics and crash reporting are two separate switches under{' '} + Settings → Privacy & Analytics. On the Cloud + Service they're on by default and you can turn them off at any time. On + self-hosted installations they're off by default and require you to opt + in. Turning one off stops new data of that type immediately.

-

Your Choices

+ +

5. Where it lives

- Account Information: You can update or correct your - account information at any time. + Cloud Service data is stored on our hosted infrastructure, scoped so + that only you and the circle you share with can access it. Files you + upload, like task photos and attachments, are kept in secure cloud + object storage provided by Cloudflare, and are served over private, + expiring links rather than public URLs. We use reasonable safeguards to + protect all of it, though no system on the internet is perfectly secure.

+ +

6. Sharing

- Marketing Communications: You can opt out of receiving - promotional emails by following the unsubscribe instructions included in - those emails. + We don't sell your data. We share it only with the service providers + that make Donetick work (Cloudflare for hosting and file storage, + PostHog and Plausible for analytics, Stripe for payments), or when + required by law.

-

Children's Privacy

+ +

7. Your choices

- Our Service is not intended for children under 13 years of age. We do - not knowingly collect personal data from children under 13. If you are a - parent or guardian and you are aware that your child has provided us - with personal data, please contact us. + You can update your profile and permanently delete your account at any + time from Settings. Deleting your account removes your + content from our systems. You can also opt out of promotional emails + using the unsubscribe link in any of them.

-

Changes to This Privacy Policy

+ +

8. Retention

- We may update our Privacy Policy from time to time. We will notify you - of any changes by posting the new Privacy Policy on this page and - updating the "Effective Date" at the top of this Privacy Policy. + We keep your data while your account is active. When you delete your + account, we delete your content (backups age out on a rolling basis).

-

Contact Us

+ +

9. Children

- If you have any questions about this Privacy Policy, please contact us - at: + Donetick isn't directed to children under 13, and we don't knowingly + collect their data. Child accounts created by a parent inside a circle + are managed by that parent.

+ +

10. Changes

+

+ We'll post any updates here with a new date, and flag material changes + with a one-time notice inside the app. +

+ +

11. Contact

+

+ Privacy questions or requests? Email{' '} + support@donetick.com. +

+ +

Favoro LLC

) diff --git a/src/views/Settings/DeveloperSettings.jsx b/src/views/Settings/DeveloperSettings.jsx index 8f5d177..c0c1671 100644 --- a/src/views/Settings/DeveloperSettings.jsx +++ b/src/views/Settings/DeveloperSettings.jsx @@ -3,6 +3,7 @@ import { Refresh, Star, Token } from '@mui/icons-material' import { Box, Button, Card, Chip, Divider, Typography } from '@mui/joy' import { useQueryClient } from '@tanstack/react-query' import { useCallback, useEffect, useState } from 'react' + import { networkManager } from '../../hooks/NetworkManager' import useConfirmationModal from '../../hooks/useConfirmationModal' import { useSSEContext } from '../../hooks/useSSEContext' @@ -16,6 +17,7 @@ import { setDevForcedPrompt, } from '../../service/FeedbackService' import { useNotification } from '../../service/NotificationProvider' +import { resetPolicyUpdate } from '../../service/PolicyUpdateService' import { apiClient } from '../../utils/ApiClient' import { commandQueue } from '../../utils/CommandQueue' import { RefreshToken } from '../../utils/Fetcher' @@ -24,18 +26,19 @@ import { syncEngine } from '../../utils/SyncEngine' import { getRefreshTokenExpiry, isNative } from '../../utils/TokenStorage' import FeedbackModal from '../Modals/FeedbackModal' import ConfirmationModal from '../Modals/Inputs/ConfirmationModal' +import PolicyUpdateModal from '../Modals/PolicyUpdateModal' const DeveloperSettings = () => { const queryClient = useQueryClient() const { confirmModalConfig, showConfirmation } = useConfirmationModal() const { data: userProfile } = useUserProfile() const { - isConnected, - isConnecting, - lastEvent, error: sseError, getConnectionStatus, getDebugInfo, + isConnected, + isConnecting, + lastEvent, } = useSSEContext() const [accessTokenExpiry, setAccessTokenExpiry] = useState(null) @@ -53,6 +56,7 @@ const DeveloperSettings = () => { const [isLoadingNotifications, setIsLoadingNotifications] = useState(false) const [isResettingSync, setIsResettingSync] = useState(false) const [feedbackModalOpen, setFeedbackModalOpen] = useState(false) + const [policyModalOpen, setPolicyModalOpen] = useState(false) const [feedbackEligibility, setFeedbackEligibility] = useState(null) const [syncDiagnostics, setSyncDiagnostics] = useState({ cursor: null, @@ -394,6 +398,15 @@ const DeveloperSettings = () => { }) } + const handleForcePolicyUpdate = async () => { + await resetPolicyUpdate() + showNotification({ + type: 'success', + message: + 'Next visit to My Chores will show the policy notice after ~1.5s', + }) + } + const handleResetFeedbackState = async () => { await resetFeedbackState() await refreshFeedbackEligibility() @@ -854,6 +867,35 @@ const DeveloperSettings = () => { + + + Policy Update Notice + + + Shown once per POLICY_VERSION to accounts created before the policy + effective date. "Force Next Prompt" clears the + acknowledgement, then open My Chores to see the automatic trigger. + + + + + + + + {isNativePlatform && ( @@ -1210,6 +1252,13 @@ const DeveloperSettings = () => { }} /> + {/* Preview only — deliberately does not acknowledge, so opening it here + never suppresses the real notice. */} + setPolicyModalOpen(false)} + /> +
) diff --git a/src/views/Terms/TermsView.jsx b/src/views/Terms/TermsView.jsx index 64534b8..ea55a5a 100644 --- a/src/views/Terms/TermsView.jsx +++ b/src/views/Terms/TermsView.jsx @@ -2,247 +2,241 @@ import React from 'react' const TermsView = () => { return ( -
+

Terms of Service

-

Effective Date: January 1, 2024

-

- These Terms of Service ("Terms") govern your access to and use of the - Donetick task management platform provided by Favoro LLC ("Donetick", "we", "us", or "our"). - By accessing or using our services, you agree to be bound by these Terms. If you do not agree to - these Terms, you may not access or use our services. + Last updated August 12, 2026

-
-

Important: Cloud vs. Self-Hosted Services

-

- Donetick is available in two deployment models with different terms and responsibilities: -

-
    -
  • Cloud-Hosted Service: Hosted at donetick.com where we provide infrastructure and data management
  • -
  • Self-Hosted Service: Open-source software you deploy on your own infrastructure
  • -
-

Please review the applicable sections carefully as they define different rights and obligations.

-
- -

1. Definitions

-
    -
  • "Cloud Service" refers to the Donetick platform hosted at donetick.com and managed by Favoro LLC
  • -
  • "Self-Hosted Service" refers to the open-source Donetick software deployed on user-controlled infrastructure
  • -
  • "Content" means all data, information, tasks, files, and other materials you create, upload, or store using our services
  • -
  • "Circle" means a collaborative workspace shared between users for task management
  • -
- -

2. Eligibility and Account Registration

-
    -
  • You must be at least 13 years old to use our services
  • -
  • Users under 18 must have parental consent
  • -
  • You are responsible for maintaining the confidentiality of your account credentials
  • -
  • You must provide accurate and complete information when creating an account
  • -
  • One person or legal entity may maintain only one account
  • -
- -

3. Cloud-Hosted Service Terms

-

This section applies only to users of the Cloud Service at donetick.com

- -

3.1 Service Availability and Uptime

-
    -
  • We strive to maintain 99.5% uptime for the Cloud Service on a monthly basis
  • -
  • Scheduled maintenance will be announced at least 24 hours in advance when possible
  • -
  • We reserve the right to temporarily suspend service for emergency maintenance
  • -
  • No SLA credits or compensation are provided for downtime unless otherwise specified in a separate agreement
  • -
- -

3.2 Data Ownership and Responsibility

-
    -
  • Your Data: You retain ownership of all Content you create or upload
  • -
  • Our Responsibility: We provide secure hosting, backup, and infrastructure management
  • -
  • Data Portability: You can export your data at any time through our export features
  • -
  • Data Retention: We retain your data for 90 days after account deletion to allow recovery
  • -
- -

3.3 Subscriptions and Billing

-
    -
  • Cloud Service subscriptions are billed monthly or annually in advance
  • -
  • Subscription fees will automatically renew unless cancelled before the next billing cycle
  • -
  • You may cancel your subscription at any time through your account settings
  • -
  • Upon cancellation, you retain access until the end of your current billing period
  • -
  • We may modify subscription prices with 30 days advance notice
  • -
  • Refunds are considered on a case-by-case basis at our discretion
  • -
- -

3.4 Cloud Service Limitations

-
    -
  • Storage limits apply based on your subscription tier
  • -
  • API rate limits may be enforced to ensure service stability
  • -
  • We may suspend accounts that exceed reasonable usage limits
  • -
- -

4. Self-Hosted Service Terms

-

This section applies to users deploying Donetick on their own infrastructure

- -

4.1 Open Source License

-
    -
  • The Self-Hosted Service is provided under the MIT License
  • -
  • You may modify, distribute, and use the software for any purpose
  • -
  • Attribution to Donetick must be maintained in derivative works
  • -
  • No warranty or support is provided for self-hosted deployments
  • -
- -

4.2 User Responsibility

-
    -
  • Infrastructure: You are solely responsible for hosting, maintenance, security, and backups
  • -
  • Data Protection: You are the data controller and responsible for compliance with applicable laws
  • -
  • Updates: You are responsible for applying security updates and patches
  • -
  • Support: No technical support is provided for self-hosted installations
  • -
- -

4.3 Limitation of Our Responsibility

-
    -
  • We provide no guarantees about the performance or security of self-hosted deployments
  • -
  • We are not responsible for any data loss, security breaches, or service interruptions in self-hosted environments
  • -
  • Technical support is limited to community forums and documentation
  • -
- -

5. Acceptable Use Policy

+

1. Agreement

- Applies to both Cloud and Self-Hosted Services + By creating an account or using Donetick Cloud at donetick.com (the + "Service"), you agree to these Terms. If you don't agree, don't use the + Service. Donetick is made by Favoro LLC ("we", "us", "our").

-

You may not use our services to:

-
    -
  • Violate any applicable laws or regulations
  • -
  • Infringe on intellectual property rights
  • -
  • Transmit malicious code or conduct security attacks
  • -
  • Harass, abuse, or harm other users
  • -
  • Distribute spam or unwanted communications
  • -
  • Attempt to reverse engineer our proprietary systems (Cloud Service)
  • -
  • Resell or redistribute the service without permission
  • -
- -

6. Content and Data

- -

6.1 Your Content Rights

-
    -
  • You retain ownership of all Content you create
  • -
  • You grant us the necessary rights to operate the service (Cloud Service only)
  • -
  • You are responsible for ensuring you have rights to any Content you upload
  • -
- -

6.2 Content Restrictions

-
    -
  • Content must not violate any laws or third-party rights
  • -
  • Content must not contain malicious code or harmful materials
  • -
  • We may remove Content that violates these Terms (Cloud Service only)
  • -
- -

7. Privacy and Security

-
    -
  • Your privacy is important to us - please review our Privacy Policy
  • -
  • We implement industry-standard security measures (Cloud Service)
  • -
  • You are responsible for security in self-hosted deployments
  • -
  • Report security vulnerabilities to security@donetick.com
  • -
- -

8. Intellectual Property

-
    -
  • The Donetick name, logo, and proprietary features are our intellectual property
  • -
  • The open-source codebase is licensed under MIT License
  • -
  • You may not use our trademarks without written permission
  • -
- -

9. Third-Party Integrations

-
    -
  • Donetick integrates with third-party services (Telegram, Discord, webhooks, etc.)
  • -
  • Your use of these integrations is subject to their respective terms
  • -
  • We are not responsible for third-party service availability or functionality
  • -
- -

10. Liability and Warranties

- -

10.1 Disclaimer of Warranties

+

2. Cloud vs. self-hosted

+

Donetick comes in two flavors, and they're governed differently.

- Our services are provided "as is" and "as available" without any warranty of any kind, - express or implied, including but not limited to merchantability, fitness for a particular purpose, - or non-infringement. + Donetick Cloud is the hosted service we run at + donetick.com. These Terms cover it. +

+

+ Self-hosted Donetick is the open-source software you + run on your own server. It's licensed under the GNU Affero General + Public License v3 (AGPLv3), and that license, not these Terms, governs + your rights to use, modify, and share it. Nothing here is meant to + restrict anything the AGPLv3 grants you. +

+

+ If you run Donetick yourself, hosting, security, backups, updates, and + data-protection obligations are yours, not ours. We don't provide + support guarantees for self-hosted installs unless we've agreed to that + separately in writing.

-

10.2 Cloud Service Liability

-
    -
  • Our total liability for the Cloud Service is limited to the amount you paid in the 12 months preceding the claim
  • -
  • We are not liable for indirect, incidental, special, or consequential damages
  • -
  • We maintain appropriate insurance and implement security best practices
  • -
- -

10.3 Self-Hosted Service Liability

-
    -
  • We provide no warranties or guarantees for self-hosted deployments
  • -
  • Our liability is limited to the maximum extent permitted by law
  • -
  • You assume all risks associated with self-hosting
  • -
- -

11. Indemnification

+

3. What Donetick does

- You agree to indemnify and hold us harmless from any claims, damages, or expenses - arising from your use of our services, violation of these Terms, or infringement of any rights. + Donetick helps you and the people in your circle track tasks, chores, + and recurring schedules. It's a productivity tool, not professional, + legal, financial, or medical advice. +

+ +

4. Your account

+

+ You're responsible for your account and for keeping your login secure. + You must be at least 13 years old (or the age of digital consent where + you live) to use the Service. Provide accurate information, and tell us + promptly if you think someone else has gotten into your account. +

+ +

5. Acceptable use

+

+ Don't use Donetick to break the law, infringe anyone's rights, upload + malware, harass other users, send spam, gain unauthorized access to our + systems or anyone's account, circumvent usage limits, or overload the + Service. +

+

+ Don't use Donetick Cloud to run a competing hosted service without our + written permission. This applies only to our Cloud Service and takes + nothing away from your AGPLv3 rights to the self-hosted software. +

+ +

6. Your content

+

+ You own everything you put into Donetick: your tasks, chores, labels, + comments, and files. You grant us a limited license to host, store, + process, and transmit it solely to operate, secure, troubleshoot, and + improve the Service for you. We don't sell your content, and we don't + use it to train AI models. +

+

+ You're responsible for having the right to upload what you upload, and + for managing who you share circles and content with. We may remove + content when reasonably necessary to enforce these Terms, comply with + the law, or address a security issue, and we'll give you notice first + where that's practical. +

+

+ How we handle personal information is covered in our{' '} + Privacy Policy, including what our analytics and + error reporting do and don't collect, and how to turn them off. +

+ +

7. Availability

+

+ We aim for roughly 99% monthly availability on the Cloud Service, but + that's a goal, not a service-level agreement, and there are no downtime + credits. We may pause parts of the Service for maintenance, security, or + emergencies, and we'll announce planned work ahead of time when we + reasonably can. Storage limits, API rate limits, and fair-use limits may + apply. +

+ +

8. Plans and billing

+

+ Donetick offers a free plan and paid plans billed monthly or annually in + advance through Stripe. Paid plans renew automatically until you cancel. +

+

+ You can cancel any time from your settings. Cancelling stops future + renewals, and you keep paid features through the end of the current + billing period. If a payment fails we may retry it or limit paid + features until it goes through. We'll give you reasonable notice before + a price change applies to your subscription. Refunds are handled + case-by-case at our discretion, except where the law requires one. + Nothing here limits your consumer-protection rights. +

+ +

9. Your data and export

+

+ Where export tools are available, you can export your content; formats + and availability may change over time. If we ever discontinue the Cloud + Service, we'll give reasonable advance notice and, where possible, a + chance to export first. +

+ +

10. Third-party integrations

+

+ Donetick connects to outside services like messaging platforms, + authentication providers, and webhooks. Those are governed by their own + terms and privacy policies, and we're not responsible for services we + don't control. Make sure you're authorized to connect whatever you + connect. +

+ +

11. Our brand

+

+ You own your content; we own the Donetick name, logo, branding, and the + proprietary parts of the Cloud Service. The AGPLv3 covers the software, + not our trademarks, so please don't use our name or logo in a way that + suggests we endorse or sponsor you.

12. Termination

- -

12.1 Termination by You

-
    -
  • You may terminate your account at any time
  • -
  • Cloud Service: Access continues until the end of your billing period
  • -
  • Self-Hosted Service: You may stop using the software at any time
  • -
- -

12.2 Termination by Us

-
    -
  • We may terminate accounts that violate these Terms
  • -
  • We may discontinue the Cloud Service with 90 days notice
  • -
  • We will provide data export capabilities before termination when possible
  • -
- -

13. Changes to These Terms

-
    -
  • We may update these Terms from time to time
  • -
  • Material changes will be announced via email or in-app notification
  • -
  • Continued use after changes constitutes acceptance of new Terms
  • -
  • For significant changes, we may require explicit acceptance
  • -
- -

14. Dispute Resolution

-
    -
  • We encourage resolving disputes informally by contacting us first
  • -
  • These Terms are governed by the laws of Delaware, United States
  • -
  • Any disputes will be resolved in the courts of Delaware
  • -
  • You may pursue small claims court for eligible disputes
  • -
- -

15. Miscellaneous

-
    -
  • If any provision is found unenforceable, the remainder remains in effect
  • -
  • Our failure to enforce any right does not waive that right
  • -
  • These Terms constitute the entire agreement between us
  • -
  • We may assign these Terms; you may not without our consent
  • -
- -

16. Contact Information

- If you have questions about these Terms, please contact us: + You can stop using Donetick and delete your account at any time from + Settings. We may suspend or end access if you violate these Terms, or + where we need to address abuse, fraud, a security incident, a legal + obligation, or unpaid fees. Where it's practical, we'll give you notice + and a chance to fix the problem first. After termination we delete or + anonymize your content per our retention practices, though limited + records may stick around for legal, security, or accounting reasons.

-
    -
  • Email: legal@donetick.com
  • -
  • Support: support@donetick.com
  • -
  • Address: Favoro LLC, [Address to be provided]
  • -
-
-

- Last Updated: January 1, 2024
- These Terms of Service are effective immediately for new users and will become effective - for existing users 30 days after posting. +

13. Security reports

+

+ Found a vulnerability? Please email{' '} + support@donetick.com and give + us a reasonable chance to fix it before disclosing it publicly.

+ +

14. Disclaimers and liability

+

+ + THE SERVICE IS PROVIDED "AS IS" AND "AS AVAILABLE," WITHOUT WARRANTIES + OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. WE DO NOT + WARRANT THAT THE SERVICE WILL BE UNINTERRUPTED, ERROR-FREE, OR SECURE, + OR THAT DATA WILL NEVER BE LOST OR CORRUPTED. + +

+

+ + TO THE MAXIMUM EXTENT PERMITTED BY LAW, FAVORO LLC IS NOT LIABLE FOR + INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE + DAMAGES, OR FOR LOST PROFITS, REVENUE, BUSINESS, GOODWILL, OR DATA. + OUR TOTAL LIABILITY IS LIMITED TO THE GREATER OF WHAT YOU PAID US IN + THE 12 MONTHS BEFORE THE CLAIM, OR $100. + +

+

+ Self-hosted installs are covered by the AGPLv3's warranty disclaimer. + We're not responsible for problems arising from your own infrastructure, + configuration, modifications, or hosting provider. Nothing in these + Terms excludes liability that can't legally be excluded. +

+ +

15. Indemnification

+

+ To the extent the law allows, you agree to cover Favoro LLC against + third-party claims arising from your violation of these Terms, your + unlawful use of the Service, your infringement of someone else's rights, + or content you submitted. We'll give you reasonable notice of any such + claim and cooperate in the defense. +

+ +

16. Disputes and governing law

+

+ Before filing anything, please email{' '} + support@donetick.com and give + us a fair chance to sort it out. These Terms are governed by the laws of + the State of Delaware, USA, without regard to conflict-of-laws rules, + and disputes go to the state or federal courts in Delaware. Either of us + can still bring an eligible claim in small claims court, and none of + this waives rights that can't legally be waived. +

+ +

17. Changes

+

+ We may update these Terms. We'll post the new version with an updated + date, and for material changes we'll give reasonable advance notice by + email or in-app notice (and get your consent where the law requires it). + Continuing to use the Service after non-material changes means you + accept them. If you don't agree to a material change, cancel before it + takes effect. +

+ +

18. The fine print

+

+ These Terms plus our Privacy Policy are the whole agreement between us. + If one provision turns out to be unenforceable, it gets trimmed to the + minimum necessary and the rest stands. Not enforcing something once + doesn't waive it later. You can't transfer these Terms without our + consent; we may transfer them in a merger, acquisition, or sale of + assets. These Terms don't create a partnership, employment, or agency + relationship. Neither of us is liable for delays caused by things + outside our reasonable control. Provisions that should survive + termination do, including those on content, intellectual property, + disclaimers, liability, indemnification, and disputes. +

+ +

19. Contact

+

+ Questions about these Terms? Email{' '} + support@donetick.com. +

+ +
+

Favoro LLC

) } diff --git a/src/views/components/PolicyUpdatePrompt.jsx b/src/views/components/PolicyUpdatePrompt.jsx new file mode 100644 index 0000000..ff4787f --- /dev/null +++ b/src/views/components/PolicyUpdatePrompt.jsx @@ -0,0 +1,53 @@ +import { useEffect, useState } from 'react' + +import { useUserProfile } from '../../queries/UserQueries' +import { + acknowledgePolicyUpdate, + shouldShowPolicyUpdate, +} from '../../service/PolicyUpdateService' +import PolicyUpdateModal from '../Modals/PolicyUpdateModal' + +// Let the screen settle before interrupting, and stay out of the way of the +// feedback prompt, which uses a longer delay from the same screen. +const OPEN_DELAY_MS = 1500 + +/** + * Surfaces the policy-change notice once per revision. Mount once, near the + * main task list. + */ +const PolicyUpdatePrompt = () => { + const [open, setOpen] = useState(false) + const { data: userProfile } = useUserProfile() + + useEffect(() => { + if (!userProfile) return + + let timer = null + let cancelled = false + + shouldShowPolicyUpdate({ userProfile }).then(eligible => { + if (!eligible || cancelled) return + timer = setTimeout(() => { + if (cancelled) return + setOpen(true) + }, OPEN_DELAY_MS) + }) + + return () => { + cancelled = true + if (timer) clearTimeout(timer) + } + }, [userProfile]) + + if (!open) return null + + return ( + setOpen(false)} + onAcknowledge={acknowledgePolicyUpdate} + /> + ) +} + +export default PolicyUpdatePrompt