Skip to content
batuhdPublic

About

Çiftler için 2 kişilik film, dizi ve anime takip uygulaması. Ortak puanlama, bölüm notları, seçim çarkı, rozetler ve istatistikler.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Minimuv logosu

🎬 Minimuv

"bizim izleme defterimiz" — Van & Sinop için özel olarak tasarlanmış, yalnızca iki kişilik film, dizi ve anime takip uygulaması.

Letterboxd'ın poster odaklı sinefil estetiği ile Duolingo'nun oyunlaştırılmış tatlı dilini bir araya getirir: ikimiz ayrı ayrı puan veriyoruz, bölüm notları spoiler kilidiyle korunuyor, ne izleyeceğimize çark karar veriyor ve rozetler ortak başarılarımızı kutluyor.

Kotlin Jetpack Compose Supabase SDK Sürüm


📱 Ekran Görüntüleri

📚 Kütüphane 🎬 Detay Sayfası 🎡 Randevu Çarkı 💑 Profil & Aşk
Kütüphane Detay Sayfası Çark Profil

✨ Özellikler

📚 Kütüphane - 4 Görünüm Modu

📱 Kompakt Liste 🖼️ Poster Satırları 🔳 3'lü Izgara 🔲 2'li Büyük Izgara
  • Durum Bazlı Gruplandırma: Devam edelim (İzliyoruz), Sırada, Tamamlandı, Bıraktık bölümleri; başlığa dokunarak katla/aç. Poster kartlarında puan, bölüm rozeti, durumu ekleyen kişinin emojisi ve 🔁 yeniden izleme sayacı.
  • Kütüphane İçi Arama: Türkçe karakter katlaması sayesinde "sifir bir" yazınca Sıfır Bir bulunur.
  • Filtre Çekmecesi: Durum, format (Film/Dizi/Anime), yıl aralığı (1960–2026 kaydırıcı) ve sıralama (Son Eklenen / Puan / İsim / Öncelik).
  • Sürükle-Bırak Sıralama: Sırada listesini basılı tutup istediğin sıraya diz; "N. sırada" rozetleri ve "👥 İkimiz de istiyoruz" etiketiyle saklanır.
🎛️ Filtreler 🔍 Akıllı Arama
  • Yazım Toleranslı Arama: Türkçe karakter katlama, Levenshtein benzerlik sıralaması, önek varyantları ve TR/EN çapraz dil denemeleri: "inceprion" bile Inception'ı bulur. Sonuçlar oturum içi önbellekte tutulur, 429 rate-limit'e saygılı retry yapılır.
  • Ekleme Akışı: Dokun: detaylı önizleme, basılı tut: hemen ekle. Zaten ekli yapımlar "✓ Eklendi" ile işaretlenir; API'de bulamazsan manuel ekleme düşer. Film/dizi için TMDB, anime için AniList (anahtarsız) kullanılır; başlık dili tercihi (TR/EN) hatırlanır.

🎬 Detay & Düzenleme

📜 Okuma Modu ✏️ Düzenleme Modu
📜 Detay ve düzenleme ekranlarının tamamı (uzun görüntüler)
  • AniList / TMDB Tarzı Okuma Modu: API'den gelen puan ve oy sayısı, yıl/süre/sezon, türler, stüdyo/yapımcı, hikâye özeti ve oyuncu/karakter kadrosu.
  • Katlanabilir Kartlarla Düzenleme: Durum, Bölümler, Takvim, Puanlar, Notlar; kapalıyken tek satırlık özet gösterir. Karta uzun basınca doğrudan düzenleme açılır.
  • Akıllı Tarihler: Kuyruğa eklenen başlığın başlangıcı boş kalır; izlemeye başlarken başlangıç, tamamlarken bitiş tarihi otomatik damgalanır. Bölüm ilerlemesi toplama ulaşınca başlık kendiliğinden Tamamlandı olur ve konfeti düşer.
  • Yeniden İzleme: Biten/araya verilen yapımlar "🔁 İzliyoruz'a al" ile yeniden başlar, sayaç artar.
  • Notlar: Emoji seçicili tatlı not kartları; ❤️ Favorimiz ile işaretle; favoriler Profil sayfasındaki ızgarada toplanır.

