सामग्री पर जाएं
सभी पोस्ट

Hydrame बनाना: बिना टोकाटाकी के स्मार्ट रिमाइंडर

एक रिमाइंडर ऐप अपने नोटिफ़िकेशन से ही जीता या मरता है। मैंने Hydrame के नोटिफ़िकेशन को कैसे डिज़ाइन किया कि वे आपको धीरे से याद दिलाएँ — और आपके दिन से लड़ने के बजाय उसके साथ ढल जाएँ, यही बता रहा हूँ।

MFKAPPS 4 मिनट पढ़ना

ज़्यादातर रिमाइंडर ऐप में एक ही घातक खामी होती है: खुद रिमाइंडर। वे एक तय समय-सारणी पर बजते हैं, आप क्या कर रहे हैं इसकी परवाह नहीं करते, और धीरे-धीरे आपको सिखा देते हैं कि उन्हें पढ़े बिना ही हटा दें। जैसे ही कोई नोटिफ़िकेशन शोर बन जाता है, पूरा ऐप शोर बन जाता है।

Hydrame एक पानी ट्रैक करने वाला ऐप है, और पानी ट्रैक करना पूरी तरह एक रिमाइंडर की समस्या है। अगर टोके अच्छे हों, तो ऐप काम करता है। अगर वे टोकाटाकी करें, तो आप गुरुवार तक उसे अनइंस्टॉल कर देते हैं। इसलिए मैंने डिज़ाइन का ज़्यादातर समय बिल्कुल एक ही सवाल पर लगाया: किसी को पानी पीने की याद कैसे दिलाई जाए, बिना वह चीज़ बने जिससे उसे चिढ़ हो जाए?

तय समय-सारणी ही दुश्मन है

भोला-भाला तरीका है हर दो घंटे में एक अलार्म। इसे बनाना आसान है और इसके साथ जीना दुखदायी। यह मीटिंग के बीच बजता है, झपकी के दौरान बजता है, और तब बजता है जब आपने अभी-अभी एक गिलास पानी पिया हो, उसके दस मिनट बाद। हर गलत समय पर आया रिमाइंडर आपका थोड़ा भरोसा छीन लेता है, और वह भरोसा वापस नहीं आता।

Hydrame को आकार देने वाली समझ यह थी: एक रिमाइंडर तभी अच्छा है जब वह उस पल में आए जब आप सचमुच उस पर कुछ कर सकें। बाकी सब मददगार का चोला पहने शोर है।

दिन के साथ ढलना

तय टाइमर के बजाय, Hydrame एक दैनिक लक्ष्य को आपके जागने के घंटों में फैलाता है और तभी टोकता है जब आप सचमुच पिछड़ गए हों और पिछले टोक के बाद पर्याप्त समय बीत चुका हो। एक ड्रिंक दर्ज करने से अगला रिमाइंडर आगे खिसक जाता है। लगातार पानी पिएँ तो शायद आपको उसकी आवाज़ ही न सुनाई दे — और असल मकसद यही है।

मुख्य शेड्यूलिंग लॉजिक जानबूझकर छोटा रखा गया है:

interface ReminderContext {
  now: Date;
  wakeHour: number;       // e.g. 8
  sleepHour: number;      // e.g. 23
  goalMl: number;         // daily target
  consumedMl: number;     // logged so far today
  lastNudge: Date | null;
  minGapMinutes: number;  // breathing room between nudges
}

function shouldNudge(ctx: ReminderContext): boolean {
  const hour = ctx.now.getHours();

  // Never during sleeping hours.
  if (hour < ctx.wakeHour || hour >= ctx.sleepHour) return false;

  // Respect a minimum gap so we never feel pushy.
  if (ctx.lastNudge) {
    const gapMin = (ctx.now.getTime() - ctx.lastNudge.getTime()) / 60000;
    if (gapMin < ctx.minGapMinutes) return false;
  }

  // How much *should* you have had by now, given the day's progress?
  const dayLength = ctx.sleepHour - ctx.wakeHour;
  const elapsed = Math.max(0, hour - ctx.wakeHour);
  const expectedMl = ctx.goalMl * (elapsed / dayLength);

  // Only nudge if you're meaningfully behind the curve.
  return ctx.consumedMl < expectedMl * 0.85;
}

गणित में कुछ भी चतुराई भरा नहीं है, और यह जानबूझकर है। 0.85 की सीमा का मतलब है “पिछड़े हुए, पर सज़ा देने की हद तक नहीं।” minGapMinutes की रोक ही एक साथी और एक टोकाटाकी करने वाले के बीच का फ़र्क है। ज़्यादातर काम बजने के कारण जोड़ने का नहीं, बल्कि हटाने का था।

नोटिफ़िकेशन की भाषा समय जितनी ही मायने रखती है

