canvasframework 0.5.13 → 0.5.15
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/components/QRCodeReader.js +9 -6
- package/core/CanvasFramework.js +95 -164
- package/package.json +1 -1
|
@@ -354,15 +354,18 @@ class QRCodeReader extends Component {
|
|
|
354
354
|
|
|
355
355
|
// Fond semi-transparent autour
|
|
356
356
|
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
|
|
357
|
-
|
|
357
|
+
|
|
358
358
|
// Haut
|
|
359
|
-
ctx.fillRect(this.x, this.y, this.width, centerY - halfSize);
|
|
359
|
+
ctx.fillRect(this.x, this.y, this.width, centerY - this.y - halfSize);
|
|
360
|
+
|
|
360
361
|
// Bas
|
|
361
|
-
ctx.fillRect(this.x, centerY + halfSize, this.width, this.height - (centerY + halfSize));
|
|
362
|
+
ctx.fillRect(this.x, centerY + halfSize, this.width, this.y + this.height - (centerY + halfSize));
|
|
363
|
+
|
|
362
364
|
// Gauche
|
|
363
|
-
ctx.fillRect(this.x, centerY - halfSize, centerX - halfSize, frameSize);
|
|
365
|
+
ctx.fillRect(this.x, centerY - halfSize, centerX - this.x - halfSize, frameSize);
|
|
366
|
+
|
|
364
367
|
// Droite
|
|
365
|
-
ctx.fillRect(centerX + halfSize, centerY - halfSize,
|
|
368
|
+
ctx.fillRect(centerX + halfSize, centerY - halfSize, this.x + this.width - (centerX + halfSize), frameSize);
|
|
366
369
|
|
|
367
370
|
// Cadre de scan
|
|
368
371
|
ctx.strokeStyle = this.scannerFrameColor;
|
|
@@ -371,7 +374,7 @@ class QRCodeReader extends Component {
|
|
|
371
374
|
|
|
372
375
|
// Coins décoratifs
|
|
373
376
|
const cornerSize = 20;
|
|
374
|
-
|
|
377
|
+
|
|
375
378
|
// Coin haut gauche
|
|
376
379
|
ctx.beginPath();
|
|
377
380
|
ctx.moveTo(centerX - halfSize, centerY - halfSize + cornerSize);
|
package/core/CanvasFramework.js
CHANGED
|
@@ -1781,189 +1781,120 @@ class CanvasFramework {
|
|
|
1781
1781
|
* @private
|
|
1782
1782
|
*/
|
|
1783
1783
|
async navigateTo(path, options = {}) {
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
}
|
|
1798
|
-
|
|
1799
|
-
const {
|
|
1800
|
-
route,
|
|
1801
|
-
params,
|
|
1802
|
-
query,
|
|
1803
|
-
pathname
|
|
1804
|
-
} = match;
|
|
1805
|
-
|
|
1806
|
-
// ===== LIFECYCLE: AVANT DE QUITTER L'ANCIENNE ROUTE =====
|
|
1807
|
-
|
|
1808
|
-
// Hook beforeLeave de la route actuelle (peut bloquer la navigation)
|
|
1809
|
-
const currentRouteData = this.routes.get(this.currentRoute);
|
|
1810
|
-
if (currentRouteData?.beforeLeave) {
|
|
1811
|
-
const canLeave = await currentRouteData.beforeLeave(this.currentParams, this.currentQuery, this);
|
|
1812
|
-
if (canLeave === false) {
|
|
1813
|
-
console.log('Navigation cancelled by beforeLeave hook');
|
|
1814
|
-
return;
|
|
1815
|
-
}
|
|
1816
|
-
}
|
|
1817
|
-
|
|
1818
|
-
// ✅ NOUVEAU : Hook onLeave (alias plus intuitif de beforeLeave, mais ne bloque pas)
|
|
1819
|
-
if (currentRouteData?.onLeave) {
|
|
1820
|
-
await currentRouteData.onLeave(this.currentParams, this.currentQuery, this);
|
|
1821
|
-
}
|
|
1822
|
-
|
|
1823
|
-
// ===== LIFECYCLE: AVANT D'ENTRER DANS LA NOUVELLE ROUTE =====
|
|
1824
|
-
|
|
1825
|
-
// Hook beforeEnter de la nouvelle route (peut bloquer la navigation)
|
|
1826
|
-
if (route.beforeEnter) {
|
|
1827
|
-
const canEnter = await route.beforeEnter(params, query, this);
|
|
1828
|
-
if (canEnter === false) {
|
|
1829
|
-
console.log('Navigation cancelled by beforeEnter hook');
|
|
1830
|
-
return;
|
|
1831
|
-
}
|
|
1832
|
-
}
|
|
1833
|
-
|
|
1834
|
-
// ✅ NOUVEAU : Hook onEnter (appelé juste avant de créer les composants)
|
|
1835
|
-
if (route.onEnter) {
|
|
1836
|
-
await route.onEnter(params, query, this);
|
|
1837
|
-
}
|
|
1838
|
-
|
|
1839
|
-
// ===== SAUVEGARDER L'ÉTAT ACTUEL =====
|
|
1840
|
-
|
|
1841
|
-
// Sauvegarder l'ancienne route pour l'animation et les hooks
|
|
1842
|
-
const oldComponents = [...this.components];
|
|
1843
|
-
const oldRoute = this.currentRoute;
|
|
1844
|
-
const oldParams = {
|
|
1845
|
-
...this.currentParams
|
|
1846
|
-
};
|
|
1847
|
-
const oldQuery = {
|
|
1848
|
-
...this.currentQuery
|
|
1849
|
-
};
|
|
1850
|
-
|
|
1851
|
-
// ===== METTRE À JOUR L'ÉTAT =====
|
|
1852
|
-
|
|
1853
|
-
this.currentRoute = pathname;
|
|
1854
|
-
this.currentParams = params;
|
|
1855
|
-
this.currentQuery = query;
|
|
1856
|
-
|
|
1857
|
-
// ===== GÉRER L'HISTORIQUE =====
|
|
1858
|
-
|
|
1859
|
-
if (!replace) {
|
|
1860
|
-
this.historyIndex++;
|
|
1861
|
-
this.history = this.history.slice(0, this.historyIndex);
|
|
1862
|
-
this.history.push({
|
|
1863
|
-
path,
|
|
1864
|
-
params,
|
|
1865
|
-
query,
|
|
1866
|
-
state
|
|
1867
|
-
});
|
|
1868
|
-
|
|
1869
|
-
// Mettre à jour l'historique du navigateur
|
|
1870
|
-
window.history.pushState({
|
|
1871
|
-
route: path,
|
|
1872
|
-
params,
|
|
1873
|
-
query,
|
|
1874
|
-
state
|
|
1875
|
-
},
|
|
1876
|
-
'',
|
|
1877
|
-
path
|
|
1878
|
-
);
|
|
1879
|
-
} else {
|
|
1880
|
-
this.history[this.historyIndex] = {
|
|
1881
|
-
path,
|
|
1882
|
-
params,
|
|
1883
|
-
query,
|
|
1884
|
-
state
|
|
1885
|
-
};
|
|
1886
|
-
window.history.replaceState({
|
|
1887
|
-
route: path,
|
|
1888
|
-
params,
|
|
1889
|
-
query,
|
|
1890
|
-
state
|
|
1891
|
-
},
|
|
1892
|
-
'',
|
|
1893
|
-
path
|
|
1894
|
-
);
|
|
1895
|
-
}
|
|
1896
|
-
|
|
1897
|
-
// ===== CRÉER LES NOUVEAUX COMPOSANTS =====
|
|
1784
|
+
const {
|
|
1785
|
+
replace = false,
|
|
1786
|
+
animate = true,
|
|
1787
|
+
direction = 'forward',
|
|
1788
|
+
transition = null,
|
|
1789
|
+
state = {}
|
|
1790
|
+
} = options;
|
|
1791
|
+
|
|
1792
|
+
const match = this.matchRoute(path);
|
|
1793
|
+
if (!match) {
|
|
1794
|
+
console.warn(`Route not found: ${path}`);
|
|
1795
|
+
return;
|
|
1796
|
+
}
|
|
1898
1797
|
|
|
1899
|
-
|
|
1900
|
-
if (typeof route.component === 'function') {
|
|
1901
|
-
route.component(this, params, query);
|
|
1902
|
-
}
|
|
1798
|
+
const { route, params, query, pathname } = match;
|
|
1903
1799
|
|
|
1904
|
-
|
|
1800
|
+
// ===== LIFECYCLE: AVANT DE QUITTER L'ANCIENNE ROUTE =====
|
|
1801
|
+
const currentRouteData = this.routes.get(this.currentRoute);
|
|
1802
|
+
if (currentRouteData?.beforeLeave) {
|
|
1803
|
+
const canLeave = await currentRouteData.beforeLeave(this.currentParams, this.currentQuery, this);
|
|
1804
|
+
if (canLeave === false) {
|
|
1805
|
+
console.log('Navigation cancelled by beforeLeave hook');
|
|
1806
|
+
return;
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1905
1809
|
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
this.startTransition(oldComponents, this.components, transitionType, direction);
|
|
1909
|
-
// Pas besoin d'appeler renderFull() ici, la boucle de rendu s'en chargera
|
|
1810
|
+
if (currentRouteData?.onLeave) {
|
|
1811
|
+
await currentRouteData.onLeave(this.currentParams, this.currentQuery, this);
|
|
1910
1812
|
}
|
|
1911
1813
|
|
|
1912
|
-
|
|
1814
|
+
// ===== LIFECYCLE: AVANT D'ENTRER DANS LA NOUVELLE ROUTE =====
|
|
1815
|
+
if (route.beforeEnter) {
|
|
1816
|
+
const canEnter = await route.beforeEnter(params, query, this);
|
|
1817
|
+
if (canEnter === false) {
|
|
1818
|
+
console.log('Navigation cancelled by beforeEnter hook');
|
|
1819
|
+
return;
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1913
1822
|
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
}
|
|
1823
|
+
if (route.onEnter) {
|
|
1824
|
+
await route.onEnter(params, query, this);
|
|
1825
|
+
}
|
|
1918
1826
|
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
currentRouteData.afterLeave(oldParams, oldQuery, this);
|
|
1925
|
-
}, this.transitionState.duration || 300);
|
|
1926
|
-
} else {
|
|
1927
|
-
// Pas d'animation, appeler immédiatement
|
|
1928
|
-
currentRouteData.afterLeave(oldParams, oldQuery, this);
|
|
1929
|
-
}
|
|
1930
|
-
}
|
|
1827
|
+
// ===== SAUVEGARDER L'ÉTAT ACTUEL =====
|
|
1828
|
+
const oldComponents = [...this.components];
|
|
1829
|
+
const oldRoute = this.currentRoute;
|
|
1830
|
+
const oldParams = { ...this.currentParams };
|
|
1831
|
+
const oldQuery = { ...this.currentQuery };
|
|
1931
1832
|
|
|
1932
|
-
|
|
1933
|
-
this._maxScrollDirty = true;
|
|
1934
|
-
|
|
1935
|
-
// ✅ ARRÊTER LES CAMÉRAS DES ANCIENS COMPOSANTS
|
|
1833
|
+
// ✅ CRUCIAL : ARRÊTER LES ANCIENNES CAMÉRAS AVANT DE CRÉER LES NOUVELLES
|
|
1936
1834
|
oldComponents.forEach(comp => {
|
|
1937
|
-
// Vérifier si c'est un composant caméra
|
|
1938
1835
|
if (comp.constructor.name === 'FloatedCamera' ||
|
|
1939
1836
|
comp.constructor.name === 'Camera' ||
|
|
1837
|
+
comp.constructor.name === 'Video' ||
|
|
1940
1838
|
comp.constructor.name === 'QRCodeReader') {
|
|
1941
|
-
// Arrêter le stream vidéo
|
|
1942
1839
|
if (comp.stopCamera && typeof comp.stopCamera === 'function') {
|
|
1943
1840
|
comp.stopCamera();
|
|
1944
1841
|
}
|
|
1842
|
+
// Destroy le composant pour être sûr
|
|
1843
|
+
if (comp.destroy && typeof comp.destroy === 'function') {
|
|
1844
|
+
comp.destroy();
|
|
1845
|
+
}
|
|
1945
1846
|
}
|
|
1946
1847
|
});
|
|
1947
|
-
|
|
1948
|
-
// ✅
|
|
1949
|
-
const
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1848
|
+
|
|
1849
|
+
// ✅ Nettoyer toutes les vidéos orphelines AVANT de créer les nouveaux composants
|
|
1850
|
+
const allVideos = document.querySelectorAll('video');
|
|
1851
|
+
allVideos.forEach(v => v.remove());
|
|
1852
|
+
|
|
1853
|
+
// ===== METTRE À JOUR L'ÉTAT =====
|
|
1854
|
+
this.currentRoute = pathname;
|
|
1855
|
+
this.currentParams = params;
|
|
1856
|
+
this.currentQuery = query;
|
|
1857
|
+
|
|
1858
|
+
// ===== GÉRER L'HISTORIQUE =====
|
|
1859
|
+
if (!replace) {
|
|
1860
|
+
this.historyIndex++;
|
|
1861
|
+
this.history = this.history.slice(0, this.historyIndex);
|
|
1862
|
+
this.history.push({ path, params, query, state });
|
|
1863
|
+
window.history.pushState({ route: path, params, query, state }, '', path);
|
|
1962
1864
|
} else {
|
|
1963
|
-
|
|
1865
|
+
this.history[this.historyIndex] = { path, params, query, state };
|
|
1866
|
+
window.history.replaceState({ route: path, params, query, state }, '', path);
|
|
1964
1867
|
}
|
|
1965
|
-
|
|
1966
|
-
|
|
1868
|
+
|
|
1869
|
+
// ===== CRÉER LES NOUVEAUX COMPOSANTS =====
|
|
1870
|
+
this.components = [];
|
|
1871
|
+
if (typeof route.component === 'function') {
|
|
1872
|
+
route.component(this, params, query);
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1875
|
+
// ===== LANCER L'ANIMATION DE TRANSITION =====
|
|
1876
|
+
if (animate && !this.transitionState.isTransitioning) {
|
|
1877
|
+
const transitionType = transition || route.transition || 'slide';
|
|
1878
|
+
this.startTransition(oldComponents, this.components, transitionType, direction);
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
// ===== LIFECYCLE: APRÈS ÊTRE ENTRÉ DANS LA NOUVELLE ROUTE =====
|
|
1882
|
+
if (route.afterEnter) {
|
|
1883
|
+
route.afterEnter(params, query, this);
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
if (currentRouteData?.afterLeave) {
|
|
1887
|
+
if (animate && this.transitionState.isTransitioning) {
|
|
1888
|
+
setTimeout(() => {
|
|
1889
|
+
currentRouteData.afterLeave(oldParams, oldQuery, this);
|
|
1890
|
+
}, this.transitionState.duration || 300);
|
|
1891
|
+
} else {
|
|
1892
|
+
currentRouteData.afterLeave(oldParams, oldQuery, this);
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
this._maxScrollDirty = true;
|
|
1897
|
+
}
|
|
1967
1898
|
|
|
1968
1899
|
/**
|
|
1969
1900
|
* Démarre une animation de transition
|