全部產品
Search
文件中心

Cloud Phone:通過Web SDK在Safari瀏覽器實現粘貼

更新時間:Dec 10, 2025

由於Safari存在安全限制,訪問剪貼簿內容時會彈出粘貼氣泡按鈕,影響將用戶端剪貼簿內容同步至雲手機剪貼簿的體驗。本文介紹如何通過Web SDK實現將本地複製的文本粘貼至Safari瀏覽器。

方案概述

  1. 在本地用戶端添加剪貼簿按鈕,點擊剪貼簿按鈕,彈出氣泡輸入框。

  2. 將用戶端中需要發送至雲手機的內容輸入至氣泡輸入框。

  3. 點擊氣泡輸入框中的立即粘貼按鈕,將內容同步至雲手機的剪貼簿和輸入框。

實現步驟

雲手機參數配置

  • 配置readClipboardDataByUser開啟,無需SDK自行讀取剪貼簿。

  • 配置useCustomIme開啟本地IME,將內容同步到雲機輸入框需要開啟本地IME。

//是否是Safari
function isSafari() {
    return /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
}
//主控配置 禁止SDK自行讀取剪貼簿和開啟本地IME
connConfig = {..., readClipboardDataByUser:isSafari(), useCustomIme:true}; 
var appInfo = {
  ...,
  connConfig: connConfig,
  ...
};
var sessionParam = {
  ...,
  appInfo: appInfo,
  ....
};
var wuyingSdk = Wuying.WebSDK;
session = wuyingSdk.createSession('appstream', sessionParam);
//縮圖配置 開啟本地IME
this.thumbnail = new window.Wuying.ThumbnailSDK({
  ...,
  connectionConfig: {
    useCustomIme: true,
  },
},
{
  onConnected: (data) => {
    this.thumbnail.session.getLocalConfig().setClipboardEnabled(true);
  },
  onDisConnected: (data) => {},
  onThumbnailData: (url) => {},
}
);

構建氣泡輸入框

在用戶端構建剪貼簿按鈕,並通過點擊按鈕喚出支援與剪貼簿互動的對話方塊。可參考如下代碼:

function showInput() {
  showCustomDialog();
  // 點擊遮罩層關閉彈框
  document.querySelector('.modal-overlay').addEventListener('click', function (e) {
      if (e.target === this) {
          closeModal();
      }
  });

  // ESC鍵關閉彈框
  document.addEventListener('keydown', function (e) {
      if (e.key === 'Escape') {
          closeModal();
      }
  });
}

function closeModal() {
  console.log('closeModal');
  const overlay = document.querySelector('.modal-overlay');
  if (overlay) {
      overlay.style.display = 'none';
      overlay.remove();
  }
}

function submitContent() {
  const content = document.querySelector('.input-field').value.trim();
  if (!content) {
      alert('請輸入內容');
      return;
  }
  //同步內容到雲機
  sendMsgToCloudPhoneOperation(content);
  closeModal();
}

function showCustomDialog() {
  // 建立模態框背景
  const overlay = document.createElement('div');
  overlay.className = 'modal-overlay';
  // Ensure the modal captures all events and is displayed at the highest level
  overlay.style.pointerEvents = 'all';
  overlay.style.zIndex = '9999';
  
  // Prevent events from propagating to underlying layers
  const stopPropagation = function(e) {
      e.stopPropagation();
  };
  
  overlay.addEventListener('contextmenu', stopPropagation, true);
  
  // Add event listeners to intercept all keyboard events
  overlay.addEventListener('keydown', stopPropagation, true);
  overlay.addEventListener('keyup', stopPropagation, true);
  overlay.addEventListener('keypress', stopPropagation, true);
  
  overlay.innerHTML = `
      <div class="modal">
          <div class="modal-header">
              <h2 class="modal-title">剪貼簿</h2>
              <button class="close-btn" onclick="closeModal()">×</button>
          </div>
          
          <div class="input-container">
              <textarea 
                  class="input-field" 
                  placeholder="請輸入內容"
                  maxlength="500"
              ></textarea>
          </div>
          
          <button class="submit-btn" onclick="submitContent()">
              立即粘貼
          </button>
      </div>
  `;

  document.body.appendChild(overlay);
  
  // Focus the textarea when the modal opens to ensure keyboard events are captured
  setTimeout(() => {
      const textarea = overlay.querySelector('.input-field');
      if (textarea) {
          textarea.focus();
      }
  }, 100);
}

將複製的文本發送至雲手機

觸發同步任務

function submitContent() {
  const content = document.querySelector('.input-field').value.trim();
  if (!content) {
      alert('請輸入內容');
      return;
  }
  //同步內容到雲機
  sendMsgToCloudPhoneOperation(content);
  closeModal();
}

將內容同步至雲手機

function sendMsgToCloudPhoneOperation(msg) {
  //主控
  if (session) {
    session.setClipboardModule('sendClipboardDataToRemote', msg) 
  }
  //縮圖
  for (const [key, value] of thumbnailSDKMap) {
      console.log('thumbnial sendMsgToCloudPhoneOperation ', key, msg);
      value.thumbnail.session.getClipboardModule().sendClipboardDataToRemote(msg);
  }
}

注意事項

新建立的對話方塊需要完全接管鍵盤事件,避免鍵盤事件被其他案頭元素接管,否則普通按鍵資訊無法在對話方塊中正確響應。配置參考如下:

overlay.addEventListener('contextmenu', stopPropagation, true);

// Add event listeners to intercept all keyboard events
overlay.addEventListener('keydown', stopPropagation, true);
overlay.addEventListener('keyup', stopPropagation, true);
overlay.addEventListener('keypress', stopPropagation, true);