बिल्कुल सही समय पर आया रिमाइंडर भी बुरा लग सकता है अगर शब्द गलत हों। “आप अपने लक्ष्य में नाकाम हो रहे हैं!” तकनीकी रूप से एक टोक है। यह किसी की लॉक स्क्रीन पर आपके ही बुलावे से आई एक छोटी-सी दुश्मनी भी है।

Hydrame के रिमाइंडर छोटे, गर्मजोश और कभी अपराधबोध न जगाने वाले हैं:

  • “एक गिलास पानी के लिए अच्छा पल है।”
  • “दिन आधा बीत गया — थोड़ा भरपाई कर लें?”

ध्यान खींचने के लिए आपस में लड़ते विस्मयादिबोधक चिह्न नहीं। “टूटने” वाली कोई लकीर नहीं। लहजा किसी दोस्त के यूँ ही कह देने जैसा है, किसी कोच के चिल्लाने जैसा नहीं।

डिफ़ॉल्ट रूप से शांत, चुनाव से समायोज्य

डिफ़ॉल्ट किसी भी ऐप का सबसे अहम डिज़ाइन फ़ैसला होते हैं, क्योंकि ज़्यादातर लोग उन्हें कभी नहीं बदलते। इसलिए Hydrame शांत आता है: टोकों की सधी हुई संख्या, रात में एक भी नहीं, और सभी को और भी कम करना आसान।

अगर आप कड़े लक्ष्य या ज़्यादा बार जाँच चाहें, तो वे मौजूद हैं। पर आप ज़्यादा में खुद शामिल होते हैं, कम से बाहर नहीं निकलते। यही एक उलटफेर — शांति को छत नहीं, फ़र्श बनाना — काफ़ी हद तक ऐप को सम्मानजनक महसूस कराता है।

मकसद कभी नोटिफ़िकेशन को अधिकतम करना नहीं था। मकसद हर एक को हक़ से कमाना था।

रिमाइंडर ऐप बनाने वाले हर किसी से मैं यही कहूँगा

  1. रिमाइंडर को घड़ी से नहीं, ऐसे पलों से जोड़ें जिन पर कुछ किया जा सके। जिस टोक पर आप कुछ न कर सकें, वह बस शोर है।
  2. हमेशा साँस लेने की जगह छोड़ें। अलर्ट के बीच एक न्यूनतम अंतराल पर कोई समझौता नहीं।
  3. भाषा किसी इंसान की तरह लिखें, किसी मीट्रिक की तरह नहीं। गर्मजोशी कुछ नहीं लेती और बहुत सारा भरोसा देती है।
  4. शांत विकल्प को डिफ़ॉल्ट बनाएँ। लोग आपके डिफ़ॉल्ट में ही रहते हैं।

Hydrame अब Google Play पर उपलब्ध है, और नोटिफ़िकेशन आज भी वही हिस्सा है जिसे मैं लगातार निखार रहा हूँ। अगर आप इसे आज़माएँ, तो मुझे बताएँ कि टोके कैसे महसूस होते हैं — वही फ़ीडबैक आगे का रास्ता तय करता है। बेशक, चुपचाप।

// संबंधित पठन

जर्नल से और भी

MFKAPPS 6 मिनट पढ़ना

एक हाइड्रेशन रूटीन जो इच्छाशक्ति पर निर्भर नहीं करता

ज़्यादातर हाइड्रेशन सलाह 'ज़्यादा पानी पिएं' पर सिमट कर रह जाती है और उम्मीद करती है कि बाकी का काम इच्छाशक्ति कर देगी। यहां एक ऐसा रूटीन है जो इच्छाशक्ति की बजाय संकेतों (cues) और हल्के रिमाइंडर्स पर बना है।

#mobile #ux #reminders
MFKAPPS 5 मिनट पढ़ना

Granyn बनाना: बिना बैंक लॉगिन वाला बजट ट्रैकर, बस तीन टेबल में

Granyn एक भी बैंक अकाउंट जोड़े बिना कई मुद्राओं में खर्च कैसे ट्रैक करता है और आवर्ती बिलों को कैसे पकड़ता है — इसके पीछे का Room स्कीमा, और इससे जुड़े समझौते।

#android #engineering #privacy
MFKAPPS 5 मिनट पढ़ना

Android नोटिफ़िकेशन एक्शन सही तरीके से: बिना ऐप खोले एक खुराक को ली गई के रूप में चिह्नित करना

Android नोटिफ़िकेशन एक्शन बटन के लिए एक व्यावहारिक गाइड — PendingIntent, activity-trampoline प्रतिबंध, goAsync(), और Room स्टेट को सुरक्षित रूप से अपडेट करना।

#android #engineering #notifications