💯 Çift Puanlama

  • Herkes kendi puanını verir; kartların üzerinde ikimizin ortalaması görünür.
  • Detaylı Puanlama: Hikaye, Karakterler, Görsellik, Ses ve Keyif kaydırıcıları (0–10); ana puan bu ortalamadan otomatik hesaplanır. Düzenleme ekranında iki puan halkası yan yana karşılaştırılır.

🕵️ Spoiler Kilidi & Bölüm Notları

  • "Ayrı ayrı izliyoruz" modunda alınan bölüm notları, karşı taraf o bölüme gelene kadar kilitli kalır — uygulama içinde de, bildirimlerde de.
  • Uzun yazmak yerine 😭🔥😱🤯😍😂🤢🤩 hızlı emoji tepkileri bırakabilirsin.

🎡 Randevu Gecesi Çarkı

Çark ekranı

  • Kararsız kaldığınızda Sırada listesinden seçim yapan, afişli dilimlerden oluşan canvas çark (afiş yoksa numara + renk lejantı).
  • Tür filtresi ve "İlk 3 / İlk 5 / İlk 10" seçenekleri; 5 saniyelik yavaşlayan dönüş, titreşimli geri bildirim, kazanan kartından tek dokunuşla detaya geçiş.
  • 🎵 Çark Sesi: Dönüş sırasında her dilim geçişinde "tik", kazanan belirlenince kısa marş (WheelSound + SoundPool); 🔊 Ses açık / 🔇 Ses kapalı anahtarı. Kazanan kartı ekranın ortasında popup olarak gösterilir.

🏅 Rozet Yolculuğu

Rozet ekranı

  • 27+ Rozet: İlk Perde 🎬, Kombo 🌪️, Anayasa Kitabı 🐉, Sinophil 🏯… hepsi çiftin ortak başarısı.
  • Sağa sola kıvrılan patika üzerinde altın madalyalar, kilitli rozetlerde ilerleme çubuğu, yeni açılan rozetlerde konfeti kutlaması.
  • Rozetler her kayıttan sonra otomatik değerlendirilir — Rozetler sekmesi açık olmasa bile.
📜 Rozet ekranının tamamı (uzun görüntü)

📊 İstatistikler: Takvim & Wrapped

🗓️ İzleme Takvimi 🎁 Yıl Özeti
📜 Wrapped ekranının tamamı (uzun görüntü)
  • İzleme Takvimi (Heatmap): GitHub tarzı katkı grafiği; ay ve gün etiketli, "Az → Çok" doygunluk lejantlı.
  • Yıl Özeti (Wrapped): Spotify tarzı kapak kartıyla: tamamlananlar, izlenen bölüm, tahmini ekran saati, Yılın En Değerlileri (top 3), aylık aktivite grafiği, tür dağılımı, ortalama puan, en aktif gün, yılın en büyük maraton günü, yılın ilk/son izlenenleri ve birlikte bayıldıklarınız (9+). ◀ ▶ ile geçmiş yıllara da gezinebilirsiniz.
  • Tutarlı İstatistikler: Takvim, wrapped, profil sayaçları ve rozetler tek doğruluk kaynağından beslenir.

👥 Profil

