সাধারণ বিজ্ঞপ্তি নিদর্শন

আমরা ওয়েব পুশের জন্য কিছু সাধারণ বাস্তবায়ন নিদর্শন দেখতে যাচ্ছি।

এটি পরিষেবা কর্মীর মধ্যে উপলব্ধ কয়েকটি ভিন্ন API ব্যবহার করা জড়িত।

বিজ্ঞপ্তি বন্ধ ইভেন্ট

শেষ বিভাগে আমরা দেখেছি কিভাবে আমরা notificationclick ইভেন্ট শুনতে পারি।

এছাড়াও একটি notificationclose ইভেন্ট রয়েছে যা বলা হয় যদি ব্যবহারকারী আপনার একটি বিজ্ঞপ্তি খারিজ করে দেয় (অর্থাৎ বিজ্ঞপ্তিতে ক্লিক করার পরিবর্তে, ব্যবহারকারী ক্রস ক্লিক করে বা বিজ্ঞপ্তিটি সোয়াইপ করে)।

এই ইভেন্টটি সাধারণত বিজ্ঞপ্তির সাথে ব্যবহারকারীর ব্যস্ততা ট্র্যাক করতে বিশ্লেষণের জন্য ব্যবহৃত হয়।

self.addEventListener('notificationclose', function (event) {
  const dismissedNotification = event.notification;

  const promiseChain = notificationCloseAnalytics();
  event.waitUntil(promiseChain);
});

একটি বিজ্ঞপ্তিতে ডেটা যোগ করা হচ্ছে

যখন একটি পুশ বার্তা প্রাপ্ত হয় তখন সাধারণ তথ্য থাকে যা শুধুমাত্র ব্যবহারকারীর বিজ্ঞপ্তিতে ক্লিক করলেই উপযোগী। উদাহরণস্বরূপ, একটি বিজ্ঞপ্তি ক্লিক করা হলে যে URLটি খোলা উচিত।

একটি পুশ ইভেন্ট থেকে ডেটা নেওয়া এবং এটিকে একটি বিজ্ঞপ্তিতে সংযুক্ত করার সবচেয়ে সহজ উপায় হল showNotification() এ পাস করা অপশন অবজেক্টে একটি data প্যারামিটার যুক্ত করা, যেমন:

const options = {
  body:
    'This notification has data attached to it that is printed ' +
    "to the console when it's clicked.",
  tag: 'data-notification',
  data: {
    time: new Date(Date.now()).toString(),
    message: 'Hello, World!',
  },
};
registration.showNotification('Notification with Data', options);

একটি ক্লিক হ্যান্ডলারের ভিতরে, event.notification.data দিয়ে ডেটা অ্যাক্সেস করা যেতে পারে।

const notificationData = event.notification.data;
console.log('');
console.log('The notification data has the following parameters:');
Object.keys(notificationData).forEach((key) => {
  console.log(`  ${key}: ${notificationData[key]}`);
});
console.log('');

একটি জানালা খুলুন

একটি বিজ্ঞপ্তির সবচেয়ে সাধারণ প্রতিক্রিয়াগুলির মধ্যে একটি হল একটি নির্দিষ্ট URL-এ একটি উইন্ডো/ট্যাব খোলা। আমরা clients.openWindow() API দিয়ে এটি করতে পারি।

আমাদের notificationclick ইভেন্টে, আমরা এইরকম কিছু কোড চালাব:

const examplePage = '/demos/notification-examples/example-page.html';
const promiseChain = clients.openWindow(examplePage);
event.waitUntil(promiseChain);

পরবর্তী বিভাগে, আমরা ব্যবহারকারীকে যে পৃষ্ঠাটিতে নির্দেশ দিতে চাই সেটি ইতিমধ্যে খোলা আছে কিনা তা কীভাবে পরীক্ষা করা যায় তা দেখব। এইভাবে, আমরা নতুন ট্যাব খোলার পরিবর্তে খোলা ট্যাবে ফোকাস করতে পারি।

একটি বিদ্যমান উইন্ডো ফোকাস করুন

যখন এটি সম্ভব হয়, ব্যবহারকারী যখনই একটি বিজ্ঞপ্তিতে ক্লিক করেন তখন একটি নতুন উইন্ডো খোলার পরিবর্তে আমাদের একটি উইন্ডোতে ফোকাস করা উচিত।

এটি কীভাবে অর্জন করা যায় তা দেখার আগে, এটি হাইলাইট করা মূল্যবান যে এটি শুধুমাত্র আপনার মূল পৃষ্ঠাগুলির জন্যই সম্ভব ৷ এর কারণ হল আমরা শুধুমাত্র আমাদের সাইটের কোন পৃষ্ঠাগুলি খোলা আছে তা দেখতে পারি। এটি বিকাশকারীদের তাদের ব্যবহারকারীরা যে সমস্ত সাইট দেখছে তা দেখতে সক্ষম হতে বাধা দেয়৷

পূর্ববর্তী উদাহরণটি গ্রহণ করে, /demos/notification-examples/example-page.html ইতিমধ্যে খোলা আছে কিনা তা দেখতে আমরা কোডটি পরিবর্তন করব।

const urlToOpen = new URL(examplePage, self.location.origin).href;

const promiseChain = clients
  .matchAll({
    type: 'window',
    includeUncontrolled: true,
  })
  .then((windowClients) => {
    let matchingClient = null;

    for (let i = 0; i < windowClients.length; i++) {
      const windowClient = windowClients[i];
      if (windowClient.url === urlToOpen) {
        matchingClient = windowClient;
        break;
      }
    }

    if (matchingClient) {
      return matchingClient.focus();
    } else {
      return clients.openWindow(urlToOpen);
    }
  });

