@servicemind.tis/tis-image-and-file-upload-and-view 1.2.24 → 1.2.25

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.
@@ -596,22 +596,27 @@ class TisRemoteUploadService {
596
596
  // Mobile Communication
597
597
  // ===========================================================================
598
598
  /**
599
- * Send message to mobile device
599
+ * Send message to mobile device via channel
600
600
  */
601
601
  sendToMobile(type, data) {
602
602
  if (!this.socketAdapter?.sendViaSocket) {
603
603
  console.warn(`[${TisRemoteUploadService.COMPONENT}] sendViaSocket not available`);
604
604
  return;
605
605
  }
606
- this.socketAdapter.sendViaSocket({
607
- action: this.channelName,
606
+ const message = {
607
+ action: 'send-to-channel',
608
608
  data: {
609
- type,
610
- ...data,
611
- desktopDeviceId: this.deviceId,
612
- timestamp: Date.now()
609
+ channel: this.channelName,
610
+ payload: {
611
+ type,
612
+ ...data,
613
+ desktopDeviceId: this.deviceId,
614
+ timestamp: Date.now()
615
+ }
613
616
  }
614
- });
617
+ };
618
+ console.log(`[${TisRemoteUploadService.COMPONENT}] Sending to mobile:`, message);
619
+ this.socketAdapter.sendViaSocket(message);
615
620
  }
616
621
  /**
617
622
  * Accept mobile connection (send SUCCESS response)
@@ -643,18 +648,61 @@ class TisRemoteUploadService {
643
648
  this.sendToMobile('connectionState', { state: 'SUCCESS' });
644
649
  }
645
650
  /**
646
- * Disconnect from mobile device
651
+ * Disconnect from mobile device - call API and clear local state
647
652
  */
648
- disconnect() {
653
+ async disconnect() {
649
654
  console.log(`[${TisRemoteUploadService.COMPONENT}] Disconnecting from mobile...`);
650
- // Notify mobile
651
- this.sendToMobile('connectionState', { state: 'DISCONNECTED' });
655
+ const mobileDeviceId = this.mobileConnection$.value?.mobileDeviceId;
656
+ // Call disconnect API via socket
657
+ if (this.socketAdapter?.callApiViaSocket && mobileDeviceId) {
658
+ try {
659
+ const callApi = this.socketAdapter.callApiViaSocket.bind(this.socketAdapter);
660
+ const response = await new Promise((resolve, reject) => {
661
+ const timeout = setTimeout(() => reject(new Error('Disconnect API timeout')), 10000);
662
+ callApi('tis-image-mobile-uploader/disconnect-mobile-link', {
663
+ desktopDeviceId: this.deviceId,
664
+ mobileDeviceId: mobileDeviceId,
665
+ initiatedBy: 'desktop'
666
+ }).pipe(take(1)).subscribe({
667
+ next: (res) => {
668
+ clearTimeout(timeout);
669
+ resolve(res);
670
+ },
671
+ error: (err) => {
672
+ clearTimeout(timeout);
673
+ reject(err);
674
+ }
675
+ });
676
+ });
677
+ console.log(`[${TisRemoteUploadService.COMPONENT}] Disconnect API response:`, response);
678
+ }
679
+ catch (error) {
680
+ console.warn(`[${TisRemoteUploadService.COMPONENT}] Disconnect API call failed:`, error);
681
+ // Continue with local cleanup anyway
682
+ }
683
+ }
684
+ // Notify mobile via channel (backup notification)
685
+ this.sendToMobile('mobile-link-disconnected', {
686
+ desktopDeviceId: this.deviceId,
687
+ initiatedBy: 'desktop'
688
+ });
652
689
  // Clear state
653
690
  this.mobileConnection$.next(null);
654
691
  this.connectionStatus$.next('disconnected');
655
692
  this.pairingSession$.next(null);
656
693
  this.clearMobileConnection();
657
694
  }
695
+ /**
696
+ * Handle disconnect initiated from remote (mobile) side
697
+ */
698
+ handleRemoteDisconnect(data) {
699
+ console.log(`[${TisRemoteUploadService.COMPONENT}] Mobile disconnected:`, data);
700
+ // Clear state without calling API (mobile already initiated)
701
+ this.mobileConnection$.next(null);
702
+ this.connectionStatus$.next('disconnected');
703
+ this.pairingSession$.next(null);
704
+ this.clearMobileConnection();
705
+ }
658
706
  // ===========================================================================
659
707
  // Channel Subscription & Message Handling
660
708
  // ===========================================================================
@@ -684,18 +732,23 @@ class TisRemoteUploadService {
684
732
  */
685
733
  handleChannelMessage(message) {
686
734
  console.log(`[${TisRemoteUploadService.COMPONENT}] Received:`, message);
687
- // Extract message type and data
688
- const type = message.type || message.data?.type;
689
- const data = message.data || message.payload || message;
735
+ // Extract message type and data - handle nested payload structure
736
+ const payload = message.payload || message.data || message;
737
+ const type = payload.type || message.type;
738
+ const data = payload;
690
739
  switch (type) {
691
740
  case 'connectionState':
692
741
  this.handleConnectionState(data);
693
742
  break;
743
+ case 'mobile-link-established':
744
+ this.handleMobileLinkEstablished(data);
745
+ break;
694
746
  case 'image-uploaded':
695
747
  case 'upload_complete':
696
748
  this.handleUploadComplete(message);
697
749
  break;
698
750
  case 'disconnect':
751
+ case 'mobile-link-disconnected':
699
752
  this.handleMobileDisconnect(data);
700
753
  break;
701
754
  default:
@@ -708,6 +761,50 @@ class TisRemoteUploadService {
708
761
  }
709
762
  }
710
763
  }
764
+ /**
765
+ * Handle mobile-link-established message
766
+ * This is sent when mobile successfully connects via the backend
767
+ */
768
+ handleMobileLinkEstablished(data) {
769
+ const mobileDeviceId = data.mobileDeviceId;
770
+ const mobileConnectionId = data.mobileConnectionId;
771
+ const userId = data.userId;
772
+ console.log(`[${TisRemoteUploadService.COMPONENT}] Mobile link established:`, {
773
+ mobileDeviceId,
774
+ mobileConnectionId,
775
+ userId
776
+ });
777
+ if (mobileDeviceId) {
778
+ // Save mobile connection
779
+ const connectionInfo = {
780
+ mobileDeviceId,
781
+ connectedAt: Date.now(),
782
+ lastActivity: Date.now()
783
+ };
784
+ this.mobileConnection$.next(connectionInfo);
785
+ this.saveMobileConnection(connectionInfo);
786
+ // Update status to connected
787
+ this.connectionStatus$.next('connected');
788
+ // Update session
789
+ const session = this.pairingSession$.value;
790
+ if (session) {
791
+ const updatedSession = {
792
+ ...session,
793
+ mobileDeviceId,
794
+ status: 'connected',
795
+ lastActivity: Date.now()
796
+ };
797
+ this.pairingSession$.next(updatedSession);
798
+ }
799
+ // Send SUCCESS acknowledgment to mobile
800
+ this.sendToMobile('connectionState', {
801
+ state: 'SUCCESS',
802
+ desktopDeviceId: this.deviceId,
803
+ mobileConnectionId
804
+ });
805
+ console.log(`[${TisRemoteUploadService.COMPONENT}] Connection established with mobile device:`, mobileDeviceId);
806
+ }
807
+ }
711
808
  /**
712
809
  * Handle connection state messages from mobile
713
810
  */
@@ -892,6 +989,10 @@ class TisQrCodeDialogComponent {
892
989
  this.isConnected = true;
893
990
  this.connectionStatus = 'connected';
894
991
  this.isLoading = false;
992
+ // Send field info to mobile since already connected
993
+ if (this.data.fieldInfo) {
994
+ this.sendFieldInfoToMobile();
995
+ }
895
996
  }
896
997
  else {
897
998
  // No existing connection, generate QR code
@@ -920,7 +1021,12 @@ class TisQrCodeDialogComponent {
920
1021
  .pipe(takeUntil(this.destroy$))
921
1022
  .subscribe(status => {
922
1023
  this.connectionStatus = status;
1024
+ const wasConnected = this.isConnected;
923
1025
  this.isConnected = status === 'connected';
1026
+ // Send field info when first connected
1027
+ if (!wasConnected && this.isConnected && this.data.fieldInfo) {
1028
+ this.sendFieldInfoToMobile();
1029
+ }
924
1030
  });
925
1031
  // Mobile connection changes
926
1032
  this.remoteUploadService.getMobileConnection()
@@ -944,6 +1050,15 @@ class TisQrCodeDialogComponent {
944
1050
  console.error('[TisQrCodeDialog] Error:', error);
945
1051
  });
946
1052
  }
1053
+ /**
1054
+ * Send field configuration to mobile device
1055
+ */
1056
+ sendFieldInfoToMobile() {
1057
+ if (!this.data.fieldInfo)
1058
+ return;
1059
+ console.log('[TisQrCodeDialog] Sending field info to mobile:', this.data.fieldInfo);
1060
+ this.remoteUploadService.sendToMobile('field-info', this.data.fieldInfo);
1061
+ }
947
1062
  startCountdown() {
948
1063
  if (this.countdownSubscription) {
949
1064
  this.countdownSubscription.unsubscribe();
@@ -2615,7 +2730,17 @@ class TisImageAndFileUploadAndViewComponent {
2615
2730
  subtitle: `Scan this QR code to upload ${this.type === 'image' ? 'images' : 'files'} from your mobile device`,
2616
2731
  qrSize: 200,
2617
2732
  showCountdown: true,
2618
- autoCloseOnUpload: false
2733
+ autoCloseOnUpload: false,
2734
+ fieldInfo: {
2735
+ label: this.label || `${this.type === 'image' ? 'Images' : 'Files'}`,
2736
+ accept: this.accept || (this.type === 'image' ? 'image/*' : '*'),
2737
+ type: this.type,
2738
+ entityType: this.entityType,
2739
+ entityId: this.entityId,
2740
+ isMultiple: this.config.isMultiple,
2741
+ limit: this.config.limit,
2742
+ isCompressed: this.config.isCompressed
2743
+ }
2619
2744
  };
2620
2745
  const dialogRef = this.dialog.open(TisQrCodeDialogComponent, {
2621
2746
  width: this.isMobile ? '100%' : '420px',