Profil ekranı

  • İsim, emoji (12 seçenek), renk ve kare kırpmalı profil fotoğrafı (Supabase Storage'a yüklenir).
  • Duolingo tarzı istatistik şeridi: 🔥 Seri · 🎬 Bitirdik · 📺 Bölüm · 🏅 Rozet.
  • Ortak favoriler ızgarası ve tek dokunuşla İzleme Takvimi / Wrapped geçişi.
  • Diğer profile dokunmak "Bu profille geç" yapar — iki telefon, iki kimlik.

🔔 Bildirimler - Üç Katman, Uygulama Kapalıyken Bile

                    ┌─ Uygulama AÇIK   → Supabase Realtime → anında bildirim
Veritabanı olayı ───┼─ Uygulama KAPALI → pg_net trigger → notify Edge Function → FCM (data-only)
                    └─ Güvenlik ağı    → WorkManager (~15 dk'da bir kontrol)
  • Bildirilenler: Başlık ekleme, durum değişiklikleri (izleme/tamamlama/bırakma…), puan verip güncelleme, başlık notu, bölüm notu (spoiler kilidine saygılı), bölüm kilometre taşları ("İkiniz de 10. bölümü geçtiniz!"), gizli notlar ve yıldönümü hatırlatmaları.
  • Çift Bildirim Koruması: FCM mesajı bildirimi doğrudan içermez; uygulama Supabase'deki gerçek durumu kontrol edip bildirimi kendisi gösterir. Realtime açıkken FCM yolu sessizce geçer. Kalıcı servis bildirimi yoktur.

📲 Uygulama İçi Güncelleme (Firebase App Distribution)

  • Tester (Van & Sinop), uygulamayı açtığında Firebase App Distribution üzerinden yeni sürüm varsa otomatik uyarılır; tek dokunuşla arka planda indirip kurar.
  • Özel güncelleme penceresi: "Yeni sürüm var 🎉" → Güncelle butonu, indirme ilerleme çubuğu, ardından sistem kurulum ekranı (Yükle).
  • google-services.json olmayan API'siz sürümde güncelleme kontrolü kendiliğinden kapanır.

🤫 Gizli Menü

Gizli menü

  • Ayarlar → Hakkında yolunu izleyip sürüm yazısına 7 kez dokunun.
  • Karşınıza çıkan "Partnere gizli not" kutusuna yazdığınız mesaj anında partnerinizin telefonuna bildirim olarak düşer. 💌

🎨 Görünüm & 🌐 Dil

Ayarlar

  • 15 Tema Rengi: Mavi, Mor, Yeşil, Pembe, Turuncu, Kırmızı, Gül, Camgöbeği, Turkuaz, Indigo, Lavanta, Limon, Mercan, Nane, Altın.
  • Letterboxd esintili Midnight koyu paleti; film/dizi/anime ve durum renkleri her ekranda sabit anlam taşır.
  • Plus Jakarta Sans tabanlı tipografi (başlık + gövde), Midnight paleti ve yumuşak gradyanlar; edge-to-edge tasarım.
  • Ayarlar kategorilere ayrılmış (açılır menüler) — Görünüm, Dil, Bildirimler, Hakkında, Tehlikeli Bölge.
  • Görüntüleme Dili (TR/EN): Liste ve detaydaki başlıklar ile açıklamalar seçilen dilde gösterilir; TMDB/AniList'ten İngilizce veri saklanır, Türkçe özeti olmayan yapımlarda otomatik İngilizce yedek kullanılır.
  • Kütüphane Görünümü: (kompakt / poster satırları / 2'li-3'lü ızgara) ayarlardan seçilebilir.
  • Tüm verileri tek dokunuşla (atomik TRUNCATE ile) sıfırlama.

🎬 Keşif: Kişi, Karakter, Yönetmen ve Stüdyo Sayfaları

  • Detay sayfasındaki oyuncular/karakterler ve yönetmen üzerine dokununca o kişinin biyografisi + tüm filmografisi açılır; listedeki yapımlardan tek dokunuşla koleksiyona eklenebilir.
  • Yapımcı/stüdyo çiplerine dokununca stüdyo sayfası açılır (filmografi).
  • Kişiler, karakterler ve stüdyolar favorilere alınabilir (❤️) — Profil sekmesindeki "Kişiler & Stüdyolar" bölümünde listelenir.
  • Arama sonuçları yapım yılına göre filtrelenebilir (2020+, 2010'lar, 2000'ler, 2000 öncesi).

⚡ Gerçek Zamanlı Senkronizasyon

  • Tüm tablolar Supabase Realtime'a abone; yapılan her değişiklik iki telefonda da anında (debounce'lu) güncellenir.

🛠️ Teknoloji

Katman Teknoloji
Dil / UI Kotlin 2.3+ + Jetpack Compose (BOM 2026.02, Material 3) + Navigation Compose
Backend Supabase - Postgres + Realtime + Storage (Auth yok) · supabase-kt 3.5
Ağ / Serileştirme Ktor 3.4 (OkHttp) + kotlinx.serialization
Film/Dizi Arama + Detay TMDB API
Anime Arama + Detay AniList GraphQL API
Görseller Coil 3
Bildirimler Firebase Cloud Messaging 24 + WorkManager + Supabase Edge Function (pg_net trigger)
Uygulama İçi Güncelleme Firebase App Distribution 16 (firebase-appdistribution) — özel InAppUpdateHost penceresi
Yerel Ayarlar Jetpack DataStore
Sürükle-Bırak sh.calvin.reorderable
Fotoğraf Kırpma vanniktech/android-image-cropper
Hedef minSdk 26 (Android 8.0) · targetSdk 36 · v3.2.5

🚀 Kurulum

Gereksinimler

  • Android Studio (Kotlin 2.3, AGP 9.x, JDK 17+)
  • minSdk 26 (Android 8.0) / targetSdk 36

1) Supabase Hazırlığı

  1. supabase.com üzerinden yeni bir proje oluşturun.

  2. SQL Editor'de supabase/init.sql dosyasını çalıştırın — tek dosyadır, tüm şemayı içerir:

    • Tablolar (profiles, titles, title_notes, title_scores, episode_progress_per_profile, episode_notes, achievements, watch_log, partner_pings, fcm_tokens, favorites)
    • profiles başlangıç verileri (Van 🌊 / Sinop 🦜)
    • avatars bucket'ı + Storage politikaları
    • RLS politikaları ve realtime yayınları
    • FCM trigger'ları (pg_net) ve reset_all_data() sıfırlama fonksiyonu

    Dosya idempotent'tir: mevcut bir veritabanında tekrar çalıştırılması güvenlidir, veri silmez.

  3. Bildirim istiyorsanız init.sql içindeki fcm_notify_event fonksiyonundaki Edge Function URL'sini kendi proje adresinizle değiştirin.

