aril 2.0.1-dev.1 → 2.0.1-dev.2
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.
|
@@ -627,6 +627,13 @@ class CustomRouteReuseStrategy {
|
|
|
627
627
|
return false;
|
|
628
628
|
}
|
|
629
629
|
const routeKey = this.getRouteKey(route);
|
|
630
|
+
// Angular `outlet.detach()`, `store()`'dan ÖNCE çalışıp wrapper view'ını DOM'dan söker →
|
|
631
|
+
// içindeki MFE `<app-xxx>` element'i disconnect olur ve barındırdığı iframe (örn. Superset embed)
|
|
632
|
+
// reload olup auth handshake'ini kalıcı kaybeder. Bu yüzden element'i HÂLÂ bağlıyken, detach'ten
|
|
633
|
+
// ÖNCE atomic `moveBefore` ile hidden container'a alıyoruz (bkz. preserveLiveElementBeforeDetach).
|
|
634
|
+
if (this.isMatcherRoute(route)) {
|
|
635
|
+
this.preserveLiveElementBeforeDetach(route);
|
|
636
|
+
}
|
|
630
637
|
console.log(`[Strategy] shouldDetach key="${routeKey}" → true`);
|
|
631
638
|
return true;
|
|
632
639
|
}
|
|
@@ -686,18 +693,16 @@ class CustomRouteReuseStrategy {
|
|
|
686
693
|
return;
|
|
687
694
|
const element = componentInstance.element;
|
|
688
695
|
const hiddenContainer = this.getHiddenContainer();
|
|
689
|
-
// Flag —
|
|
690
|
-
//
|
|
696
|
+
// Flag — fallback (moveBefore desteklenmeyen tarayıcı) removeChild yaptığında disconnectedCallback
|
|
697
|
+
// bunu okuyup destroy'ı atlar. moveBefore yolunda callback hiç tetiklenmez (flag zararsız kalır).
|
|
691
698
|
element.__arilPreserveDuringDetach = true;
|
|
692
|
-
//
|
|
693
|
-
if (
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
//
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
console.log('Web component element hidden container\'a taşındı (state korunuyor)');
|
|
700
|
-
}
|
|
699
|
+
// `shouldDetach` çoğu durumda element'i detach'ten ÖNCE zaten taşıdı → burada no-op.
|
|
700
|
+
if (hiddenContainer.contains(element))
|
|
701
|
+
return;
|
|
702
|
+
// Taşınmadıysa (ör. shouldDetach element'i bulamadı): bu noktada element Angular tarafından
|
|
703
|
+
// zaten disconnect edilmiş olabilir; moveInto bağlıysa moveBefore, değilse appendChild kullanır.
|
|
704
|
+
this.moveInto(hiddenContainer, element);
|
|
705
|
+
console.log('Web component element hidden container\'a taşındı (state korunuyor)');
|
|
701
706
|
}
|
|
702
707
|
catch (error) {
|
|
703
708
|
console.warn('Web component element preserve edilirken hata:', error);
|
|
@@ -720,35 +725,45 @@ class CustomRouteReuseStrategy {
|
|
|
720
725
|
return;
|
|
721
726
|
const element = componentInstance.element;
|
|
722
727
|
const hiddenContainer = this.getHiddenContainer();
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
console.log('Web component element component view\'a eklendi (retrieve sırasında)');
|
|
734
|
-
// Props'ları güncellemek için flag set et (component kendi populateProps'unu çağıracak)
|
|
735
|
-
componentInstance.propsUpdated = false;
|
|
736
|
-
return true;
|
|
737
|
-
}
|
|
728
|
+
if (!hiddenContainer.contains(element))
|
|
729
|
+
return;
|
|
730
|
+
// ÖNEMLI: element'i hidden container'dan ERKEN çıkarmıyoruz. `retrieve`, Angular
|
|
731
|
+
// `outlet.attach()`'ten ÖNCE çağrılır → vc henüz DOM'a bağlı değildir. Erken removeChild
|
|
732
|
+
// element'i disconnect eder ve iframe reload olur (tam kaçındığımız şey). Bunun yerine
|
|
733
|
+
// element'i hidden container'da (bağlı) bırakıp vc bağlanınca atomic moveBefore ile
|
|
734
|
+
// doğrudan hidden → vc taşıyoruz; iframe hiç reload olmaz.
|
|
735
|
+
const tryRestore = () => {
|
|
736
|
+
const vcNative = componentInstance.vc?.nativeElement;
|
|
737
|
+
if (!vcNative || !vcNative.isConnected)
|
|
738
738
|
return false;
|
|
739
|
-
|
|
740
|
-
//
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
739
|
+
this.moveInto(vcNative, element);
|
|
740
|
+
// Flag'i moveInto SONRASI sil: fallback removeChild yaparsa disconnectedCallback flag'i hâlâ görsün.
|
|
741
|
+
delete element.__arilPreserveDuringDetach;
|
|
742
|
+
componentInstance.propsUpdated = false;
|
|
743
|
+
console.log('Web component element component view\'a eklendi (retrieve sırasında)');
|
|
744
|
+
return true;
|
|
745
|
+
};
|
|
746
|
+
// Hemen dene (vc genelde bağlı değil) → değilse microtask'te tekrar dene. `outlet.attach()`
|
|
747
|
+
// retrieve'den hemen sonra SENKRON çalışır; microtask geçerli task bitince (attach tamamlanmış,
|
|
748
|
+
// vc bağlı) ama PAINT'ten ÖNCE koşar → element yerine oturur, tab geçişinde boş-flash olmaz.
|
|
749
|
+
if (tryRestore())
|
|
750
|
+
return;
|
|
751
|
+
queueMicrotask(() => {
|
|
752
|
+
if (tryRestore())
|
|
753
|
+
return;
|
|
754
|
+
// Son çare: vc hâlâ bağlı değil. Element'i yine de vc'ye taşı ki tab boş kalmasın
|
|
755
|
+
// (attach view'ı bağlayınca görünür olur — iframe reload olabilir ama eski davranış korunur).
|
|
756
|
+
const vcNative = componentInstance.vc?.nativeElement;
|
|
757
|
+
if (vcNative) {
|
|
758
|
+
this.moveInto(vcNative, element);
|
|
759
|
+
delete element.__arilPreserveDuringDetach;
|
|
760
|
+
componentInstance.propsUpdated = false;
|
|
750
761
|
}
|
|
751
|
-
|
|
762
|
+
else {
|
|
763
|
+
componentInstance.needsRestore = true;
|
|
764
|
+
console.log('Web component element restore edilecek (view hazır değil, ngAfterViewInit\'te tekrar denenecek)');
|
|
765
|
+
}
|
|
766
|
+
});
|
|
752
767
|
}
|
|
753
768
|
catch (error) {
|
|
754
769
|
console.warn('Web component element restore edilirken hata:', error);
|
|
@@ -772,6 +787,61 @@ class CustomRouteReuseStrategy {
|
|
|
772
787
|
}
|
|
773
788
|
return container;
|
|
774
789
|
}
|
|
790
|
+
/**
|
|
791
|
+
* `el`'i `target`'ın son çocuğu olacak şekilde TAŞIR. `moveBefore` (atomic move) destekleniyor ve
|
|
792
|
+
* her iki düğüm de bağlıysa onu kullanır: nested browsing context (iframe) reload OLMADAN ve custom
|
|
793
|
+
* element'in connected/disconnected callback'leri tetiklenmeden taşır → iframe-tabanlı embed'lerin
|
|
794
|
+
* (Superset) auth handshake'i + scroll/filtre state'i korunur. Desteklenmiyorsa veya taşıma kısıtları
|
|
795
|
+
* ihlal edilirse (disconnected / cross-document) removeChild+appendChild'a düşer (eski davranış: iframe
|
|
796
|
+
* reload olur ama işlem güvenli tamamlanır).
|
|
797
|
+
*/
|
|
798
|
+
moveInto(target, el) {
|
|
799
|
+
const mover = target;
|
|
800
|
+
if (typeof mover.moveBefore === 'function' && el.isConnected && target.isConnected) {
|
|
801
|
+
try {
|
|
802
|
+
mover.moveBefore(el, null);
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
catch {
|
|
806
|
+
// moveBefore kısıtları ihlal edildi → aşağıdaki klasik taşımaya düş.
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
if (el.parentNode && el.parentNode !== target) {
|
|
810
|
+
el.parentNode.removeChild(el);
|
|
811
|
+
}
|
|
812
|
+
if (!target.contains(el)) {
|
|
813
|
+
target.appendChild(el);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* `shouldDetach` içinden, Angular `outlet.detach()` çalışmadan ÖNCE çağrılır: canlı outlet'teki MFE
|
|
818
|
+
* element'ini `aril-tab-id` attribute'undan bulup atomic `moveBefore` ile hidden container'a taşır.
|
|
819
|
+
* Böylece Angular wrapper view'ını söktüğünde `<app-xxx>` element'i zaten güvenli/bağlı konumdadır ve
|
|
820
|
+
* barındırdığı iframe reload olmaz. Element bulunamaz ya da zaten hidden container'daysa no-op →
|
|
821
|
+
* `store()` eski yoluyla devreye girer (regresyon yok).
|
|
822
|
+
*/
|
|
823
|
+
preserveLiveElementBeforeDetach(route) {
|
|
824
|
+
try {
|
|
825
|
+
const tabId = this.getTabIdFromRoute(route);
|
|
826
|
+
if (!tabId)
|
|
827
|
+
return;
|
|
828
|
+
const hiddenContainer = this.getHiddenContainer();
|
|
829
|
+
const candidates = document.querySelectorAll(`[aril-tab-id="${tabId}"]`);
|
|
830
|
+
for (const candidate of Array.from(candidates)) {
|
|
831
|
+
const el = candidate;
|
|
832
|
+
if (hiddenContainer.contains(el))
|
|
833
|
+
continue;
|
|
834
|
+
// Fallback removeChild yolunda disconnectedCallback'in destroy'ı atlaması için flag'i taşımadan ÖNCE set et.
|
|
835
|
+
el.__arilPreserveDuringDetach = true;
|
|
836
|
+
this.moveInto(hiddenContainer, el);
|
|
837
|
+
console.log(`[Strategy] pre-detach preserve: <${el.tagName.toLowerCase()}> tab="${tabId}" hidden container'a taşındı`);
|
|
838
|
+
break;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
catch (error) {
|
|
842
|
+
console.warn('[Strategy] pre-detach preserve hatası:', error);
|
|
843
|
+
}
|
|
844
|
+
}
|
|
775
845
|
/**
|
|
776
846
|
* Detached route view'ı içindeki plugin/MFE custom element'lerini (tag adında `-`
|
|
777
847
|
* bulunan ve `customElements`'a kayıtlı olanları) hidden container'a taşır ve
|