mirror of
https://github.com/IliesAllali/parenthese.git
synced 2026-11-06 23:32:08 +00:00
mesure : copie du lien de partage, page vie privée à jour
share_copied quand le propriétaire copie le lien, le mot de passe ou le message d'invitation (what, seasonal pour le message de Noël), ou crée le lien d'un co-gestionnaire (manager_invite). Rien de ce qui est copié ne part. La page vie privée (fr, en) décrit maintenant tout ce que l'app mesure : démo, modifications comptées sans leur contenu, propositions, partage. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
332b5711ff
commit
ef620c9cb5
4 files changed
+21
-8
No files matched your search
@@ -7,7 +7,8 @@ import './SettingsPanels.css'
|
||||
import PzBusy from './PzBusy.jsx'
|
||||
import { HELP_URL } from '../utils/siteLinks.js'
|
||||
import { t, dateLocale } from '../i18n/index.js'
|
||||
import { buildInviteText } from '../utils/inviteText.js'
|
||||
import { buildInviteText, isChristmasSeason } from '../utils/inviteText.js'
|
||||
import { toOpaqueTreeId, trackAppEvent } from '../utils/analytics.js'
|
||||
import { sexLabel } from '../utils/personSex.js'
|
||||
import Skeleton from './Skeleton.jsx'
|
||||
|
||||
@@ -346,10 +347,19 @@ const ContributionPanel = ({
|
||||
const [inviteText, setInviteText] = useState('')
|
||||
useEffect(() => { setInviteText(defaultInviteText) }, [defaultInviteText])
|
||||
|
||||
const handleCopy = async (value, label) => {
|
||||
// what : link, password ou message. Ce qui a été copié, jamais le texte lui-même
|
||||
const handleCopy = async (value, label, what) => {
|
||||
const text = String(value || '').trim()
|
||||
if (!text) return
|
||||
try { await navigator.clipboard.writeText(text); setCopyFeedback(label) }
|
||||
try {
|
||||
await navigator.clipboard.writeText(text)
|
||||
setCopyFeedback(label)
|
||||
trackAppEvent('share_copied', {
|
||||
what,
|
||||
...(what === 'message' ? { seasonal: Boolean(seasonalInvite && isChristmasSeason()) } : {}),
|
||||
tree_id: toOpaqueTreeId(treeId),
|
||||
})
|
||||
}
|
||||
catch { setCopyFeedback(t('Copie indisponible')) }
|
||||
}
|
||||
|
||||
@@ -398,7 +408,7 @@ const ContributionPanel = ({
|
||||
</div>
|
||||
<div className="contrib-invite-link">
|
||||
<code className="contrib-link-url">{inviteShareUrl || t('Lien indisponible')}</code>
|
||||
<button type="button" className="pz-btn pz-btn--primary pz-btn--sm" disabled={!inviteShareUrl} onClick={() => handleCopy(inviteShareUrl, t('Lien copié'))}><Copy size={14} strokeWidth={2} />{t('Copier')}</button>
|
||||
<button type="button" className="pz-btn pz-btn--primary pz-btn--sm" disabled={!inviteShareUrl} onClick={() => handleCopy(inviteShareUrl, t('Lien copié'), 'link')}><Copy size={14} strokeWidth={2} />{t('Copier')}</button>
|
||||
</div>
|
||||
<div className="contrib-invite-passwords">
|
||||
<div className="contrib-role-row">
|
||||
@@ -412,7 +422,7 @@ const ContributionPanel = ({
|
||||
) : (
|
||||
<>
|
||||
<button type="button" className={`contrib-pass-reveal${knownShare && !showPassword ? ' contrib-pass-reveal--blurred' : ''}`} onClick={() => setShowPassword((v) => !v)} disabled={!knownShare} title={showPassword ? t('Cliquer pour masquer') : t('Cliquer pour révéler')}>{knownShare || t('Pas encore enregistré')}</button>
|
||||
{knownShare && <button type="button" className="contrib-pill-btn contrib-pill-btn--edit" onClick={() => handleCopy(knownShare, t('Mot de passe copié'))}>{t('Copier')}</button>}
|
||||
{knownShare && <button type="button" className="contrib-pill-btn contrib-pill-btn--edit" onClick={() => handleCopy(knownShare, t('Mot de passe copié'), 'password')}>{t('Copier')}</button>}
|
||||
{!knownShare && <button type="button" className="contrib-pill-btn contrib-pill-btn--edit" disabled={inviteSaving} onClick={() => setPasswordMode('remember')}>{t("Saisir l'actuel")}</button>}
|
||||
<button type="button" className="contrib-pill-btn contrib-pill-btn--edit" disabled={inviteSaving} onClick={() => setPasswordMode('change')}>{t('Changer')}</button>
|
||||
</>
|
||||
@@ -427,7 +437,7 @@ const ContributionPanel = ({
|
||||
{defaultInviteText && (
|
||||
<div className="contrib-invite-message">
|
||||
<div className="contrib-invite-message-row">
|
||||
<button type="button" className="contrib-pill-btn contrib-pill-btn--edit" onClick={() => handleCopy(inviteText, t('Message copié'))}><Copy size={14} strokeWidth={2} />{t("Copier le message d'invitation")}</button>
|
||||
<button type="button" className="contrib-pill-btn contrib-pill-btn--edit" onClick={() => handleCopy(inviteText, t('Message copié'), 'message')}><Copy size={14} strokeWidth={2} />{t("Copier le message d'invitation")}</button>
|
||||
<button type="button" className="contrib-link-btn" aria-expanded={showInviteMessage} aria-controls="contrib-invite-text" onClick={() => setShowInviteMessage((v) => !v)}>
|
||||
{showInviteMessage ? t('Masquer le message') : t('Voir ou modifier le message')}
|
||||
</button>
|
||||
|
||||
@@ -4,6 +4,7 @@ import PzBusy from './PzBusy.jsx'
|
||||
import { dateLocale, t } from '../i18n/index.js'
|
||||
import { initialOf } from '../utils/initial.js'
|
||||
import Skeleton from './Skeleton.jsx'
|
||||
import { toOpaqueTreeId, trackAppEvent } from '../utils/analytics.js'
|
||||
|
||||
// Onglet Gestion des paramètres de l'arbre (issue #145). Le propriétaire invite des co-gestionnaires par leur
|
||||
// adresse : Parenthèse n'envoie pas de mail, il donne un lien à transmettre. Les co-gestionnaires voient la liste.
|
||||
@@ -42,6 +43,8 @@ const TreeManagersSection = ({ treeId, authToken, currentUserId = null, oidcName
|
||||
const url = invitationUrl(token)
|
||||
let copied
|
||||
try { await navigator.clipboard.writeText(url); copied = true } catch { copied = false }
|
||||
// Le lien créé compte comme un partage même si le presse-papiers est refusé (il est alors montré en clair)
|
||||
trackAppEvent('share_copied', { what: 'manager_invite', copied, tree_id: toOpaqueTreeId(treeId) })
|
||||
setLink({ url, email: forEmail, copied })
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
|
||||
<h2>Mesure d'audience</h2>
|
||||
<p>Parenthèse utilise PostHog pour compter les visites et voir ce qui est utilisé. PostHog est hébergé aux États-Unis, les données d'usage décrites ici y sont envoyées.</p>
|
||||
<p>Ce qui est mesuré, et rien de plus. Sur le site, la visite d'une page, le défilement, la lecture de la vidéo de présentation, les clics sur les boutons « Créer mon arbre », avec la provenance (lien d'arrivée, page précédente, mobile ou ordinateur). Dans l'application, l'ouverture de l'écran de compte, la création d'un compte ou d'un arbre, et pour les arbres partagés, l'ouverture, le temps passé et le type de contenu consulté (texte, photo, vidéo), avec le type d'accès. L'arbre y est désigné par un code brouillé, jamais par son nom.</p>
|
||||
<p>Ce qui est mesuré, et rien de plus. Sur le site, la visite d'une page, le défilement, la lecture de la vidéo de présentation, les clics sur les boutons « Créer mon arbre », avec la provenance (lien d'arrivée, page précédente, mobile ou ordinateur). Dans l'application, l'ouverture de l'écran de compte, la création d'un compte ou d'un arbre, l'ouverture de l'arbre d'exemple et les gestes qu'on y fait, les modifications d'un arbre comptées sans leur contenu (ajout d'une personne, d'un portrait ou de souvenirs, import d'un fichier GEDCOM, enregistrement), l'envoi et la relecture des propositions de la famille, la copie du lien, du mot de passe ou du message de partage (jamais ce qui est copié), et pour les arbres partagés, l'ouverture, le temps passé et le type de contenu consulté (texte, photo, vidéo), avec le type d'accès. L'arbre y est désigné par un code brouillé, jamais par son nom.</p>
|
||||
<p>Il n'y a pas de capture automatique des clics ni des pages, et pas d'enregistrement des sessions. Aucun contenu d'arbre (nom, personne, photo) n'est envoyé, ni l'adresse de l'arbre, retirée des liens avant tout envoi. Quand vous êtes connecté à votre compte, un identifiant technique du compte (jamais votre adresse email) relie vos visites entre elles. Un cookie est posé sur parenthese.io et ses sous-domaines pour reconnaître la même visite entre le site et l'application.</p>
|
||||
|
||||
<h2>Vos droits</h2>
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
|
||||
<h2>Audience measurement</h2>
|
||||
<p>Parenthèse uses PostHog to count visits and see what gets used. PostHog is hosted in the United States, and the usage data described here is sent there.</p>
|
||||
<p>Here is what is measured, and nothing more. On the website, page views, scrolling, playing the introduction video, clicks on the “Start your tree” buttons, with where they came from (link used to arrive, previous page, mobile or computer). In the app, opening the account screen, creating an account or a tree, and for shared trees, opening them, the time spent and the type of content viewed (text, photo, video), with the type of access. The tree is identified there by a scrambled code, never by its name.</p>
|
||||
<p>Here is what is measured, and nothing more. On the website, page views, scrolling, playing the introduction video, clicks on the “Start your tree” buttons, with where they came from (link used to arrive, previous page, mobile or computer). In the app, opening the account screen, creating an account or a tree, opening the example tree and what is done in it, edits to a tree counted without their content (adding a person, a portrait or memories, importing a GEDCOM file, saving), sending and reviewing the family's suggestions, copying the share link, password or message (never what is copied), and for shared trees, opening them, the time spent and the type of content viewed (text, photo, video), with the type of access. The tree is identified there by a scrambled code, never by its name.</p>
|
||||
<p>There is no automatic capture of clicks or pages, and no session recording. No tree content (name, person, photo) is sent, and neither is the address of the tree, which is removed from links before anything is sent. When you are logged in to your account, a technical account identifier (never your email address) links your visits together. A cookie is set on parenthese.io and its subdomains to recognize the same visit across the site and the app.</p>
|
||||
|
||||
<h2>Your rights</h2>
|
||||
|
||||
Reference in new issue
Block a user