2) TMDB Anahtarı (Repoya EKLENMEZ)

Proje ana dizinindeki local.properties dosyasına aşağıdaki satırı ekleyin (bu dosya .gitignore içindedir, git reposuna asla gitmez):

tmdb.api.key=BU_KISMA_TMDB_API_ANAHTARINIZI_YAZIN

Anahtar, derleme sırasında BuildConfig.TMDB_API_KEY değişkenine okunur. Ücretsiz anahtar: themoviedb.org. Anime tarafı (AniList) anahtar gerektirmeden çalışır.

⚠️ Supabase anahtarları kodda veya repoda saklanmaz. Supabase URL'si ve anon key, uygulamanın ilk açılışında elle girilir, gerçekten çalıştığı doğrulanır (profiles tablosuna probe atılır) ve yalnızca telefonun DataStore'unda saklanır.

3) Derleme

./gradlew :app:assembleDebug
# Çıktı APK konumu: app/build/outputs/apk/debug/app-debug.apk

4) İlk Açılış (Her telefonda bir kez)

  1. Supabase URL ve anon key bilgilerinizi girin (Project Settings → API).
  2. Profilinizi seçin: Van veya Sinop

Bilgiler DataStore'da saklanır; Profil sekmesinden istediğiniz an diğer profile geçebilirsiniz.

