samre-cli 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "samre-cli",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "CLI officiel d'injection automatique du SDK Samré dans les applications mobiles (Flutter, React Native)",
5
5
  "main": "bin/samre.js",
6
6
  "bin": {
@@ -79,38 +79,40 @@ class _SamreOverlayState extends State<SamreOverlay> {
79
79
  children: [
80
80
  widget.child,
81
81
 
82
- // ── Bouton Flottant en Bas à Droite ──────────────────────────────
82
+ // ── Bouton Flottant Rehaussé avec SafeArea (Au-dessus des barres de navigation) ──
83
83
  Positioned(
84
- bottom: 24,
85
- right: 20,
86
- child: Material(
87
- elevation: 8,
88
- borderRadius: BorderRadius.circular(24),
89
- color: _canSubmit ? const Color(0xFF2563EB) : Colors.black.withOpacity(0.75),
90
- child: InkWell(
84
+ bottom: 48,
85
+ right: 18,
86
+ child: SafeArea(
87
+ child: Material(
88
+ elevation: 10,
91
89
  borderRadius: BorderRadius.circular(24),
92
- onTap: _canSubmit ? _openDialog : null,
93
- child: Padding(
94
- padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
95
- child: Row(
96
- mainAxisSize: MainAxisSize.min,
97
- children: [
98
- Icon(
99
- _canSubmit ? Icons.verified_user : Icons.timer_outlined,
100
- color: Colors.white,
101
- size: 18,
102
- ),
103
- const SizedBox(width: 8),
104
- Text(
105
- _canSubmit ? 'Valider Journée' : 'Test en cours (\${_secondsRemaining}s)',
106
- style: const TextStyle(
90
+ color: _canSubmit ? const Color(0xFF2563EB) : Colors.black.withOpacity(0.85),
91
+ child: InkWell(
92
+ borderRadius: BorderRadius.circular(24),
93
+ onTap: _canSubmit ? _openDialog : null,
94
+ child: Padding(
95
+ padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
96
+ child: Row(
97
+ mainAxisSize: MainAxisSize.min,
98
+ children: [
99
+ Icon(
100
+ _canSubmit ? Icons.verified_user : Icons.timer_outlined,
107
101
  color: Colors.white,
108
- fontWeight: FontWeight.bold,
109
- fontSize: 12,
110
- decoration: TextDecoration.none,
102
+ size: 18,
111
103
  ),
112
- ),
113
- ],
104
+ const SizedBox(width: 8),
105
+ Text(
106
+ _canSubmit ? 'Valider Journée' : 'Test en cours (\${_secondsRemaining}s)',
107
+ style: const TextStyle(
108
+ color: Colors.white,
109
+ fontWeight: FontWeight.bold,
110
+ fontSize: 12,
111
+ decoration: TextDecoration.none,
112
+ ),
113
+ ),
114
+ ],
115
+ ),
114
116
  ),
115
117
  ),
116
118
  ),
@@ -54,6 +54,24 @@ export const FlutterUtil = {
54
54
  return sdkPath;
55
55
  },
56
56
 
57
+ cleanMainDartContent(rawContent) {
58
+ let content = rawContent;
59
+
60
+ // 1. Supprimer l'import du SDK Samré
61
+ content = content.replace(/import\s+['"]samre_sdk\.dart['"];\s*\n?/g, '');
62
+ content = content.replace(/\/\/\s*SDK Samré\s*\n?/gi, '');
63
+ content = content.replace(/\/\/\s*👉\s*SamreOverlay[^\n]*\n?/gi, '');
64
+
65
+ // 2. Supprimer la propriété builder SamreOverlay dans MaterialApp
66
+ content = content.replace(/builder\s*:\s*\([^)]*\)\s*=>\s*SamreOverlay\s*\(\s*child\s*:\s*child\s*\?\?\s*const\s*SizedBox\(\)\s*\),?\s*\n?/g, '');
67
+ content = content.replace(/builder\s*:\s*\([^)]*\)\s*=>\s*SamreOverlay\s*\(\s*child\s*:\s*([^)]+)\),?\s*\n?/g, 'builder: (context, child) => $1,\n');
68
+
69
+ // 3. Déballer SamreOverlay s'il entoure un widget (ex: home: SamreOverlay(child: SplashPage()))
70
+ content = content.replace(/SamreOverlay\s*\(\s*child\s*:\s*([^)]+)\)/g, '$1');
71
+
72
+ return content;
73
+ },
74
+
57
75
  injectIntoMain(cwd = process.cwd()) {
58
76
  const mainPath = path.join(cwd, 'lib', 'main.dart');
59
77
  const backupPath = path.join(cwd, 'lib', 'main.dart.samre_bak');
@@ -62,50 +80,45 @@ export const FlutterUtil = {
62
80
  return { injected: false, reason: 'main.dart introuvable' };
63
81
  }
64
82
 
65
- const content = fs.readFileSync(mainPath, 'utf-8');
83
+ const originalContent = fs.readFileSync(mainPath, 'utf-8');
66
84
 
67
- // Sauvegarde de secours si pas encore existante
68
- if (!fs.existsSync(backupPath)) {
69
- fs.writeFileSync(backupPath, content, 'utf-8');
70
- }
85
+ // Nettoyer d'abord tout résidu ou ancienne injection
86
+ let cleanContent = this.cleanMainDartContent(originalContent);
71
87
 
72
- // Si déjà injecté
73
- if (content.includes('SamreOverlay') || content.includes('samre_sdk.dart')) {
74
- return { injected: true, alreadyInjected: true, backupPath };
88
+ // Sauvegarde de secours du fichier propre
89
+ if (!fs.existsSync(backupPath)) {
90
+ fs.writeFileSync(backupPath, cleanContent, 'utf-8');
75
91
  }
76
92
 
77
- let modified = content;
93
+ let modified = cleanContent;
78
94
 
79
- // 1. Ajouter l'import en haut
80
- const importStatement = "import 'package:flutter/material.dart';\nimport 'samre_sdk.dart';\n";
95
+ // 1. Ajouter l'import de samre_sdk en haut (sans dupliquer)
81
96
  if (!modified.includes('samre_sdk.dart')) {
82
- modified = importStatement + modified;
97
+ modified = "import 'samre_sdk.dart';\n" + modified;
83
98
  }
84
99
 
85
- // 2. Tenter d'injecter dans builder de MaterialApp (Idéal pour tous les écrans et le routage)
86
- if (modified.includes('MaterialApp(') && !modified.includes('SamreOverlay')) {
87
- // Si MaterialApp a déjà une propriété builder
100
+ // 2. Injecter proprement dans builder de MaterialApp
101
+ if (modified.includes('MaterialApp(')) {
102
+ // Si MaterialApp a déjà une propriété builder existante
88
103
  const builderRegex = /builder\s*:\s*\(([^)]*)\)\s*=>\s*([^,\n;]+)/;
89
104
  if (builderRegex.test(modified)) {
90
105
  modified = modified.replace(builderRegex, (match, args, body) => {
91
106
  return `builder: (${args}) => SamreOverlay(child: ${body.trim()})`;
92
107
  });
93
- fs.writeFileSync(mainPath, modified, 'utf-8');
94
- return { injected: true, modifiedBuilder: true, backupPath };
108
+ } else {
109
+ // Sinon insérer builder: (context, child) => SamreOverlay(...)
110
+ modified = modified.replace(
111
+ /MaterialApp\s*\(/,
112
+ 'MaterialApp(\n builder: (context, child) => SamreOverlay(child: child ?? const SizedBox()),'
113
+ );
95
114
  }
96
-
97
- // Sinon insérer la propriété builder juste après MaterialApp(
98
- modified = modified.replace(
99
- /MaterialApp\s*\(/,
100
- 'MaterialApp(\n builder: (context, child) => SamreOverlay(child: child ?? const SizedBox()),'
101
- );
102
115
  fs.writeFileSync(mainPath, modified, 'utf-8');
103
116
  return { injected: true, modifiedBuilder: true, backupPath };
104
117
  }
105
118
 
106
119
  // Fallback : injection sur home:
107
120
  const homeRegex = /home\s*:\s*([^,\n\);]+)/;
108
- if (homeRegex.test(modified) && !modified.includes('SamreOverlay')) {
121
+ if (homeRegex.test(modified)) {
109
122
  modified = modified.replace(homeRegex, (match, p1) => {
110
123
  return `home: SamreOverlay(child: ${p1.trim()})`;
111
124
  });
@@ -126,22 +139,30 @@ export const FlutterUtil = {
126
139
  let sdkDeleted = false;
127
140
  let mainRestored = false;
128
141
 
142
+ // 1. Supprimer le fichier SDK
129
143
  if (fs.existsSync(sdkPath)) {
130
144
  fs.unlinkSync(sdkPath);
131
145
  sdkDeleted = true;
132
146
  }
133
147
 
148
+ // 2. Si un backup existe, essayer de le restaurer
134
149
  if (fs.existsSync(backupPath)) {
135
- fs.copyFileSync(backupPath, mainPath);
136
- fs.unlinkSync(backupPath);
137
- mainRestored = true;
138
- } else if (fs.existsSync(mainPath)) {
139
- // Nettoyage manuel si pas de backup
140
- let content = fs.readFileSync(mainPath, 'utf-8');
141
- content = content.replace(/import\s+['"]samre_sdk\.dart['"];\s*\n?/g, '');
142
- content = content.replace(/builder\s*:\s*\([^)]*\)\s*=>\s*SamreOverlay\s*\(\s*child\s*:\s*child\s*\?\?\s*const\s*SizedBox\(\)\s*\),?\s*\n?/g, '');
143
- content = content.replace(/SamreOverlay\s*\(\s*child\s*:\s*([^)]+)\)/g, '$1');
144
- fs.writeFileSync(mainPath, content, 'utf-8');
150
+ try {
151
+ const backupContent = fs.readFileSync(backupPath, 'utf-8');
152
+ const cleanBackup = this.cleanMainDartContent(backupContent);
153
+ fs.writeFileSync(mainPath, cleanBackup, 'utf-8');
154
+ fs.unlinkSync(backupPath);
155
+ mainRestored = true;
156
+ } catch {
157
+ // Fallback nettoyage direct
158
+ }
159
+ }
160
+
161
+ // 3. Dans tous les cas, s'assurer que main.dart est 100% purgé de toute trace de Samré
162
+ if (fs.existsSync(mainPath)) {
163
+ const currentContent = fs.readFileSync(mainPath, 'utf-8');
164
+ const cleanContent = this.cleanMainDartContent(currentContent);
165
+ fs.writeFileSync(mainPath, cleanContent, 'utf-8');
145
166
  mainRestored = true;
146
167
  }
147
168