feat: disable intercom for non speckle distributions + partner badge (#84)

* feat: disable intercom for non speckle distributions + partner badge

* no logging
This commit is contained in:
Oğuzhan Koral
2026-01-16 18:00:49 +03:00
committed by GitHub
parent 19f306756c
commit eef0a59719
4 changed files with 98 additions and 10 deletions
+26 -4
View File
@@ -49,9 +49,26 @@
>
<span class="">Update</span>
</FormButton> -->
<div class="text-[8px] text-foreground-disabled max-[150px]:hidden">
<div
class="text-[8px] text-foreground-disabled max-[150px]:hidden"
:class="{ 'mr-2': !hostAppStore.isDistributedBySpeckle }"
>
{{ hostAppStore.connectorVersion }}
</div>
<div
v-if="!hostAppStore.isDistributedBySpeckle && hostAppStore.hostAppName"
v-tippy="
`${hostAppStore.hostAppName
.charAt(0)
.toUpperCase()}${hostAppStore.hostAppName.slice(
1
)} connector is not distributed by Speckle.`
"
class="text-xs text-foreground-disabled max-[150px]:hidden mr-1"
>
<CommonBadge color="secondary">Partner</CommonBadge>
</div>
<HeaderButton
v-if="hostAppStore.isDistributedBySpeckle"
v-tippy="'Documentation and help'"
@@ -65,7 +82,11 @@
class="w-4 text-foreground-disabled group-hover:text-foreground-2"
/>
</HeaderButton>
<HeaderButton v-tippy="'Send us feedback'" @click="openFeedbackDialog()">
<HeaderButton
v-if="hostAppStore.isDistributedBySpeckle"
v-tippy="'Send us feedback'"
@click="openFeedbackDialog()"
>
<ChatBubbleLeftIcon
class="w-4 text-foreground-disabled group-hover:text-foreground-2"
/>
@@ -106,8 +127,9 @@ const { $intercom } = useNuxtApp()
const openFeedbackDialog = () => {
if (
hostAppStore.hostAppName?.toLowerCase() === 'revit' &&
hostAppStore.hostAppVersion?.includes('2022')
(hostAppStore.hostAppName?.toLowerCase() === 'revit' &&
hostAppStore.hostAppVersion?.includes('2022')) ||
!hostAppStore.isDistributedBySpeckle
) {
showFeedbackDialog.value = true
} else {
+1 -5
View File
@@ -341,11 +341,7 @@ const activeWorkspace = computed(() => {
if (activeWorkspace) return activeWorkspace
}
// if activeWorkspace is null will mean that it is personal projects - this fallback wont be the case soon
return {
id: 'personalProject',
name: 'Personal Projects'
} as WorkspaceListWorkspaceItemFragment
return workspaces.value?.[0] // fallback to first workspace if none is active
})
const selectedWorkspace = ref<WorkspaceListWorkspaceItemFragment | undefined>(
+61 -1
View File
@@ -288,14 +288,19 @@ export type AdminInviteList = {
export type AdminMutations = {
__typename?: 'AdminMutations';
/** @deprecated Use grantWorkspaceFeature instead */
giveAccessToWorkspaceFeature: Scalars['Boolean']['output'];
grantWorkspaceFeature: Scalars['Boolean']['output'];
/** @deprecated Use revokeWorkspaceFeature instead */
removeAccessToWorkspaceFeature: Scalars['Boolean']['output'];
revokeWorkspaceFeature: Scalars['Boolean']['output'];
/**
* A server administrator can update the verification status of an user's email.
* The server administrator is recommended to confirm ownership of the email address
* with the user before performing this action.
*/
updateEmailVerification: Scalars['Boolean']['output'];
updateWorkspaceLimits: Scalars['Boolean']['output'];
updateWorkspacePlan: Scalars['Boolean']['output'];
};
@@ -305,16 +310,31 @@ export type AdminMutationsGiveAccessToWorkspaceFeatureArgs = {
};
export type AdminMutationsGrantWorkspaceFeatureArgs = {
input: WorkspaceFeatureGrantUpdateInput;
};
export type AdminMutationsRemoveAccessToWorkspaceFeatureArgs = {
input: AdminAccessToWorkspaceFeatureInput;
};
export type AdminMutationsRevokeWorkspaceFeatureArgs = {
input: WorkspaceFeatureGrantUpdateInput;
};
export type AdminMutationsUpdateEmailVerificationArgs = {
input: AdminUpdateEmailVerificationInput;
};
export type AdminMutationsUpdateWorkspaceLimitsArgs = {
input: WorkspaceLimitsUpdateInput;
};
export type AdminMutationsUpdateWorkspacePlanArgs = {
input: AdminUpdateWorkspacePlanInput;
};
@@ -3098,7 +3118,8 @@ export type PendingWorkspaceCollaborator = {
email?: Maybe<Scalars['String']['output']>;
id: Scalars['ID']['output'];
inviteId: Scalars['String']['output'];
invitedBy: LimitedUser;
/** Nullable if inviter gets deleted */
invitedBy?: Maybe<LimitedUser>;
/** Target workspace role */
role: Scalars['String']['output'];
/** E-mail address or name of the invited user */
@@ -6591,16 +6612,30 @@ export enum WorkspaceFeatureFlagName {
Presentations = 'presentations'
}
/** Either the ID or slug must be set */
export type WorkspaceFeatureGrantUpdateInput = {
featureName: WorkspaceFeatureName;
workspaceId?: InputMaybe<Scalars['ID']['input']>;
workspaceSlug?: InputMaybe<Scalars['String']['input']>;
};
export enum WorkspaceFeatureName {
AccIntegration = 'accIntegration',
Automate = 'automate',
/** @deprecated Use projectDashboards instead */
Dashboards = 'dashboards',
DashboardsExperimental = 'dashboardsExperimental',
DomainBasedSecurityPolicies = 'domainBasedSecurityPolicies',
DomainDiscoverability = 'domainDiscoverability',
EmbedPrivateProjects = 'embedPrivateProjects',
ExclusiveMembership = 'exclusiveMembership',
HideSpeckleBranding = 'hideSpeckleBranding',
Issues = 'issues',
Markup = 'markup',
OidcSso = 'oidcSso',
PortfolioDashboards = 'portfolioDashboards',
Presentations = 'presentations',
ProjectDashboards = 'projectDashboards',
SavedViews = 'savedViews',
WorkspaceDataRegionSpecificity = 'workspaceDataRegionSpecificity'
}
@@ -6781,6 +6816,30 @@ export enum WorkspaceJoinRequestStatus {
Pending = 'pending'
}
export type WorkspaceLimits = {
__typename?: 'WorkspaceLimits';
commentsHistoryInDays?: Maybe<Scalars['Int']['output']>;
dashboardCount?: Maybe<Scalars['Int']['output']>;
modelCount?: Maybe<Scalars['Int']['output']>;
projectCount?: Maybe<Scalars['Int']['output']>;
versionsHistoryInDays?: Maybe<Scalars['Int']['output']>;
};
export type WorkspaceLimitsInput = {
commentsHistoryInDays?: InputMaybe<Scalars['Int']['input']>;
dashboardCount?: InputMaybe<Scalars['Int']['input']>;
modelCount?: InputMaybe<Scalars['Int']['input']>;
projectCount?: InputMaybe<Scalars['Int']['input']>;
versionsHistoryInDays?: InputMaybe<Scalars['Int']['input']>;
};
/** Either the ID or slug must be set */
export type WorkspaceLimitsUpdateInput = {
limits?: InputMaybe<WorkspaceLimitsInput>;
workspaceId?: InputMaybe<Scalars['ID']['input']>;
workspaceSlug?: InputMaybe<Scalars['String']['input']>;
};
export type WorkspaceMutations = {
__typename?: 'WorkspaceMutations';
addDomain: Workspace;
@@ -6932,6 +6991,7 @@ export type WorkspacePermissionChecksCanMoveProjectToWorkspaceArgs = {
export type WorkspacePlan = {
__typename?: 'WorkspacePlan';
createdAt: Scalars['DateTime']['output'];
limits: WorkspaceLimits;
name: WorkspacePlans;
paymentMethod: WorkspacePaymentMethod;
status: WorkspacePlanStatuses;
+10
View File
@@ -7,6 +7,7 @@ import Intercom, {
trackEvent
} from '@intercom/messenger-js-sdk'
import { useAccountStore } from '~/store/accounts'
import { useHostAppStore } from '~/store/hostApp'
import { storeToRefs } from 'pinia'
const disabledRoutes: string[] = []
@@ -15,7 +16,9 @@ export const useIntercom = () => {
const route = useRoute()
const accountStore = useAccountStore()
const hostAppStore = useHostAppStore()
const { activeAccount } = storeToRefs(accountStore)
const { isDistributedBySpeckle } = storeToRefs(hostAppStore)
const isInitialized = ref(false)
@@ -80,6 +83,13 @@ export const useIntercom = () => {
}
})
// we listen to changes in the host app distribution status that fetched on updateConnector composable after the intercom is initialized, we cant simply rely on activeAccount watcher
watch(isDistributedBySpeckle, (newValue) => {
if (!newValue) {
shutdownIntercom()
}
})
watch(activeAccount, (newValue) => {
if (newValue) {
if (!isInitialized.value) {