5) Bildirimler için Firebase (İsteğe Bağlı)

  • app/google-services.json dosyasını Firebase konsolundan indirip app/ klasörüne koyun — derleme sırasında değerler BuildConfig'e işlenir; dosya yoksa FCM sessizce devre dışı kalır (realtime + WorkManager çalışmaya devam eder).
  • Firebase'den service account JSON'u alın ve Supabase Dashboard → Edge Functions → Secrets bölümüne FCM_SERVICE_ACCOUNT adıyla ekleyin, sonra supabase/functions/notify fonksiyonunu deploy edin.

📦 Yayınlar (Release) — v3.2.5

Her sürümde aynı versionCode/versionName ile iki APK üretilir; ikisi de debug keystore ile imzalanır (app/build.gradle.kts → signingConfigs.release). Çıktı yolu aynı olduğu için önce API'siz, sonra API'li derlenir.

1️⃣ API'li Sürüm (TMDB anahtarlı) — masaüstüne

TMDB araması, kişi/stüdyo sayfaları ve İngilizce açıklama fallback'i tam çalışır; tester telefonlarına ve Firebase App Distribution'a bu yüklenir.

# local.properties'e TMDB anahtarınız yazılı olduğundan emin olun (tmdb.api.key=...)
./gradlew :app:assembleRelease
cp app/build/outputs/apk/release/app-release.apk ~/Masaüstü/minimuv-vX.Y.Z.apk

2️⃣ API'siz Sürüm — GitHub Releases'e

TMDB anahtarı derlenmez (boş BuildConfig), bu yüzden arama kapalıdır; gerisi çalışır.

./gradlew :app:assembleRelease -PtmdbApiKey=""
cp app/build/outputs/apk/release/app-release.apk ~/Sürümler/minimuv-vX.Y.Z.apk   # GitHub'a yüklenir

İn-app güncelleme için: versionCode telefonda kurulu olandan büyük olmalı; Firebase aynı versionCode'un yeniden yüklenmesini reddettiği için her testte mutlaka artırın. google-services.json repoda yoktur; GitHub sürümünde FCM pasiftir. Kişisel sürüm için dosyayı app/ klasörüne koyup yeniden derleyin.


🗄️ Supabase Şeması

Tüm veritabanı şeması tek bir dosyada toplanmıştır: supabase/init.sql — tablolar, RLS, seed, Storage politikaları, realtime yayınları ve FCM trigger'ları dahil. Şemada değişiklik yapılacağı zaman yalnızca bu dosya güncellenir.

Tablolar

Tablo Amaç Önemli Alanlar
profiles Sabit iki profil name, emoji, avatar_color, avatar_url
titles İzlenen içerikler type (film/dizi/anime), status, score (çift ortalaması), overview + overview_en, title_en, episode_progress, total_episodes, start_date, finish_date, total_rewatches, watch_mode (birlikte/ayrı), priority_order, is_private, is_favorite
title_favorites Bir başlığı hangi profilin favorilediği title_id + profile_id (benzersiz)
title_notes Başlıklara yazılan tekil notlar title_id, profile_id, note_text, emoji
title_scores Kişi bazlı puanlar title_id + profile_id (benzersiz), score, story, characters, visuals, audio, enjoyment
episode_progress_per_profile Ayrı modda kişisel bölüm ilerlemesi title_id + profile_id (benzersiz), current_episode
episode_notes Bölüm bazlı notlar (spoiler korumalı) episode_number, note_text, emoji_reaction
achievements Çift bazlı rozetler achievement_key (benzersiz), progress_current/target
watch_log Takvim/istatistik günlüğü date, episodes_watched
partner_pings Gizli menü mesajları from_profile, message
fcm_tokens Cihaz push token'ları token (benzersiz), profile_id
favorites Kişi/karakter/stüdyo favorileri profile_id, fav_type (person/character/studio), source, external_id, name, image_url

Ayrıca: aynı yapım (aynı tür + harici ID) veritabanı seviyesinde iki kez eklenemez (partial unique index); titles güncellemelerinde updated_at otomatik işlenir.

