@smartsoft001-mobilems/angular 2.78.0 → 2.79.0
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.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __decorate, __metadata } from 'tslib';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { Injectable, inject, PLATFORM_ID, signal, effect, computed, input, output, HostListener, Component, ApplicationRef, EnvironmentInjector, createComponent, InjectionToken, Directive, contentChild, Inject, viewChild, ElementRef, APP_INITIALIZER, NgModule } from '@angular/core';
|
|
3
|
+
import { Injectable, inject, PLATFORM_ID, signal, effect, computed, input, output, HostListener, Component, ApplicationRef, EnvironmentInjector, createComponent, InjectionToken, Directive, contentChild, Inject, NgZone, viewChild, model, ElementRef, APP_INITIALIZER, NgModule } from '@angular/core';
|
|
4
4
|
import { Meta, Title, DomSanitizer } from '@angular/platform-browser';
|
|
5
5
|
import { StyleService as StyleService$1, ReduxAction, AppBaseComponent, PageBaseComponent, BaseComponent } from '@smartsoft001/angular';
|
|
6
6
|
import { HttpClient } from '@angular/common/http';
|
|
@@ -14,10 +14,12 @@ import { TranslateService } from '@ngx-translate/core';
|
|
|
14
14
|
import { CrudSearchService, CrudService, CrudFacade } from '@smartsoft001/crud-shell-angular';
|
|
15
15
|
import * as _ from 'lodash';
|
|
16
16
|
import { Debounce } from 'lodash-decorators';
|
|
17
|
+
import Swiper from 'swiper';
|
|
18
|
+
import { Navigation, Autoplay } from 'swiper/modules';
|
|
19
|
+
import { toSignal } from '@angular/core/rxjs-interop';
|
|
17
20
|
import { ConfigPageType, ArticleWidgetType } from '@smartsoft001-mobilems/models';
|
|
18
21
|
import { Masonry } from '@thisissoon/angular-masonry';
|
|
19
22
|
import { capitalize } from '@smartsoft001/utils';
|
|
20
|
-
import { toSignal } from '@angular/core/rxjs-interop';
|
|
21
23
|
|
|
22
24
|
function setTranslationsAndLang(service) {
|
|
23
25
|
const map = {
|
|
@@ -272,7 +274,9 @@ class FileUrlService {
|
|
|
272
274
|
if (path[0] === '/') {
|
|
273
275
|
path = path.substring(1);
|
|
274
276
|
}
|
|
275
|
-
const shouldSkipExtensionReplacement = isStringPath ||
|
|
277
|
+
const shouldSkipExtensionReplacement = isStringPath ||
|
|
278
|
+
path.includes('media/dictionaries') ||
|
|
279
|
+
path.includes('media/articles');
|
|
276
280
|
if (!shouldSkipExtensionReplacement) {
|
|
277
281
|
path = this.replaceExtensionIfCache(path, mode);
|
|
278
282
|
}
|
|
@@ -1565,6 +1569,12 @@ class FiltersContext extends BaseComponent {
|
|
|
1565
1569
|
get authors() {
|
|
1566
1570
|
return this.filterGet('=', 'authors');
|
|
1567
1571
|
}
|
|
1572
|
+
set formFeature(val) {
|
|
1573
|
+
this.filterSet(this.formFeature, val, 'formFeature', '=');
|
|
1574
|
+
}
|
|
1575
|
+
get formFeature() {
|
|
1576
|
+
return this.filterGet('=', 'formFeature');
|
|
1577
|
+
}
|
|
1568
1578
|
set targetGroups(val) {
|
|
1569
1579
|
this.filterSet(this.targetGroups, val, 'targetGroups', '=');
|
|
1570
1580
|
}
|
|
@@ -1589,6 +1599,12 @@ class FiltersContext extends BaseComponent {
|
|
|
1589
1599
|
get extraNumbersValue() {
|
|
1590
1600
|
return this.filterGet('=', 'extraNumbersValue');
|
|
1591
1601
|
}
|
|
1602
|
+
set inventoryNumber(val) {
|
|
1603
|
+
this.filterSet(this.inventoryNumber, val, 'inventoryNumber', '=');
|
|
1604
|
+
}
|
|
1605
|
+
get inventoryNumber() {
|
|
1606
|
+
return this.filterGet('=', 'inventoryNumber');
|
|
1607
|
+
}
|
|
1592
1608
|
set filters(filters) {
|
|
1593
1609
|
this.multipleFilterSet(filters?.map(({ val, key, type }) => ({
|
|
1594
1610
|
currentValue: this.filterGet(type, key),
|
|
@@ -1745,6 +1761,790 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.0", ngImpor
|
|
|
1745
1761
|
args: ['window:scroll', []]
|
|
1746
1762
|
}] } });
|
|
1747
1763
|
|
|
1764
|
+
class SliderBaseComponent {
|
|
1765
|
+
constructor() {
|
|
1766
|
+
this.fileUrlService = inject(FileUrlService);
|
|
1767
|
+
this.slides = input([], ...(ngDevMode ? [{ debugName: "slides" }] : []));
|
|
1768
|
+
this.autoplayEnabled = signal(true, ...(ngDevMode ? [{ debugName: "autoplayEnabled" }] : []));
|
|
1769
|
+
this.windowWidth = signal(typeof window !== 'undefined' ? window.innerWidth : 1024, ...(ngDevMode ? [{ debugName: "windowWidth" }] : []));
|
|
1770
|
+
// Computed signal that recalculates images when windowWidth or slides change
|
|
1771
|
+
this.slideImages = computed(() => {
|
|
1772
|
+
const width = this.windowWidth();
|
|
1773
|
+
const slides = this.slides();
|
|
1774
|
+
return slides.map((slide) => {
|
|
1775
|
+
let imageSource;
|
|
1776
|
+
if (width < 768) {
|
|
1777
|
+
imageSource =
|
|
1778
|
+
slide.imageMobile || slide.imageTablet || slide.imageDesktop;
|
|
1779
|
+
}
|
|
1780
|
+
else if (width < 1024) {
|
|
1781
|
+
imageSource =
|
|
1782
|
+
slide.imageTablet || slide.imageDesktop || slide.imageMobile;
|
|
1783
|
+
}
|
|
1784
|
+
else {
|
|
1785
|
+
imageSource =
|
|
1786
|
+
slide.imageDesktop || slide.imageTablet || slide.imageMobile;
|
|
1787
|
+
}
|
|
1788
|
+
if (!imageSource) {
|
|
1789
|
+
return '/gfx/no-image.png';
|
|
1790
|
+
}
|
|
1791
|
+
return this.fileUrlService.get(imageSource);
|
|
1792
|
+
});
|
|
1793
|
+
}, ...(ngDevMode ? [{ debugName: "slideImages" }] : []));
|
|
1794
|
+
this.ngZone = inject(NgZone);
|
|
1795
|
+
this.swiperContainer = viewChild('swiperContainer', ...(ngDevMode ? [{ debugName: "swiperContainer" }] : []));
|
|
1796
|
+
effect(() => {
|
|
1797
|
+
const slides = this.slides();
|
|
1798
|
+
if (this.swiper && slides.length > 0) {
|
|
1799
|
+
this.swiper.update();
|
|
1800
|
+
}
|
|
1801
|
+
});
|
|
1802
|
+
}
|
|
1803
|
+
ngOnInit() {
|
|
1804
|
+
this.initSwiper();
|
|
1805
|
+
// Listen to window resize to recreate swiper completely
|
|
1806
|
+
this.resizeListener = () => {
|
|
1807
|
+
this.ngZone.run(() => {
|
|
1808
|
+
this.windowWidth.set(window.innerWidth);
|
|
1809
|
+
this.recreateSwiper();
|
|
1810
|
+
});
|
|
1811
|
+
};
|
|
1812
|
+
window.addEventListener('resize', this.resizeListener);
|
|
1813
|
+
}
|
|
1814
|
+
ngOnDestroy() {
|
|
1815
|
+
if (this.resizeListener && typeof window !== 'undefined') {
|
|
1816
|
+
window.removeEventListener('resize', this.resizeListener);
|
|
1817
|
+
}
|
|
1818
|
+
if (this.swiper) {
|
|
1819
|
+
this.swiper.destroy(true, true);
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
toggleAutoplay() {
|
|
1823
|
+
this.autoplayEnabled.update((current) => !current);
|
|
1824
|
+
if (this.swiper) {
|
|
1825
|
+
if (this.autoplayEnabled()) {
|
|
1826
|
+
this.swiper.params.autoplay = {
|
|
1827
|
+
delay: 5000,
|
|
1828
|
+
disableOnInteraction: false,
|
|
1829
|
+
};
|
|
1830
|
+
this.swiper.autoplay.start();
|
|
1831
|
+
}
|
|
1832
|
+
else {
|
|
1833
|
+
this.swiper.autoplay.stop();
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
getImage(slide) {
|
|
1838
|
+
let imageSource;
|
|
1839
|
+
if (typeof window !== 'undefined') {
|
|
1840
|
+
const width = window.innerWidth;
|
|
1841
|
+
if (width < 768) {
|
|
1842
|
+
imageSource =
|
|
1843
|
+
slide.imageMobile || slide.imageTablet || slide.imageDesktop;
|
|
1844
|
+
}
|
|
1845
|
+
else if (width < 1024) {
|
|
1846
|
+
imageSource =
|
|
1847
|
+
slide.imageTablet || slide.imageDesktop || slide.imageMobile;
|
|
1848
|
+
}
|
|
1849
|
+
else {
|
|
1850
|
+
imageSource =
|
|
1851
|
+
slide.imageDesktop || slide.imageTablet || slide.imageMobile;
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
else {
|
|
1855
|
+
imageSource =
|
|
1856
|
+
slide.imageDesktop || slide.imageTablet || slide.imageMobile;
|
|
1857
|
+
}
|
|
1858
|
+
// Return the image source directly if it's a URL, otherwise use FileUrlService
|
|
1859
|
+
if (!imageSource) {
|
|
1860
|
+
return '/gfx/no-image.png';
|
|
1861
|
+
}
|
|
1862
|
+
return this.fileUrlService.get(imageSource);
|
|
1863
|
+
}
|
|
1864
|
+
initSwiper() {
|
|
1865
|
+
const container = this.swiperContainer();
|
|
1866
|
+
if (!container)
|
|
1867
|
+
return;
|
|
1868
|
+
// if (isPlatformServer(this.platformId)) return;
|
|
1869
|
+
this.swiper = new Swiper(container.nativeElement, {
|
|
1870
|
+
modules: [Navigation, Autoplay],
|
|
1871
|
+
loop: true,
|
|
1872
|
+
autoplay: {
|
|
1873
|
+
delay: 5000,
|
|
1874
|
+
disableOnInteraction: false,
|
|
1875
|
+
},
|
|
1876
|
+
navigation: {
|
|
1877
|
+
nextEl: '.swiper-button-next',
|
|
1878
|
+
prevEl: '.swiper-button-prev',
|
|
1879
|
+
},
|
|
1880
|
+
slidesPerView: 1,
|
|
1881
|
+
spaceBetween: 0,
|
|
1882
|
+
});
|
|
1883
|
+
}
|
|
1884
|
+
recreateSwiper() {
|
|
1885
|
+
const container = this.swiperContainer();
|
|
1886
|
+
if (!container)
|
|
1887
|
+
return;
|
|
1888
|
+
// Destroy existing swiper
|
|
1889
|
+
if (this.swiper) {
|
|
1890
|
+
this.swiper.destroy(true, true);
|
|
1891
|
+
this.swiper = undefined;
|
|
1892
|
+
}
|
|
1893
|
+
// Small delay to ensure DOM is updated after signal change
|
|
1894
|
+
setTimeout(() => {
|
|
1895
|
+
this.createSwiper(container.nativeElement);
|
|
1896
|
+
}, 0);
|
|
1897
|
+
}
|
|
1898
|
+
createSwiper(element) {
|
|
1899
|
+
this.swiper = new Swiper(element, {
|
|
1900
|
+
modules: [Navigation, Autoplay],
|
|
1901
|
+
loop: true,
|
|
1902
|
+
autoplay: {
|
|
1903
|
+
delay: 5000,
|
|
1904
|
+
disableOnInteraction: false,
|
|
1905
|
+
},
|
|
1906
|
+
navigation: {
|
|
1907
|
+
nextEl: '.swiper-button-next',
|
|
1908
|
+
prevEl: '.swiper-button-prev',
|
|
1909
|
+
},
|
|
1910
|
+
slidesPerView: 1,
|
|
1911
|
+
spaceBetween: 0,
|
|
1912
|
+
});
|
|
1913
|
+
}
|
|
1914
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.0", ngImport: i0, type: SliderBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1915
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "20.1.0", type: SliderBaseComponent, isStandalone: true, inputs: { slides: { classPropertyName: "slides", publicName: "slides", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "swiperContainer", first: true, predicate: ["swiperContainer"], descendants: true, isSignal: true }], ngImport: i0 }); }
|
|
1916
|
+
}
|
|
1917
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.0", ngImport: i0, type: SliderBaseComponent, decorators: [{
|
|
1918
|
+
type: Directive
|
|
1919
|
+
}], ctorParameters: () => [] });
|
|
1920
|
+
|
|
1921
|
+
class SearchBaseComponent {
|
|
1922
|
+
constructor() {
|
|
1923
|
+
this.route = inject(ActivatedRoute);
|
|
1924
|
+
this.router = inject(Router);
|
|
1925
|
+
this.service = inject(SearchService);
|
|
1926
|
+
this.params = toSignal(this.route.params);
|
|
1927
|
+
this.text = signal('', ...(ngDevMode ? [{ debugName: "text" }] : []));
|
|
1928
|
+
this.data = signal(null, ...(ngDevMode ? [{ debugName: "data" }] : []));
|
|
1929
|
+
this.tabs = signal([], ...(ngDevMode ? [{ debugName: "tabs" }] : []));
|
|
1930
|
+
this.searchMap = {
|
|
1931
|
+
fallbackId: 'obiekty',
|
|
1932
|
+
fallbackLabel: 'Obiekty',
|
|
1933
|
+
fallbackProperty: 'objects',
|
|
1934
|
+
searchTabs: [],
|
|
1935
|
+
};
|
|
1936
|
+
this.activeTab = signal(this.searchMap.fallbackId, ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
|
|
1937
|
+
effect(async () => {
|
|
1938
|
+
const { text } = this.params();
|
|
1939
|
+
this.text.set(text);
|
|
1940
|
+
const data = await firstValueFrom(this.service.search(text ? text : '_'));
|
|
1941
|
+
let path = this.searchMap.fallbackId;
|
|
1942
|
+
const tabs = [];
|
|
1943
|
+
for (const tab of this.searchMap.searchTabs) {
|
|
1944
|
+
if (data[tab.property]) {
|
|
1945
|
+
tabs.push({
|
|
1946
|
+
id: tab.id,
|
|
1947
|
+
label: `${tab.label} (${data[tab.property]})`,
|
|
1948
|
+
});
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
if (!tabs.length) {
|
|
1952
|
+
tabs.push({
|
|
1953
|
+
id: this.searchMap.fallbackId,
|
|
1954
|
+
label: `${this.searchMap.fallbackLabel} (${data[this.searchMap.fallbackProperty]})`,
|
|
1955
|
+
});
|
|
1956
|
+
}
|
|
1957
|
+
for (const tab of this.searchMap.searchTabs) {
|
|
1958
|
+
if (data[tab.property]) {
|
|
1959
|
+
path = tab.id;
|
|
1960
|
+
break;
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
this.data.set(data);
|
|
1964
|
+
this.tabs.set(tabs);
|
|
1965
|
+
this.activeTab.set(path);
|
|
1966
|
+
await this.router.navigate([`/wyszukaj/${text}/${path}`]);
|
|
1967
|
+
});
|
|
1968
|
+
effect(() => {
|
|
1969
|
+
const activeTab = this.activeTab();
|
|
1970
|
+
const text = this.text();
|
|
1971
|
+
this.router.navigate([`/wyszukaj/${text}/${activeTab}`]);
|
|
1972
|
+
});
|
|
1973
|
+
}
|
|
1974
|
+
ngOnInit() {
|
|
1975
|
+
this.service.setEnabled(true);
|
|
1976
|
+
}
|
|
1977
|
+
ngOnDestroy() {
|
|
1978
|
+
this.service.setEnabled(false);
|
|
1979
|
+
}
|
|
1980
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.0", ngImport: i0, type: SearchBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1981
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.1.0", type: SearchBaseComponent, isStandalone: true, ngImport: i0 }); }
|
|
1982
|
+
}
|
|
1983
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.0", ngImport: i0, type: SearchBaseComponent, decorators: [{
|
|
1984
|
+
type: Directive
|
|
1985
|
+
}], ctorParameters: () => [] });
|
|
1986
|
+
|
|
1987
|
+
class MediaTabBaseComponent {
|
|
1988
|
+
constructor() {
|
|
1989
|
+
this.item = input.required(...(ngDevMode ? [{ debugName: "item" }] : []));
|
|
1990
|
+
this.formFeatureTypes = input.required(...(ngDevMode ? [{ debugName: "formFeatureTypes" }] : []));
|
|
1991
|
+
this.models = computed(() => {
|
|
1992
|
+
const obj = this.item();
|
|
1993
|
+
let filtered = [];
|
|
1994
|
+
if (obj.additionalImages && Array.isArray(obj.additionalImages)) {
|
|
1995
|
+
filtered = obj.additionalImages
|
|
1996
|
+
.filter((file) => file?.formFeature
|
|
1997
|
+
? this.formFeatureTypes().includes(file.formFeature)
|
|
1998
|
+
: false)
|
|
1999
|
+
.sort((a, b) => (a?.position ?? 0) - (b?.position ?? 0));
|
|
2000
|
+
}
|
|
2001
|
+
return filtered;
|
|
2002
|
+
}, ...(ngDevMode ? [{ debugName: "models" }] : []));
|
|
2003
|
+
}
|
|
2004
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.0", ngImport: i0, type: MediaTabBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2005
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.0", type: MediaTabBaseComponent, isStandalone: true, inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, formFeatureTypes: { classPropertyName: "formFeatureTypes", publicName: "formFeatureTypes", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 }); }
|
|
2006
|
+
}
|
|
2007
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.0", ngImport: i0, type: MediaTabBaseComponent, decorators: [{
|
|
2008
|
+
type: Directive
|
|
2009
|
+
}] });
|
|
2010
|
+
|
|
2011
|
+
class GalleryFullscreenBaseComponent {
|
|
2012
|
+
constructor() {
|
|
2013
|
+
this.fileUrlService = inject(FileUrlService);
|
|
2014
|
+
this.document = inject(DOCUMENT);
|
|
2015
|
+
this.ngZone = inject(NgZone);
|
|
2016
|
+
this.items = input(...(ngDevMode ? [undefined, { debugName: "items" }] : []));
|
|
2017
|
+
this.alt = input('', ...(ngDevMode ? [{ debugName: "alt" }] : []));
|
|
2018
|
+
this.id = input('imagePreview', ...(ngDevMode ? [{ debugName: "id" }] : []));
|
|
2019
|
+
this.selectedIndex = model(0, ...(ngDevMode ? [{ debugName: "selectedIndex" }] : []));
|
|
2020
|
+
this.closeChange = output();
|
|
2021
|
+
// Touch pinch gesture tracking
|
|
2022
|
+
this.touchStartDistance = 0;
|
|
2023
|
+
this.touchStartZoom = 1;
|
|
2024
|
+
// Pinch midpoint (client coords) and transform at start of pinch
|
|
2025
|
+
this.pinchStartClientX = 0;
|
|
2026
|
+
this.pinchStartClientY = 0;
|
|
2027
|
+
this.pinchStartTransformX = 0;
|
|
2028
|
+
this.pinchStartTransformY = 0;
|
|
2029
|
+
// Pan/drag gesture tracking
|
|
2030
|
+
this.isPanning = signal(false, ...(ngDevMode ? [{ debugName: "isPanning" }] : []));
|
|
2031
|
+
this.panStartX = 0;
|
|
2032
|
+
this.panStartY = 0;
|
|
2033
|
+
this.panStartTransformX = 0;
|
|
2034
|
+
this.panStartTransformY = 0;
|
|
2035
|
+
this.touchStartedOnButton = false;
|
|
2036
|
+
this.canGoPrevious = computed(() => this.fullscreenIndex() > 0, ...(ngDevMode ? [{ debugName: "canGoPrevious" }] : []));
|
|
2037
|
+
this.canGoNext = computed(() => {
|
|
2038
|
+
const items = this.items();
|
|
2039
|
+
return items && this.fullscreenIndex() < items.length - 1;
|
|
2040
|
+
}, ...(ngDevMode ? [{ debugName: "canGoNext" }] : []));
|
|
2041
|
+
// Fullscreen state
|
|
2042
|
+
this.fullscreenIndex = signal(0, ...(ngDevMode ? [{ debugName: "fullscreenIndex" }] : []));
|
|
2043
|
+
this.zoomLevel = signal(1, ...(ngDevMode ? [{ debugName: "zoomLevel" }] : []));
|
|
2044
|
+
this.rotation = signal(0, ...(ngDevMode ? [{ debugName: "rotation" }] : []));
|
|
2045
|
+
this.transform = computed(() => {
|
|
2046
|
+
const trans = this.imageTransform();
|
|
2047
|
+
return `
|
|
2048
|
+
translate(${trans.x}px, ${trans.y}px)
|
|
2049
|
+
scale(${this.zoomLevel()})
|
|
2050
|
+
rotate(${this.rotation()}deg)
|
|
2051
|
+
`;
|
|
2052
|
+
}, ...(ngDevMode ? [{ debugName: "transform" }] : []));
|
|
2053
|
+
this.imageTransform = signal({ x: 0, y: 0 }, ...(ngDevMode ? [{ debugName: "imageTransform" }] : []));
|
|
2054
|
+
// Loading indicator for fullscreen image
|
|
2055
|
+
this.isFullscreenLoading = signal(true, ...(ngDevMode ? [{ debugName: "isFullscreenLoading" }] : []));
|
|
2056
|
+
this.fullscreenItem = computed(() => {
|
|
2057
|
+
const items = this.items();
|
|
2058
|
+
const index = this.fullscreenIndex();
|
|
2059
|
+
if (!items)
|
|
2060
|
+
return null;
|
|
2061
|
+
return items[index] || null;
|
|
2062
|
+
}, ...(ngDevMode ? [{ debugName: "fullscreenItem" }] : []));
|
|
2063
|
+
// OpenSeadragon viewer instance
|
|
2064
|
+
this.osdViewer = null;
|
|
2065
|
+
this.openseadragonModule = null;
|
|
2066
|
+
this.osdContainerId = computed(() => `osd-viewer-${this.id()}`, ...(ngDevMode ? [{ debugName: "osdContainerId" }] : []));
|
|
2067
|
+
// Reset fullscreen zoom when changing images
|
|
2068
|
+
effect(() => {
|
|
2069
|
+
this.fullscreenIndex();
|
|
2070
|
+
this.zoomLevel.set(1);
|
|
2071
|
+
this.imageTransform.set({ x: 0, y: 0 });
|
|
2072
|
+
this.rotation.set(0);
|
|
2073
|
+
// Load new image in OpenSeadragon if viewer exists
|
|
2074
|
+
if (this.osdViewer) {
|
|
2075
|
+
const item = this.fullscreenItem();
|
|
2076
|
+
if (item?.image) {
|
|
2077
|
+
this.loadOsdImage(item.image);
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
2080
|
+
});
|
|
2081
|
+
}
|
|
2082
|
+
ngAfterViewInit() {
|
|
2083
|
+
this.initFullscreen();
|
|
2084
|
+
}
|
|
2085
|
+
ngOnDestroy() {
|
|
2086
|
+
this.stopLoading();
|
|
2087
|
+
this.zoomLevel.set(1);
|
|
2088
|
+
this.imageTransform.set({ x: 0, y: 0 });
|
|
2089
|
+
this.document.body.classList.remove('smart-gallery-fullscreen-active');
|
|
2090
|
+
// Destroy OpenSeadragon viewer
|
|
2091
|
+
if (this.osdViewer) {
|
|
2092
|
+
this.ngZone.runOutsideAngular(() => {
|
|
2093
|
+
try {
|
|
2094
|
+
this.osdViewer.destroy();
|
|
2095
|
+
}
|
|
2096
|
+
catch (e) {
|
|
2097
|
+
// Ignore errors
|
|
2098
|
+
}
|
|
2099
|
+
});
|
|
2100
|
+
this.osdViewer = null;
|
|
2101
|
+
}
|
|
2102
|
+
}
|
|
2103
|
+
async initFullscreen() {
|
|
2104
|
+
this.fullscreenIndex.set(this.selectedIndex());
|
|
2105
|
+
this.document.body.classList.add('smart-gallery-fullscreen-active');
|
|
2106
|
+
const item = this.fullscreenItem();
|
|
2107
|
+
if (!item?.image)
|
|
2108
|
+
return;
|
|
2109
|
+
try {
|
|
2110
|
+
// Lazy load OpenSeadragon
|
|
2111
|
+
if (!this.openseadragonModule) {
|
|
2112
|
+
this.openseadragonModule = await import('openseadragon');
|
|
2113
|
+
}
|
|
2114
|
+
// Wait for template to render
|
|
2115
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
2116
|
+
const container = this.document.getElementById(this.osdContainerId());
|
|
2117
|
+
if (!container) {
|
|
2118
|
+
this.startLoading();
|
|
2119
|
+
return;
|
|
2120
|
+
}
|
|
2121
|
+
// Create viewer outside Angular zone for better performance
|
|
2122
|
+
if (!this.osdViewer) {
|
|
2123
|
+
this.osdViewer = this.ngZone.runOutsideAngular(() => {
|
|
2124
|
+
const viewer = this.openseadragonModule.default({
|
|
2125
|
+
element: container,
|
|
2126
|
+
prefixUrl: 'https://openseadragon.github.io/openseadragon/images/',
|
|
2127
|
+
animationTime: 0.5,
|
|
2128
|
+
blendTime: 0.1,
|
|
2129
|
+
constrainDuringPan: true,
|
|
2130
|
+
maxZoomPixelRatio: 2,
|
|
2131
|
+
minZoomLevel: 0,
|
|
2132
|
+
visibilityRatio: 1,
|
|
2133
|
+
zoomPerScroll: 1.2,
|
|
2134
|
+
showNavigator: false,
|
|
2135
|
+
showNavigationControl: false,
|
|
2136
|
+
gestureSettingsMouse: {
|
|
2137
|
+
scrollToZoom: true,
|
|
2138
|
+
clickToZoom: false,
|
|
2139
|
+
dblClickToZoom: true,
|
|
2140
|
+
pinchToZoom: true,
|
|
2141
|
+
flickEnabled: true,
|
|
2142
|
+
flickMinSpeed: 0.5,
|
|
2143
|
+
flickMomentum: 0.25,
|
|
2144
|
+
},
|
|
2145
|
+
gestureSettingsTouch: {
|
|
2146
|
+
scrollToZoom: false,
|
|
2147
|
+
clickToZoom: false,
|
|
2148
|
+
dblClickToZoom: true,
|
|
2149
|
+
pinchToZoom: true,
|
|
2150
|
+
flickEnabled: true,
|
|
2151
|
+
flickMinSpeed: 0.5,
|
|
2152
|
+
flickMomentum: 0.25,
|
|
2153
|
+
},
|
|
2154
|
+
});
|
|
2155
|
+
// Sync zoom level with component state (run inside Angular zone)
|
|
2156
|
+
viewer.addHandler('open', () => {
|
|
2157
|
+
this.ngZone.run(() => {
|
|
2158
|
+
this.stopLoading();
|
|
2159
|
+
try {
|
|
2160
|
+
const viewport = viewer.viewport;
|
|
2161
|
+
viewport.setRotation(0);
|
|
2162
|
+
viewport.goHome(true);
|
|
2163
|
+
this.rotation.set(0);
|
|
2164
|
+
const homeZoom = viewer.viewport.getHomeZoom();
|
|
2165
|
+
// Dynamically set minZoomLevel to 50% of home zoom
|
|
2166
|
+
// This ensures all images can zoom out to exactly 50% regardless of aspect ratio
|
|
2167
|
+
viewer.viewport.minZoomLevel = homeZoom * 0.5;
|
|
2168
|
+
const currentZoom = viewer.viewport.getZoom();
|
|
2169
|
+
// Normalize: 100% = fit to screen (home zoom)
|
|
2170
|
+
const normalizedZoom = currentZoom / homeZoom;
|
|
2171
|
+
this.zoomLevel.set(normalizedZoom);
|
|
2172
|
+
}
|
|
2173
|
+
catch (e) {
|
|
2174
|
+
this.zoomLevel.set(1);
|
|
2175
|
+
this.rotation.set(0);
|
|
2176
|
+
}
|
|
2177
|
+
});
|
|
2178
|
+
});
|
|
2179
|
+
viewer.addHandler('zoom', () => {
|
|
2180
|
+
this.ngZone.run(() => {
|
|
2181
|
+
try {
|
|
2182
|
+
const homeZoom = viewer.viewport.getHomeZoom();
|
|
2183
|
+
const currentZoom = viewer.viewport.getZoom();
|
|
2184
|
+
const normalizedZoom = currentZoom / homeZoom;
|
|
2185
|
+
this.zoomLevel.set(normalizedZoom);
|
|
2186
|
+
}
|
|
2187
|
+
catch (e) {
|
|
2188
|
+
// Ignore errors
|
|
2189
|
+
}
|
|
2190
|
+
});
|
|
2191
|
+
});
|
|
2192
|
+
return viewer;
|
|
2193
|
+
});
|
|
2194
|
+
}
|
|
2195
|
+
// Load image into OpenSeadragon
|
|
2196
|
+
await this.loadOsdImage(item.image);
|
|
2197
|
+
}
|
|
2198
|
+
catch (error) {
|
|
2199
|
+
console.error('Failed to initialize OpenSeadragon:', error);
|
|
2200
|
+
this.startLoading();
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
// Called from template when fullscreen image loads or fails
|
|
2204
|
+
onFullscreenImageLoad() {
|
|
2205
|
+
this.stopLoading();
|
|
2206
|
+
}
|
|
2207
|
+
startLoading() {
|
|
2208
|
+
this.isFullscreenLoading.set(true);
|
|
2209
|
+
}
|
|
2210
|
+
stopLoading() {
|
|
2211
|
+
this.isFullscreenLoading.set(false);
|
|
2212
|
+
}
|
|
2213
|
+
closeFullscreen() {
|
|
2214
|
+
this.closeChange.emit();
|
|
2215
|
+
}
|
|
2216
|
+
rotateRight() {
|
|
2217
|
+
this.rotation.update((r) => (r + 90) % 360);
|
|
2218
|
+
if (this.osdViewer) {
|
|
2219
|
+
this.ngZone.runOutsideAngular(() => {
|
|
2220
|
+
try {
|
|
2221
|
+
const viewport = this.osdViewer.viewport;
|
|
2222
|
+
viewport.setRotation(this.rotation());
|
|
2223
|
+
viewport.applyConstraints();
|
|
2224
|
+
}
|
|
2225
|
+
catch (e) {
|
|
2226
|
+
return;
|
|
2227
|
+
}
|
|
2228
|
+
});
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
handleKeyboardEvent(event) {
|
|
2232
|
+
switch (event.key) {
|
|
2233
|
+
case 'Escape':
|
|
2234
|
+
this.closeFullscreen();
|
|
2235
|
+
event.preventDefault();
|
|
2236
|
+
break;
|
|
2237
|
+
case 'ArrowLeft':
|
|
2238
|
+
this.previousImage();
|
|
2239
|
+
event.preventDefault();
|
|
2240
|
+
break;
|
|
2241
|
+
case 'ArrowRight':
|
|
2242
|
+
this.nextImage();
|
|
2243
|
+
event.preventDefault();
|
|
2244
|
+
break;
|
|
2245
|
+
case '+':
|
|
2246
|
+
case '=':
|
|
2247
|
+
this.zoomIn();
|
|
2248
|
+
event.preventDefault();
|
|
2249
|
+
break;
|
|
2250
|
+
case '-':
|
|
2251
|
+
this.zoomOut();
|
|
2252
|
+
event.preventDefault();
|
|
2253
|
+
break;
|
|
2254
|
+
case '0':
|
|
2255
|
+
this.resetZoom();
|
|
2256
|
+
event.preventDefault();
|
|
2257
|
+
break;
|
|
2258
|
+
}
|
|
2259
|
+
}
|
|
2260
|
+
handleTouchStart(event) {
|
|
2261
|
+
// Check if touch started on a button
|
|
2262
|
+
const target = event.target;
|
|
2263
|
+
this.touchStartedOnButton = !!target.closest('button');
|
|
2264
|
+
if (this.touchStartedOnButton)
|
|
2265
|
+
return true;
|
|
2266
|
+
// If OpenSeadragon is active, let it handle gestures
|
|
2267
|
+
if (this.osdViewer)
|
|
2268
|
+
return false;
|
|
2269
|
+
event.preventDefault();
|
|
2270
|
+
event.stopPropagation();
|
|
2271
|
+
// Handle pinch gesture (two fingers)
|
|
2272
|
+
if (event.touches.length === 2) {
|
|
2273
|
+
const touch1 = event.touches[0];
|
|
2274
|
+
const touch2 = event.touches[1];
|
|
2275
|
+
this.touchStartDistance = this.getDistance(touch1, touch2);
|
|
2276
|
+
this.touchStartZoom = this.zoomLevel();
|
|
2277
|
+
this.isPanning.set(false);
|
|
2278
|
+
// store pinch midpoint (client coordinates) and current transform to keep the midpoint fixed while scaling
|
|
2279
|
+
const midX = (touch1.clientX + touch2.clientX) / 2;
|
|
2280
|
+
const midY = (touch1.clientY + touch2.clientY) / 2;
|
|
2281
|
+
this.pinchStartClientX = midX;
|
|
2282
|
+
this.pinchStartClientY = midY;
|
|
2283
|
+
this.pinchStartTransformX = this.imageTransform().x;
|
|
2284
|
+
this.pinchStartTransformY = this.imageTransform().y;
|
|
2285
|
+
}
|
|
2286
|
+
else if (event.touches.length === 1 && this.zoomLevel() > 1) {
|
|
2287
|
+
// Handle pan gesture only if zoomed in
|
|
2288
|
+
this.isPanning.set(true);
|
|
2289
|
+
this.panStartX = event.touches[0].clientX;
|
|
2290
|
+
this.panStartY = event.touches[0].clientY;
|
|
2291
|
+
this.panStartTransformX = this.imageTransform().x;
|
|
2292
|
+
this.panStartTransformY = this.imageTransform().y;
|
|
2293
|
+
}
|
|
2294
|
+
return false;
|
|
2295
|
+
}
|
|
2296
|
+
handleTouchMove(event) {
|
|
2297
|
+
if (this.touchStartedOnButton)
|
|
2298
|
+
return true;
|
|
2299
|
+
// If OpenSeadragon is active, let it handle gestures
|
|
2300
|
+
if (this.osdViewer)
|
|
2301
|
+
return false;
|
|
2302
|
+
event.preventDefault();
|
|
2303
|
+
event.stopPropagation();
|
|
2304
|
+
// Handle pinch zoom (two fingers)
|
|
2305
|
+
if (event.touches.length === 2 && this.touchStartDistance > 0) {
|
|
2306
|
+
const touch1 = event.touches[0];
|
|
2307
|
+
const touch2 = event.touches[1];
|
|
2308
|
+
const currentDistance = this.getDistance(touch1, touch2);
|
|
2309
|
+
const scale = currentDistance / this.touchStartDistance;
|
|
2310
|
+
const newZoom = Math.max(0.5, Math.min(5, this.touchStartZoom * scale));
|
|
2311
|
+
// adjust transform so the pinch midpoint remains under the same screen point
|
|
2312
|
+
const el = this.document.getElementById(this.id());
|
|
2313
|
+
if (el) {
|
|
2314
|
+
const rect = el.getBoundingClientRect();
|
|
2315
|
+
// relative point inside the element (in element pixels) at start of pinch
|
|
2316
|
+
const relX = (this.pinchStartClientX - rect.left - this.pinchStartTransformX) /
|
|
2317
|
+
this.touchStartZoom;
|
|
2318
|
+
const relY = (this.pinchStartClientY - rect.top - this.pinchStartTransformY) /
|
|
2319
|
+
this.touchStartZoom;
|
|
2320
|
+
const newTx = this.pinchStartClientX - rect.left - relX * newZoom;
|
|
2321
|
+
const newTy = this.pinchStartClientY - rect.top - relY * newZoom;
|
|
2322
|
+
this.imageTransform.set({ x: newTx, y: newTy });
|
|
2323
|
+
}
|
|
2324
|
+
this.zoomLevel.set(newZoom);
|
|
2325
|
+
}
|
|
2326
|
+
// Handle pan/drag (one finger while zoomed)
|
|
2327
|
+
else if (event.touches.length === 1 &&
|
|
2328
|
+
this.isPanning() &&
|
|
2329
|
+
this.zoomLevel() > 1) {
|
|
2330
|
+
const deltaX = event.touches[0].clientX - this.panStartX;
|
|
2331
|
+
const deltaY = event.touches[0].clientY - this.panStartY;
|
|
2332
|
+
this.imageTransform.set({
|
|
2333
|
+
x: this.panStartTransformX + deltaX,
|
|
2334
|
+
y: this.panStartTransformY + deltaY,
|
|
2335
|
+
});
|
|
2336
|
+
}
|
|
2337
|
+
return false;
|
|
2338
|
+
}
|
|
2339
|
+
handleTouchEnd() {
|
|
2340
|
+
this.touchStartDistance = 0;
|
|
2341
|
+
this.touchStartZoom = 1;
|
|
2342
|
+
this.isPanning.set(false);
|
|
2343
|
+
}
|
|
2344
|
+
handleMouseDown(event) {
|
|
2345
|
+
if (this.zoomLevel() <= 1)
|
|
2346
|
+
return false;
|
|
2347
|
+
event.preventDefault();
|
|
2348
|
+
this.isPanning.set(true);
|
|
2349
|
+
this.panStartX = event.clientX;
|
|
2350
|
+
this.panStartY = event.clientY;
|
|
2351
|
+
this.panStartTransformX = this.imageTransform().x;
|
|
2352
|
+
this.panStartTransformY = this.imageTransform().y;
|
|
2353
|
+
return false;
|
|
2354
|
+
}
|
|
2355
|
+
handleMouseMove(event) {
|
|
2356
|
+
if (!this.isPanning() || this.zoomLevel() <= 1)
|
|
2357
|
+
return false;
|
|
2358
|
+
event.preventDefault();
|
|
2359
|
+
const deltaX = event.clientX - this.panStartX;
|
|
2360
|
+
const deltaY = event.clientY - this.panStartY;
|
|
2361
|
+
requestAnimationFrame(() => {
|
|
2362
|
+
this.imageTransform.set({
|
|
2363
|
+
x: this.panStartTransformX + deltaX,
|
|
2364
|
+
y: this.panStartTransformY + deltaY,
|
|
2365
|
+
});
|
|
2366
|
+
});
|
|
2367
|
+
return false;
|
|
2368
|
+
}
|
|
2369
|
+
handleMouseUp() {
|
|
2370
|
+
this.isPanning.set(false);
|
|
2371
|
+
}
|
|
2372
|
+
handleWheel(event) {
|
|
2373
|
+
// If OpenSeadragon is active, let it handle wheel events
|
|
2374
|
+
if (this.osdViewer) {
|
|
2375
|
+
event.preventDefault();
|
|
2376
|
+
event.stopPropagation();
|
|
2377
|
+
return false;
|
|
2378
|
+
}
|
|
2379
|
+
return false;
|
|
2380
|
+
}
|
|
2381
|
+
previousImage() {
|
|
2382
|
+
if (this.canGoPrevious()) {
|
|
2383
|
+
// start loading when navigating
|
|
2384
|
+
this.startLoading();
|
|
2385
|
+
this.fullscreenIndex.update((i) => i - 1);
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
nextImage() {
|
|
2389
|
+
if (this.canGoNext()) {
|
|
2390
|
+
// start loading when navigating
|
|
2391
|
+
this.startLoading();
|
|
2392
|
+
this.fullscreenIndex.update((i) => i + 1);
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
selectThumbnail(index) {
|
|
2396
|
+
if (index === this.fullscreenIndex()) {
|
|
2397
|
+
// same index — no navigation, but ensure loading is false
|
|
2398
|
+
this.stopLoading();
|
|
2399
|
+
return;
|
|
2400
|
+
}
|
|
2401
|
+
// start loading when selecting thumbnail
|
|
2402
|
+
this.startLoading();
|
|
2403
|
+
this.fullscreenIndex.set(index);
|
|
2404
|
+
}
|
|
2405
|
+
zoomIn() {
|
|
2406
|
+
if (this.osdViewer) {
|
|
2407
|
+
this.ngZone.runOutsideAngular(() => {
|
|
2408
|
+
try {
|
|
2409
|
+
const viewport = this.osdViewer.viewport;
|
|
2410
|
+
viewport.zoomBy(1.2);
|
|
2411
|
+
viewport.applyConstraints();
|
|
2412
|
+
this.ngZone.run(() => {
|
|
2413
|
+
const homeZoom = viewport.getHomeZoom();
|
|
2414
|
+
const currentZoom = viewport.getZoom();
|
|
2415
|
+
this.zoomLevel.set(currentZoom / homeZoom);
|
|
2416
|
+
});
|
|
2417
|
+
}
|
|
2418
|
+
catch (e) {
|
|
2419
|
+
// Fallback to manual zoom
|
|
2420
|
+
this.ngZone.run(() => {
|
|
2421
|
+
this.zoomLevel.update((z) => Math.min(z + 0.5, 5));
|
|
2422
|
+
});
|
|
2423
|
+
}
|
|
2424
|
+
});
|
|
2425
|
+
return;
|
|
2426
|
+
}
|
|
2427
|
+
this.zoomLevel.update((z) => Math.min(z + 0.5, 5));
|
|
2428
|
+
}
|
|
2429
|
+
zoomOut() {
|
|
2430
|
+
if (this.osdViewer) {
|
|
2431
|
+
this.ngZone.runOutsideAngular(() => {
|
|
2432
|
+
try {
|
|
2433
|
+
const viewport = this.osdViewer.viewport;
|
|
2434
|
+
viewport.zoomBy(1 / 1.2);
|
|
2435
|
+
viewport.applyConstraints();
|
|
2436
|
+
this.ngZone.run(() => {
|
|
2437
|
+
const homeZoom = viewport.getHomeZoom();
|
|
2438
|
+
const currentZoom = viewport.getZoom();
|
|
2439
|
+
this.zoomLevel.set(currentZoom / homeZoom);
|
|
2440
|
+
});
|
|
2441
|
+
}
|
|
2442
|
+
catch (e) {
|
|
2443
|
+
// Fallback to manual zoom
|
|
2444
|
+
this.ngZone.run(() => {
|
|
2445
|
+
this.zoomLevel.update((z) => Math.max(z - 0.5, 0.5));
|
|
2446
|
+
});
|
|
2447
|
+
}
|
|
2448
|
+
});
|
|
2449
|
+
return;
|
|
2450
|
+
}
|
|
2451
|
+
this.zoomLevel.update((z) => Math.max(z - 0.5, 0.5));
|
|
2452
|
+
}
|
|
2453
|
+
resetZoom() {
|
|
2454
|
+
this.rotation.set(0);
|
|
2455
|
+
if (this.osdViewer) {
|
|
2456
|
+
this.ngZone.runOutsideAngular(() => {
|
|
2457
|
+
try {
|
|
2458
|
+
const viewport = this.osdViewer.viewport;
|
|
2459
|
+
// First reset rotation, then go home - order matters!
|
|
2460
|
+
viewport.setRotation(0);
|
|
2461
|
+
viewport.applyConstraints();
|
|
2462
|
+
viewport.goHome(true);
|
|
2463
|
+
viewport.applyConstraints();
|
|
2464
|
+
this.ngZone.run(() => {
|
|
2465
|
+
this.zoomLevel.set(1); // Home = 100%
|
|
2466
|
+
});
|
|
2467
|
+
}
|
|
2468
|
+
catch (e) {
|
|
2469
|
+
// Fallback to manual reset
|
|
2470
|
+
this.ngZone.run(() => {
|
|
2471
|
+
this.zoomLevel.set(1);
|
|
2472
|
+
this.imageTransform.set({ x: 0, y: 0 });
|
|
2473
|
+
});
|
|
2474
|
+
}
|
|
2475
|
+
});
|
|
2476
|
+
return;
|
|
2477
|
+
}
|
|
2478
|
+
this.zoomLevel.set(1);
|
|
2479
|
+
this.imageTransform.set({ x: 0, y: 0 });
|
|
2480
|
+
}
|
|
2481
|
+
async downloadImage() {
|
|
2482
|
+
const item = this.fullscreenItem();
|
|
2483
|
+
if (!item?.image)
|
|
2484
|
+
return;
|
|
2485
|
+
const url = this.fileUrlService.get(item.image, 'noCache');
|
|
2486
|
+
const filename = `${item.image.id || 'image'}.${item.image.extension || 'jpg'}`;
|
|
2487
|
+
try {
|
|
2488
|
+
const response = await fetch(url);
|
|
2489
|
+
const blob = await response.blob();
|
|
2490
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
2491
|
+
const link = this.document.createElement('a');
|
|
2492
|
+
link.href = blobUrl;
|
|
2493
|
+
link.download = filename;
|
|
2494
|
+
link.click();
|
|
2495
|
+
URL.revokeObjectURL(blobUrl);
|
|
2496
|
+
}
|
|
2497
|
+
catch (error) {
|
|
2498
|
+
console.error('Failed to download image:', error);
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
async loadOsdImage(image) {
|
|
2502
|
+
if (!this.osdViewer)
|
|
2503
|
+
return;
|
|
2504
|
+
const url = this.fileUrlService.get(image, 'noCache');
|
|
2505
|
+
this.ngZone.runOutsideAngular(() => {
|
|
2506
|
+
try {
|
|
2507
|
+
// Close any existing image
|
|
2508
|
+
try {
|
|
2509
|
+
this.osdViewer.close();
|
|
2510
|
+
}
|
|
2511
|
+
catch (e) {
|
|
2512
|
+
// Ignore errors
|
|
2513
|
+
}
|
|
2514
|
+
// Open the new image
|
|
2515
|
+
this.osdViewer.open({
|
|
2516
|
+
type: 'image',
|
|
2517
|
+
url: url,
|
|
2518
|
+
});
|
|
2519
|
+
}
|
|
2520
|
+
catch (error) {
|
|
2521
|
+
console.error('Failed to load image in OpenSeadragon:', error);
|
|
2522
|
+
this.ngZone.run(() => {
|
|
2523
|
+
this.stopLoading();
|
|
2524
|
+
});
|
|
2525
|
+
}
|
|
2526
|
+
});
|
|
2527
|
+
}
|
|
2528
|
+
getDistance(touch1, touch2) {
|
|
2529
|
+
const dx = touch1.clientX - touch2.clientX;
|
|
2530
|
+
const dy = touch1.clientY - touch2.clientY;
|
|
2531
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
2532
|
+
}
|
|
2533
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.0", ngImport: i0, type: GalleryFullscreenBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2534
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.0", type: GalleryFullscreenBaseComponent, isStandalone: true, inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, alt: { classPropertyName: "alt", publicName: "alt", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, selectedIndex: { classPropertyName: "selectedIndex", publicName: "selectedIndex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedIndex: "selectedIndexChange", closeChange: "closeChange" }, host: { listeners: { "document:keydown": "handleKeyboardEvent($event)", "mousedown": "handleMouseDown($event)", "mousemove": "handleMouseMove($event)", "mouseup": "handleMouseUp()" } }, ngImport: i0 }); }
|
|
2535
|
+
}
|
|
2536
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.0", ngImport: i0, type: GalleryFullscreenBaseComponent, decorators: [{
|
|
2537
|
+
type: Directive,
|
|
2538
|
+
args: [{
|
|
2539
|
+
host: {
|
|
2540
|
+
'(document:keydown)': 'handleKeyboardEvent($event)',
|
|
2541
|
+
'(mousedown)': 'handleMouseDown($event)',
|
|
2542
|
+
'(mousemove)': 'handleMouseMove($event)',
|
|
2543
|
+
'(mouseup)': 'handleMouseUp()',
|
|
2544
|
+
},
|
|
2545
|
+
}]
|
|
2546
|
+
}], ctorParameters: () => [] });
|
|
2547
|
+
|
|
1748
2548
|
class FooterComponent {
|
|
1749
2549
|
constructor() {
|
|
1750
2550
|
this.configsFacade = inject(ConfigsFacade);
|
|
@@ -2545,5 +3345,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.0", ngImpor
|
|
|
2545
3345
|
* Generated bundle index. Do not edit.
|
|
2546
3346
|
*/
|
|
2547
3347
|
|
|
2548
|
-
export { ARTICLES_WIDGET_COMPONENTS_TOKEN, AppComponent, AuthStorageService, COMPONENTS, ClickOutsideDirective, ConfigsFacade, ConfigsService, ContrastService, CrudBaseService, DIRECTIVES, DictionaryService, FileUrlService, FiltersBaseComponent, FiltersContext, FooterComponent, GameType, GlobalService, HeaderComponent, HomeComponent, HoverDirective, ImageBox, ListMode, MasonryGridComponent, MenuComponent, MetaService, ModalContainerComponent, ModalRef, ModalService, NotFoundComponent, PageComponent, PageStaticComponent, QueryFilterService, SEARCH_CONFIG_TOKEN, SERVICES, ScrollTopComponent, ScrollableDirective, SearchService, SeoService, SettingsService, SharedConfig, SharedModule, StyleService, TRANSLATE_DATA_PL, TranslationService, WcagService, WidgetBaseComponent, WidgetComponent, WidgetTextComponent, authenticationGuard, environment, getSearchFilterQuery, setTranslationsAndLang, unauthorizedGuard };
|
|
3348
|
+
export { ARTICLES_WIDGET_COMPONENTS_TOKEN, AppComponent, AuthStorageService, COMPONENTS, ClickOutsideDirective, ConfigsFacade, ConfigsService, ContrastService, CrudBaseService, DIRECTIVES, DictionaryService, FileUrlService, FiltersBaseComponent, FiltersContext, FooterComponent, GalleryFullscreenBaseComponent, GameType, GlobalService, HeaderComponent, HomeComponent, HoverDirective, ImageBox, ListMode, MasonryGridComponent, MediaTabBaseComponent, MenuComponent, MetaService, ModalContainerComponent, ModalRef, ModalService, NotFoundComponent, PageComponent, PageStaticComponent, QueryFilterService, SEARCH_CONFIG_TOKEN, SERVICES, ScrollTopComponent, ScrollableDirective, SearchBaseComponent, SearchService, SeoService, SettingsService, SharedConfig, SharedModule, SliderBaseComponent, StyleService, TRANSLATE_DATA_PL, TranslationService, WcagService, WidgetBaseComponent, WidgetComponent, WidgetTextComponent, authenticationGuard, environment, getSearchFilterQuery, setTranslationsAndLang, unauthorizedGuard };
|
|
2549
3349
|
//# sourceMappingURL=smartsoft001-mobilems-angular.mjs.map
|