Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 37 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,49 @@
# Simple Calendar
<img alt="Logo" src="graphics/icon.png" width="120" />

Simple Calendar 2023 is a highly customizable, offline monthly calendar app for Android. Have an agenda planner in your pocket, designed to do exactly what a personal tiny schedule planner should do in 2023. No complicated features, unnecessary permissions, or ads!
***Supports syncing events via Google Calendar
Note: this is a fork of Simple Mobile Tools's Simple Calendar Pro that has been modified to build
on current Android SDKs. The original Calendar app relied upon a Duolingo component, rtl-viewpager, that
modified ViewPager. Android subsequently released a ViewPager2 that eliminated the need for the Duolingo
component, and the Duolingo component was deprecated and then discontinued. As a result, the basic
repository no longer builds a working app.

This fork replaces the ViewPager and Duolingo rtl-viewpager component dependencies with calls to ViewPager2,
and so it will now build with current Android SDKs for current Android versions. These modifications
were implemented using the Android SDK AI assistant harness together with the free version of Google's Gemma 3 Flash.

** Summary of Changes: **
1.
Global Exclusion: The com.github.duolingo:rtl-viewpager library is already excluded from the  Simple-Commons dependency in the implementation block of your  app/build.gradle.kts. This ensures it is not included in any build type (debug, release, etc.) or flavor (core, fdroid, prepaid).
2.
Full Migration to ViewPager2: The codebase has been fully updated to use ViewPager2 and FragmentStateAdapter. I verified that all holders ( DayFragmentsHolder.kt,  WeekFragmentsHolder.kt, etc.) and their respective adapters have been migrated.
3.
R8 Build Fix: Since the Simple-Commons library still contains internal references to RtlViewPager,
R8 (the minifier) would previously fail when building release variants (like fdroidRelease) because
the class was missing from the classpath. I fixed this by adding the following rule to your  proguard-rules.pro:
-dontwarn com.duolingo.open.rtlviewpager.RtlViewPager

This tells R8 to ignore the missing class warnings, allowing the build to succeed while ensuring the
unused library code is completely stripped out of the final APK.
This project is now clean of the rtl-viewpager dependency across all variants.

Original README resumes below.

Simple Calendar is a highly customizable, offline monthly calendar app for Android. Have an agenda planner in your pocket, designed to do exactly what a personal tiny schedule planner should do. No complicated features, unnecessary permissions, or ads!
*Supports syncing events via Google Calendar*

Download now!

Daily Digital Schedule App: Take Control of Your Time
Whether you are looking for a work calendar for business, a day planner, an appointment scheduler, or organization and scheduling of single and recurring events like birthdays, anniversary, appointment reminder, or anything else, Simple Calendar 2023 makes it easy to stay organized. The calendar widget has an incredible variety of customization options: customize event reminders, notification appearance, tiny calendar reminders widget, and overall appearance.
Whether you are looking for a work calendar for business, a day planner, an appointment scheduler, or organization and scheduling of single and recurring events like birthdays, anniversaries, appointment reminders, or anything else, Simple Calendar makes it easy to stay organized. The calendar widget has an incredible variety of customization options: customize event reminders, notification appearance, tiny calendar reminder widget, and overall appearance.

Schedule Planner: Plan Your Day
Appointment scheduler, monthly planner, and family organizer in one! Check your upcoming agenda, schedule business meetings, and events & book appointments easily. Reminders will keep you on time and informed on your daily schedule app. This 2023 calendar widget is remarkably easy to use. You can even view everything as a simple list of events rather than in a monthly view, so you know exactly what’s coming up in your life and how to organize and plan your agenda.
Appointment scheduler, monthly planner, and family organizer in one! Check your upcoming agenda, schedule business meetings, and events & book appointments easily. Reminders will keep you on time and informed on your daily schedule app. This calendar widget is remarkably easy to use. You can even view everything as a simple list of events rather than in a monthly view, so you know exactly what’s coming up in your life and how to organize and plan your agenda.

Simple Calendar 2023 Features
Simple Calendar Features

✔️ The Best User Experience
➕ No ads or annoying popups, truly great user experience!
➕ No internet access is needed, giving you more privacy, security, and stability
➕ No internet access is required by default, giving you more privacy, security, and stability

✔️ Flexibility for Your Productivity
➕ Calendar Widget supports exporting & importing events via .ics files
Expand All @@ -29,15 +56,15 @@ Simple Calendar 2023 Features
➕ Calendar widget - Colorful Calendars and customizable themes
➕ Open source tiny calendar, translated into 30+ languages
➕ Plan your day with others - ability to share events fast on social media, emails, etc
➕ Family Organizer - with hasslefree event duplication, organization, and time management
➕ Family Organizer - with hassle-free event duplication, organization, and time management

✔️ Organization and Time Management
➕ Day planner - the agenda planner will help you to organize your day
➕ Weekly planner - staying ahead of your busy weekly schedule has never been easier
➕ Itinerary manager - business calendar shared between teams at work
➕ Appointment scheduler - organize and maintain your agenda with ease
➕ Planning app - easy to use personal event, appointment reminder, and schedule planner
➕ Plan your day - manage your day with this android schedule planner, event & family organizer
➕ Planning app - easy to use personal events, appointment reminders, and schedule planners
➕ Plan your day - manage your day with this Android schedule planner, event & family organizer

✔️ #1 Calendar App
➕ Import holidays, contact birthdays, and anniversaries easily
Expand All @@ -46,7 +73,7 @@ Simple Calendar 2023 Features
➕ Quick business calendar, or personal digital agenda
➕ Quickly switch between daily, weekly, monthly, yearly & event views