Canlı DB ↔ init.sql farkı: Canlı projede, init.sql'de bulunmayan v3 kimlik/çok kullanıcı nesneleri var (profiles.auth_user_id/username/..., friendships, watch_proposals, reports, current_profile_id() vb.). Bunlar terk edilmiş v2-temel hattından kalmıştır ve uygulama tarafından kullanılmaz. Veri kaybını önlemek için canlıdan silinmedi; yeni kurulumlar bu nesneler olmadan çalışır. İleride ya tamamen kaldırılmalı ya da v3 hattıyla birlikte yeniden benimsenmelidir.

Başlangıç Verisi (Seed)

insert into public.profiles (name, emoji, avatar_color)
select 'Van', '🌊', '#4EA8DE' where not exists (select 1 from public.profiles where name = 'Van');

insert into public.profiles (name, emoji, avatar_color)
select 'Sinop', '🦜', '#FF8FA3' where not exists (select 1 from public.profiles where name = 'Sinop');

🗂️ Mimari

app/src/main/java/com/sinop/minimuv/
├── core/            # SupabaseProvider, RealtimeManager, SearchApi (TMDB+AniList),
│                    # bildirim çekirdeği: NotificationHelper + PartnerEvents,
│                    # MinimuvMessagingService (FCM) + NotificationWorker (WorkManager),
│                    # WheelSound (çark sesleri, SoundPool)
├── data/            # Modeller, SettingsStore (DataStore), Repository sınıfları,
│                    # Achievements (27 rozet tanımı + ortak istatistik hesabı) + AchievementChecker
├── ui/
│   ├── theme/       # Midnight paleti, 15 vurgu rengi, Plus Jakarta Sans tipografisi
│   ├── components/  # PosterCard, StatusChip, ScoreBadge, InAppUpdateHost, Confetti...
│   └── screens/
│       ├── list/    # Gruplandırılmış kütüphane (LibraryScreen), 4 görünüm modu, filtreler,
│       │            # sürükle-bırak sıra düzenleme (PlanOrderScreen)
│       ├── detail/  # Okuma modu + katlanabilir kartlı düzenleme (DetailScreen, DetailEditCards)
│       ├── add/     # Debounce'lu arama, önizleme sayfası, manuel ekleme (AddScreen)
│       ├── wheel/   # Afişli randevu çarkı (WheelScreen) + ses (WheelSound)
│       ├── achievements/  # Rozet yolculuğu (AchievementsScreen)
│       ├── stats/   # Heatmap (26 hafta) + Wrapped (yıl özeti)
│       ├── profile/ # Profil yönetimi, kırpmalı fotoğraf, favoriler (ProfileScreen)
│       ├── setup/   # Doğrulamalı Supabase bağlantısı + profil seçimi
│       └── settings # Tema, bildirim araçları, gizli menü, sıfırlama (SettingsScreen)
└── supabase/
    ├── init.sql           # Tek dosyada tüm şema (idempotent)
    └── functions/notify/  # FCM Edge Function (service account ile OAuth → FCM v1 API)

⚠️ Güvenlik Modeli (Bilinçli Tercih)

Uygulamada kullanıcı adı/şifre sistemi yoktur. Veritabanına "anon key" ile bağlanılır, profil ayrımı cihazın yerel hafızasındaki seçimle yapılır. Bu, anon key'i bilen herkesin verilerinize erişebileceği anlamına gelir:

  • Supabase URL + anon key ikilisini kimseyle paylaşmayın (APK içinde bulunmaz, ilk açılışta elle girilir).
  • Repoyu private tutun; kişisel bir proje olduğu için bu basitleştirme kabul edilmiştir.

📄 Lisans

Kişisel proje — her hakkı saklıdır. Van & Sinop için, sevgiyle yapıldı. 💑

About

Çiftler için 2 kişilik film, dizi ve anime takip uygulaması. Ortak puanlama, bölüm notları, seçim çarkı, rozetler ve istatistikler.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages