@@ -5,6 +5,7 @@ import * as packageJson from '../../../../../package.json'
5
5
import { RemixUiSettings } from '@remix-ui/settings' //eslint-disable-line
6
6
import { Registry } from '@remix-project/remix-lib'
7
7
import { PluginViewWrapper } from '@remix-ui/helper'
8
+
8
9
declare global {
9
10
interface Window {
10
11
_paq : any
@@ -15,7 +16,8 @@ const _paq = (window._paq = window._paq || [])
15
16
const profile = {
16
17
name : 'settings' ,
17
18
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' ] ,
19
21
events : [ ] ,
20
22
icon : 'assets/img/settings.webp' ,
21
23
description : 'Remix-IDE settings' ,
@@ -104,38 +106,114 @@ export default class SettingsTab extends ViewPlugin {
104
106
return this . get ( 'settings/copilot/suggest/activate' )
105
107
}
106
108
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' )
118
119
}
119
- this . dispatch ( {
120
- ...this
121
- } )
122
120
}
123
121
124
122
updateMatomoPerfAnalyticsChoice ( isChecked ) {
123
+ console . log ( '[Matomo][settings] updateMatomoPerfAnalyticsChoice called with' , isChecked )
125
124
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)
127
126
localStorage . setItem ( 'matomo-analytics-consent' , Date . now ( ) . toString ( ) )
128
127
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' ) ;
133
143
} 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 )
136
217
}
137
- this . dispatch ( {
138
- ...this
139
- } )
140
218
}
141
219
}
0 commit comments