اپ iOS و اندروید

تیک — اپ کارهای روزانه برای iOS و اندروید

یک اپ ساده برای کارهای هر روز: کار را اضافه می‌کنی، تیک می‌زنی، تمام. ظاهرش شیشه‌ای و مینیمال است، مثل خود iOS 27. فارسی و انگلیسی دارد، تقویمش شمسی است، و ویجتش از روی صفحه‌ی اصلی گوشی تیک می‌خورد. هم برای آیفون و آیپد هست، هم برای گوشی و تبلت اندروید.

SwiftSwiftUISwiftDataKotlinJetpack ComposeRoom

سه نمای صفحه‌ی «امروز» در اپ تیک: انگلیسی و روشن، فارسی و راست‌به‌چپ، و تیره؛ با کارت‌های شیشه‌ای و نوار پیشرفت
صفحه‌ی «امروز» روی آیفون در سه حالت: انگلیسی، فارسی راست‌به‌چپ، و تیره. کارهای انجام‌شده خط می‌خورند و به پایین فهرست می‌روند.

مشکل چه بود؟

اپ‌های کار روزانه معمولاً یکی از این دو مشکل را دارند: یا آن‌قدر ساده‌اند که به درد برنامه‌ریزی نمی‌خورند، یا آن‌قدر شلوغ‌اند که اضافه کردن یک کار ساده، خودش یک کار حساب می‌شود.

من یک چیز می‌خواستم: صبح کارهای امروز را سریع بنویسم و در طول روز تیکشان بزنم. و چون فارسی‌زبانم، تقویم شمسی و راست‌به‌چپ درست برایم مهم بود — نه یک ترجمه‌ی نصفه‌نیمه.

چی ساختم؟

«تیک»، اول یک اپ بومی iOS برای آیفون و آیپد، و بعد همین اپ برای اندروید. صفحه‌ی اولش «امروز» است: کارهای امروز، کارهای عقب‌افتاده، و یک نوار پیشرفت. هر کار می‌تواند یادداشت، زیرکار، تاریخ و ساعت، اولویت، عکس و تکرار داشته باشد — ولی هر کدام را که لازم نداری، از تنظیمات خاموش می‌کنی و از فرم حذف می‌شود.

  • لیست‌های شخصی با رنگ و آیکون، و چهار لیست هوشمند: امروز، برنامه‌ریزی‌شده، همه، انجام‌شده‌ها
  • یادآور با دو دکمه روی خود اعلان: «انجام شد» و «۱۰ دقیقه‌ی دیگر یادم بنداز»
  • ویجت صفحه‌ی اصلی در سه اندازه، و سه ویجت برای صفحه‌ی قفل
  • تم روشن و تیره، ۱۱ رنگ اصلی و ۶ آیکون برای خود اپ
  • و وقتی آخرین کار روز تیک بخورد، کمی کاغذ رنگی روی صفحه می‌ریزد
سه صفحه از اپ تیک: فیلد افزودن سریع که بالای کیبورد باز شده، فرم ویرایش کار به فارسی با تاریخ شمسی، و صفحه‌ی لیست‌ها
افزودن سریع، فرم ویرایش کار با تاریخ شمسی، و صفحه‌ی لیست‌ها.

یک دکمه که به فیلد تبدیل می‌شود

سریع‌ترین راه اضافه کردن کار، نوشتنش است — نه باز کردن یک فرم. دکمه‌ی شیشه‌ای «+» پایین صفحه با یک لمس، با افکت Liquid Glass «ذوب» می‌شود و به یک فیلد متن تبدیل می‌شود.

نکته‌ی اصلی این است که بعد از زدن اینتر، فیلد بسته نمی‌شود. صبح می‌شود پنج کار را پشت‌سرهم تایپ کرد، بدون یک لمس اضافه. برای جزئیات بیشتر هم دکمه‌ای کنار فیلد هست که فرم کامل را با همان عنوان باز می‌کند.

فارسی واقعی، نه فقط ترجمه

زبان اپ از داخل خود اپ عوض می‌شود، مستقل از زبان گوشی. با یک لمس، کل رابط راست‌به‌چپ می‌شود و فونت وزیرمتن جای فونت سیستم را می‌گیرد.

تقویم پیش‌فرض شمسی است و هفته از شنبه شروع می‌شود. تکرار «هر ماه» هم با ماه‌های شمسی حساب می‌شود: کاری که اول مهر است، دفعه‌ی بعد اول آبان می‌آید. و به انتخاب خودم، عددها همه‌جا لاتین می‌مانند — در ساعت، در تاریخ، و حتی در درصد پیشرفت.

ویجتی که تیک می‌خورد

صفحه‌ی اصلی آیفون با دو ویجت تیک در اندازه‌ی بزرگ و متوسط که کارهای امروز را نشان می‌دهند
ویجت بزرگ و متوسط روی صفحه‌ی اصلی. دایره‌ی کنار هر کار، همان‌جا تیک می‌خورد.

ویجت و اپ دو برنامه‌ی جدا هستند، ولی باید یک داده را ببینند. پایگاه داده (SwiftData) در یک App Group مشترک ذخیره می‌شود تا هر دو به آن دسترسی داشته باشند، و تیک زدن از روی ویجت با App Intents انجام می‌شود — بدون اینکه اپ باز شود.

بخش سختش این بود که اپ بعدش بفهمد داده عوض شده. ویجت در یک فرایند جدا کار می‌کند، پس اپ هنوز نسخه‌ی قدیمی را در حافظه دارد. راه‌حل: ویجت بعد از هر تغییر یک «مهر زمان» در تنظیمات مشترک می‌گذارد، و اپ وقتی دوباره باز می‌شود آن را می‌بیند و داده را از نو می‌خواند.

کارهای تکراری

وقتی یک کار تکراری را تیک می‌زنی، نسخه‌ی بعدی‌اش خودکار ساخته می‌شود — و اگر تیک را برداری، همان نسخه هم پاک می‌شود. کاری که دیر تیک بخورد هم دوباره در گذشته ساخته نمی‌شود؛ نسخه‌ی بعدی همیشه از فردا به بعد است.

درسی که از تست‌ها گرفتم

نسخه‌ی اول، «هر ماه» را فقط از تاریخ آخرین کار حساب می‌کرد. تست نشان داد کاری که ۳۱ ژانویه بود، بعد از فوریه ۲۸ام می‌شد — و برای همیشه ۲۸ام می‌ماند.

حالا روز اصلی ماه کنار قانون تکرار نگه داشته می‌شود و هر وقت ماه اجازه بدهد، کار به همان روز برمی‌گردد. در تقویم شمسی هم همین است: کار ۳۱ شهریور در ماه‌های ۳۰روزه روز ۳۰ می‌آید، و در فروردین بعد دوباره ۳۱ام.

روی آیپد

اپ تیک روی آیپد: نوار کناری با لیست‌ها و صفحه‌ی امروز؛ یکی انگلیسی و روشن، دیگری فارسی و تیره
روی آیپد، تب‌ها جایشان را به یک نوار کناری با جستجو می‌دهند. در حالت فارسی، نوار کناری به سمت راست می‌رود.

نسخه‌ی اندروید

بعد از iOS، همین اپ را برای اندروید هم ساختم: با همان امکانات، برای گوشی و تبلت. این بار با Kotlin و Jetpack Compose، و بدون یک خط کد مشترک با نسخه‌ی iOS. منطق اپ، از تقویم شمسی تا قانون‌های تکرار، از نو نوشته شد و تست شد تا دقیقاً مثل نسخه‌ی iOS رفتار کند.

سه صفحه از اپ تیک روی اندروید: صفحه‌ی امروز به انگلیسی، همان صفحه به فارسی و راست‌به‌چپ، و فرم ویرایش کار در تم تیره
تیک روی اندروید: صفحه‌ی «امروز» به انگلیسی و فارسی، و فرم ویرایش کار در تم تیره.

شیشه، به سبک تلگرام

اندروید Liquid Glass ندارد. ظاهر شیشه‌ای را از طراحی تازه‌ی تلگرام برای اندروید الهام گرفتم: نوار تب‌ها، دکمه‌ها و نوار بالای صفحه شیشه‌ی مات‌اند، و از اندروید ۱۲ به بالا هر چه پشتشان رد شود، محو دیده می‌شود.

روی اندروید ۱۳ به بالا یک قدم جلوتر رفتم: وقتی انگشت روی نوار تب‌ها می‌لغزد، یک «قطره‌ی آب» شفاف زیر انگشت حرکت می‌کند و آیکون‌های زیرش را کمی خم می‌کند؛ شکستِ نور روی کارت گرافیک حساب می‌شود. روی گوشی‌های قدیمی‌تر، همان شکل‌ها با یک رنگ نیمه‌شفاف ساده کشیده می‌شوند.

ویجتی که باید برعکس می‌شد

صفحه‌ی اصلی اندروید با ویجت بزرگ تیک به فارسی: تاریخ شمسی، نوار پیشرفتی که از راست پر می‌شود، و کارهای امروز
ویجت بزرگ به فارسی، روی گوشی‌ای که زبانش انگلیسی است. دایره‌ی کنار هر کار همان‌جا تیک می‌خورد.

ویجت اندروید با Jetpack Glance ساخته شده و مثل iOS از روی صفحه‌ی اصلی تیک می‌خورد. ولی لانچر اندروید، ویجت را به زبانِ گوشی می‌چیند، نه به زبانِ اپ. پس اگر اپ فارسی باشد و گوشی انگلیسی، ردیف‌ها باید دستی برعکس شوند.

نسخه‌ی اول درست برعکس نمی‌شد. معلوم شد از اندروید ۱۳ به بعد، زبانی که برای خودِ اپ انتخاب می‌شود، روی چیزی هم که اپ «زبان گوشی» می‌بیند اثر می‌گذارد؛ پس ویجت فکر می‌کرد گوشی هم فارسی است. راه‌حل این بود که زبان واقعی گوشی را مستقیم از سیستم بپرسم. حالا ویجت در هر ترکیبی درست است، و در حالت فارسی حتی نوار پیشرفتش هم از راست پر می‌شود.

باگی که فقط در نسخه‌ی نهایی بود

در نسخه‌ی آزمایشی همه‌چیز درست بود، ولی در فایل نهایی (APK) ویجت روی دایره‌ی «در حال بارگذاری» می‌ماند. ابزاری که کد نهایی را کوچک و فشرده می‌کند (R8)، سازنده‌ی یکی از کلاس‌های WorkManager را حذف کرده بود؛ کلاسی که فقط از روی اسمش ساخته می‌شود. برای همین ویجت هیچ‌وقت کشیده نمی‌شد.

یک قانون کوچک برای نگه داشتن آن کلاس، مشکل را حل کرد. درسش این بود که فایل نهایی را هم خودم امتحان کنم، نه فقط نسخه‌ی آزمایشی و تست‌ها را.

روی تبلت اندروید

اپ تیک روی تبلت اندروید در حالت افقی: نوار کناری با لیست‌ها و صفحه‌ی امروز؛ یکی انگلیسی و روشن، دیگری فارسی و تیره
روی تبلت، مثل آیپد، یک نوار کناری با جستجو جای تب‌ها را می‌گیرد. فرم ویرایش و تنظیمات هم به‌جای پر کردن کل صفحه، مثل یک کارت وسط صفحه باز می‌شوند.

تست‌ها

منطق نسخه‌ی iOS با ۳۵ تست واحد پوشش داده شده: تاریخ شمسی و میلادی با عدد لاتین، همه‌ی قانون‌های تکرار، اینکه کدام کار در «امروز» بیاید و به چه ترتیبی، و تیک زدن از روی ویجت. ۱۷ تست رابط کاربری هم مسیرهای اصلی را مثل یک کاربر واقعی امتحان می‌کنند — و عکس‌های آیفونِ همین صفحه را هم همان تست‌ها گرفته‌اند.

نسخه‌ی اندروید ۴۸ تست واحد و ۱۰ تست روی گوشی دارد. تقویم شمسی‌اش هم برای تک‌تک روزهای سال ۱۹۰۰ تا ۲۱۰۰ میلادی با کتابخانه‌ی ICU مقایسه شده؛ همان چیزی که iOS برای تقویم از آن استفاده می‌کند.

با چه ابزارهایی

iOSاندروید
رابط کاربریSwiftUI برای iOS 27، با Liquid GlassJetpack Compose و Material 3، با شیشه‌ی Haze
دادهSwiftData، مشترک با ویجت از طریق App GroupRoom برای کارها و DataStore برای تنظیمات
ویجتWidgetKit و App IntentsJetpack Glance
یادآورUserNotifications، با دکمه روی خود اعلانآلارم دقیق و اعلان با دکمه
زبان‌هاString Catalog با انگلیسی و فارسیزبانِ جدا برای خود اپ، با انگلیسی و فارسی
تست۳۵ تست واحد با Swift Testing و ۱۷ تست رابط کاربری۴۸ تست واحد و ۱۰ تست روی گوشی
جزئیاتآیکون‌ها با کد کشیده شده‌اند و صداها از فرمول ریاضی ساخته شده‌اند

نتیجه

اپی برای کارهای هر روز: سریع برای نوشتن، راحت برای تیک زدن، و فارسیِ درست. برای استفاده‌ی شخصی ساخته شده، پس در اپ‌استور و گوگل‌پلی نیست. نسخه‌ی iOS با یک Apple ID رایگان، مستقیم از Xcode روی آیفون نصب می‌شود. نسخه‌ی اندروید را هم می‌شود به‌صورت یک فایل APK از گیت‌هاب دانلود کرد و مستقیم روی گوشی نصب کرد. راهنمای نصب هر دو در گیت‌هاب هست.

حالا تیک سایت خودش را هم دارد، با دموی زنده و دانلود مستقیم: tik.mahyarmozafar.ir. داستان ساختش را در صفحه‌ی سایت تیک نوشته‌ام.

پروژه‌ای دارید؟

اگر کاری شبیه این لازم دارید، خوشحال می‌شم دربارش حرف بزنیم.