├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── resources.properties
│ │ │ ├── drawable-nodpi
│ │ │ │ ├── slide_one.png
│ │ │ │ ├── slide_two.png
│ │ │ │ ├── slide_three.png
│ │ │ │ ├── icon_birday_eye_1.png
│ │ │ │ ├── icon_birday_eye_2.png
│ │ │ │ ├── icon_birday_eye_3.png
│ │ │ │ ├── icon_birday_eye_4.png
│ │ │ │ ├── icon_birday_eye_5.png
│ │ │ │ ├── icon_birday_eye_6.png
│ │ │ │ ├── icon_birday_angry_1.png
│ │ │ │ ├── icon_birday_angry_2.png
│ │ │ │ ├── icon_birday_angry_3.png
│ │ │ │ ├── icon_birday_angry_4.png
│ │ │ │ ├── icon_birday_angry_5.png
│ │ │ │ ├── icon_birday_angry_6.png
│ │ │ │ ├── icon_birday_angry_7.png
│ │ │ │ ├── icon_birday_angry_8.png
│ │ │ │ ├── icon_birday_angry_9.png
│ │ │ │ ├── icon_birday_normal.png
│ │ │ │ ├── icon_birday_wing_1.png
│ │ │ │ ├── icon_birday_wing_2.png
│ │ │ │ ├── icon_birday_wing_3.png
│ │ │ │ ├── icon_birday_wing_4.png
│ │ │ │ ├── icon_birday_wing_5.png
│ │ │ │ ├── icon_birday_wing_6.png
│ │ │ │ ├── icon_birday_wing_7.png
│ │ │ │ ├── icon_birday_wing_8.png
│ │ │ │ ├── birday_widget_preview.png
│ │ │ │ ├── icon_birday_angry_10.png
│ │ │ │ └── birday_minimal_widget_preview.png
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── raw
│ │ │ │ └── birday_notification.mp3
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── values
│ │ │ │ ├── ic_launcher_background.xml
│ │ │ │ ├── attrs.xml
│ │ │ │ ├── ids.xml
│ │ │ │ └── arrays.xml
│ │ │ ├── xml
│ │ │ │ ├── filepaths.xml
│ │ │ │ ├── backup_rules.xml
│ │ │ │ ├── widget_upcoming_info.xml
│ │ │ │ ├── data_extraction_rules.xml
│ │ │ │ ├── widget_minimal_info.xml
│ │ │ │ ├── fragment_favorites_scene.xml
│ │ │ │ └── fragment_home_scene.xml
│ │ │ ├── drawable
│ │ │ │ ├── static_branding_image.xml
│ │ │ │ ├── widget_inner_rounded_container.xml
│ │ │ │ ├── colored_shadow_gradient.xml
│ │ │ │ ├── scroll_line_drawable.xml
│ │ │ │ ├── scroll_thumb_drawable.xml
│ │ │ │ ├── ic_triangle_24dp.xml
│ │ │ │ ├── custom_cursor.xml
│ │ │ │ ├── bottom_navbar_item.xml
│ │ │ │ ├── ic_favorites_24dp.xml
│ │ │ │ ├── line.xml
│ │ │ │ ├── ic_dot_small_24dp.xml
│ │ │ │ ├── ic_star_24dp.xml
│ │ │ │ ├── ic_delete_24dp.xml
│ │ │ │ ├── ic_arrow_up_24dp.xml
│ │ │ │ ├── ic_arrow_left_24dp.xml
│ │ │ │ ├── ic_arrow_right_24dp.xml
│ │ │ │ ├── ic_apps_24dp.xml
│ │ │ │ ├── ic_note_24dp.xml
│ │ │ │ ├── ic_app_behavior_24dp.xml
│ │ │ │ ├── ic_zodiac_sagittarius.xml
│ │ │ │ ├── ic_stats_24dp.xml
│ │ │ │ ├── ic_octagram_24dp.xml
│ │ │ │ ├── ic_dot_black_24dp.xml
│ │ │ │ ├── ic_balloon_24dp.xml
│ │ │ │ ├── ic_alert_24dp.xml
│ │ │ │ ├── ic_date_black_24dp.xml
│ │ │ │ ├── ic_clear_24dp.xml
│ │ │ │ ├── ic_death_anniversary_24dp.xml
│ │ │ │ ├── ic_backup_restore_24dp.xml
│ │ │ │ ├── ic_note_missing_24dp.xml
│ │ │ │ ├── ic_inverted_circle_foreground_black_24dp.xml
│ │ │ │ ├── ic_apps_email_24dp.xml
│ │ │ │ ├── time_picker_chip_color.xml
│ │ │ │ ├── ic_edit_24dp.xml
│ │ │ │ ├── ic_neutral_72dp.xml
│ │ │ │ ├── ic_pen_24dp.xml
│ │ │ │ ├── ic_zodiac_libra.xml
│ │ │ │ ├── ic_apps_telegram_24dp.xml
│ │ │ │ ├── ic_zodiac_taurus.xml
│ │ │ │ ├── ic_anniversary_24dp.xml
│ │ │ │ ├── ic_zodiac_aquarius.xml
│ │ │ │ ├── nav_animation_home.xml
│ │ │ │ ├── thumb.xml
│ │ │ │ ├── time_picker_chip_background_color.xml
│ │ │ │ ├── ic_play_store_black_24dp.xml
│ │ │ │ ├── ic_smile_24dp.xml
│ │ │ │ ├── nav_animation_settings.xml
│ │ │ │ ├── ic_zodiac_pisces.xml
│ │ │ │ ├── nav_animation_favorites.xml
│ │ │ │ ├── ic_zodiac_scorpio.xml
│ │ │ │ ├── snackbar_background.xml
│ │ │ │ ├── dialog_bg_monet.xml
│ │ │ │ ├── ic_event_type_black_24dp.xml
│ │ │ │ ├── ic_zodiac_gemini.xml
│ │ │ │ ├── ic_ring_24dp.xml
│ │ │ │ ├── ic_zodiac_capricorn.xml
│ │ │ │ ├── ic_zodiac_aries.xml
│ │ │ │ ├── ic_sad_72dp.xml
│ │ │ │ ├── ic_troubleshoot_24dp.xml
│ │ │ │ ├── ic_other_24dp.xml
│ │ │ │ ├── ic_instagram_black_24dp.xml
│ │ │ │ ├── ic_apps_messages_24dp.xml
│ │ │ │ ├── ic_person_search_24dp.xml
│ │ │ │ ├── ic_notifications_24dp.xml
│ │ │ │ ├── static_birday_dark.xml
│ │ │ │ ├── static_birday_light.xml
│ │ │ │ ├── ic_cool_black_24dp.xml
│ │ │ │ ├── ic_apps_messenger_24dp.xml
│ │ │ │ ├── ic_zodiac_virgo.xml
│ │ │ │ ├── ic_customization_24dp.xml
│ │ │ │ ├── ic_home_24dp.xml
│ │ │ │ ├── ic_zodiac_leo.xml
│ │ │ │ ├── ic_minar_logo_24dp.xml
│ │ │ │ ├── ic_zodiac_cancer.xml
│ │ │ │ ├── ic_share_black_24dp.xml
│ │ │ │ ├── ic_date_question_black_24dp.xml
│ │ │ │ ├── ic_settings_24dp.xml
│ │ │ │ ├── ic_apps_dialer_24dp.xml
│ │ │ │ ├── ic_github_black_24dp.xml
│ │ │ │ ├── ic_party_24dp.xml
│ │ │ │ ├── ic_apps_threema_24dp.xml
│ │ │ │ ├── ic_party_white_24dp.xml
│ │ │ │ ├── ic_translate_24dp.xml
│ │ │ │ ├── ic_name_day_24dp.xml
│ │ │ │ ├── ic_apps_whatsapp_24dp.xml
│ │ │ │ ├── birday_logo_mono.xml
│ │ │ │ ├── placeholder_other_image.xml
│ │ │ │ ├── animated_angry_notification_icon.xml
│ │ │ │ ├── placeholder_birthday_image.xml
│ │ │ │ ├── placeholder_name_day_image.xml
│ │ │ │ ├── placeholder_death_image.xml
│ │ │ │ ├── static_notification_icon.xml
│ │ │ │ ├── placeholder_anniversary_image.xml
│ │ │ │ ├── birday_logo.xml
│ │ │ │ └── ic_apps_signal_24dp.xml
│ │ │ ├── mipmap-anydpi
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── values-v27
│ │ │ │ └── styles.xml
│ │ │ ├── anim
│ │ │ │ ├── nav_enter_anim.xml
│ │ │ │ ├── nav_pop_enter_anim.xml
│ │ │ │ ├── nav_exit_anim.xml
│ │ │ │ ├── nav_exit_secondary_anim.xml
│ │ │ │ ├── nav_pop_exit_anim.xml
│ │ │ │ ├── nav_pop_enter_secondary_anim.xml
│ │ │ │ ├── nav_enter_secondary_anim.xml
│ │ │ │ └── nav_pop_exit_secondary_anim.xml
│ │ │ ├── layout
│ │ │ │ ├── preference_switch_widget.xml
│ │ │ │ ├── event_type_list_item.xml
│ │ │ │ ├── month_header_row.xml
│ │ │ │ ├── clear_db_row.xml
│ │ │ │ ├── json_export_row.xml
│ │ │ │ ├── json_import_row.xml
│ │ │ │ ├── time_picker_row.xml
│ │ │ │ ├── birday_export_row.xml
│ │ │ │ ├── birday_import_row.xml
│ │ │ │ ├── add_demo_entries_row.xml
│ │ │ │ ├── notification_sound_row.xml
│ │ │ │ ├── csv_export_row.xml
│ │ │ │ ├── csv_import_row.xml
│ │ │ │ ├── disable_optimizations_row.xml
│ │ │ │ ├── dialog_notes.xml
│ │ │ │ ├── missed_carousel_item.xml
│ │ │ │ ├── calendar_export_row.xml
│ │ │ │ ├── calendar_import_row.xml
│ │ │ │ └── contacts_import_row.xml
│ │ │ ├── values-v31
│ │ │ │ ├── arrays.xml
│ │ │ │ └── styles.xml
│ │ │ ├── values-night-v31
│ │ │ │ └── styles.xml
│ │ │ ├── menu
│ │ │ │ └── navigation_bottomappbar.xml
│ │ │ └── values-v32
│ │ │ │ └── arrays.xml
│ │ ├── ic_launcher-playstore.png
│ │ └── java
│ │ │ └── com
│ │ │ └── minar
│ │ │ └── birday
│ │ │ ├── model
│ │ │ ├── EventCode.kt
│ │ │ ├── EventType.kt
│ │ │ ├── EventDataItem.kt
│ │ │ ├── ImportedEvent.kt
│ │ │ ├── ContactInfo.kt
│ │ │ ├── EventResult.kt
│ │ │ └── Event.kt
│ │ │ ├── utilities
│ │ │ ├── FragmentUtils.kt
│ │ │ ├── ColorUtils.kt
│ │ │ ├── LocalDateJsonSerializer.kt
│ │ │ ├── FileUtils.kt
│ │ │ ├── ChineseCalendarUtils.kt
│ │ │ └── AppRater.kt
│ │ │ ├── persistence
│ │ │ ├── LocalDateTypeConverter.kt
│ │ │ └── EventDatabase.kt
│ │ │ ├── receivers
│ │ │ └── NotificationActionReceiver.kt
│ │ │ ├── widgets
│ │ │ ├── EventWidgetProvider.kt
│ │ │ └── MinimalWidgetProvider.kt
│ │ │ ├── viewmodels
│ │ │ └── InsertEventViewModel.kt
│ │ │ ├── preferences
│ │ │ └── standard
│ │ │ │ ├── NotificationSoundPreference.kt
│ │ │ │ ├── ExperimentalDisclaimerPreference.kt
│ │ │ │ ├── ClearDBPreference.kt
│ │ │ │ └── AddDemoEntriesPreference.kt
│ │ │ ├── fragments
│ │ │ └── dialogs
│ │ │ │ └── ImportContactsBottomSheet.kt
│ │ │ └── workers
│ │ │ └── ImportContactsWorker.kt
│ └── test
│ │ └── java
│ │ └── com
│ │ └── minar
│ │ └── birday
│ │ └── utils
│ │ └── ChineseCalendarUnitTest.kt
└── proguard-rules.pro
├── fastlane
└── metadata
│ └── android
│ ├── en-US
│ ├── title.txt
│ ├── short_description.txt
│ ├── images
│ │ ├── icon.png
│ │ ├── featureGraphic.png
│ │ └── phoneScreenshots
│ │ │ ├── 01.png
│ │ │ ├── 02.png
│ │ │ ├── 03.png
│ │ │ ├── 04.png
│ │ │ ├── 05.png
│ │ │ ├── 06.png
│ │ │ ├── 07.png
│ │ │ ├── 08.png
│ │ │ ├── 09.png
│ │ │ └── 10.png
│ ├── changelogs
│ │ ├── 21.txt
│ │ ├── 8.txt
│ │ ├── 15.txt
│ │ ├── 10.txt
│ │ ├── 26.txt
│ │ ├── 27.txt
│ │ ├── 33.txt
│ │ ├── 20.txt
│ │ ├── 35.txt
│ │ ├── 19.txt
│ │ ├── 13.txt
│ │ ├── 25.txt
│ │ ├── 31.txt
│ │ ├── 37.txt
│ │ ├── 9.txt
│ │ ├── 11.txt
│ │ ├── 23.txt
│ │ └── 14.txt
│ └── full_description.txt
│ └── fr-FR
│ ├── title.txt
│ └── short_description.txt
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── crowdin.yml
├── settings.gradle.kts
├── .github
├── workflows
│ └── build.yaml
└── FUNDING.yml
├── .gitignore
├── scripts
└── check_translate_missing_strings.sh
└── gradle.properties
/app/.gitignore:
--------------------------------------------------------------------------------
1 | build
2 | release
3 | debug
--------------------------------------------------------------------------------
/app/src/main/res/resources.properties:
--------------------------------------------------------------------------------
1 | unqualifiedResLocale=en-US
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/title.txt:
--------------------------------------------------------------------------------
1 | Birday - Birthday Manager
--------------------------------------------------------------------------------
/fastlane/metadata/android/fr-FR/title.txt:
--------------------------------------------------------------------------------
1 | Birday - Gestionnaire d'anniversaires
2 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/short_description.txt:
--------------------------------------------------------------------------------
1 | A simple yet useful birthday manager. Birday is free and ad-free! 🥳
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/slide_one.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/slide_one.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/slide_two.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/slide_two.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/raw/birday_notification.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/raw/birday_notification.mp3
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/slide_three.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/slide_three.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/fastlane/metadata/android/en-US/images/icon.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/fr-FR/short_description.txt:
--------------------------------------------------------------------------------
1 | Un gestionnaire d'anniversaire simple et utile. Birday est gratuit et sans publicité! 🥳
2 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_eye_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_eye_1.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_eye_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_eye_2.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_eye_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_eye_3.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_eye_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_eye_4.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_eye_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_eye_5.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_eye_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_eye_6.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/21.txt:
--------------------------------------------------------------------------------
1 | - New list to detail transition
2 | - Splashscreen improved
3 | - Important fixes
4 | - Translations updated
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/8.txt:
--------------------------------------------------------------------------------
1 | - Added vietnamese translation
2 | - Notifications improved
3 | - Icon restyled
4 | - Some important fixes
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_angry_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_angry_1.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_angry_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_angry_2.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_angry_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_angry_3.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_angry_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_angry_4.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_angry_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_angry_5.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_angry_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_angry_6.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_angry_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_angry_7.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_angry_8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_angry_8.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_angry_9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_angry_9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_normal.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_wing_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_wing_1.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_wing_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_wing_2.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_wing_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_wing_3.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_wing_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_wing_4.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_wing_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_wing_5.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_wing_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_wing_6.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_wing_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_wing_7.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_wing_8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_wing_8.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/birday_widget_preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/birday_widget_preview.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/icon_birday_angry_10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/icon_birday_angry_10.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/featureGraphic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/fastlane/metadata/android/en-US/images/featureGraphic.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/01.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/02.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/03.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/04.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/05.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/06.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/07.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/07.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/08.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/08.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/09.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/09.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/10.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/birday_minimal_widget_preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/m-i-n-a-r/birday/HEAD/app/src/main/res/drawable-nodpi/birday_minimal_widget_preview.png
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 |
--------------------------------------------------------------------------------
/crowdin.yml:
--------------------------------------------------------------------------------
1 | files:
2 | - source: app/src/main/res/values/strings.xml
3 | translation: /app/src/main/res/values-%android_code%/strings.xml
4 | translate_attributes: 0
5 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/filepaths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/model/EventCode.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.model
2 |
3 | enum class EventCode {
4 | BIRTHDAY,
5 | ANNIVERSARY,
6 | DEATH,
7 | NAME_DAY,
8 | OTHER
9 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/model/EventType.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.model
2 |
3 | data class EventType(val codeName: EventCode, val value: String) {
4 | override fun toString(): String = value // The value shown in the spinner
5 | }
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/15.txt:
--------------------------------------------------------------------------------
1 | - Choose any notification time you want, thanks to the new timepicker!
2 | - Fixed an important time zone related bug
3 | - Some UI improvements
4 | - Traditional chinese translation, updated other languages
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/10.txt:
--------------------------------------------------------------------------------
1 | - Animated notification icon
2 | - Many graphic improvements
3 | - Russian translation, thanks koterpillar
4 | - Under the hood improvements
5 | - Less annoying permission related toast messages
6 | - Fixed some typos
--------------------------------------------------------------------------------
/app/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
9 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/26.txt:
--------------------------------------------------------------------------------
1 | - Other options and preview for the minimal widget
2 | - Advanced overview mode
3 | - UI Improvements
4 | - New list animations and transitions
5 | - Some fixes, including a better contacts import
6 | - Many translations updated
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/27.txt:
--------------------------------------------------------------------------------
1 | - Other options and preview for the minimal widget
2 | - Advanced overview mode
3 | - UI Improvements
4 | - New list animations and transitions
5 | - Some fixes, including a better contacts import
6 | - Many translations updated
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/33.txt:
--------------------------------------------------------------------------------
1 | - Many important fixes (csv import for example)
2 | - Recently missed events in quick apps dialog
3 | - Auto export (experimental)
4 | - Export to calendar (experimental, long press to delete local calendar)
5 | - New translations and more!
--------------------------------------------------------------------------------
/app/src/main/res/drawable/static_branding_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/20.txt:
--------------------------------------------------------------------------------
1 | - Shortcut to disable battery optimizations
2 | - Shortcut to change notification sound
3 | - New animation and icon for name days
4 | - Search improved and fixed
5 | - Optimizations for small screens/ big text sizes
6 | - Other important fixes and improvements
--------------------------------------------------------------------------------
/app/src/main/res/drawable/widget_inner_rounded_container.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/colored_shadow_gradient.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/scroll_line_drawable.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/scroll_thumb_drawable.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_triangle_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/35.txt:
--------------------------------------------------------------------------------
1 | - Many important fixes, again
2 | - Material3 Expressive
3 | - Open contacts details from event details, if available
4 | - Better disable battery optimization procedure
5 | - Choose where to export Birday, csv, json backups
6 | - Better layout for current/next age
7 | - New translations and translations updated
--------------------------------------------------------------------------------
/app/src/main/res/drawable/custom_cursor.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/utilities/FragmentUtils.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.utilities
2 |
3 | import androidx.fragment.app.DialogFragment
4 | import androidx.fragment.app.FragmentManager
5 |
6 | fun DialogFragment.showIfNotAdded(fragmentManager: FragmentManager, tag: String) {
7 | if (!isAdded) {
8 | show(fragmentManager, tag)
9 | }
10 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bottom_navbar_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_favorites_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | -keep class com.minar.birday.model.EventResult
9 | -keep class androidx.constraintlayout.** { *; }
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/line.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_dot_small_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/19.txt:
--------------------------------------------------------------------------------
1 | - Material You! Now Birday uses the latest design guidelines
2 | - Support for anniversaries, death anniversaries and more
3 | - Quick glance 10 days view in the stats card
4 | - Edit the notes from the details page
5 | - System accent color (Android 12+)
6 | - New splashscreen
7 | - New translations, previous translations updated
8 | - Many fixes
9 | - Various UI improvements
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/13.txt:
--------------------------------------------------------------------------------
1 | - Fixed an important bug involving leap years
2 | - Notes improved, an icon is shown if the event has a note
3 | - Decreased widget minimum size, improved update behavior
4 | - Emoji allowed in name and last name fields
5 | - Long press on the round buttons when the card is hidden to open the corresponding menu
6 | - Portuguese translation, typos fixed
7 | - Other fixes and improvements
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_star_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/25.txt:
--------------------------------------------------------------------------------
1 | - The old widget is back, and is now customizable
2 | - New experimental settings (Angry Bird mode, delete search results)
3 | - Additional notification up to 21 days before
4 | - Choose to send the additional notification only for favorite contacts
5 | - Import the events in your calendar
6 | - More UI improvements, translate the app button
7 | - Translations updated and many bugs fixed
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_delete_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_arrow_up_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_arrow_left_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_arrow_right_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_apps_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_note_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/31.txt:
--------------------------------------------------------------------------------
1 | - Black Amoled theme, UI improvements
2 | - Multiple additional notifications
3 | - Group or ungroup notifications
4 | - Disable animation looping
5 | - Display the events in alphabetical order
6 | - Selectable conflict strategy when importing
7 | - Android 14 predictive back
8 | - Rearranged the settings
9 | - Demo elements DB, for testing purposes
10 | - New translations, translations updated
11 | - Many fixes and much more!
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/utilities/ColorUtils.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.utilities
2 |
3 | import android.content.Context
4 | import android.util.TypedValue
5 | import androidx.annotation.AttrRes
6 |
7 | // Return any attr color, to use it programmatically
8 | fun getThemeColor(@AttrRes attrRes: Int, context: Context): Int {
9 | val typedValue = TypedValue()
10 | context.theme.resolveAttribute(attrRes, typedValue, true)
11 | return typedValue.data
12 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_app_behavior_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_zodiac_sagittarius.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_stats_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_octagram_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_dot_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_balloon_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/model/EventDataItem.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.model
2 |
3 | // A wrapper around EventResult, to also consider the month header as an object
4 | sealed class EventDataItem {
5 | data class EventItem(val eventResult: EventResult) : EventDataItem() {
6 | override val id = eventResult.id.toLong()
7 | }
8 |
9 | data class IndexHeader(val headerTitle: String) : EventDataItem() {
10 | override val id = Long.MIN_VALUE
11 | }
12 |
13 | abstract val id: Long
14 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_alert_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_date_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_clear_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_death_anniversary_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v27/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/37.txt:
--------------------------------------------------------------------------------
1 | - Many important fixes, again
2 | - Material3 Expressive and various UI improvements
3 | - Open contacts details from event details, if available
4 | - Better disable battery optimization procedure
5 | - Tristate favorite button: normal, favorite, ignored (no notification for that event, ever)
6 | - Choose what to import from Birday, csv, json and calendar import
7 | - Choose where to export Birday, csv, json backups
8 | - Better layout for current/next age
9 | - New translations and translations updated
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/9.txt:
--------------------------------------------------------------------------------
1 | - Create yearless events
2 | - The yearless events imported will remain yearless
3 | - Surname first option
4 | - The favorite screen has now a better layout and a countdown for each event!
5 | - Unified details and actions screen: simply tap an event to open it
6 | - Share an event: tap the share button to share a message containing the information about the event!
7 | - Celebrating 1500 Play Store downloads with a new accent color
8 | - Some important fixes and improvements
9 | - Translations updated
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_backup_restore_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_note_missing_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/nav_enter_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/preference_switch_widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/nav_pop_enter_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_inverted_circle_foreground_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/event_type_list_item.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_apps_email_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/time_picker_chip_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/11.txt:
--------------------------------------------------------------------------------
1 | - Option to enable the dark theme for the widget
2 | - Czech translation, thanks Miloš Koliáš
3 | - Easily hide and show the top cards with a beautiful animation, to fully support multiwindows
4 | - Every favorite event has now an handy note field, just tap on it!*
5 | - Animated event counter in the stats dialog
6 | - App size shrinked even more!
7 | - New and updated splashscreen animation
8 | - A lot of under the hood improvements and fixes
9 |
10 | * Despite this new field, the previous backups will still work and restore without any problem!
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_edit_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_neutral_72dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_pen_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_zodiac_libra.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_apps_telegram_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_zodiac_taurus.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | @file:Suppress("UnstableApiUsage")
2 |
3 | pluginManagement {
4 | repositories {
5 | gradlePluginPortal()
6 | google()
7 | mavenCentral()
8 | }
9 | }
10 |
11 | dependencyResolutionManagement {
12 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
13 | repositories {
14 | google()
15 | mavenCentral()
16 | maven("https://jitpack.io")
17 | }
18 | }
19 |
20 | plugins {
21 | id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
22 | }
23 |
24 | rootProject.name = "Birday"
25 | include(":app")
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_anniversary_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_zodiac_aquarius.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/nav_animation_home.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
10 |
11 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/thumb.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/time_picker_chip_background_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.github/workflows/build.yaml:
--------------------------------------------------------------------------------
1 | name: Build
2 | on: [pull_request, push]
3 | jobs:
4 | build:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - name: Setup Java 17
8 | uses: actions/setup-java@v3
9 | with:
10 | distribution: 'corretto'
11 | java-version: '17'
12 | - name: Checkout the code
13 | uses: actions/checkout@v2
14 | - name: Setup Android SDK
15 | uses: android-actions/setup-android@v3.2.0
16 | - name: Change wrapper permissions
17 | run: chmod +x ./gradlew
18 | - name: Build gradle project
19 | run: ./gradlew build
20 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_play_store_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_smile_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/nav_animation_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
10 |
11 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_zodiac_pisces.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/nav_animation_favorites.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
10 |
11 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_zodiac_scorpio.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/snackbar_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 |
9 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/23.txt:
--------------------------------------------------------------------------------
1 | - New full Material 3 UI
2 | - New full Material 3 widget
3 | - The widget features a list of all the events
4 | - Experimental settings (import/export CSV, import/export JSON, delete all events, hide on scroll, auto import from contacts at launch)
5 | - Android 13 specific features (monochrome icon, per app language support)
6 | - Dates from year 0 to tomorrow supported
7 | - Almost every single icon is animated now
8 | - New animated type selector to filter the events by type
9 | - New yearly overview screen
10 | - Many optimizations
11 | - A lot of bugs fixed
12 | - New languages supported
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/dialog_bg_monet.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
7 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_event_type_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_zodiac_gemini.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_ring_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/nav_exit_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/nav_exit_secondary_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/nav_pop_exit_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_zodiac_capricorn.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/nav_pop_enter_secondary_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_zodiac_aries.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_sad_72dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_troubleshoot_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_other_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/14.txt:
--------------------------------------------------------------------------------
1 | - Images are now fully supported in notifications, details and events
2 | - Option to disable the Images
3 | - Option to send the notification only for favorite events
4 | - Show last name in notification
5 | - New details screen, new animations
6 | - New and smarter datepicker (supports years from 1500 and keyboard)
7 | - Confetti effect the day of the event
8 | - New (now default) aqua accent
9 | - Better navigation (animations, flow)
10 | - Better backup validation
11 | - Easily revert an event deletion
12 | - A lot (i mean, seriously) of visual improvements
13 | - Many crashes and performance issues were fixed
14 | - Romanian and brazilian translations, portuguese, english, french, german and spanish updated
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_instagram_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_apps_messages_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_person_search_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_notifications_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/static_birday_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/static_birday_light.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cool_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/widget_upcoming_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: paypal.me/minardev
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_apps_messenger_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_zodiac_virgo.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/persistence/LocalDateTypeConverter.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.persistence
2 |
3 | import androidx.room.TypeConverter
4 | import java.lang.Exception
5 | import java.time.LocalDate
6 |
7 | class LocalDateTypeConverter {
8 | @TypeConverter
9 | fun stringToLocalDate(value: String?): LocalDate {
10 | // Extra steps to avoid crashes for leap years
11 | return try {
12 | if (value == null) LocalDate.now()
13 | else LocalDate.parse(value)
14 | } catch (_: Exception) {
15 | if (value!!.substring(5) == "02-29")
16 | LocalDate.parse("${value.substring(0,5)}03-01")
17 | else LocalDate.now()
18 | }
19 | }
20 |
21 | @TypeConverter
22 | fun localDateToString(date: LocalDate?): String? {
23 | return date?.toString()
24 | }
25 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_customization_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/receivers/NotificationActionReceiver.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.receivers
2 |
3 | import android.app.NotificationManager
4 | import android.content.BroadcastReceiver
5 | import android.content.Context
6 | import android.content.Intent
7 |
8 | class NotificationActionReceiver : BroadcastReceiver() {
9 | @Override
10 | override fun onReceive(context: Context, intent: Intent) {
11 | if (Intent.ACTION_BOOT_COMPLETED != intent.action) {
12 | val notificationId: Int = intent.getIntExtra("notificationId", 0)
13 |
14 | // Just cancel the notification. Any additional logic goes above this block
15 | val manager: NotificationManager =
16 | context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
17 | manager.cancel(notificationId)
18 | }
19 | }
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/nav_enter_secondary_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
18 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/data_extraction_rules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
10 |
13 |
16 |
17 |
18 |
21 |
24 |
27 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/nav_pop_exit_secondary_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
18 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_home_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_zodiac_leo.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_minar_logo_24dp.xml:
--------------------------------------------------------------------------------
1 |
8 |
13 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_zodiac_cancer.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/widget_minimal_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_share_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/utilities/LocalDateJsonSerializer.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.utilities
2 |
3 | import com.google.gson.TypeAdapter
4 | import com.google.gson.stream.JsonReader
5 | import com.google.gson.stream.JsonWriter
6 | import java.time.LocalDate
7 | import java.time.format.DateTimeFormatter
8 |
9 | // This class helps gson to serialize and deserialize a LocalDate
10 | class LocalDateJsonSerializer : TypeAdapter() {
11 |
12 | // Write a date to JSON, using a standard format
13 | override fun write(out: JsonWriter, value: LocalDate) {
14 | out.value(DateTimeFormatter.ISO_LOCAL_DATE.format(value))
15 | }
16 |
17 | // Read a date from JSON. If invalid, return the actual date
18 | override fun read(input: JsonReader): LocalDate {
19 | return try {
20 | LocalDate.parse(input.nextString())
21 | } catch (_: Exception) {
22 | LocalDate.now()
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_date_question_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_settings_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_apps_dialer_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/widgets/EventWidgetProvider.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.widgets
2 |
3 | import android.appwidget.AppWidgetManager
4 | import android.content.ComponentName
5 | import android.content.Context
6 | import android.content.Intent
7 | import com.minar.birday.R
8 |
9 |
10 | class EventWidgetProvider : BirdayWidgetProvider() {
11 |
12 | override var widgetLayout
13 | get() = R.layout.widget_upcoming
14 | set(_) {
15 | R.layout.widget_upcoming
16 | }
17 |
18 | override fun onReceive(context: Context, intent: Intent) {
19 | val action = intent.action
20 | if (action.equals(AppWidgetManager.ACTION_APPWIDGET_UPDATE)) {
21 | val mgr = AppWidgetManager.getInstance(context)
22 | val cn = ComponentName(context, EventWidgetProvider::class.java)
23 | mgr.getAppWidgetIds(cn).forEach { appWidgetId ->
24 | updateAppWidget(context, mgr, appWidgetId)
25 | }
26 | }
27 | super.onReceive(context, intent)
28 | }
29 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_github_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/widgets/MinimalWidgetProvider.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.widgets
2 |
3 | import android.appwidget.AppWidgetManager
4 | import android.content.ComponentName
5 | import android.content.Context
6 | import android.content.Intent
7 | import com.minar.birday.R
8 |
9 |
10 | class MinimalWidgetProvider : BirdayWidgetProvider() {
11 |
12 | override var widgetLayout
13 | get() = R.layout.widget_minimal
14 | set(_) {
15 | R.layout.widget_minimal
16 | }
17 |
18 | override fun onReceive(context: Context, intent: Intent) {
19 | val action = intent.action
20 | if (action.equals(AppWidgetManager.ACTION_APPWIDGET_UPDATE)) {
21 | val mgr = AppWidgetManager.getInstance(context)
22 | val cn = ComponentName(context, MinimalWidgetProvider::class.java)
23 | mgr.getAppWidgetIds(cn).forEach { appWidgetId ->
24 | updateAppWidget(context, mgr, appWidgetId)
25 | }
26 | }
27 | super.onReceive(context, intent)
28 | }
29 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_party_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/model/ImportedEvent.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.model
2 |
3 | // Used to hold an imported contact in contacts importer
4 | data class ImportedEvent(
5 | val id: String,
6 | val completeName: String,
7 | val eventDate: String,
8 | val image: ByteArray? = null,
9 | val eventType: String = EventCode.BIRTHDAY.name,
10 | val customLabel: String? = null
11 | ) {
12 | override fun equals(other: Any?): Boolean {
13 | if (this === other) return true
14 | if (javaClass != other?.javaClass) return false
15 |
16 | other as ImportedEvent
17 |
18 | if (completeName != other.completeName) return false
19 | if (eventDate != other.eventDate) return false
20 | if (eventType != other.eventType) return false
21 | if (!image.contentEquals(other.image)) return false
22 |
23 | return true
24 | }
25 |
26 | override fun hashCode(): Int {
27 | var result = completeName.hashCode()
28 | result = 31 * result + eventDate.hashCode()
29 | result = 31 * result + image.contentHashCode()
30 | return result
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/month_header_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/libraries
5 | /.idea/modules.xml
6 | /.idea/workspace.xml
7 | .DS_Store
8 | /build
9 | /captures
10 | .externalNativeBuild
11 |
12 | ### Android ###
13 | # Built application files
14 | *.apk
15 | *.aab
16 | *.ap_
17 | output-metadata.json
18 |
19 | # Files for the ART/Dalvik VM
20 | *.dex
21 |
22 | # Java class files
23 | *.class
24 |
25 | # Generated files
26 | bin/
27 | gen/
28 | out/
29 |
30 | # Gradle files
31 | .gradle/
32 | build/
33 |
34 | # Local configuration file (sdk path, etc)
35 | local.properties
36 |
37 | # Proguard folder generated by Eclipse
38 | proguard/
39 |
40 | # Log Files
41 | *.log
42 |
43 | # Android Studio Navigation editor temp files
44 | .navigation/
45 |
46 | # Android Studio captures folder
47 | captures/
48 |
49 | # Intellij
50 | *.iml
51 | .idea/
52 |
53 | # External native build folder generated in Android Studio 2.2 and later
54 | .externalNativeBuild
55 |
56 | # Freeline
57 | freeline.py
58 | freeline/
59 | freeline_project_description.json
60 |
61 | # Android Patch
62 | gen-external-apklibs
63 |
64 | # Json Output
65 | app/debug/output.json
66 | app/release/output.json
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/utilities/FileUtils.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.utilities
2 |
3 | import android.content.ContentResolver
4 | import android.content.Context
5 | import android.content.Intent
6 | import android.net.Uri
7 | import androidx.annotation.AnyRes
8 | import com.minar.birday.BuildConfig
9 | import com.minar.birday.R
10 |
11 | // Get the URI for a file in the raw folder
12 | fun getResourceUri(@AnyRes resourceId: Int): Uri =
13 | Uri.Builder()
14 | .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
15 | .authority(BuildConfig.APPLICATION_ID)
16 | .path(resourceId.toString())
17 | .build()
18 |
19 | // Share a content Uri (e.g. an Uri from SAF)
20 | fun shareUri(context: Context, uri: Uri) {
21 | val shareIntent = Intent(Intent.ACTION_SEND).apply {
22 | addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
23 | putExtra(Intent.EXTRA_STREAM, uri)
24 | type = context.contentResolver.getType(uri) ?: "*/*"
25 | }
26 | if (shareIntent.resolveActivity(context.packageManager) != null)
27 | context.startActivity(Intent.createChooser(shareIntent, context.getString(R.string.share_event)))
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_apps_threema_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
13 |
14 |
--------------------------------------------------------------------------------
/scripts/check_translate_missing_strings.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | FOLDER_TO_CHECK="${1}"
4 |
5 | ################################################################################
6 | gather_main_strings() {
7 | local strings_main_file="app/src/main/res/values/strings.xml"
8 |
9 | STRINGS_MAIN=$(grep "name=" "${strings_main_file}" | \
10 | grep -v "translatable" | cut -d '"' -f2)
11 | }
12 |
13 | gather_strings_to_be_translated() {
14 | local strings_to_check_file="app/src/main/res/${FOLDER_TO_CHECK}/strings.xml"
15 |
16 | # Check if file exists, exit otherwise
17 | if [ ! -f "${strings_to_check_file}" ]; then
18 | echo "Folder pattern should look like 'values-'"
19 | echo "File ($strings_to_check_file) does not exist, exiting..."
20 | exit 1
21 | fi
22 |
23 | STRINGS_TO_CHECK=$(grep "name=" "${strings_to_check_file}" | \
24 | grep -v "translatable" | cut -d '"' -f2)
25 | }
26 | ################################################################################
27 |
28 | gather_main_strings
29 | gather_strings_to_be_translated
30 |
31 | echo "The missing strings on ${FOLDER_TO_CHECK} are: "
32 | echo "${STRINGS_MAIN[@]}" "${STRINGS_TO_CHECK[@]}" | \
33 | tr ' ' '\n' | sort | uniq -u
34 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_party_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_translate_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v31/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | - @string/system_theme
6 | - @string/aqua
7 | - @string/brown
8 | - @string/blue
9 | - @string/green
10 | - @string/orange
11 | - @string/yellow
12 | - @string/teal
13 | - @string/violet
14 | - @string/pink
15 | - @string/light_blue
16 | - @string/red
17 | - @string/lime
18 | - @string/crimson
19 |
20 |
21 |
22 | - system
23 | - aqua
24 | - brown
25 | - blue
26 | - green
27 | - orange
28 | - yellow
29 | - teal
30 | - violet
31 | - pink
32 | - lightBlue
33 | - red
34 | - lime
35 | - crimson
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night-v31/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
13 |
14 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v31/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
13 |
14 |
15 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/navigation_bottomappbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
40 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v32/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | - @string/monet
6 | - @string/system_theme
7 | - @string/aqua
8 | - @string/brown
9 | - @string/blue
10 | - @string/green
11 | - @string/orange
12 | - @string/yellow
13 | - @string/teal
14 | - @string/violet
15 | - @string/pink
16 | - @string/light_blue
17 | - @string/red
18 | - @string/lime
19 | - @string/crimson
20 |
21 |
22 |
23 | - monet
24 | - system
25 | - aqua
26 | - brown
27 | - blue
28 | - green
29 | - orange
30 | - yellow
31 | - teal
32 | - violet
33 | - pink
34 | - lightBlue
35 | - red
36 | - lime
37 | - crimson
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/clear_db_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/json_export_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/json_import_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/time_picker_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/birday_export_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/birday_import_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/add_demo_entries_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/notification_sound_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/csv_export_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/csv_import_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/disable_optimizations_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/test/java/com/minar/birday/utils/ChineseCalendarUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.utils
2 |
3 | import com.ibm.icu.util.*
4 | import com.minar.birday.utilities.CalendarAdapter
5 | import com.minar.birday.utilities.chineseAnimalGeneric
6 | import org.junit.Assert.assertEquals
7 | import org.junit.Test
8 | import java.time.LocalDate
9 |
10 |
11 | // Implementation of calendar adapter for original ICU
12 | class ICUCalendar(private val calendar: Calendar): CalendarAdapter {
13 | override fun setTimeInMillis(value: Long) {
14 | calendar.timeInMillis = value
15 | }
16 |
17 | override fun get(field: Int): Int = calendar.get(field)
18 | }
19 |
20 | fun chineseAnimalTest(date: LocalDate): Int = chineseAnimalGeneric(
21 | getChinese = { ICUCalendar(ChineseCalendar()) },
22 | date
23 | )
24 |
25 | class ChineseAnimalUnitTest {
26 | // 2020 is the year of the Rat (0)
27 | // However, it started on January 25th, so January 10 is still in the year of the Pig (11)
28 |
29 | @Test
30 | fun chineseAnimal_is_pig_2020_early_January() {
31 | assertEquals(11, chineseAnimalTest(LocalDate.of(2020, 1, 20)))
32 | }
33 |
34 | @Test
35 | fun chineseAnimal_is_rat_2020_late_January() {
36 | assertEquals(0, chineseAnimalTest(LocalDate.of(2020, 1, 28)))
37 | }
38 |
39 | @Test
40 | fun chineseAnimal_is_rat_2020_June() {
41 | assertEquals(0, chineseAnimalTest(LocalDate.of(2020, 6, 1)))
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_name_day_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
13 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_apps_whatsapp_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/viewmodels/InsertEventViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.viewmodels
2 |
3 | import android.annotation.SuppressLint
4 | import android.app.Application
5 | import androidx.lifecycle.AndroidViewModel
6 | import androidx.lifecycle.LiveData
7 | import androidx.lifecycle.MutableLiveData
8 | import androidx.lifecycle.viewModelScope
9 | import com.minar.birday.activities.MainActivity
10 | import com.minar.birday.model.ContactInfo
11 | import com.minar.birday.persistence.ContactsRepository
12 | import kotlinx.coroutines.Dispatchers
13 | import kotlinx.coroutines.launch
14 | import kotlinx.coroutines.withContext
15 |
16 | @ExperimentalStdlibApi
17 | class InsertEventViewModel(application: Application) : AndroidViewModel(application) {
18 | private val contactsRepository = ContactsRepository()
19 |
20 | private val _contactsList = MutableLiveData>(emptyList())
21 |
22 | // Don't expose the Mutable version explicitly
23 | val contactsList: LiveData> = _contactsList
24 |
25 | @SuppressLint("MissingPermission")
26 | fun initContactsList(act: MainActivity) {
27 | if (act.askContactsPermission()) {
28 |
29 | val resolver = getApplication().contentResolver
30 | viewModelScope.launch {
31 | val contacts = withContext(Dispatchers.IO) {
32 | contactsRepository.queryContacts(resolver)
33 | }
34 | _contactsList.postValue(contacts)
35 | }
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/model/ContactInfo.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.model
2 |
3 | /**
4 | * Data class to group together the smallest information about a contact,
5 | * when extracted from the contacts list.
6 | *
7 | * Not intended to be an entity, but just a POJO in our business logic.
8 | */
9 | data class ContactInfo(
10 | val id: String,
11 | val name: String,
12 | val surname: String,
13 | val image: ByteArray?,
14 | ) {
15 | val fullName: String
16 | get() =
17 | if (surname.isBlank())
18 | name
19 | else
20 | "$name,$surname".replace("\\s".toRegex(), " ")
21 |
22 | override fun toString() = "$name $surname"
23 |
24 | override fun equals(other: Any?): Boolean {
25 | if (this === other) return true
26 | if (javaClass != other?.javaClass) return false
27 |
28 | other as ContactInfo
29 |
30 | if (id != other.id) return false
31 | if (name != other.name) return false
32 | if (surname != other.surname) return false
33 | if (image != null) {
34 | if (other.image == null) return false
35 | if (!image.contentEquals(other.image)) return false
36 | } else if (other.image != null) return false
37 |
38 | return true
39 | }
40 |
41 | override fun hashCode(): Int {
42 | var result = id.hashCode()
43 | result = 31 * result + name.hashCode()
44 | result = 31 * result + surname.hashCode()
45 | result = 31 * result + (image?.contentHashCode() ?: 0)
46 | return result
47 | }
48 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/birday_logo_mono.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/preferences/standard/NotificationSoundPreference.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.preferences.standard
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.provider.Settings
6 | import android.util.AttributeSet
7 | import android.view.View
8 | import android.widget.Toast
9 | import androidx.preference.Preference
10 | import androidx.preference.PreferenceViewHolder
11 | import com.minar.birday.R
12 | import com.minar.birday.databinding.NotificationSoundRowBinding
13 |
14 |
15 | // A custom preference to open the notification sound settings for Birday
16 | class NotificationSoundPreference(context: Context, attrs: AttributeSet?) :
17 | Preference(context, attrs),
18 | View.OnClickListener {
19 | private lateinit var binding: NotificationSoundRowBinding
20 |
21 | override fun onBindViewHolder(holder: PreferenceViewHolder) {
22 | super.onBindViewHolder(holder)
23 | binding = NotificationSoundRowBinding.bind(holder.itemView)
24 | binding.root.setOnClickListener(this)
25 | }
26 |
27 | override fun onClick(v: View) {
28 | try {
29 | val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
30 | .putExtra("android.provider.extra.APP_PACKAGE", context.packageName)
31 | .putExtra(Settings.EXTRA_CHANNEL_ID, "events_channel")
32 | context.startActivity(intent)
33 | } catch (_: Exception) {
34 | Toast.makeText(
35 | context, context.getString(R.string.wtf), Toast.LENGTH_LONG
36 | ).show()
37 | }
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/placeholder_other_image.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
15 |
19 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/animated_angry_notification_icon.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/model/EventResult.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.model
2 |
3 | import java.io.Serializable
4 | import java.time.LocalDate
5 |
6 | data class EventResult (
7 | val id: Int,
8 | val type: String? = EventCode.BIRTHDAY.name,
9 | var name: String,
10 | var surname: String? = "",
11 | var favorite: Boolean? = false,
12 | val yearMatter: Boolean? = true,
13 | var originalDate: LocalDate,
14 | val nextDate: LocalDate? = null,
15 | var notes: String? = "",
16 | val image: ByteArray? = null,
17 | ): Serializable {
18 | override fun equals(other: Any?): Boolean {
19 | if (this === other) return true
20 | if (javaClass != other?.javaClass) return false
21 |
22 | other as EventResult
23 |
24 | if (id != other.id) return false
25 | if (type != other.type) return false
26 | if (name != other.name) return false
27 | if (surname != other.surname) return false
28 | if (yearMatter != other.yearMatter) return false
29 | if (originalDate != other.originalDate) return false
30 | if (!image.contentEquals(other.image)) return false
31 |
32 | return true
33 | }
34 |
35 | override fun hashCode(): Int {
36 | var result = id
37 | result = 31 * result + (type?.hashCode() ?: 0)
38 | result = 31 * result + name.hashCode()
39 | result = 31 * result + (surname?.hashCode() ?: 0)
40 | result = 31 * result + (favorite?.hashCode() ?: 0)
41 | result = 31 * result + (yearMatter?.hashCode() ?: 0)
42 | result = 31 * result + originalDate.hashCode()
43 | result = 31 * result + (nextDate?.hashCode() ?: 0)
44 | result = 31 * result + (notes?.hashCode() ?: 0)
45 | result = 31 * result + (image?.contentHashCode() ?: 0)
46 | return result
47 | }
48 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/utilities/ChineseCalendarUtils.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.utilities
2 |
3 | import android.icu.util.*
4 | import java.time.LocalDate
5 | import java.time.ZoneOffset
6 |
7 | // Adapter to use either Android's provided ICU or the original one.
8 | interface CalendarAdapter {
9 |
10 | // Wrapper for Calendar.setTimeInMillis
11 | fun setTimeInMillis(value: Long)
12 |
13 | // Wrapper for Calendar.get
14 | fun get(field: Int): Int
15 | }
16 |
17 | /**
18 | * Finds the Chinese calendar year animal corresponding to the given date, using the provided
19 | * ICU implementation.
20 | * @param getChinese Function to create a Chinese calendar
21 | * @returns Animal index, starting from 0 = rat
22 | */
23 | fun chineseAnimalGeneric(getChinese: () -> C, date: LocalDate): Int {
24 | // Convert the given date to a UNIX epoch value, assuming Beijing time
25 | val millis = date.atTime(12, 0)
26 | .toInstant(ZoneOffset.ofHours(8))
27 | .toEpochMilli()
28 | // Create a Chinese calendar instance for the given epoch value
29 | val chinese = getChinese()
30 | chinese.setTimeInMillis(millis)
31 | // Extract the year, which corresponds to the animal cycle
32 | val year = chinese.get(Calendar.YEAR)
33 | return (year - 1) % 12
34 | }
35 |
36 | // Implementation of calendar adapter for Android-provided ICU.
37 | class AndroidCalendar(private val calendar: Calendar): CalendarAdapter {
38 | override fun setTimeInMillis(value: Long) {
39 | calendar.timeInMillis = value
40 | }
41 | override fun get(field: Int): Int = calendar.get(field)
42 | }
43 |
44 | // Return the Animal index (starting from 0 = rat) corresponding to the given date
45 | fun chineseAnimal(date: LocalDate): Int = chineseAnimalGeneric(
46 | getChinese = { AndroidCalendar(ChineseCalendar()) },
47 | date
48 | )
49 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_notes.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/missed_carousel_item.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
18 |
19 |
26 |
27 |
39 |
40 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 | # Kotlin code style for this project: "official" or "obsolete":
21 | kotlin.code.style=official
22 | android.nonTransitiveRClass=false
23 | # Generate compile-time only R class for app modules
24 | android.enableAppCompileTimeRClass=true
25 | # Only keep the single relevant constructor for types mentioned in XML files
26 | # instead of using a parameter wildcard which keeps them all
27 | android.useMinimalKeepRules=true
28 | # Enable resource optimizations for release build
29 | android.enableResourceOptimizations=true
30 | # Gradle
31 | org.gradle.caching=true
32 | org.gradle.configureondemand=true
33 | # Use R8 in full mode instead of ProGuard compatibility mode.
34 | android.enableR8.fullMode=true
35 | # Build BuildConfig as Bytecode
36 | android.enableBuildConfigAsBytecode=true
37 | # Suppress unsupported CompileSdk warning
38 | android.suppressUnsupportedCompileSdk=35
--------------------------------------------------------------------------------
/app/src/main/res/drawable/placeholder_birthday_image.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
15 |
19 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/placeholder_name_day_image.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
15 |
19 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/fragment_favorites_scene.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
22 |
23 |
24 |
25 |
37 |
38 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/preferences/standard/ExperimentalDisclaimerPreference.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.preferences.standard
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.util.AttributeSet
6 | import androidx.core.net.toUri
7 | import androidx.preference.Preference
8 | import androidx.preference.PreferenceViewHolder
9 | import com.minar.birday.BuildConfig
10 | import com.minar.birday.R
11 | import com.minar.birday.activities.MainActivity
12 | import com.minar.birday.databinding.ExperimentalDisclaimerRowBinding
13 |
14 |
15 | class ExperimentalDisclaimerPreference(context: Context, attrs: AttributeSet?) :
16 | Preference(context, attrs) {
17 |
18 | override fun onBindViewHolder(holder: PreferenceViewHolder) {
19 | super.onBindViewHolder(holder)
20 | val binding = ExperimentalDisclaimerRowBinding.bind(holder.itemView)
21 |
22 | // Animate the vector drawable
23 | (context as MainActivity).animateAvd(
24 | binding.animatedDanger,
25 | R.drawable.animated_experimental_danger, 1500
26 | )
27 |
28 | // Set the "open Github develop branch" button
29 | binding.checkGithubButton.setOnClickListener {
30 | (context as MainActivity).vibrate()
31 | val uri = context.getString(R.string.github_repo_develop).toUri()
32 | context.startActivity(Intent(Intent.ACTION_VIEW, uri))
33 | }
34 |
35 | // Set the "translate the app" button
36 | binding.translateButton.setOnClickListener {
37 | (context as MainActivity).vibrate()
38 | val uri = context.getString(R.string.crowdin_project).toUri()
39 | context.startActivity(Intent(Intent.ACTION_VIEW, uri))
40 | }
41 |
42 | // Set the app version name and number text
43 | val versionCode = BuildConfig.VERSION_CODE
44 | val versionName = BuildConfig.VERSION_NAME
45 | val versionInfo = "v$versionName ($versionCode)"
46 | binding.appVersionInfo.text = versionInfo
47 | }
48 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/utilities/AppRater.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.utilities
2 |
3 | import android.content.SharedPreferences
4 | import androidx.fragment.app.FragmentActivity
5 | import com.minar.birday.activities.MainActivity
6 | import com.minar.birday.fragments.dialogs.RateBottomSheet
7 | import androidx.core.content.edit
8 |
9 | object AppRater {
10 |
11 | private const val DO_NOT_SHOW_AGAIN = "do_not_show_again"
12 | private const val APP_RATING = "app_rating"
13 | private const val LAUNCH_COUNT = "launch_count"
14 | private const val DATE_FIRST_LAUNCH = "date_first_launch"
15 | private const val DAYS_UNTIL_PROMPT = 2 // Min number of days
16 | private const val LAUNCHES_UNTIL_PROMPT = 3 // Min number of launches
17 |
18 | @JvmStatic
19 | fun appLaunched(activity: MainActivity) {
20 | val prefs = activity.getSharedPreferences(APP_RATING, 0)
21 | if (prefs.getBoolean(DO_NOT_SHOW_AGAIN, false)) return
22 | prefs.edit {
23 |
24 | // Increment launch counter
25 | val launchCount = prefs.getLong(LAUNCH_COUNT, 0) + 1
26 | putLong(LAUNCH_COUNT, launchCount)
27 |
28 | // Get date of first launch
29 | var dateFirstLaunch = prefs.getLong(DATE_FIRST_LAUNCH, 0)
30 | if (dateFirstLaunch == 0L) {
31 | dateFirstLaunch = System.currentTimeMillis()
32 | putLong(DATE_FIRST_LAUNCH, dateFirstLaunch)
33 | }
34 |
35 | // Wait at least n days before opening
36 | if (launchCount >= LAUNCHES_UNTIL_PROMPT) {
37 | if (System.currentTimeMillis() >= dateFirstLaunch + DAYS_UNTIL_PROMPT * 24 * 60 * 60 * 1000) {
38 | showRateDialog(activity, this)
39 | }
40 | }
41 | }
42 | }
43 |
44 | private fun showRateDialog(activity: FragmentActivity, editor: SharedPreferences.Editor) {
45 | val bottomSheet = RateBottomSheet(editor)
46 | if (bottomSheet.isAdded) return
47 | bottomSheet.show(activity.supportFragmentManager, "rate_bottom_sheet")
48 | }
49 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/model/Event.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.model
2 |
3 | import androidx.room.ColumnInfo
4 | import androidx.room.Entity
5 | import androidx.room.Index
6 | import androidx.room.PrimaryKey
7 | import com.google.gson.annotations.Expose
8 | import java.time.LocalDate
9 |
10 | @Entity(
11 | indices = [Index(
12 | value = arrayOf("name", "surname", "originalDate"),
13 | unique = true
14 | )]
15 | )
16 | data class Event(
17 | @PrimaryKey(autoGenerate = true)
18 | val id: Int,
19 | @Expose
20 | val type: String? = EventCode.BIRTHDAY.name,
21 | @Expose
22 | val name: String,
23 | @Expose
24 | val surname: String? = "",
25 | val favorite: Boolean? = false,
26 | @Expose
27 | val yearMatter: Boolean? = true,
28 | @Expose
29 | val originalDate: LocalDate,
30 | @Expose
31 | val notes: String? = "",
32 | @ColumnInfo(typeAffinity = ColumnInfo.BLOB)
33 | val image: ByteArray? = null,
34 | ) {
35 | override fun equals(other: Any?): Boolean {
36 | if (this === other) return true
37 | if (javaClass != other?.javaClass) return false
38 |
39 | other as Event
40 |
41 | if (id != other.id) return false
42 | if (type != other.type) return false
43 | if (name != other.name) return false
44 | if (surname != other.surname) return false
45 | if (originalDate != other.originalDate) return false
46 | if (!image.contentEquals(other.image)) return false
47 |
48 | return true
49 | }
50 |
51 | override fun hashCode(): Int {
52 | var result = id
53 | result = 31 * result + (type?.hashCode() ?: 0)
54 | result = 31 * result + name.hashCode()
55 | result = 31 * result + (surname?.hashCode() ?: 0)
56 | result = 31 * result + (favorite?.hashCode() ?: 0)
57 | result = 31 * result + (yearMatter?.hashCode() ?: 0)
58 | result = 31 * result + originalDate.hashCode()
59 | result = 31 * result + (notes?.hashCode() ?: 0)
60 | result = 31 * result + (image?.contentHashCode() ?: 0)
61 | return result
62 | }
63 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/placeholder_death_image.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
15 |
19 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/static_notification_icon.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/calendar_export_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
26 |
27 |
34 |
35 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/calendar_import_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
26 |
27 |
34 |
35 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/contacts_import_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
26 |
27 |
34 |
35 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/placeholder_anniversary_image.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
15 |
19 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/preferences/standard/ClearDBPreference.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.preferences.standard
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import android.view.View
6 | import androidx.preference.Preference
7 | import androidx.preference.PreferenceViewHolder
8 | import com.google.android.material.dialog.MaterialAlertDialogBuilder
9 | import com.minar.birday.R
10 | import com.minar.birday.activities.MainActivity
11 | import com.minar.birday.databinding.ClearDbRowBinding
12 | import com.minar.birday.persistence.EventDatabase
13 | import com.minar.birday.utilities.smartFixName
14 | import kotlinx.coroutines.CoroutineScope
15 | import kotlinx.coroutines.Dispatchers
16 | import kotlinx.coroutines.launch
17 |
18 |
19 | // A custom preference to nuke the DB
20 | class ClearDBPreference(context: Context, attrs: AttributeSet?) :
21 | Preference(context, attrs),
22 | View.OnClickListener {
23 | private lateinit var binding: ClearDbRowBinding
24 |
25 | override fun onBindViewHolder(holder: PreferenceViewHolder) {
26 | super.onBindViewHolder(holder)
27 | binding = ClearDbRowBinding.bind(holder.itemView)
28 | binding.root.setOnClickListener(this)
29 | }
30 |
31 | override fun onClick(v: View) {
32 | val act = context as MainActivity
33 | act.vibrate()
34 |
35 | MaterialAlertDialogBuilder(act)
36 | .setTitle(R.string.delete_db_dialog_title)
37 | .setIcon(R.drawable.ic_alert_24dp)
38 | .setMessage(R.string.delete_db_dialog_description)
39 | .setPositiveButton(act.resources.getString(android.R.string.ok)) { dialog, _ ->
40 | CoroutineScope(Dispatchers.IO).launch {
41 | // Delete every saved data and send a snackbar
42 | EventDatabase.getBirdayDatabase(context).clearAllTables()
43 | }.invokeOnCompletion {
44 | act.showSnackbar(
45 | context.getString(R.string.app_intro_done_button).lowercase()
46 | .smartFixName(forceCapitalize = true)
47 | )
48 | dialog.dismiss()
49 | }
50 | }
51 | .setNegativeButton(act.resources.getString(android.R.string.cancel)) { dialog, _ ->
52 | dialog.dismiss()
53 | }
54 | .show()
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/birday_logo.xml:
--------------------------------------------------------------------------------
1 |
8 |
14 |
18 |
19 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_apps_signal_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/persistence/EventDatabase.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.persistence
2 |
3 | import android.content.Context
4 | import androidx.room.Database
5 | import androidx.room.Room
6 | import androidx.room.RoomDatabase
7 | import androidx.room.TypeConverters
8 | import androidx.room.migration.Migration
9 | import androidx.sqlite.db.SupportSQLiteDatabase
10 | import com.minar.birday.model.Event
11 |
12 |
13 | @Database(entities = [Event::class], version = 11, exportSchema = false)
14 | @TypeConverters(LocalDateTypeConverter::class)
15 | abstract class EventDatabase : RoomDatabase() {
16 | abstract fun eventDao(): EventDao
17 |
18 | companion object {
19 | @Volatile
20 | private var INSTANCE: EventDatabase? = null
21 |
22 | // Migration strategy to add two columns from version 9 to 10
23 | private val MIGRATION_9_10: Migration = object : Migration(9, 10) {
24 | override fun migrate(db: SupportSQLiteDatabase) {
25 | db.execSQL(
26 | "ALTER TABLE Event ADD COLUMN notes TEXT DEFAULT ''"
27 | )
28 | db.execSQL(
29 | "ALTER TABLE Event ADD COLUMN image BLOB"
30 | )
31 | }
32 | }
33 | // Migration strategy to uppercase the type from version 10 to 11
34 | private val MIGRATION_10_11: Migration = object : Migration(10, 11) {
35 | override fun migrate(db: SupportSQLiteDatabase) {
36 | db.execSQL(
37 | "UPDATE Event SET type = UPPER(type)"
38 | )
39 | }
40 | }
41 | fun getBirdayDatabase(context: Context): EventDatabase {
42 | val tempInstance = INSTANCE
43 | if (tempInstance != null) {
44 | return tempInstance
45 | }
46 | synchronized(this) {
47 | val instance = Room.databaseBuilder(
48 | context.applicationContext,
49 | EventDatabase::class.java,
50 | "BirdayDB"
51 | )
52 | .addMigrations(MIGRATION_9_10)
53 | .addMigrations(MIGRATION_10_11)
54 | .build()
55 | INSTANCE = instance
56 | return instance
57 | }
58 | }
59 |
60 | fun destroyInstance() {
61 | if (INSTANCE?.isOpen == true) {
62 | INSTANCE?.close()
63 | }
64 | INSTANCE = null
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/fragments/dialogs/ImportContactsBottomSheet.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.fragments.dialogs
2 |
3 | import android.annotation.SuppressLint
4 | import android.os.Bundle
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.view.ViewGroup
8 | import androidx.fragment.app.activityViewModels
9 | import androidx.lifecycle.lifecycleScope
10 | import com.google.android.material.bottomsheet.BottomSheetDialogFragment
11 | import com.minar.birday.R
12 | import com.minar.birday.activities.MainActivity
13 | import com.minar.birday.databinding.BottomSheetImportContactsBinding
14 | import com.minar.birday.persistence.ContactsRepository
15 | import com.minar.birday.viewmodels.MainViewModel
16 | import kotlinx.coroutines.Dispatchers
17 | import kotlinx.coroutines.launch
18 | import kotlinx.coroutines.withContext
19 |
20 | class ImportContactsBottomSheet : BottomSheetDialogFragment() {
21 | private val viewModel: MainViewModel by activityViewModels()
22 | private lateinit var act: MainActivity
23 | private val contactsRepository = ContactsRepository()
24 |
25 | override fun onCreateView(
26 | inflater: LayoutInflater,
27 | container: ViewGroup?,
28 | savedInstanceState: Bundle?
29 | ): View {
30 | act = requireActivity() as MainActivity
31 | return BottomSheetImportContactsBinding.inflate(inflater, container, false).root
32 | }
33 |
34 | @SuppressLint("MissingPermission")
35 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
36 | val binding = BottomSheetImportContactsBinding.bind(view)
37 | act.animateAvd(
38 | binding.importContactsImage,
39 | R.drawable.animated_balloon, 1500L
40 | )
41 | binding.importContactsCancelButton.setOnClickListener { dismiss() }
42 | binding.importContactsConfirmButton.setOnClickListener {
43 | binding.importContactsButtons.visibility = View.INVISIBLE
44 | binding.importContactsProgressIndicator.visibility = View.VISIBLE
45 | // Actually import contacts
46 | viewLifecycleOwner.lifecycleScope.launch {
47 | val events = withContext(Dispatchers.IO) {
48 | contactsRepository.getEventsFromContacts(requireContext().contentResolver)
49 | }
50 | viewModel.insertAll(events)
51 | dismiss()
52 | }
53 | }
54 | }
55 |
56 | companion object {
57 | const val TAG = "import_contacts_bottom_sheet"
58 | }
59 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/workers/ImportContactsWorker.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.workers
2 |
3 | import android.Manifest
4 | import android.content.pm.PackageManager
5 | import androidx.core.content.ContextCompat
6 | import androidx.preference.PreferenceManager
7 | import androidx.work.CoroutineWorker
8 | import androidx.work.WorkerParameters
9 | import com.minar.birday.persistence.ContactsRepository
10 | import com.minar.birday.persistence.EventDatabase
11 | import kotlinx.coroutines.Dispatchers
12 | import kotlinx.coroutines.withContext
13 | import java.util.concurrent.TimeUnit
14 | import android.content.Context
15 | import androidx.core.content.edit
16 |
17 | // Imports from contacts in background if the app is unused for more than a week
18 | class ImportContactsWorker(appContext: Context, params: WorkerParameters) :
19 | CoroutineWorker(appContext, params) {
20 |
21 | override suspend fun doWork(): Result {
22 | val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext)
23 | val autoImport = prefs.getBoolean("auto_import", false)
24 | if (!autoImport) return Result.success()
25 |
26 | val lastLaunch = prefs.getLong("last_launch", 0L)
27 | val now = System.currentTimeMillis()
28 | val weekMillis = TimeUnit.DAYS.toMillis(7)
29 |
30 | // If the app has been launched in the last week, skip
31 | if (lastLaunch + weekMillis > now) {
32 | return Result.success()
33 | }
34 |
35 | if (ContextCompat.checkSelfPermission(
36 | applicationContext,
37 | Manifest.permission.READ_CONTACTS
38 | ) != PackageManager.PERMISSION_GRANTED
39 | ) {
40 | return Result.success()
41 | }
42 |
43 | return try {
44 | val events = withContext(Dispatchers.IO) {
45 | ContactsRepository().getEventsFromContacts(applicationContext.contentResolver)
46 | }
47 |
48 | if (events.isNotEmpty()) {
49 | withContext(Dispatchers.IO) {
50 | val db = EventDatabase.getBirdayDatabase(applicationContext)
51 | val dao = db.eventDao()
52 | val replaceOnConflict = prefs.getBoolean("replace_on_conflict", true)
53 | if (replaceOnConflict) dao.insertAllEventReplace(events) else dao.insertAllEventIgnore(
54 | events
55 | )
56 | }
57 | prefs.edit { putLong("last_launch", now) }
58 | }
59 |
60 | Result.success()
61 | } catch (_: Exception) {
62 | Result.failure()
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/fragment_home_scene.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
22 |
23 |
24 |
25 |
28 |
29 |
30 |
31 |
32 |
44 |
45 |
54 |
55 |
56 |
59 |
60 |
61 |
62 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/app/src/main/java/com/minar/birday/preferences/standard/AddDemoEntriesPreference.kt:
--------------------------------------------------------------------------------
1 | package com.minar.birday.preferences.standard
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import android.view.View
6 | import androidx.preference.Preference
7 | import androidx.preference.PreferenceViewHolder
8 | import com.google.android.material.dialog.MaterialAlertDialogBuilder
9 | import com.minar.birday.R
10 | import com.minar.birday.activities.MainActivity
11 | import com.minar.birday.databinding.AddDemoEntriesRowBinding
12 | import com.minar.birday.preferences.backup.CsvImporter
13 | import com.minar.birday.utilities.getResourceUri
14 | import com.minar.birday.utilities.smartFixName
15 | import kotlinx.coroutines.CoroutineScope
16 | import kotlinx.coroutines.Dispatchers
17 | import kotlinx.coroutines.launch
18 |
19 |
20 | // A custom preference to add some demo entries to the DB
21 | class AddDemoEntriesPreference(context: Context, attrs: AttributeSet?) :
22 | Preference(context, attrs),
23 | View.OnClickListener {
24 | private lateinit var binding: AddDemoEntriesRowBinding
25 |
26 | override fun onBindViewHolder(holder: PreferenceViewHolder) {
27 | super.onBindViewHolder(holder)
28 | binding = AddDemoEntriesRowBinding.bind(holder.itemView)
29 | binding.root.setOnClickListener(this)
30 | }
31 |
32 | override fun onClick(v: View) {
33 | val act = context as MainActivity
34 | act.vibrate()
35 |
36 | MaterialAlertDialogBuilder(act)
37 | .setTitle(R.string.delete_db_dialog_title)
38 | .setIcon(R.drawable.ic_alert_24dp)
39 | .setMessage(R.string.add_demo_entries_dialog_description)
40 | .setPositiveButton(act.resources.getString(android.R.string.ok)) { dialog, _ ->
41 | CoroutineScope(Dispatchers.IO).launch {
42 | // Insert a series of events from a csv in assets
43 | val csvImporter = CsvImporter(act, null)
44 | csvImporter.importEventsCsv(
45 | act,
46 | getResourceUri(R.raw.birday_demo_entries)
47 | )
48 | }.invokeOnCompletion {
49 | act.showSnackbar(
50 | context.getString(R.string.app_intro_done_button).lowercase()
51 | .smartFixName(forceCapitalize = true)
52 | )
53 | dialog.dismiss()
54 | }
55 | }
56 | .setNegativeButton(act.resources.getString(android.R.string.cancel)) { dialog, _ ->
57 | dialog.dismiss()
58 | }
59 | .show()
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | - @string/system_theme
6 | - @string/dark_theme
7 | - @string/light_theme
8 | - @string/black_theme
9 |
10 |
11 |
12 | - system
13 | - dark
14 | - light
15 | - black
16 |
17 |
18 |
19 | - @string/aqua
20 | - @string/brown
21 | - @string/blue
22 | - @string/green
23 | - @string/orange
24 | - @string/yellow
25 | - @string/teal
26 | - @string/violet
27 | - @string/pink
28 | - @string/light_blue
29 | - @string/red
30 | - @string/lime
31 | - @string/crimson
32 |
33 |
34 |
35 | - aqua
36 | - brown
37 | - blue
38 | - green
39 | - orange
40 | - yellow
41 | - teal
42 | - violet
43 | - pink
44 | - lightBlue
45 | - red
46 | - lime
47 | - crimson
48 |
49 |
50 |
51 | - @string/one_day_before
52 | - @string/two_days_before
53 | - @string/three_days_before
54 | - @string/four_days_before
55 | - @string/five_days_before
56 | - @string/six_days_before
57 | - @string/seven_days_before
58 | - @string/ten_days_before
59 | - @string/fourteen_days_before
60 | - @string/twentyone_days_before
61 |
62 |
63 |
64 | - 1
65 | - 2
66 | - 3
67 | - 4
68 | - 5
69 | - 6
70 | - 7
71 | - 10
72 | - 14
73 | - 21
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/full_description.txt:
--------------------------------------------------------------------------------
1 | Introduction 👋
2 | This app was created to remember and manage events in a simple and effective way.
3 | The app contains some basic personalization options and an introduction, plus some new resources like animated vector drawables and the automatic dark/light theme. Support and updates are guaranteed!
4 |
5 |
6 | Why should I use Birday? 😕
7 | Well, I'll tell you 3 main reasons:
8 |
9 | - It can help you to remember every birthday in the moment you prefer!
10 | - It will cost just a few MB of storage!
11 | - It's beautiful, full of animations and simple to use!
12 |
13 |
14 | Birday allows you to import the events directly from your contacts or calendar, with a simple favorite system and a set of stats to discover!
15 | if you're starting to develop apps and you need an app to look at, to find some inspiration and tricks: click on the GitHub link, and the Birday source code is served!
16 |
17 |
18 | Features 🎂
19 |
20 | - Simple events timeline, with the next date and the name of each person
21 | - Normal/favorite/ignored system, to aggregate your favorite events and see more information
22 | - Overview screen and a lot of basic and advanced settings
23 | - Import birthdays from contacts or calendar with basic duplicate detection, select what to import
24 | - Backup your events easily, in native, csv or json format, and choose where to save the backup
25 | - 30+ language available. If you don't see your language, you can translate the app yourself!
26 | - Easily delete, modify or share every event
27 | - Each favorite event has an handy note field
28 | - Customizable notification the day of the event, and additional notification(s)!
29 | - Light, dark and black Amoled theme; Material3 Expressive
30 | - Selectable accent and Monet accent (12 choices)
31 | - Hide and unhide the top cards for maximum ui flexibility
32 | - A quick search bar, yearly overview and type selector!
33 | - 2 customizable widgets
34 | - First introduction and beautiful animations including an animated notification icon
35 | - Many possible customization and options
36 |
37 |
38 | Please note: the notification system relies on the Android OS resources, thus some manufacturers may cause malfunctions. The reason is that some Xiaomi, Huawei and Oneplus devices kill the apps instead of simply closing it, or block the automatic startup of the app process. I can't fix this, but you can find more information on dontkillmyapp.com.
39 |
40 |
41 |
--------------------------------------------------------------------------------