event.waitUntil(promiseChain);

এর কোড মাধ্যমে পদক্ষেপ করা যাক.

প্রথমে আমরা URL API ব্যবহার করে আমাদের উদাহরণ পৃষ্ঠা পার্স করি। এটি একটি ঝরঝরে কৌশল যা আমি জেফ পসনিক থেকে তুলেছি। location অবজেক্টের সাথে new URL() কল করলে স্ট্রিংটি আপেক্ষিক হলে একটি পরম URL প্রদান করবে (যেমন / https://example.com/ হয়ে যাবে)।

আমরা ইউআরএলটিকে পরম করি যাতে আমরা পরবর্তীতে উইন্ডো ইউআরএলের সাথে এটিকে মেলাতে পারি।

const urlToOpen = new URL(examplePage, self.location.origin).href;

তারপরে আমরা WindowClient অবজেক্টের একটি তালিকা পাই, যা বর্তমানে খোলা ট্যাব এবং উইন্ডোগুলির তালিকা। (মনে রাখবেন এইগুলি শুধুমাত্র আপনার মূলের জন্য ট্যাব।)

const promiseChain = clients.matchAll({
  type: 'window',
  includeUncontrolled: true,
});

matchAll মধ্যে পাস করা বিকল্পগুলি সমস্ত ব্রাউজারকে জানায় যে আমরা শুধুমাত্র "উইন্ডো" টাইপ ক্লায়েন্টদের জন্য অনুসন্ধান করতে চাই (অর্থাৎ শুধুমাত্র ট্যাব এবং উইন্ডোগুলির সন্ধান করুন এবং ওয়েব কর্মীদের বাদ দিন)। includeUncontrolled আমাদের আপনার মূল থেকে সমস্ত ট্যাব অনুসন্ধান করতে দেয় যা বর্তমান পরিষেবা কর্মী দ্বারা নিয়ন্ত্রিত নয়, অর্থাৎ এই কোডটি চালাচ্ছেন পরিষেবা কর্মী৷ সাধারনত, matchAll() কল করার সময় আপনি সর্বদা includeUncontrolled সত্য হতে চান।

আমরা প্রত্যাবর্তিত প্রতিশ্রুতিটিকে promiseChain হিসাবে ক্যাপচার করি যাতে আমরা আমাদের পরিষেবা কর্মীকে জীবিত রেখে পরবর্তীতে এটিকে event.waitUntil() এ পাস করতে পারি।

যখন matchAll() প্রতিশ্রুতি সমাধান হয়ে যায়, তখন আমরা ফিরে আসা উইন্ডো ক্লায়েন্টের মাধ্যমে পুনরাবৃত্তি করি এবং তাদের URL গুলিকে আমরা যে URL খুলতে চাই তার সাথে তুলনা করি। যদি আমরা একটি মিল খুঁজে পাই, আমরা সেই ক্লায়েন্টকে ফোকাস করি, যা সেই উইন্ডোটিকে ব্যবহারকারীদের দৃষ্টি আকর্ষণ করবে। matchingClient.focus() কল দিয়ে ফোকাস করা হয়।

যদি আমরা একটি মিলিত ক্লায়েন্ট খুঁজে না পাই, আমরা একটি নতুন উইন্ডো খুলি, যেমনটি পূর্ববর্তী বিভাগে ছিল।

.then((windowClients) => {
  let matchingClient = null;

  for (let i = 0; i < windowClients.length; i++) {
    const windowClient = windowClients[i];
    if (windowClient.url === urlToOpen) {
      matchingClient = windowClient;
      break;
    }
  }

  if (matchingClient) {
    return matchingClient.focus();
  } else {
    return clients.openWindow(urlToOpen);
  }
});

বিজ্ঞপ্তি একত্রিত করা

আমরা দেখেছি যে একটি বিজ্ঞপ্তিতে একটি ট্যাগ যুক্ত করা এমন একটি আচরণে অপ্ট ইন করে যেখানে একই ট্যাগ সহ বিদ্যমান কোনো বিজ্ঞপ্তি প্রতিস্থাপিত হয়।

তবে আপনি বিজ্ঞপ্তি API ব্যবহার করে বিজ্ঞপ্তিগুলি ভেঙে যাওয়ার সাথে আরও পরিশীলিত হতে পারেন। একটি চ্যাট অ্যাপ বিবেচনা করুন, যেখানে ডেভেলপার সাম্প্রতিক বার্তা দেখানোর পরিবর্তে "আপনার কাছে ম্যাট থেকে দুটি বার্তা আছে" এর মতো একটি বার্তা দেখানোর জন্য একটি নতুন বিজ্ঞপ্তি চাইতে পারে।

আপনি এটি করতে পারেন, বা registration.getNotifications() API ব্যবহার করে অন্য উপায়ে বর্তমান বিজ্ঞপ্তিগুলিকে ম্যানিপুলেট করতে পারেন যা আপনাকে আপনার ওয়েব অ্যাপের জন্য বর্তমানে দৃশ্যমান সমস্ত বিজ্ঞপ্তিগুলিতে অ্যাক্সেস দেয়৷

চ্যাট উদাহরণ বাস্তবায়নের জন্য আমরা কিভাবে এই API ব্যবহার করতে পারি তা দেখুন।

আমাদের চ্যাট অ্যাপে, ধরা যাক প্রতিটি বিজ্ঞপ্তিতে কিছু ডেটা রয়েছে যার মধ্যে একটি ব্যবহারকারীর নাম রয়েছে।

প্রথম জিনিস যা আমরা করতে চাই তা হল একটি নির্দিষ্ট ব্যবহারকারীর নাম সহ ব্যবহারকারীর জন্য কোনো খোলা বিজ্ঞপ্তি খুঁজে বের করা। আমরা registration.getNotifications() পাব এবং সেগুলি লুপ করব এবং একটি নির্দিষ্ট ব্যবহারকারীর নামের জন্য notification.data চেক করব:

const promiseChain = registration.getNotifications().then((notifications) => {
  let currentNotification;

  for (let i = 0; i < notifications.length; i++) {
    if (notifications[i].data && notifications[i].data.userName === userName) {
      currentNotification = notifications[i];
    }
  }

  return currentNotification;
});

পরবর্তী ধাপ হল এই বিজ্ঞপ্তিটিকে একটি নতুন বিজ্ঞপ্তি দিয়ে প্রতিস্থাপন করা।

এই জাল বার্তা অ্যাপটিতে, আমরা আমাদের নতুন বিজ্ঞপ্তির ডেটাতে একটি গণনা যোগ করে নতুন বার্তাগুলির সংখ্যা ট্র্যাক করব এবং প্রতিটি নতুন বিজ্ঞপ্তির সাথে এটি বৃদ্ধি করব।

.then((currentNotification) => {
  let notificationTitle;
  const options = {
    icon: userIcon,
  }

  if (currentNotification) {
    // We have an open notification, let's do something with it.
    const messageCount = currentNotification.data.newMessageCount + 1;

    options.body = `You have ${messageCount} new messages from ${userName}.`;
    options.data = {
      userName: userName,
      newMessageCount: messageCount
    };
    notificationTitle = `New Messages from ${userName}`;

    // Remember to close the old notification.
    currentNotification.close();
  } else {
    options.body = `"${userMessage}"`;
    options.data = {
      userName: userName,
      newMessageCount: 1
    };
    notificationTitle = `New Message from ${userName}`;
  }

  return registration.showNotification(
    notificationTitle,
    options
  );
});

যদি বর্তমানে একটি বিজ্ঞপ্তি প্রদর্শিত হয়, আমরা বার্তার সংখ্যা বৃদ্ধি করি এবং সেই অনুযায়ী বিজ্ঞপ্তির শিরোনাম এবং বডি বার্তা সেট করি। যদি কোন বিজ্ঞপ্তি না থাকে, আমরা 1 এর একটি newMessageCount সহ একটি নতুন বিজ্ঞপ্তি তৈরি করি৷

ফলাফল হল যে প্রথম বার্তাটি দেখতে এইরকম হবে:

মার্জ ছাড়াই প্রথম বিজ্ঞপ্তি।

একটি দ্বিতীয় বিজ্ঞপ্তি এতে বিজ্ঞপ্তিগুলিকে ভেঙে ফেলবে:

মার্জ সহ দ্বিতীয় বিজ্ঞপ্তি।

এই পদ্ধতির সাথে চমৎকার জিনিস হল যে আপনার ব্যবহারকারী যদি একের পর এক প্রদর্শিত বিজ্ঞপ্তিগুলিকে প্রত্যক্ষ করেন তবে এটি কেবলমাত্র সর্বশেষ বার্তার সাথে বিজ্ঞপ্তিটি প্রতিস্থাপন করার চেয়ে আরও বেশি সংহত দেখাবে এবং অনুভব করবে৷

নিয়মের ব্যতিক্রম

আমি বলেছি যে যখন আপনি একটি ধাক্কা পাবেন তখন আপনাকে অবশ্যই একটি বিজ্ঞপ্তি দেখাতে হবে এবং এটি বেশিরভাগ সময় সত্য। একটি দৃশ্য যেখানে আপনাকে একটি বিজ্ঞপ্তি দেখাতে হবে না তা হল যখন ব্যবহারকারী আপনার সাইট খোলা এবং ফোকাস করে।

আপনার পুশ ইভেন্টের ভিতরে, আপনি উইন্ডো ক্লায়েন্ট পরীক্ষা করে এবং একটি ফোকাসড উইন্ডো খোঁজার মাধ্যমে একটি বিজ্ঞপ্তি দেখানোর প্রয়োজন আছে কিনা তা পরীক্ষা করতে পারেন।

সমস্ত উইন্ডো পাওয়ার এবং একটি ফোকাসড উইন্ডো খুঁজতে কোডটি এইরকম দেখাচ্ছে:

function isClientFocused() {
  return clients
    .matchAll({
      type: 'window',
      includeUncontrolled: true,
    })
    .then((windowClients) => {
      let clientIsFocused = false;

      for (let i = 0; i < windowClients.length; i++) {
        const windowClient = windowClients[i];
        if (windowClient.focused) {
          clientIsFocused = true;
          break;
        }
      }

      return clientIsFocused;
    });
}

আমরা আমাদের সমস্ত উইন্ডো ক্লায়েন্ট পেতে clients.matchAll() ব্যবহার করি এবং তারপরে আমরা focused প্যারামিটার চেক করে তাদের লুপ করি।

আমাদের পুশ ইভেন্টের ভিতরে, আমরা একটি বিজ্ঞপ্তি দেখানোর প্রয়োজন কিনা তা সিদ্ধান্ত নিতে এই ফাংশনটি ব্যবহার করব:

const promiseChain = isClientFocused().then((clientIsFocused) => {
  if (clientIsFocused) {
    console.log("Don't need to show a notification.");
    return;
  }

  // Client isn't focused, we need to show a notification.
  return self.registration.showNotification('Had to show a notification.');
});

event.waitUntil(promiseChain);

একটি ধাক্কা ইভেন্ট থেকে একটি পৃষ্ঠা বার্তা

আমরা দেখেছি যে ব্যবহারকারী বর্তমানে আপনার সাইটে থাকলে আপনি একটি বিজ্ঞপ্তি দেখানো এড়িয়ে যেতে পারেন। কিন্তু যদি আপনি এখনও ব্যবহারকারীকে জানাতে চান যে একটি ইভেন্ট ঘটেছে, কিন্তু একটি বিজ্ঞপ্তি খুব ভারী হাতে?

একটি পদ্ধতি হল পরিষেবা কর্মী থেকে পৃষ্ঠায় একটি বার্তা পাঠানো, এইভাবে ওয়েব পৃষ্ঠা ব্যবহারকারীকে একটি বিজ্ঞপ্তি বা একটি আপডেট দেখাতে পারে, তাদের ইভেন্ট সম্পর্কে অবহিত করে৷ এটি এমন পরিস্থিতিতে উপযোগী যখন পৃষ্ঠায় একটি সূক্ষ্ম বিজ্ঞপ্তি ব্যবহারকারীর জন্য আরও ভাল এবং বন্ধুত্বপূর্ণ হয়।

ধরা যাক আমরা একটি পুশ পেয়েছি, চেক করেছি যে আমাদের ওয়েব অ্যাপ বর্তমানে ফোকাস করছে, তারপর আমরা প্রতিটি খোলা পৃষ্ঠায় "একটি বার্তা পোস্ট" করতে পারি, যেমন:

const promiseChain = isClientFocused().then((clientIsFocused) => {
  if (clientIsFocused) {
    windowClients.forEach((windowClient) => {
      windowClient.postMessage({
        message: 'Received a push message.',
        time: new Date().toString(),
      });
    });
  } else {
    return self.registration.showNotification('No focused windows', {
      body: 'Had to show a notification instead of messaging each page.',
    });
  }
});

event.waitUntil(promiseChain);

প্রতিটি পৃষ্ঠায়, আমরা একটি বার্তা ইভেন্ট শ্রোতা যোগ করে বার্তা শুনি:

navigator.serviceWorker.addEventListener('message', function (event) {
  console.log('Received a message from service worker: ', event.data);
});

এই বার্তা শ্রোতার মধ্যে, আপনি যা চান তা করতে পারেন, আপনার পৃষ্ঠায় একটি কাস্টম UI দেখাতে পারেন বা বার্তাটিকে সম্পূর্ণরূপে উপেক্ষা করতে পারেন৷

এটিও লক্ষণীয় যে আপনি যদি আপনার ওয়েব পৃষ্ঠায় একটি বার্তা শ্রোতাকে সংজ্ঞায়িত না করেন তবে পরিষেবা কর্মীর বার্তাগুলি কিছুই করবে না৷

একটি পৃষ্ঠা ক্যাশে এবং একটি উইন্ডো খুলুন

একটি দৃশ্যকল্প যা এই গাইডের সুযোগের বাইরে কিন্তু আলোচনার যোগ্য হল যে আপনি আপনার বিজ্ঞপ্তিতে ক্লিক করার পর ব্যবহারকারীরা যে ওয়েব পৃষ্ঠাগুলি দেখার আশা করেন সেগুলিকে ক্যাশে করে আপনি আপনার ওয়েব অ্যাপের সামগ্রিক UX উন্নত করতে পারেন৷

এর জন্য আপনার পরিষেবা কর্মী সেট আপ করা প্রয়োজন ইভেন্টগুলিকে fetch করার জন্য, কিন্তু আপনি যদি একটি fetch শ্রোতা আনয়ন প্রয়োগ করেন, তাহলে নিশ্চিত করুন যে আপনি আপনার বিজ্ঞপ্তি দেখানোর আগে আপনার প্রয়োজনীয় পৃষ্ঠা এবং সম্পদগুলি ক্যাশে করে আপনার push ইভেন্টে এটির সুবিধা গ্রহণ করছেন৷

ব্রাউজার সামঞ্জস্য

notificationclose ইভেন্ট

ব্রাউজার সমর্থন

  • ক্রোম: 50।
  • প্রান্ত: 17।
  • ফায়ারফক্স: 44.
  • সাফারি: 16।

উৎস

Clients.openWindow()

ব্রাউজার সমর্থন

  • ক্রোম: 40।
  • প্রান্ত: 17।
  • ফায়ারফক্স: 44.
  • সাফারি: 11.1।

উৎস

ServiceWorkerRegistration.getNotifications()

ব্রাউজার সমর্থন

  • ক্রোম: 40।
  • প্রান্ত: 17।
  • ফায়ারফক্স: 44.
  • সাফারি: 16।

উৎস

clients.matchAll()

ব্রাউজার সমর্থন

  • ক্রোম: 42।
  • প্রান্ত: 17।
  • ফায়ারফক্স: 54।
  • সাফারি: 11.1।

উৎস

আরও তথ্যের জন্য, পরিষেবা কর্মীদের পোস্টের এই ভূমিকাটি দেখুন।

পরের দিকে কোথায় যেতে হবে

কোড ল্যাব

,

আমরা ওয়েব পুশের জন্য কিছু সাধারণ বাস্তবায়ন নিদর্শন দেখতে যাচ্ছি।

এটি পরিষেবা কর্মীর মধ্যে উপলব্ধ কয়েকটি ভিন্ন API ব্যবহার করা জড়িত।

বিজ্ঞপ্তি বন্ধ ইভেন্ট

শেষ বিভাগে আমরা দেখেছি কিভাবে আমরা notificationclick ইভেন্ট শুনতে পারি।

এছাড়াও একটি notificationclose ইভেন্ট রয়েছে যা বলা হয় যদি ব্যবহারকারী আপনার একটি বিজ্ঞপ্তি খারিজ করে দেয় (অর্থাৎ বিজ্ঞপ্তিতে ক্লিক করার পরিবর্তে, ব্যবহারকারী ক্রস ক্লিক করে বা বিজ্ঞপ্তিটি সোয়াইপ করে)।

এই ইভেন্টটি সাধারণত বিজ্ঞপ্তির সাথে ব্যবহারকারীর ব্যস্ততা ট্র্যাক করতে বিশ্লেষণের জন্য ব্যবহৃত হয়।

self.addEventListener('notificationclose', function (event) {
  const dismissedNotification = event.notification;

  const promiseChain = notificationCloseAnalytics();
  event.waitUntil(promiseChain);
});

একটি বিজ্ঞপ্তিতে ডেটা যোগ করা হচ্ছে

যখন একটি পুশ বার্তা প্রাপ্ত হয় তখন সাধারণ তথ্য থাকে যা শুধুমাত্র ব্যবহারকারীর বিজ্ঞপ্তিতে ক্লিক করলেই উপযোগী। উদাহরণস্বরূপ, একটি বিজ্ঞপ্তি ক্লিক করা হলে যে URLটি খোলা উচিত।

একটি পুশ ইভেন্ট থেকে ডেটা নেওয়া এবং এটিকে একটি বিজ্ঞপ্তিতে সংযুক্ত করার সবচেয়ে সহজ উপায় হল showNotification() এ পাস করা অপশন অবজেক্টে একটি data প্যারামিটার যুক্ত করা, যেমন:

const options = {
  body:
    'This notification has data attached to it that is printed ' +
    "to the console when it's clicked.",
  tag: 'data-notification',
  data: {
    time: new Date(Date.now()).toString(),
    message: 'Hello, World!',
  },
};
registration.showNotification('Notification with Data', options);

একটি ক্লিক হ্যান্ডলারের ভিতরে, event.notification.data দিয়ে ডেটা অ্যাক্সেস করা যেতে পারে।

const notificationData = event.notification.data;
console.log('');
console.log('The notification data has the following parameters:');
Object.keys(notificationData).forEach((key) => {
  console.log(`  ${key}: ${notificationData[key]}`);
});
console.log('');

একটি জানালা খুলুন

একটি বিজ্ঞপ্তির সবচেয়ে সাধারণ প্রতিক্রিয়াগুলির মধ্যে একটি হল একটি নির্দিষ্ট URL-এ একটি উইন্ডো/ট্যাব খোলা। আমরা clients.openWindow() API দিয়ে এটি করতে পারি।

আমাদের notificationclick ইভেন্টে, আমরা এইরকম কিছু কোড চালাব:

const examplePage = '/demos/notification-examples/example-page.html';
const promiseChain = clients.openWindow(examplePage);
event.waitUntil(promiseChain);

পরবর্তী বিভাগে, আমরা ব্যবহারকারীকে যে পৃষ্ঠাটিতে নির্দেশ দিতে চাই সেটি ইতিমধ্যে খোলা আছে কিনা তা কীভাবে পরীক্ষা করা যায় তা দেখব। এইভাবে, আমরা নতুন ট্যাব খোলার পরিবর্তে খোলা ট্যাবে ফোকাস করতে পারি।

একটি বিদ্যমান উইন্ডো ফোকাস করুন

যখন এটি সম্ভব হয়, ব্যবহারকারী যখনই একটি বিজ্ঞপ্তিতে ক্লিক করেন তখন একটি নতুন উইন্ডো খোলার পরিবর্তে আমাদের একটি উইন্ডোতে ফোকাস করা উচিত।

এটি কীভাবে অর্জন করা যায় তা দেখার আগে, এটি হাইলাইট করা মূল্যবান যে এটি শুধুমাত্র আপনার মূল পৃষ্ঠাগুলির জন্যই সম্ভব ৷ এর কারণ হল আমরা শুধুমাত্র আমাদের সাইটের কোন পৃষ্ঠাগুলি খোলা আছে তা দেখতে পারি। এটি বিকাশকারীদের তাদের ব্যবহারকারীরা যে সমস্ত সাইট দেখছে তা দেখতে সক্ষম হতে বাধা দেয়৷

পূর্ববর্তী উদাহরণটি গ্রহণ করে, /demos/notification-examples/example-page.html ইতিমধ্যে খোলা আছে কিনা তা দেখতে আমরা কোডটি পরিবর্তন করব।

const urlToOpen = new URL(examplePage, self.location.origin).href;

const promiseChain = clients
  .matchAll({
    type: 'window',
    includeUncontrolled: true,
  })
  .then((windowClients) => {
    let matchingClient = null;

    for (let i = 0; i < windowClients.length; i++) {
      const windowClient = windowClients[i];
      if (windowClient.url === urlToOpen) {
        matchingClient = windowClient;
        break;
      }
    }

    if (matchingClient) {
      return matchingClient.focus();
    } else {
      return clients.openWindow(urlToOpen);
    }
  });

event.waitUntil(promiseChain);

এর কোড মাধ্যমে পদক্ষেপ করা যাক.

প্রথমে আমরা URL API ব্যবহার করে আমাদের উদাহরণ পৃষ্ঠা পার্স করি। এটি একটি ঝরঝরে কৌশল যা আমি জেফ পসনিক থেকে তুলেছি। location অবজেক্টের সাথে new URL() কল করলে স্ট্রিংটি আপেক্ষিক হলে একটি পরম URL প্রদান করবে (যেমন / https://example.com/ হয়ে যাবে)।

আমরা ইউআরএলটিকে পরম করি যাতে আমরা পরবর্তীতে উইন্ডো ইউআরএলের সাথে এটিকে মেলাতে পারি।

const urlToOpen = new URL(examplePage, self.location.origin).href;

তারপরে আমরা WindowClient অবজেক্টের একটি তালিকা পাই, যা বর্তমানে খোলা ট্যাব এবং উইন্ডোগুলির তালিকা। (মনে রাখবেন এইগুলি শুধুমাত্র আপনার মূলের জন্য ট্যাব।)

const promiseChain = clients.matchAll({
  type: 'window',
  includeUncontrolled: true,
});

matchAll মধ্যে পাস করা বিকল্পগুলি সমস্ত ব্রাউজারকে জানায় যে আমরা শুধুমাত্র "উইন্ডো" টাইপ ক্লায়েন্টদের জন্য অনুসন্ধান করতে চাই (অর্থাৎ শুধুমাত্র ট্যাব এবং উইন্ডোগুলির সন্ধান করুন এবং ওয়েব কর্মীদের বাদ দিন)। includeUncontrolled আমাদের আপনার মূল থেকে সমস্ত ট্যাব অনুসন্ধান করতে দেয় যা বর্তমান পরিষেবা কর্মী দ্বারা নিয়ন্ত্রিত নয়, অর্থাৎ এই কোডটি চালাচ্ছেন পরিষেবা কর্মী৷ সাধারনত, matchAll() কল করার সময় আপনি সর্বদা includeUncontrolled সত্য হতে চান।

আমরা প্রত্যাবর্তিত প্রতিশ্রুতিটিকে promiseChain হিসাবে ক্যাপচার করি যাতে আমরা আমাদের পরিষেবা কর্মীকে জীবিত রেখে পরবর্তীতে এটিকে event.waitUntil() এ পাস করতে পারি।

যখন matchAll() প্রতিশ্রুতি সমাধান হয়ে যায়, তখন আমরা ফিরে আসা উইন্ডো ক্লায়েন্টের মাধ্যমে পুনরাবৃত্তি করি এবং তাদের URL গুলিকে আমরা যে URL খুলতে চাই তার সাথে তুলনা করি। যদি আমরা একটি মিল খুঁজে পাই, আমরা সেই ক্লায়েন্টকে ফোকাস করি, যা সেই উইন্ডোটিকে ব্যবহারকারীদের দৃষ্টি আকর্ষণ করবে। matchingClient.focus() কল দিয়ে ফোকাস করা হয়।

যদি আমরা একটি মিলিত ক্লায়েন্ট খুঁজে না পাই, আমরা একটি নতুন উইন্ডো খুলি, যেমনটি পূর্ববর্তী বিভাগে ছিল।

.then((windowClients) => {
  let matchingClient = null;

  for (let i = 0; i < windowClients.length; i++) {
    const windowClient = windowClients[i];
    if (windowClient.url === urlToOpen) {
      matchingClient = windowClient;
      break;
    }
  }

  if (matchingClient) {
    return matchingClient.focus();
  } else {
    return clients.openWindow(urlToOpen);
  }
});

বিজ্ঞপ্তি একত্রিত করা

আমরা দেখেছি যে একটি বিজ্ঞপ্তিতে একটি ট্যাগ যুক্ত করা এমন একটি আচরণে অপ্ট ইন করে যেখানে একই ট্যাগ সহ বিদ্যমান কোনো বিজ্ঞপ্তি প্রতিস্থাপিত হয়।

তবে আপনি বিজ্ঞপ্তি API ব্যবহার করে বিজ্ঞপ্তিগুলি ভেঙে যাওয়ার সাথে আরও পরিশীলিত হতে পারেন। একটি চ্যাট অ্যাপ বিবেচনা করুন, যেখানে ডেভেলপার সাম্প্রতিক বার্তা দেখানোর পরিবর্তে "আপনার কাছে ম্যাট থেকে দুটি বার্তা আছে" এর মতো একটি বার্তা দেখানোর জন্য একটি নতুন বিজ্ঞপ্তি চাইতে পারে।

আপনি এটি করতে পারেন, বা registration.getNotifications() API ব্যবহার করে অন্য উপায়ে বর্তমান বিজ্ঞপ্তিগুলিকে ম্যানিপুলেট করতে পারেন যা আপনাকে আপনার ওয়েব অ্যাপের জন্য বর্তমানে দৃশ্যমান সমস্ত বিজ্ঞপ্তিগুলিতে অ্যাক্সেস দেয়৷

চ্যাট উদাহরণ বাস্তবায়নের জন্য আমরা কিভাবে এই API ব্যবহার করতে পারি তা দেখুন।

আমাদের চ্যাট অ্যাপে, ধরা যাক প্রতিটি বিজ্ঞপ্তিতে কিছু ডেটা রয়েছে যার মধ্যে একটি ব্যবহারকারীর নাম রয়েছে।

প্রথম জিনিস যা আমরা করতে চাই তা হল একটি নির্দিষ্ট ব্যবহারকারীর নাম সহ ব্যবহারকারীর জন্য কোনো খোলা বিজ্ঞপ্তি খুঁজে বের করা। আমরা registration.getNotifications() পাব এবং সেগুলি লুপ করব এবং একটি নির্দিষ্ট ব্যবহারকারীর নামের জন্য notification.data চেক করব:

const promiseChain = registration.getNotifications().then((notifications) => {
  let currentNotification;

  for (let i = 0; i < notifications.length; i++) {
    if (notifications[i].data && notifications[i].data.userName === userName) {
      currentNotification = notifications[i];
    }
  }

  return currentNotification;
});

পরবর্তী ধাপ হল এই বিজ্ঞপ্তিটিকে একটি নতুন বিজ্ঞপ্তি দিয়ে প্রতিস্থাপন করা।

এই জাল বার্তা অ্যাপটিতে, আমরা আমাদের নতুন বিজ্ঞপ্তির ডেটাতে একটি গণনা যোগ করে নতুন বার্তাগুলির সংখ্যা ট্র্যাক করব এবং প্রতিটি নতুন বিজ্ঞপ্তির সাথে এটি বৃদ্ধি করব।

.then((currentNotification) => {
  let notificationTitle;
  const options = {
    icon: userIcon,
  }

  if (currentNotification) {
    // We have an open notification, let's do something with it.
    const messageCount = currentNotification.data.newMessageCount + 1;

    options.body = `You have ${messageCount} new messages from ${userName}.`;
    options.data = {
      userName: userName,
      newMessageCount: messageCount
    };
    notificationTitle = `New Messages from ${userName}`;

    // Remember to close the old notification.
    currentNotification.close();
  } else {
    options.body = `"${userMessage}"`;
    options.data = {
      userName: userName,
      newMessageCount: 1
    };
    notificationTitle = `New Message from ${userName}`;
  }

  return registration.showNotification(
    notificationTitle,
    options
  );
});

যদি বর্তমানে একটি বিজ্ঞপ্তি প্রদর্শিত হয়, আমরা বার্তার সংখ্যা বৃদ্ধি করি এবং সেই অনুযায়ী বিজ্ঞপ্তির শিরোনাম এবং বডি বার্তা সেট করি। যদি কোন বিজ্ঞপ্তি না থাকে, আমরা 1 এর একটি newMessageCount সহ একটি নতুন বিজ্ঞপ্তি তৈরি করি৷

ফলাফল হল যে প্রথম বার্তাটি দেখতে এইরকম হবে:

মার্জ ছাড়াই প্রথম বিজ্ঞপ্তি।

একটি দ্বিতীয় বিজ্ঞপ্তি এতে বিজ্ঞপ্তিগুলিকে ভেঙে ফেলবে:

মার্জ সহ দ্বিতীয় বিজ্ঞপ্তি।

এই পদ্ধতির সাথে চমৎকার জিনিস হল যে আপনার ব্যবহারকারী যদি একের পর এক প্রদর্শিত বিজ্ঞপ্তিগুলিকে প্রত্যক্ষ করেন তবে এটি কেবলমাত্র সর্বশেষ বার্তার সাথে বিজ্ঞপ্তিটি প্রতিস্থাপন করার চেয়ে আরও বেশি সংহত দেখাবে এবং অনুভব করবে৷

নিয়মের ব্যতিক্রম

আমি বলেছি যে যখন আপনি একটি ধাক্কা পাবেন তখন আপনাকে অবশ্যই একটি বিজ্ঞপ্তি দেখাতে হবে এবং এটি বেশিরভাগ সময় সত্য। একটি দৃশ্য যেখানে আপনাকে একটি বিজ্ঞপ্তি দেখাতে হবে না তা হল যখন ব্যবহারকারী আপনার সাইট খোলা এবং ফোকাস করে।

আপনার পুশ ইভেন্টের ভিতরে, আপনি উইন্ডো ক্লায়েন্ট পরীক্ষা করে এবং একটি ফোকাসড উইন্ডো খোঁজার মাধ্যমে একটি বিজ্ঞপ্তি দেখানোর প্রয়োজন আছে কিনা তা পরীক্ষা করতে পারেন।

সমস্ত উইন্ডো পাওয়ার এবং একটি ফোকাসড উইন্ডো খুঁজতে কোডটি এইরকম দেখাচ্ছে:

function isClientFocused() {
  return clients
    .matchAll({
      type: 'window',
      includeUncontrolled: true,
    })
    .then((windowClients) => {
      let clientIsFocused = false;

      for (let i = 0; i < windowClients.length; i++) {
        const windowClient = windowClients[i];
        if (windowClient.focused) {
          clientIsFocused = true;
          break;
        }
      }

      return clientIsFocused;
    });
}

আমরা আমাদের সমস্ত উইন্ডো ক্লায়েন্ট পেতে clients.matchAll() ব্যবহার করি এবং তারপরে আমরা focused প্যারামিটার চেক করে তাদের লুপ করি।

আমাদের পুশ ইভেন্টের ভিতরে, আমরা একটি বিজ্ঞপ্তি দেখানোর প্রয়োজন কিনা তা সিদ্ধান্ত নিতে এই ফাংশনটি ব্যবহার করব:

const promiseChain = isClientFocused().then((clientIsFocused) => {
  if (clientIsFocused) {
    console.log("Don't need to show a notification.");
    return;
  }

  // Client isn't focused, we need to show a notification.
  return self.registration.showNotification('Had to show a notification.');
});

event.waitUntil(promiseChain);

একটি ধাক্কা ইভেন্ট থেকে একটি পৃষ্ঠা বার্তা

আমরা দেখেছি যে ব্যবহারকারী বর্তমানে আপনার সাইটে থাকলে আপনি একটি বিজ্ঞপ্তি দেখানো এড়িয়ে যেতে পারেন। কিন্তু যদি আপনি এখনও ব্যবহারকারীকে জানাতে চান যে একটি ইভেন্ট ঘটেছে, কিন্তু একটি বিজ্ঞপ্তি খুব ভারী হাতে?

একটি পদ্ধতি হল পরিষেবা কর্মী থেকে পৃষ্ঠায় একটি বার্তা পাঠানো, এইভাবে ওয়েব পৃষ্ঠা ব্যবহারকারীকে একটি বিজ্ঞপ্তি বা একটি আপডেট দেখাতে পারে, তাদের ইভেন্ট সম্পর্কে অবহিত করে৷ এটি এমন পরিস্থিতিতে উপযোগী যখন পৃষ্ঠায় একটি সূক্ষ্ম বিজ্ঞপ্তি ব্যবহারকারীর জন্য আরও ভাল এবং বন্ধুত্বপূর্ণ হয়।

ধরা যাক আমরা একটি পুশ পেয়েছি, চেক করেছি যে আমাদের ওয়েব অ্যাপ বর্তমানে ফোকাস করছে, তারপর আমরা প্রতিটি খোলা পৃষ্ঠায় "একটি বার্তা পোস্ট" করতে পারি, যেমন:

const promiseChain = isClientFocused().then((clientIsFocused) => {
  if (clientIsFocused) {
    windowClients.forEach((windowClient) => {
      windowClient.postMessage({
        message: 'Received a push message.',
        time: new Date().toString(),
      });
    });
  } else {
    return self.registration.showNotification('No focused windows', {
      body: 'Had to show a notification instead of messaging each page.',
    });
  }
});

event.waitUntil(promiseChain);

প্রতিটি পৃষ্ঠায়, আমরা একটি বার্তা ইভেন্ট শ্রোতা যোগ করে বার্তা শুনি:

navigator.serviceWorker.addEventListener('message', function (event) {
  console.log('Received a message from service worker: ', event.data);
});

এই বার্তা শ্রোতার মধ্যে, আপনি যা চান তা করতে পারেন, আপনার পৃষ্ঠায় একটি কাস্টম UI দেখাতে পারেন বা বার্তাটিকে সম্পূর্ণরূপে উপেক্ষা করতে পারেন৷

এটিও লক্ষণীয় যে আপনি যদি আপনার ওয়েব পৃষ্ঠায় একটি বার্তা শ্রোতাকে সংজ্ঞায়িত না করেন তবে পরিষেবা কর্মীর বার্তাগুলি কিছুই করবে না৷

একটি পৃষ্ঠা ক্যাশে এবং একটি উইন্ডো খুলুন

একটি দৃশ্যকল্প যা এই গাইডের সুযোগের বাইরে কিন্তু আলোচনার যোগ্য হল যে আপনি আপনার বিজ্ঞপ্তিতে ক্লিক করার পর ব্যবহারকারীরা যে ওয়েব পৃষ্ঠাগুলি দেখার আশা করেন সেগুলিকে ক্যাশে করে আপনি আপনার ওয়েব অ্যাপের সামগ্রিক UX উন্নত করতে পারেন৷

এর জন্য আপনার পরিষেবা কর্মী সেট আপ করা প্রয়োজন ইভেন্টগুলিকে fetch করার জন্য, কিন্তু আপনি যদি একটি fetch শ্রোতা আনয়ন প্রয়োগ করেন, তাহলে নিশ্চিত করুন যে আপনি আপনার বিজ্ঞপ্তি দেখানোর আগে আপনার প্রয়োজনীয় পৃষ্ঠা এবং সম্পদগুলি ক্যাশে করে আপনার push ইভেন্টে এটির সুবিধা গ্রহণ করছেন৷

ব্রাউজার সামঞ্জস্য

notificationclose ইভেন্ট

ব্রাউজার সমর্থন

  • ক্রোম: 50।
  • প্রান্ত: 17।
  • ফায়ারফক্স: 44.
  • সাফারি: 16।

উৎস

Clients.openWindow()

ব্রাউজার সমর্থন

  • ক্রোম: 40।
  • প্রান্ত: 17।
  • ফায়ারফক্স: 44.
  • সাফারি: 11.1।

উৎস

ServiceWorkerRegistration.getNotifications()

ব্রাউজার সমর্থন

  • ক্রোম: 40।
  • প্রান্ত: 17।
  • ফায়ারফক্স: 44.
  • সাফারি: 16।

উৎস

clients.matchAll()

ব্রাউজার সমর্থন

  • ক্রোম: 42।
  • প্রান্ত: 17।
  • ফায়ারফক্স: 54।
  • সাফারি: 11.1।

উৎস

আরও তথ্যের জন্য, পরিষেবা কর্মীদের পোস্টের এই ভূমিকাটি দেখুন।

পরের দিকে কোথায় যেতে হবে

কোড ল্যাব