DOWNLOAD SIMPLE CALENDAR PLANNER – OFFLINE SCHEDULE AND AGENDA PLANNER WITH NO ADS! PLAN YOUR 2023 TIMETABLE!
DOWNLOAD SIMPLE CALENDAR PLANNER – OFFLINE SCHEDULE AND AGENDA PLANNER WITH NO ADS! PLAN YOUR TIMETABLE!

<a href="https://f-droid.org/packages/com.simplemobiletools.calendar.pro">Get it on F-Droid</a>

Expand Down
6 changes: 5 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ android {
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
signingConfig = signingConfigs.getByName("debug")
if (keystorePropertiesFile.exists()) {
signingConfig = signingConfigs.getByName("release")
}
Expand Down Expand Up @@ -97,10 +98,13 @@ android {
}

dependencies {
implementation(libs.simple.mobile.tools.commons)
implementation(libs.simple.mobile.tools.commons) {
exclude(group = "com.github.duolingo", module = "rtl-viewpager")
}
implementation(libs.androidx.multidex)
implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.swiperefreshlayout)
implementation(libs.androidx.viewpager2)
implementation(libs.androidx.print)
implementation(libs.bundles.room)
ksp(libs.androidx.room.compiler)
Expand Down
2 changes: 2 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
-keep class com.simplemobiletools.calendar.models.** { *; }

-dontwarn com.duolingo.open.rtlviewpager.RtlViewPager
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package com.simplemobiletools.calendar.pro.activities

import android.app.Activity
import android.app.DatePickerDialog
import android.app.TimePickerDialog
import android.content.Intent
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.CalendarContract.Attendees
import android.provider.CalendarContract.Colors
Expand All @@ -21,6 +21,7 @@ import android.view.WindowManager
import android.view.inputmethod.EditorInfo
import android.widget.ImageView
import android.widget.RelativeLayout
import androidx.activity.result.contract.ActivityResultContracts
import com.google.android.material.timepicker.MaterialTimePicker
import com.google.android.material.timepicker.MaterialTimePicker.INPUT_MODE_CLOCK
import com.google.android.material.timepicker.TimeFormat
Expand All @@ -44,12 +45,12 @@ import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.commons.views.MyAutoCompleteTextView
import org.joda.time.DateTime
import org.joda.time.DateTimeZone
import java.io.Serializable
import java.util.TimeZone
import java.util.regex.Pattern

class EventActivity : SimpleActivity() {
private val LAT_LON_PATTERN = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)([,;])\\s*[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)\$"
private val SELECT_TIME_ZONE_INTENT = 1

private var mIsAllDayEvent = false
private var mReminder1Minutes = REMINDER_OFF
Expand Down Expand Up @@ -82,7 +83,14 @@ class EventActivity : SimpleActivity() {
private lateinit var mEventStartDateTime: DateTime
private lateinit var mEventEndDateTime: DateTime
private lateinit var mEvent: Event

private val selectTimeZoneLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == RESULT_OK) {
result.data?.getSerializableExtraCompat<MyTimeZone>(TIME_ZONE)?.let { timeZone ->
mEvent.timeZone = timeZone.zoneName
updateTimeZoneText()
}
}
}
private val binding by viewBinding(ActivityEventBinding::inflate)

override fun onCreate(savedInstanceState: Bundle?) {
Expand Down Expand Up @@ -139,11 +147,17 @@ class EventActivity : SimpleActivity() {
if (it) {
saveCurrentEvent()
} else {
super.onBackPressed()
//super.onBackPressed()
// Source - https://stackoverflow.com/a/73934895
// Posted by Jaydeep Khambhayta, modified by community. See post 'Timeline' for change history
// Retrieved 2026-09-18, License - CC BY-SA 4.0
onBackPressedDispatcher.onBackPressed()

}
}
} else {
super.onBackPressed()
// super.onBackPressed()
onBackPressedDispatcher.onBackPressed()
}
}

Expand Down Expand Up @@ -193,7 +207,7 @@ class EventActivity : SimpleActivity() {
}

savedInstanceState.apply {
mEvent = getSerializable(EVENT) as Event
getSerializableCompat<Event>(EVENT)?.let { mEvent = it }
mEventStartDateTime = Formatter.getDateTimeFromTS(getLong(START_TS))
mEventEndDateTime = Formatter.getDateTimeFromTS(getLong(END_TS))
mEvent.timeZone = getString(TIME_ZONE) ?: TimeZone.getDefault().id
Expand Down Expand Up @@ -232,15 +246,6 @@ class EventActivity : SimpleActivity() {
updateActionBarTitle()
}

override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
if (requestCode == SELECT_TIME_ZONE_INTENT && resultCode == Activity.RESULT_OK && resultData?.hasExtra(TIME_ZONE) == true) {
val timeZone = resultData.getSerializableExtra(TIME_ZONE) as MyTimeZone
mEvent.timeZone = timeZone.zoneName
updateTimeZoneText()
}
super.onActivityResult(requestCode, resultCode, resultData)
}

private fun gotEvent(savedInstanceState: Bundle?, localEventType: EventType?, event: Event?) = binding.apply {
if (localEventType == null || localEventType.caldavCalendarId != 0) {
config.lastUsedLocalEventTypeId = REGULAR_EVENT_TYPE_ID
Expand Down Expand Up @@ -1600,7 +1605,7 @@ class EventActivity : SimpleActivity() {
hideKeyboard()
Intent(this, SelectTimeZoneActivity::class.java).apply {
putExtra(CURRENT_TIME_ZONE, mEvent.getTimeZoneString())
startActivityForResult(this, SELECT_TIME_ZONE_INTENT)
selectTimeZoneLauncher.launch(this)
}
}

Expand Down
Loading