-
Notifications
You must be signed in to change notification settings - Fork 7
fix(profile): click analytics [MOSOWEB-43] #67
Changes from all commits
bee2259
c3ef109
e62a0b0
790456e
71ec6cd
98213c7
fc0a7c6
6e37ff9
960b1c3
e1c750b
7e06e91
ce5e34d
50f23a2
c1aad78
97af09d
a680560
1a86114
b1d2788
035000d
41fb0e3
5d8cd51
c328875
67e84ca
2989ae2
ad1d671
77851e1
386f564
8e333fb
2f4a0b7
7e256c5
848bdcb
f964cbb
1e28075
b65df8c
68f952b
c535447
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,13 @@ | ||
<script setup lang="ts"> | ||
import type { mastodon } from 'masto' | ||
import { engagement } from '~~/telemetry/generated/ui' | ||
import { engagementDetails } from '~~/telemetry/engagementDetails' | ||
import { toggleFollowAccount, useRelationship } from '~~/composables/masto/relationship' | ||
|
||
const { account, command, context, ...props } = defineProps<{ | ||
const { account, command, context, gleanContext, ...props } = defineProps<{ | ||
account: mastodon.v1.Account | ||
relationship?: mastodon.v1.Relationship | ||
gleanContext?: string | ||
context?: 'followedBy' | 'following' | ||
command?: boolean | ||
}>() | ||
|
@@ -65,6 +68,57 @@ const buttonStyle = $computed(() => { | |
// If not following, use a button style | ||
return 'text-inverted bg-primary border-primary' | ||
}) | ||
|
||
const dataGlean = $computed(() => { | ||
if (!gleanContext) | ||
return undefined | ||
|
||
let action | ||
if (relationship?.blocking) | ||
action = 'follow-btn.unblock' | ||
else if (relationship?.muting) | ||
action = 'follow-btn.unmute' | ||
else if (relationship ? relationship.following : context === 'following') | ||
action = 'follow-btn.unfollow' | ||
else if (relationship?.requested) | ||
action = 'follow-btn.withdraw-follow-request' | ||
else if ((relationship ? relationship.followedBy : context === 'followedBy') && account.locked) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this horrendous conditional comes from somewhere else in the |
||
action = 'follow-btn.follow-request' | ||
else | ||
action = 'follow-btn.follow' | ||
|
||
return `${gleanContext}.${action}` | ||
}) | ||
|
||
function handleClick() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did some clever ordering with the contents of this function. I'm open to some non-clever alternatives There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reordering of contents in this function might be causing the bug where the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ooh good catch. I was unaware of this "mixed" use case. That counts as a 7th state for this horrible button component :'( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's make sure that whatever changes we make, the end result matches what is on production. We don't want to introduce any usability differences in this PR, only analytics events. We can follow up with improvements to this terrible button in a future PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pushed up fixing the bug by removing my cleverness and bringing back the original order of events There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Verified that I'm no longer seeing that bug! |
||
function recordEngagement() { | ||
engagement.record({ | ||
ui_identifier: dataGlean, | ||
mastodon_account_id: account.id, | ||
mastodon_account_handle: account.acct, | ||
...engagementDetails[dataGlean], | ||
}) | ||
} | ||
|
||
const unfollow = relationship?.following || relationship?.requested | ||
|
||
// Make sure recordEngagement is called before making changes to account/relationship | ||
if (relationship?.blocking) { | ||
recordEngagement() | ||
unblock() | ||
} | ||
else if (relationship?.muting) { | ||
recordEngagement() | ||
unmute() | ||
} | ||
else if (unfollow) { | ||
toggleFollowAccount(relationship!, account, dataGlean) | ||
} | ||
else { | ||
recordEngagement() | ||
toggleFollowAccount(relationship!, account) | ||
} | ||
} | ||
</script> | ||
|
||
<template> | ||
|
@@ -75,7 +129,7 @@ const buttonStyle = $computed(() => { | |
rounded-full flex="~ gap2 center" font-500 min-w-30 h-fit px3 py1 | ||
:class="buttonStyle" | ||
:hover="!relationship?.blocking && !relationship?.muting && relationship?.following ? 'border-red text-red' : 'bg-base border-primary text-primary'" | ||
@click="relationship?.blocking ? unblock() : relationship?.muting ? unmute() : toggleFollowAccount(relationship!, account)" | ||
@click="handleClick" | ||
> | ||
<template v-if="relationship?.blocking"> | ||
<span elk-group-hover="hidden">{{ $t('account.blocking') }}</span> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
<script setup lang="ts"> | ||
import type { mastodon } from 'masto' | ||
import { toggleBlockAccount, toggleBlockDomain, toggleMuteAccount } from '~~/composables/masto/relationship' | ||
import { engagement } from '~~/telemetry/generated/ui' | ||
import { engagementDetails } from '~~/telemetry/engagementDetails' | ||
|
||
const { account } = defineProps<{ | ||
account: mastodon.v1.Account | ||
|
@@ -21,39 +23,63 @@ const { client } = $(useMasto()) | |
const useStarFavoriteIcon = usePreferences('useStarFavoriteIcon') | ||
const { share, isSupported: isShareSupported } = useShare() | ||
|
||
function recordEngagement(dataGlean: string) { | ||
engagement.record({ | ||
ui_identifier: dataGlean, | ||
mastodon_account_id: account.id, | ||
mastodon_account_handle: account.acct, | ||
...engagementDetails[dataGlean], | ||
}) | ||
} | ||
|
||
function shareAccount() { | ||
recordEngagement('profile.more.share-account') | ||
share({ url: location.href }) | ||
} | ||
|
||
async function toggleReblogs() { | ||
if (!relationship!.showingReblogs && await openConfirmDialog({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you're gonna see me separate out |
||
title: t('confirm.show_reblogs.title', [account.acct]), | ||
confirm: t('confirm.show_reblogs.confirm'), | ||
cancel: t('confirm.show_reblogs.cancel'), | ||
}) !== 'confirm') | ||
return | ||
if (!relationship!.showingReblogs) { | ||
if (await openConfirmDialog({ | ||
title: t('confirm.show_reblogs.title', [account.acct]), | ||
confirm: t('confirm.show_reblogs.confirm'), | ||
cancel: t('confirm.show_reblogs.cancel'), | ||
}) !== 'confirm') | ||
return | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. perhaps we should add analytics to the cancel cases of these dialogues? |
||
recordEngagement('profile.more.show-boosts') | ||
} | ||
else { | ||
recordEngagement('profile.more.hide-boosts') | ||
} | ||
|
||
const showingReblogs = !relationship?.showingReblogs | ||
relationship = await client.v1.accounts.follow(account.id, { reblogs: showingReblogs }) | ||
} | ||
|
||
async function addUserNote() { | ||
recordEngagement('profile.more.add-note') | ||
emit('addNote') | ||
} | ||
|
||
async function removeUserNote() { | ||
recordEngagement('profile.more.remove-note') | ||
|
||
if (!relationship!.note || relationship!.note.length === 0) | ||
return | ||
|
||
const newNote = await client.v1.accounts.createNote(account.id, { comment: '' }) | ||
relationship!.note = newNote.note | ||
emit('removeNote') | ||
} | ||
|
||
function report() { | ||
recordEngagement('profile.more.report.open') | ||
openReportDialog(account) | ||
} | ||
</script> | ||
|
||
<template> | ||
<CommonDropdown :eager-mount="command"> | ||
<button flex gap-1 items-center w-full rounded op75 hover="op100 text-purple" group aria-label="More actions"> | ||
<button flex gap-1 items-center w-full rounded op75 hover="op100 text-purple" group aria-label="More actions" data-glean="profile.more.open"> | ||
<div rounded-5 p2 elk-group-hover="bg-purple/10"> | ||
<div i-ri:more-2-fill /> | ||
</div> | ||
|
@@ -62,12 +88,15 @@ async function removeUserNote() { | |
<template #popper> | ||
<NuxtLink v-if="notLocal" :to="account.url" external target="_blank"> | ||
<CommonDropdownItem | ||
is="button" | ||
:text="$t('menu.open_in_original_site')" | ||
icon="i-ri:arrow-right-up-line" | ||
:command="command" | ||
data-glean="profile.more.open-in-original-site" | ||
/> | ||
</NuxtLink> | ||
<CommonDropdownItem | ||
is="button" | ||
v-if="isShareSupported" | ||
:text="`Share @${account.acct}`" | ||
icon="i-ri:share-line" | ||
|
@@ -78,26 +107,30 @@ async function removeUserNote() { | |
<template v-if="currentUser"> | ||
<template v-if="!isSelf"> | ||
<CommonDropdownItem | ||
is="button" | ||
:text="$t('menu.mention_account', [`@${account.acct}`])" | ||
icon="i-ri:at-line" | ||
:command="command" | ||
@click="mentionUser(account)" | ||
@click="mentionUser(account, 'profile.more.mention')" | ||
/> | ||
<CommonDropdownItem | ||
is="button" | ||
:text="$t('menu.direct_message_account', [`@${account.acct}`])" | ||
icon="i-ri:message-3-line" | ||
:command="command" | ||
@click="directMessageUser(account)" | ||
@click="directMessageUser(account, 'profile.more.direct-message')" | ||
/> | ||
|
||
<CommonDropdownItem | ||
is="button" | ||
v-if="!relationship?.showingReblogs" | ||
icon="i-ri:repeat-line" | ||
:text="$t('menu.show_reblogs', [`@${account.acct}`])" | ||
:command="command" | ||
@click="toggleReblogs()" | ||
/> | ||
<CommonDropdownItem | ||
is="button" | ||
v-else | ||
:text="$t('menu.hide_reblogs', [`@${account.acct}`])" | ||
icon="i-ri:repeat-line" | ||
|
@@ -106,13 +139,15 @@ async function removeUserNote() { | |
/> | ||
|
||
<CommonDropdownItem | ||
is="button" | ||
v-if="!relationship?.note || relationship?.note?.length === 0" | ||
:text="$t('menu.add_personal_note', [`@${account.acct}`])" | ||
icon="i-ri-edit-2-line" | ||
:command="command" | ||
@click="addUserNote()" | ||
/> | ||
<CommonDropdownItem | ||
is="button" | ||
v-else | ||
:text="$t('menu.remove_personal_note', [`@${account.acct}`])" | ||
icon="i-ri-edit-2-line" | ||
|
@@ -121,75 +156,82 @@ async function removeUserNote() { | |
/> | ||
|
||
<CommonDropdownItem | ||
is="button" | ||
v-if="!relationship?.muting" | ||
:text="$t('menu.mute_account', [`@${account.acct}`])" | ||
icon="i-ri:volume-mute-line" | ||
:command="command" | ||
@click="toggleMuteAccount (relationship!, account)" | ||
@click="toggleMuteAccount (relationship!, account, 'profile.more.mute')" | ||
/> | ||
<CommonDropdownItem | ||
is="button" | ||
v-else | ||
:text="$t('menu.unmute_account', [`@${account.acct}`])" | ||
icon="i-ri:volume-up-fill" | ||
:command="command" | ||
@click="toggleMuteAccount (relationship!, account)" | ||
@click="toggleMuteAccount (relationship!, account, 'profile.more.unmute')" | ||
/> | ||
|
||
<CommonDropdownItem | ||
is="button" | ||
v-if="!relationship?.blocking" | ||
:text="$t('menu.block_account', [`@${account.acct}`])" | ||
icon="i-ri:forbid-2-line" | ||
:command="command" | ||
@click="toggleBlockAccount (relationship!, account)" | ||
@click="toggleBlockAccount (relationship!, account, 'profile.more.block')" | ||
/> | ||
<CommonDropdownItem | ||
is="button" | ||
v-else | ||
:text="$t('menu.unblock_account', [`@${account.acct}`])" | ||
icon="i-ri:checkbox-circle-line" | ||
:command="command" | ||
@click="toggleBlockAccount (relationship!, account)" | ||
@click="toggleBlockAccount (relationship!, account, 'profile.more.unblock')" | ||
/> | ||
|
||
<template v-if="getServerName(account) !== currentServer"> | ||
<CommonDropdownItem | ||
is="button" | ||
v-if="!relationship?.domainBlocking" | ||
:text="$t('menu.block_domain', [getServerName(account)])" | ||
icon="i-ri:shut-down-line" | ||
:command="command" | ||
@click="toggleBlockDomain(relationship!, account)" | ||
@click="toggleBlockDomain(relationship!, account, 'profile.more.block-domain')" | ||
/> | ||
<CommonDropdownItem | ||
is="button" | ||
v-else | ||
:text="$t('menu.unblock_domain', [getServerName(account)])" | ||
icon="i-ri:restart-line" | ||
:command="command" | ||
@click="toggleBlockDomain(relationship!, account)" | ||
@click="toggleBlockDomain(relationship!, account, 'profile.more.unblock-domain')" | ||
/> | ||
</template> | ||
|
||
<CommonDropdownItem | ||
is="button" | ||
:text="$t('menu.report_account', [`@${account.acct}`])" | ||
icon="i-ri:flag-2-line" | ||
:command="command" | ||
@click="openReportDialog(account)" | ||
@click="report()" | ||
/> | ||
</template> | ||
|
||
<template v-else> | ||
<NuxtLink to="/pinned"> | ||
<CommonDropdownItem :text="$t('account.pinned')" icon="i-ri:pushpin-line" :command="command" /> | ||
<CommonDropdownItem is="button" :text="$t('account.pinned')" icon="i-ri:pushpin-line" :command="command" data-glean="profile.more.goto-pinned" /> | ||
</NuxtLink> | ||
<NuxtLink to="/favourites"> | ||
<CommonDropdownItem :text="$t('account.favourites')" :icon="useStarFavoriteIcon ? 'i-ri:star-line' : 'i-ri:heart-3-line'" :command="command" /> | ||
<CommonDropdownItem is="button" :text="$t('account.favourites')" :icon="useStarFavoriteIcon ? 'i-ri:star-line' : 'i-ri:heart-3-line'" :command="command" data-glean="profile.more.goto-favorites" /> | ||
</NuxtLink> | ||
<NuxtLink to="/mutes"> | ||
<CommonDropdownItem :text="$t('account.muted_users')" icon="i-ri:volume-mute-line" :command="command" /> | ||
<CommonDropdownItem is="button" :text="$t('account.muted_users')" icon="i-ri:volume-mute-line" :command="command" data-glean="profile.more.goto-mutes" /> | ||
</NuxtLink> | ||
<NuxtLink to="/blocks"> | ||
<CommonDropdownItem :text="$t('account.blocked_users')" icon="i-ri:forbid-2-line" :command="command" /> | ||
<CommonDropdownItem is="button" :text="$t('account.blocked_users')" icon="i-ri:forbid-2-line" :command="command" data-glean="profile.more.goto-blocks" /> | ||
</NuxtLink> | ||
<NuxtLink to="/domain_blocks"> | ||
<CommonDropdownItem :text="$t('account.blocked_domains')" icon="i-ri:shut-down-line" :command="command" /> | ||
<CommonDropdownItem is="button" :text="$t('account.blocked_domains')" icon="i-ri:shut-down-line" :command="command" data-glean="profile.more.goto-domain-blocks" /> | ||
</NuxtLink> | ||
</template> | ||
</template> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. all |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ const userSettings = useUserSettings() | |
replace | ||
text-secondary | ||
exact-active-class="text-primary" | ||
data-glean="profile.details.posts" | ||
> | ||
<template #default="{ isExactActive }"> | ||
<CommonLocalizedNumber | ||
|
@@ -31,6 +32,7 @@ const userSettings = useUserSettings() | |
:to="getAccountFollowingRoute(account)" | ||
replace | ||
text-secondary exact-active-class="text-primary" | ||
data-glean="profile.details.following" | ||
> | ||
<template #default="{ isExactActive }"> | ||
<template | ||
|
@@ -56,6 +58,7 @@ const userSettings = useUserSettings() | |
:to="getAccountFollowersRoute(account)" | ||
replace text-secondary | ||
exact-active-class="text-primary" | ||
data-glean="profile.details.followers" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not able to get these There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay cool. I'm sure there are some optimizations we can make, but I don't wanna hold up this PR for that so I'm cool with this for now. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good to me. We can solve this with something applicable to all anchor tags |
||
> | ||
<template #default="{ isExactActive }"> | ||
<template v-if="!getPreferences(userSettings, 'hideFollowerCount')"> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gleanContext
would beprofile
inprofile.follow.unfollow
Several components use
AccountFollowButton
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you feel about renaming these ones to include something specific to it being the follow button? For instance
profile.follow-btn.unfollow
- I feel like that might make it a little more clear but also may be overkill?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought "follow" would be sufficient to denote the button :( but your comment is proof that it isn't. I will change all these to
follow-btn