Skip to content

Commit 49437d4

Browse files
author
ci-bot
committed
lint
1 parent 8744423 commit 49437d4

File tree

2 files changed

+111
-33
lines changed

2 files changed

+111
-33
lines changed

apps/remix-ide/src/app/tabs/settings-tab.tsx

Lines changed: 103 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import * as packageJson from '../../../../../package.json'
55
import {RemixUiSettings} from '@remix-ui/settings' //eslint-disable-line
66
import { Registry } from '@remix-project/remix-lib'
77
import { PluginViewWrapper } from '@remix-ui/helper'
8+
89
declare global {
910
interface Window {
1011
_paq: any
@@ -15,7 +16,8 @@ const _paq = (window._paq = window._paq || [])
1516
const profile = {
1617
name: 'settings',
1718
displayName: 'Settings',
18-
methods: ['get', 'updateCopilotChoice', 'getCopilotSetting', 'updateMatomoPerfAnalyticsChoice'],
19+
// updateMatomoAnalyticsMode deprecated: tracking mode now derived purely from perf toggle (Option B)
20+
methods: ['get', 'updateCopilotChoice', 'getCopilotSetting', 'updateMatomoPerfAnalyticsChoice', 'updateMatomoAnalyticsMode'],
1921
events: [],
2022
icon: 'assets/img/settings.webp',
2123
description: 'Remix-IDE settings',
@@ -104,38 +106,114 @@ export default class SettingsTab extends ViewPlugin {
104106
return this.get('settings/copilot/suggest/activate')
105107
}
106108

107-
updateMatomoAnalyticsChoice(isChecked) {
108-
this.config.set('settings/matomo-analytics', isChecked)
109-
// set timestamp to local storage to track when the user has given consent
110-
localStorage.setItem('matomo-analytics-consent', Date.now().toString())
111-
this.useMatomoAnalytics = isChecked
112-
if (!isChecked) {
113-
// revoke tracking consent
114-
_paq.push(['forgetConsentGiven']);
115-
} else {
116-
// user has given consent to process their data
117-
_paq.push(['setConsentGiven']);
109+
updateMatomoAnalyticsChoice(_isChecked) {
110+
// Deprecated legacy toggle (disabled in UI). Mode now derives from performance analytics only.
111+
// Intentionally no-op to avoid user confusion; kept for backward compat if invoked programmatically.
112+
}
113+
114+
// Deprecated public method: retained for backward compatibility (external plugins or old code calling it).
115+
// It now simply forwards to performance-based derivation by toggling perf flag if needed.
116+
updateMatomoAnalyticsMode(_mode: 'cookie' | 'anon') {
117+
if (window.localStorage.getItem('matomo-debug') === 'true') {
118+
console.debug('[Matomo][settings] DEPRECATED updateMatomoAnalyticsMode call ignored; mode derived from perf toggle')
118119
}
119-
this.dispatch({
120-
...this
121-
})
122120
}
123121

124122
updateMatomoPerfAnalyticsChoice(isChecked) {
123+
console.log('[Matomo][settings] updateMatomoPerfAnalyticsChoice called with', isChecked)
125124
this.config.set('settings/matomo-perf-analytics', isChecked)
126-
// set timestamp to local storage to track when the user has given consent
125+
// Timestamp consent indicator (we treat enabling perf as granting cookie consent; disabling as revoking)
127126
localStorage.setItem('matomo-analytics-consent', Date.now().toString())
128127
this.useMatomoPerfAnalytics = isChecked
129-
this.emit('matomoPerfAnalyticsChoiceUpdated', isChecked)
130-
if (!isChecked) {
131-
// revoke tracking consent for performance data
132-
_paq.push(['disableCookies'])
128+
129+
const MATOMO_TRACKING_MODE_DIMENSION_ID = 1 // only remaining custom dimension (tracking mode)
130+
const mode = isChecked ? 'cookie' : 'anon'
131+
132+
// Always re-assert cookie consent boundary so runtime flip is clean
133+
_paq.push(['requireCookieConsent'])
134+
135+
if (mode === 'cookie') {
136+
// Cookie mode: give cookie consent and remember it
137+
_paq.push(['rememberConsentGiven']);
138+
_paq.push(['enableBrowserFeatureDetection']);
139+
_paq.push(['setCustomDimension', MATOMO_TRACKING_MODE_DIMENSION_ID, 'cookie']);
140+
_paq.push(['trackEvent', 'tracking_mode_change', 'cookie']);
141+
console.log('Granting cookie consent for Matomo (switching to cookie mode)');
142+
(window as any).__initMatomoTracking('cookie');
133143
} else {
134-
// user has given consent to process their performance data
135-
_paq.push(['setCookieConsentGiven'])
144+
// Anonymous mode: revoke cookie consent completely
145+
//_paq.push(['setConsentGiven']);
146+
console.log('Revoking cookie consent for Matomo (switching to anon mode)')
147+
//_paq.push(['forgetCookieConsentGiven']) // This removes cookie consent and deletes cookies
148+
//_paq.push(['disableCookies']) // Extra safety - prevent any new cookies
149+
150+
// Manual cookie deletion as backup (Matomo cookies typically start with _pk_)
151+
this.deleteMatomoCookies()
152+
153+
_paq.push(['setCustomDimension', MATOMO_TRACKING_MODE_DIMENSION_ID, 'anon'])
154+
_paq.push(['trackEvent', 'tracking_mode_change', 'anon'])
155+
if (window.localStorage.getItem('matomo-debug') === 'true') {
156+
_paq.push(['trackEvent', 'debug', 'anon_mode_active_toggle'])
157+
}
158+
(window as any).__initMatomoTracking('anon');
159+
}
160+
161+
// Performance dimension removed: mode alone now encodes cookie vs anon. Keep event for analytics toggle if useful.
162+
_paq.push(['trackEvent', 'perf_analytics_toggle', isChecked ? 'on' : 'off'])
163+
if (window.localStorage.getItem('matomo-debug') === 'true') {
164+
console.debug('[Matomo][settings] perf toggle -> mode derived', { perf: isChecked, mode })
165+
}
166+
167+
// If running inside Electron, propagate mode to desktop tracker & emit desktop-specific event.
168+
if ((window as any).electronAPI) {
169+
try {
170+
(window as any).electronAPI.setTrackingMode(mode)
171+
// Also send an explicit desktop event (uses new API if available)
172+
if ((window as any).electronAPI.trackDesktopEvent) {
173+
(window as any).electronAPI.trackDesktopEvent('tracking_mode_change', mode, isChecked ? 'on' : 'off')
174+
}
175+
} catch (e) {
176+
console.warn('[Matomo][desktop-sync] failed to set tracking mode in electron layer', e)
177+
}
178+
}
179+
// Persist deprecated mode key for backward compatibility (other code might read it)
180+
this.config.set('settings/matomo-analytics-mode', mode)
181+
this.config.set('settings/matomo-analytics', mode === 'cookie') // legacy boolean
182+
this.useMatomoAnalytics = true
183+
184+
this.emit('matomoPerfAnalyticsChoiceUpdated', isChecked);
185+
186+
const buffer = (window as any).__drainMatomoQueue();
187+
(window as any).__loadMatomoScript();
188+
(window as any).__restoreMatomoQueue(buffer);
189+
190+
this.dispatch({ ...this })
191+
}
192+
193+
// Helper method to manually delete Matomo cookies
194+
private deleteMatomoCookies() {
195+
try {
196+
// Get all cookies
197+
const cookies = document.cookie.split(';')
198+
199+
for (let cookie of cookies) {
200+
const eqPos = cookie.indexOf('=')
201+
const name = eqPos > -1 ? cookie.substr(0, eqPos).trim() : cookie.trim()
202+
203+
// Delete Matomo cookies (typically start with _pk_)
204+
if (name.startsWith('_pk_')) {
205+
// Delete for current domain and path
206+
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`
207+
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=${window.location.hostname}`
208+
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.${window.location.hostname}`
209+
210+
if (window.localStorage.getItem('matomo-debug') === 'true') {
211+
console.debug('[Matomo][cookie-cleanup] Deleted cookie:', name)
212+
}
213+
}
214+
}
215+
} catch (e) {
216+
console.warn('[Matomo][cookie-cleanup] Failed to delete cookies:', e)
136217
}
137-
this.dispatch({
138-
...this
139-
})
140218
}
141219
}

libs/remix-core-plugin/src/lib/helpers/fetch-etherscan.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,22 @@ export const fetchContractFromEtherscan = async (plugin, endpoint: string | Netw
2525
// Prefer central V2 API host with chainid param (works across Etherscan-supported networks)
2626
const v2CentralUrl = 'https://api.etherscan.io/v2/api?chainid=' + chainId + '&module=contract&action=getsourcecode&address=' + contractAddress + '&apikey=' + etherscanKey
2727
let response = await fetch(v2CentralUrl)
28-
let centralV2Status = response.status;
29-
let centralV2StatusText = response.statusText;
28+
const centralV2Status = response.status;
29+
const centralV2StatusText = response.statusText;
3030

3131
// If central V2 not OK, try per-network V2, then per-network V1
3232
if (!response.ok) {
3333
const v2PerNetworkUrl = 'https://' + endpointStr + '/v2/api?chainid=' + chainId + '&module=contract&action=getsourcecode&address=' + contractAddress + '&apikey=' + etherscanKey
34-
let v2PerNetworkResponse = await fetch(v2PerNetworkUrl)
35-
let v2PerNetworkStatus = v2PerNetworkResponse.status;
36-
let v2PerNetworkStatusText = v2PerNetworkResponse.statusText;
34+
const v2PerNetworkResponse = await fetch(v2PerNetworkUrl)
35+
const v2PerNetworkStatus = v2PerNetworkResponse.status;
36+
const v2PerNetworkStatusText = v2PerNetworkResponse.statusText;
3737
if (v2PerNetworkResponse.ok) {
3838
response = v2PerNetworkResponse;
3939
} else {
4040
const v1Url = 'https://' + endpointStr + '/api?module=contract&action=getsourcecode&address=' + contractAddress + '&apikey=' + etherscanKey
41-
let v1Response = await fetch(v1Url)
42-
let v1Status = v1Response.status;
43-
let v1StatusText = v1Response.statusText;
41+
const v1Response = await fetch(v1Url)
42+
const v1Status = v1Response.status;
43+
const v1StatusText = v1Response.statusText;
4444
if (v1Response.ok) {
4545
response = v1Response;
4646
} else {

0 commit comments

Comments
 (0)