diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index ae78c113..dadabc6b 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -1,113 +1,302 @@ + + + + + + + + + + + + + + + + + + + + + - - -
- - - - xmlns:android - - ^$ - - - -
-
- - - - xmlns:.* - - ^$ - - - BY_NAME - -
-
- - - - .*:id - - http://schemas.android.com/apk/res/android - - - -
-
- - - - .*:name - - http://schemas.android.com/apk/res/android - - - -
-
- - - - name - - ^$ - - - -
-
- - - - style - - ^$ - - - -
-
- - - - .* - - ^$ - - - BY_NAME - -
-
- - - - .* - - http://schemas.android.com/apk/res/android - - - ANDROID_ATTRIBUTE_ORDER - -
-
- - - - .* - - .* - - - BY_NAME - -
-
-
+ + +
+ +
\ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 9bba60da..e9969a1c 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -4,9 +4,10 @@ diff --git a/.idea/misc.xml b/.idea/misc.xml index cef74a4b..7bab05e8 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,5 +1,16 @@ + + + - + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 7f68460d..00000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index b4abe850..69ec8974 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ android { applicationId "com.thesunnahrevival.sunnahassistant" minSdkVersion rootProject.minSdkVersion targetSdkVersion rootProject.targetSdkVersion - versionCode 8 - versionName "1.0.1-release" + versionCode 9 + versionName "1.0.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" javaCompileOptions { @@ -99,6 +99,10 @@ dependencies { //Firebase implementation platform('com.google.firebase:firebase-bom:27.0.0') implementation 'com.google.firebase:firebase-analytics-ktx' + implementation 'com.google.firebase:firebase-messaging' + + //Material Banner + implementation "com.sergivonavi:materialbanner:1.2.0" testImplementation "junit:junit:$junit_version" androidTestImplementation "androidx.test:runner:$test_runner_version" diff --git a/app/release/1.0.2.apk b/app/release/1.0.2.apk new file mode 100644 index 00000000..54a72297 Binary files /dev/null and b/app/release/1.0.2.apk differ diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json new file mode 100644 index 00000000..7676cb5b --- /dev/null +++ b/app/release/output-metadata.json @@ -0,0 +1,20 @@ +{ + "version": 3, + "artifactType": { + "type": "APK", + "kind": "Directory" + }, + "applicationId": "com.thesunnahrevival.sunnahassistant", + "variantName": "release", + "elements": [ + { + "type": "SINGLE", + "filters": [], + "attributes": [], + "versionCode": 9, + "versionName": "1.0.2", + "outputFile": "app-release.apk" + } + ], + "elementType": "File" +} \ No newline at end of file diff --git a/app/schemas/com.thesunnahrevival.sunnahassistant.data.local.SunnahAssistantDatabase/5.json b/app/schemas/com.thesunnahrevival.sunnahassistant.data.local.SunnahAssistantDatabase/5.json new file mode 100644 index 00000000..421eeeda --- /dev/null +++ b/app/schemas/com.thesunnahrevival.sunnahassistant.data.local.SunnahAssistantDatabase/5.json @@ -0,0 +1,288 @@ +{ + "formatVersion": 1, + "database": { + "version": 5, + "identityHash": "dab576296fd585f4dc5a00f83dd21cd2", + "entities": [ + { + "tableName": "reminders_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`reminderName` TEXT, `reminderInfo` TEXT, `timeInSeconds` INTEGER NOT NULL, `category` TEXT, `frequency` TEXT, `isEnabled` INTEGER NOT NULL, `day` INTEGER NOT NULL, `month` INTEGER NOT NULL, `year` INTEGER NOT NULL, `offset` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `customScheduleDays` TEXT)", + "fields": [ + { + "fieldPath": "reminderName", + "columnName": "reminderName", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "reminderInfo", + "columnName": "reminderInfo", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "timeInSeconds", + "columnName": "timeInSeconds", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "frequency", + "columnName": "frequency", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "isEnabled", + "columnName": "isEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "day", + "columnName": "day", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "month", + "columnName": "month", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "year", + "columnName": "year", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "offset", + "columnName": "offset", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "customScheduleDays", + "columnName": "customScheduleDays", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "app_settings", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `formattedAddress` TEXT, `latitude` REAL NOT NULL, `longitude` REAL NOT NULL, `method` INTEGER NOT NULL, `asrCalculationMethod` INTEGER NOT NULL, `isAutomatic` INTEGER NOT NULL, `month` INTEGER NOT NULL, `hijriOffSet` INTEGER NOT NULL, `isLightMode` INTEGER NOT NULL, `isFirstLaunch` INTEGER NOT NULL, `showNextReminderNotification` INTEGER NOT NULL, `showOnBoardingTutorial` INTEGER NOT NULL, `isDisplayHijriDate` INTEGER NOT NULL, `savedSpinnerPosition` INTEGER NOT NULL, `isExpandedLayout` INTEGER NOT NULL, `notificationToneUri` TEXT, `isVibrate` INTEGER NOT NULL, `priority` INTEGER NOT NULL, `latitudeAdjustmentMethod` INTEGER NOT NULL, `isShowHijriDateWidget` INTEGER NOT NULL, `isShowNextReminderWidget` INTEGER NOT NULL, `isAfterUpdate` INTEGER NOT NULL, `categories` TEXT, `language` TEXT NOT NULL, `doNotDisturbMinutes` INTEGER NOT NULL, `useReliableAlarms` INTEGER NOT NULL, `numberOfLaunches` INTEGER NOT NULL, `shareAnonymousUsageData` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "formattedAddress", + "columnName": "formattedAddress", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "latitude", + "columnName": "latitude", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "longitude", + "columnName": "longitude", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "calculationMethod", + "columnName": "method", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "asrCalculationMethod", + "columnName": "asrCalculationMethod", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isAutomatic", + "columnName": "isAutomatic", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "month", + "columnName": "month", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "hijriOffSet", + "columnName": "hijriOffSet", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isLightMode", + "columnName": "isLightMode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isFirstLaunch", + "columnName": "isFirstLaunch", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "showNextReminderNotification", + "columnName": "showNextReminderNotification", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "showOnBoardingTutorial", + "columnName": "showOnBoardingTutorial", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isDisplayHijriDate", + "columnName": "isDisplayHijriDate", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "savedSpinnerPosition", + "columnName": "savedSpinnerPosition", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isExpandedLayout", + "columnName": "isExpandedLayout", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationToneUri", + "columnName": "notificationToneUri", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "isVibrate", + "columnName": "isVibrate", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "priority", + "columnName": "priority", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "latitudeAdjustmentMethod", + "columnName": "latitudeAdjustmentMethod", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isShowHijriDateWidget", + "columnName": "isShowHijriDateWidget", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isShowNextReminderWidget", + "columnName": "isShowNextReminderWidget", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isAfterUpdate", + "columnName": "isAfterUpdate", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "categories", + "columnName": "categories", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "language", + "columnName": "language", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "doNotDisturbMinutes", + "columnName": "doNotDisturbMinutes", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "useReliableAlarms", + "columnName": "useReliableAlarms", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "numberOfLaunches", + "columnName": "numberOfLaunches", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "shareAnonymousUsageData", + "columnName": "shareAnonymousUsageData", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'dab576296fd585f4dc5a00f83dd21cd2')" + ] + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d0a7ab37..eeb66fec 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,86 +18,68 @@ android:hasFragileUserData="true" android:theme="@style/AppTheme"> - + - - - + - - - - - - - - - + - + + - - - - + - - - - - + - - - + + - - - - + + android:resource="@xml/today_reminders_widget_info" /> - + + android:resource="@xml/prayer_reminders_widget_info" /> + android:label="@string/hijri_date_widget_label"> @@ -118,10 +100,27 @@ - - + + + + + + + + + + + diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/data/local/SunnahAssistantDatabase.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/data/local/SunnahAssistantDatabase.kt index 26169c1f..b350dcb0 100644 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/data/local/SunnahAssistantDatabase.kt +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/data/local/SunnahAssistantDatabase.kt @@ -18,7 +18,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.util.* -@Database(entities = [Reminder::class, AppSettings::class], version = 4) +@Database(entities = [Reminder::class, AppSettings::class], version = 5) @TypeConverters(RoomTypeConverter::class) abstract class SunnahAssistantDatabase : RoomDatabase() { abstract fun reminderDao(): ReminderDao @@ -81,30 +81,43 @@ abstract class SunnahAssistantDatabase : RoomDatabase() { } } + private val MIGRATION_4_5: Migration = object : Migration(4, 5) { + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("UPDATE app_settings SET isAfterUpdate = 1") + } + } + fun getInstance(context: Context): SunnahAssistantDatabase = - INSTANCE ?: synchronized(this) { - INSTANCE ?: buildDatabase(context).also { INSTANCE = it } - } + INSTANCE ?: synchronized(this) { + INSTANCE ?: buildDatabase(context).also { INSTANCE = it } + } - private fun buildDatabase(context: Context) = Room.databaseBuilder(context.applicationContext, - SunnahAssistantDatabase::class.java, "SunnahAssistant.db") + private fun buildDatabase(context: Context) = Room.databaseBuilder( + context.applicationContext, + SunnahAssistantDatabase::class.java, "SunnahAssistant.db" + ) .addCallback( object : Callback() { override fun onCreate(db: SupportSQLiteDatabase) { super.onCreate(db) CoroutineScope(Dispatchers.IO).launch { - INSTANCE?.reminderDao()?.insertReminder(demoReminder(context.getString(R.string.demo_reminder), context.resources.getStringArray(R.array.categories)[3])) + INSTANCE?.reminderDao()?.insertReminder( + demoReminder( + context.getString(R.string.demo_reminder), + context.resources.getStringArray(R.array.categories)[3] + ) + ) val categories = TreeSet() categories.addAll(context.resources.getStringArray(R.array.categories)) INSTANCE?.reminderDao()?.insertSettings(initialSettings(categories)) } } - } + } ) - .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4) + .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5) .build() } } \ No newline at end of file diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/firebase/SAFirebaseMessagingService.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/firebase/SAFirebaseMessagingService.kt new file mode 100644 index 00000000..d64f8d28 --- /dev/null +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/firebase/SAFirebaseMessagingService.kt @@ -0,0 +1,42 @@ +package com.thesunnahrevival.sunnahassistant.firebase + +import android.app.Notification +import android.app.NotificationManager +import android.app.PendingIntent +import android.app.PendingIntent.FLAG_CANCEL_CURRENT +import android.content.Context +import android.content.Intent +import com.google.firebase.messaging.FirebaseMessagingService +import com.google.firebase.messaging.RemoteMessage +import com.thesunnahrevival.sunnahassistant.utilities.createNotification +import com.thesunnahrevival.sunnahassistant.views.MainActivity + +class SAFirebaseMessagingService : FirebaseMessagingService() { + override fun onMessageReceived(remoteMessage: RemoteMessage) { + // Check if message contains a notification payload. + remoteMessage.notification?.let { + val notification = createNotification( + applicationContext, + it.title, + it.body, + Notification.PRIORITY_DEFAULT, + null, + false + ) + + // Check if message contains a data payload. + if (remoteMessage.data.isNotEmpty() && remoteMessage.data["link"] != null) { + val intent = Intent(applicationContext, MainActivity::class.java) + intent.putExtra("link", remoteMessage.data["link"]) + val activity = + PendingIntent.getActivity(applicationContext, 0, intent, FLAG_CANCEL_CURRENT) + notification.contentIntent = activity + } + val notificationManager = + getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + notificationManager.notify(-2, notification) + } + + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/utilities/NextReminderService.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/utilities/NextReminderService.kt index fb8a84c1..96d5dabe 100644 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/utilities/NextReminderService.kt +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/utilities/NextReminderService.kt @@ -115,9 +115,8 @@ class NextReminderService : Service() { val stickyNotification: Notification = createNotification( context, title, text, NotificationCompat.PRIORITY_LOW, notificationToneUri, isVibrate) - if (isForegroundEnabled) - context.startForeground(1, stickyNotification) + startForeground(1, stickyNotification) else context.stopForeground(true) } diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/utilities/NotificationUtil.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/utilities/NotificationUtil.kt index 16e6f272..5cf97e41 100644 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/utilities/NotificationUtil.kt +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/utilities/NotificationUtil.kt @@ -15,17 +15,29 @@ import androidx.navigation.NavDeepLinkBuilder import com.thesunnahrevival.sunnahassistant.R import com.thesunnahrevival.sunnahassistant.views.MainActivity -fun createNotification(context: Context, title: String?, text: String?, priority: Int, notificationToneUri: Uri?, isVibrate: Boolean): Notification { +fun createNotification( + context: Context, + title: String?, + text: String?, + priority: Int, + notificationToneUri: Uri?, + isVibrate: Boolean, + isFCMMessage: Boolean = false +): Notification { var category = "" if (priority == -1) { category = "Next Reminder" - } - else { - val reminderNotificationChannel = getReminderNotificationChannel(context) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && reminderNotificationChannel != null) { - category = reminderNotificationChannel.id - } + } else { + if (!isFCMMessage) { + val reminderNotificationChannel = getReminderNotificationChannel(context) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && + reminderNotificationChannel != null + ) { + category = reminderNotificationChannel.id + } + } else + category = "Developer" } val res = context.resources @@ -34,24 +46,24 @@ fun createNotification(context: Context, title: String?, text: String?, priority val picture = BitmapFactory.decodeResource(res, R.drawable.logo) val intent = Intent(context, MainActivity::class.java) - var activity: PendingIntent - if (priority != -1) - activity = PendingIntent.getActivity(context, 0, intent, 0) - else - activity = NavDeepLinkBuilder(context) - .setGraph(R.navigation.navigation) - .setDestination(R.id.notificationSettingsFragment) - .createPendingIntent() + val activity = if (priority != -1) + PendingIntent.getActivity(context, 0, intent, 0) + else + NavDeepLinkBuilder(context) + .setGraph(R.navigation.navigation) + .setDestination(R.id.notificationSettingsFragment) + .createPendingIntent() var builder: NotificationCompat.Builder builder = NotificationCompat.Builder(context, category) - .setSmallIcon(R.drawable.ic_alarm) - .setContentTitle(title) - .setContentText(text) - .setContentIntent(activity) - .setPriority(priority) - .setTicker(title) - .setStyle(NotificationCompat.BigTextStyle() - .bigText(text) + .setSmallIcon(R.drawable.ic_alarm) + .setContentTitle(title) + .setContentText(text) + .setContentIntent(activity) + .setPriority(priority) + .setTicker(title) + .setStyle( + NotificationCompat.BigTextStyle() + .bigText(text) .setBigContentTitle(title) .setSummaryText("Reminder")) .setAutoCancel(true) @@ -76,12 +88,29 @@ fun createNotificationChannels(context: Context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { deleteReminderNotificationChannel(context) val notificationManager = context.getSystemService(NotificationManager::class.java) - val channel = NotificationChannel("remindersDefault", "Reminders", NotificationManager.IMPORTANCE_DEFAULT) + val channel = NotificationChannel( + "remindersDefault", + context.getString(R.string.reminders), + NotificationManager.IMPORTANCE_DEFAULT + ) notificationManager.createNotificationChannel(channel) + val nextReminderChannel = NotificationChannel( - "Next Reminder", context.getString(R.string.next_reminder_sticky_notification), NotificationManager.IMPORTANCE_LOW) - nextReminderChannel.description = context.getString(R.string.sticky_notification_description) + "Next Reminder", + context.getString(R.string.next_reminder_sticky_notification), + NotificationManager.IMPORTANCE_LOW + ) + nextReminderChannel.description = + context.getString(R.string.sticky_notification_description) notificationManager.createNotificationChannel(nextReminderChannel) + + val messagesFromDeveloper = NotificationChannel( + "Developer", + context.getString(R.string.developers_messages), + NotificationManager.IMPORTANCE_DEFAULT + ) + nextReminderChannel.description = context.getString(R.string.developer_messages_description) + notificationManager.createNotificationChannel(messagesFromDeveloper) } } diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/utilities/SunnahAssistantUtil.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/utilities/SunnahAssistantUtil.kt index 6d5a8a02..bc7e3d9e 100644 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/utilities/SunnahAssistantUtil.kt +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/utilities/SunnahAssistantUtil.kt @@ -17,8 +17,6 @@ import com.thesunnahrevival.sunnahassistant.data.model.Frequency import com.thesunnahrevival.sunnahassistant.data.model.Reminder import com.thesunnahrevival.sunnahassistant.widgets.HijriDateWidget import com.thesunnahrevival.sunnahassistant.widgets.TodayRemindersWidget -import com.thesunnahrevival.sunnahassistant.widgets.TodaysRemindersWidgetDark -import com.thesunnahrevival.sunnahassistant.widgets.TodaysRemindersWidgetTransparent import java.util.* val supportedLocales = arrayOf("en", "ar") @@ -26,8 +24,11 @@ val supportedLocales = arrayOf("en", "ar") fun generateEmailIntent(): Intent { val intent = Intent(Intent.ACTION_SENDTO) intent.data = Uri.parse("mailto:") - intent.putExtra(Intent.EXTRA_EMAIL, arrayOf("thesunnahrevival.tsr@gmail.com")) - intent.putExtra(Intent.EXTRA_SUBJECT, "Sunnah Assistant App" + " - Version " + BuildConfig.VERSION_NAME) + intent.putExtra(Intent.EXTRA_EMAIL, arrayOf("contact@thesunnahrevival.com")) + intent.putExtra( + Intent.EXTRA_SUBJECT, + "Sunnah Assistant App" + " - Version " + BuildConfig.VERSION_NAME + ) intent.putExtra(Intent.EXTRA_TEXT, emailText) return intent } @@ -143,14 +144,8 @@ fun updateTodayRemindersWidgets(context: Context?) { // Use an array and EXTRA_APPWIDGET_IDS instead of AppWidgetManager.EXTRA_APPWIDGET_ID, // since it seems the onUpdate() is only fired on that: - var ids = AppWidgetManager.getInstance(context) - .getAppWidgetIds(ComponentName(context, TodayRemindersWidget::class.java)) - appWidgetManager.notifyAppWidgetViewDataChanged(ids, R.id.widgetListView) - ids = AppWidgetManager.getInstance(context) - .getAppWidgetIds(ComponentName(context, TodaysRemindersWidgetDark::class.java)) - appWidgetManager.notifyAppWidgetViewDataChanged(ids, R.id.widgetListView) - ids = AppWidgetManager.getInstance(context) - .getAppWidgetIds(ComponentName(context, TodaysRemindersWidgetTransparent::class.java)) + val ids = AppWidgetManager.getInstance(context) + .getAppWidgetIds(ComponentName(context, TodayRemindersWidget::class.java)) appWidgetManager.notifyAppWidgetViewDataChanged(ids, R.id.widgetListView) } diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/AboutAppFragment.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/AboutAppFragment.kt index 5f327f7f..ec0419da 100644 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/AboutAppFragment.kt +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/AboutAppFragment.kt @@ -14,7 +14,6 @@ import com.google.firebase.analytics.FirebaseAnalytics import com.thesunnahrevival.sunnahassistant.BuildConfig import com.thesunnahrevival.sunnahassistant.R import com.thesunnahrevival.sunnahassistant.utilities.generateEmailIntent -import com.thesunnahrevival.sunnahassistant.utilities.openPlayStore class AboutAppFragment : BottomSheetDialogFragment(), View.OnClickListener { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, @@ -48,7 +47,6 @@ class AboutAppFragment : BottomSheetDialogFragment(), View.OnClickListener { R.id.telegram -> intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://t.me/thesunnahrevival")) R.id.contact_us -> intent = generateEmailIntent() - R.id.support_developer -> context?.let { openPlayStore(it, "com.thesunnahrevival.supportdeveloper") } } intent?.let { startActivity(it) } } diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/ChangelogFragment.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/ChangelogFragment.kt index 51c0e969..4f59d5ab 100644 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/ChangelogFragment.kt +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/ChangelogFragment.kt @@ -1,16 +1,12 @@ package com.thesunnahrevival.sunnahassistant.views import android.os.Bundle -import android.text.Html import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.CompoundButton import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProviders -import androidx.navigation.fragment.findNavController import com.thesunnahrevival.sunnahassistant.R -import com.thesunnahrevival.sunnahassistant.utilities.createNotificationChannels import com.thesunnahrevival.sunnahassistant.utilities.generateEmailIntent import com.thesunnahrevival.sunnahassistant.utilities.openPlayStore import com.thesunnahrevival.sunnahassistant.viewmodels.SunnahAssistantViewModel @@ -22,8 +18,6 @@ class ChangelogFragment: Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view = inflater.inflate(R.layout.changelog_layout, container, false) - - context?.let { createNotificationChannels(it) } val myActivity = activity if (myActivity != null){ @@ -38,10 +32,8 @@ class ChangelogFragment: Fragment() { } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - collect_data_switch.text = Html.fromHtml(getString(R.string.share_anonymous_usage_data)) - - privacy_policy.setOnClickListener{ - findNavController().navigate(R.id.privacyPolicyFragment) + help_translate_app.setOnClickListener { + translateLink(this) } send_feedback.setOnClickListener { startActivity(generateEmailIntent()) @@ -49,13 +41,6 @@ class ChangelogFragment: Fragment() { rate_this_app.setOnClickListener { openPlayStore(requireActivity(), requireActivity().packageName) } - collect_data_switch.setOnCheckedChangeListener{ buttonView: CompoundButton, isChecked: Boolean -> - if (buttonView.isPressed) { - (requireActivity() as MainActivity).firebaseAnalytics.setAnalyticsCollectionEnabled(isChecked) - viewModel.settingsValue?.shareAnonymousUsageData = isChecked - viewModel.settingsValue?.let { viewModel.updateSettings(it) } - } - } } } \ No newline at end of file diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/MainActivity.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/MainActivity.kt index b91d90c3..9fd7d1ea 100644 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/MainActivity.kt +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/MainActivity.kt @@ -16,6 +16,7 @@ import com.google.firebase.analytics.ktx.analytics import com.google.firebase.ktx.Firebase import com.thesunnahrevival.sunnahassistant.R import com.thesunnahrevival.sunnahassistant.data.model.AppSettings +import com.thesunnahrevival.sunnahassistant.utilities.createNotificationChannels import com.thesunnahrevival.sunnahassistant.viewmodels.SunnahAssistantViewModel import com.thesunnahrevival.sunnahassistant.views.home.MainFragment import kotlinx.coroutines.CoroutineScope @@ -34,13 +35,15 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + createNotificationChannels(this) setSupportActionBar(findViewById(R.id.toolbar)) val navController = this.findNavController(R.id.myNavHostFragment) NavigationUI.setupActionBarWithNavController(this, navController) activity = this firebaseAnalytics = Firebase.analytics getSettings() - + if (intent.extras?.get("link") != null) + findNavController(R.id.myNavHostFragment).navigate(R.id.webviewFragment, intent.extras) } private fun getSettings() { @@ -72,18 +75,16 @@ class MainActivity : AppCompatActivity() { else AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) //Dark Mode - if (settings.numberOfLaunches > 0 && settings.numberOfLaunches % 5 == 0) { - showInAppReviewPrompt(activity) - } else if (settings.numberOfLaunches > 0 && settings.numberOfLaunches % 3 == 0) { + if (settings.numberOfLaunches > 0 && settings.numberOfLaunches % 3 == 0) { checkForUpdates(activity) - } else if (settings.numberOfLaunches > 0 && settings.numberOfLaunches % 4 == 0) { - val random = Random.nextInt(1, 4) - + } else if (settings.numberOfLaunches > 0 && settings.numberOfLaunches % 5 == 0) { + val random = Random.nextInt(1, 5) //Work-around to get the active fragment - val navHostFragment: Fragment? = supportFragmentManager.findFragmentById(R.id.myNavHostFragment) + val navHostFragment: Fragment? = supportFragmentManager + .findFragmentById(R.id.myNavHostFragment) val fragment = navHostFragment?.childFragmentManager?.fragments?.get(0) - if (fragment is MainFragment){ + if (fragment is MainFragment) { when (random) { 1 -> { showHelpTranslateSnackBar(fragment) @@ -91,18 +92,20 @@ class MainActivity : AppCompatActivity() { 2 -> { showSendFeedbackSnackBar(fragment) } - else -> { + 3 -> { showShareAppSnackBar(fragment) } + 4 -> { + showInAppReviewPrompt(activity) + } } } } } - override fun onSupportNavigateUp(): Boolean { - val navController = this.findNavController(R.id.myNavHostFragment) + val navController = findNavController(R.id.myNavHostFragment) return navController.navigateUp() } @@ -112,14 +115,16 @@ class MainActivity : AppCompatActivity() { // Creates instance of the manager. val appUpdateManager = AppUpdateManagerFactory.create(this) appUpdateManager - .appUpdateInfo - .addOnSuccessListener { appUpdateInfo -> - // If the update is downloaded but not installed, - // notify the user to complete the update. - if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) { - popupSnackbar(activity, getString(R.string.update_downloaded), Snackbar.LENGTH_INDEFINITE, - getString(R.string.restart)) { appUpdateManager.completeUpdate() } - } + .appUpdateInfo + .addOnSuccessListener { appUpdateInfo -> + // If the update is downloaded but not installed, + // notify the user to complete the update. + if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) { + popupSnackbar( + activity, getString(R.string.update_downloaded), Snackbar.LENGTH_INDEFINITE, + getString(R.string.restart) + ) { appUpdateManager.completeUpdate() } } + } } } \ No newline at end of file diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/ViewsUtil.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/ViewsUtil.kt index 5f8b973a..f0bff7ed 100644 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/ViewsUtil.kt +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/ViewsUtil.kt @@ -6,6 +6,7 @@ import android.view.View import android.widget.Spinner import androidx.appcompat.widget.Toolbar import androidx.core.content.ContextCompat +import androidx.fragment.app.Fragment import androidx.recyclerview.widget.RecyclerView import com.getkeepsafe.taptargetview.TapTarget import com.getkeepsafe.taptargetview.TapTargetSequence @@ -16,6 +17,8 @@ import com.google.android.play.core.install.model.AppUpdateType import com.google.android.play.core.install.model.InstallStatus import com.google.android.play.core.install.model.UpdateAvailability import com.google.android.play.core.review.ReviewManagerFactory +import com.sergivonavi.materialbanner.Banner +import com.sergivonavi.materialbanner.BannerInterface import com.thesunnahrevival.sunnahassistant.R import com.thesunnahrevival.sunnahassistant.utilities.supportedLocales import com.thesunnahrevival.sunnahassistant.views.adapters.ReminderListAdapter @@ -25,64 +28,86 @@ import java.util.* val requestCodeForUpdate: Int = 1 -fun showOnBoardingTutorial(activity: MainActivity, reminderRecyclerAdapter: ReminderListAdapter, spinner: Spinner, recyclerView: RecyclerView) { +fun showOnBoardingTutorial( + activity: MainActivity, + reminderRecyclerAdapter: ReminderListAdapter, + spinner: Spinner, + recyclerView: RecyclerView +) { TapTargetSequence(activity) - .targets( - TapTarget.forView(activity.findViewById(R.id.fab), activity.getString(R.string.add_new_reminder), activity.getString(R.string.add_new_reminder_description)) - .outerCircleColor(android.R.color.holo_blue_dark) - .cancelable(false) - .textColor(R.color.bottomSheetColor) - .transparentTarget(true), - TapTarget.forView(spinner, activity.getString(R.string.spinner_tutorial), activity.getString(R.string.spinner_tutorial_description)) - .outerCircleColor(android.R.color.holo_blue_dark) - .cancelable(false) - .textColor(R.color.bottomSheetColor) - .transparentTarget(true), - TapTarget.forToolbarOverflow(activity?.findViewById(R.id.toolbar) as Toolbar, - activity.getString(R.string.change_theme), - activity.getString(R.string.change_theme_description)) - .outerCircleColor(android.R.color.holo_blue_dark) - .transparentTarget(true) - .cancelable(false) - .textColor(R.color.bottomSheetColor) - .tintTarget(true), - TapTarget.forView( - recyclerView, - activity.getString(R.string.edit_reminder), - activity.getString(R.string.edit_reminder_description)) - .outerCircleColor(android.R.color.holo_blue_dark) - .cancelable(false) - .tintTarget(true) - .textColor(R.color.bottomSheetColor) - .transparentTarget(true)) - .listener(object : TapTargetSequence.Listener { - override fun onSequenceFinish() { - showFilterReminderOnBoarding(activity, reminderRecyclerAdapter) - } - override fun onSequenceStep(lastTarget: TapTarget, targetClicked: Boolean) {} - override fun onSequenceCanceled(lastTarget: TapTarget) {} - }) - .start() + .targets( + TapTarget.forView( + activity.findViewById(R.id.fab), + activity.getString(R.string.add_new_reminder), + activity.getString(R.string.add_new_reminder_description) + ) + .outerCircleColor(android.R.color.holo_blue_dark) + .cancelable(false) + .textColor(R.color.bottomSheetColor) + .transparentTarget(true), + TapTarget.forView( + spinner, + activity.getString(R.string.spinner_tutorial), + activity.getString(R.string.spinner_tutorial_description) + ) + .outerCircleColor(android.R.color.holo_blue_dark) + .cancelable(false) + .textColor(R.color.bottomSheetColor) + .transparentTarget(true), + TapTarget.forToolbarOverflow( + activity?.findViewById(R.id.toolbar) as Toolbar, + activity.getString(R.string.change_theme), + activity.getString(R.string.change_theme_description) + ) + .outerCircleColor(android.R.color.holo_blue_dark) + .transparentTarget(true) + .cancelable(false) + .textColor(R.color.bottomSheetColor) + .tintTarget(true), + TapTarget.forView( + recyclerView, + activity.getString(R.string.edit_reminder), + activity.getString(R.string.edit_reminder_description) + ) + .outerCircleColor(android.R.color.holo_blue_dark) + .cancelable(false) + .tintTarget(true) + .textColor(R.color.bottomSheetColor) + .transparentTarget(true) + ) + .listener(object : TapTargetSequence.Listener { + override fun onSequenceFinish() { + showFilterReminderOnBoarding(activity, reminderRecyclerAdapter) + } + + override fun onSequenceStep(lastTarget: TapTarget, targetClicked: Boolean) {} + override fun onSequenceCanceled(lastTarget: TapTarget) {} + }) + .start() } -private fun showFilterReminderOnBoarding(activity: MainActivity, reminderRecyclerAdapter: ReminderListAdapter) { +private fun showFilterReminderOnBoarding( + activity: MainActivity, + reminderRecyclerAdapter: ReminderListAdapter +) { TapTargetView.showFor( - activity, - TapTarget.forToolbarMenuItem( - activity.findViewById(R.id.toolbar) as Toolbar, - R.id.filter, - activity.getString(R.string.filter_displayed_reminders), - activity.getString(R.string.filter_displayed_reminders_description)) - .cancelable(false) - .outerCircleColor(android.R.color.holo_blue_dark) - .textColor(R.color.bottomSheetColor) - .tintTarget(true), object : TapTargetView.Listener() { - override fun onTargetClick(view: TapTargetView) { - reminderRecyclerAdapter.deleteReminder(0) - view.dismiss(true) - } - }) + activity, + TapTarget.forToolbarMenuItem( + activity.findViewById(R.id.toolbar) as Toolbar, + R.id.filter, + activity.getString(R.string.filter_displayed_reminders), + activity.getString(R.string.filter_displayed_reminders_description) + ) + .cancelable(false) + .outerCircleColor(android.R.color.holo_blue_dark) + .textColor(R.color.bottomSheetColor) + .tintTarget(true), object : TapTargetView.Listener() { + override fun onTargetClick(view: TapTargetView) { + reminderRecyclerAdapter.deleteReminder(0) + view.dismiss(true) + } + }) } fun showInAppReviewPrompt(activity: MainActivity) { @@ -107,45 +132,43 @@ fun checkForUpdates(activity: MainActivity) { // Checks that the platform will allow the specified type of update. appUpdateInfoTask.addOnSuccessListener { appUpdateInfo -> if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE - && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE) + && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE) ) { appUpdateManager.registerListener { state -> if (state.installStatus() == InstallStatus.DOWNLOADED) { // After the update is downloaded, show a notification // and request user confirmation to restart the app. - popupSnackbar(activity, activity.getString(R.string.update_downloaded), Snackbar.LENGTH_INDEFINITE, - activity.getString(R.string.restart)) { appUpdateManager.completeUpdate() } + popupSnackbar( + activity, + activity.getString(R.string.update_downloaded), + Snackbar.LENGTH_INDEFINITE, + activity.getString(R.string.restart) + ) { appUpdateManager.completeUpdate() } } } // Request the update. appUpdateManager.startUpdateFlowForResult( - appUpdateInfo, - AppUpdateType.FLEXIBLE, - activity, - requestCodeForUpdate) + appUpdateInfo, + AppUpdateType.FLEXIBLE, + activity, + requestCodeForUpdate + ) } } } -fun popupSnackbar(fragment: MainFragment, message: String, duration: Int, actionMessage: String, listener: View.OnClickListener) { +fun popupSnackbar( + activity: MainActivity, + message: String, + duration: Int, + actionMessage: String, + listener: View.OnClickListener +) { Snackbar.make( - fragment.coordinator_layout, - message, - duration - ).apply { - setAction(actionMessage, listener) - view.setBackgroundColor(ContextCompat.getColor(fragment.requireContext(), R.color.fabColor)) - setActionTextColor(fragment.resources.getColor(android.R.color.black)) - show() - } -} - -fun popupSnackbar(activity: MainActivity, message: String, duration: Int, actionMessage: String, listener: View.OnClickListener) { - Snackbar.make( - activity.coordinator_layout, - message, - duration + activity.coordinator_layout, + message, + duration ).apply { setAction(actionMessage, listener) view.setBackgroundColor(ContextCompat.getColor(activity, R.color.fabColor)) @@ -154,57 +177,101 @@ fun popupSnackbar(activity: MainActivity, message: String, duration: Int, action } } -fun showHelpTranslateSnackBar(mainFragment : MainFragment) { - if (!supportedLocales.contains(Locale.getDefault().language)){ - val message = mainFragment.getString(R.string.help_translate_app, Locale.getDefault().displayLanguage) - val messageAction = mainFragment.getString(R.string.translate) - val listener = View.OnClickListener { - val browserIntent = Intent(Intent.ACTION_VIEW, - Uri.parse("https://crwd.in/sunnah-assistant")) - if (mainFragment.activity?.packageManager?.let { it1 -> browserIntent.resolveActivity(it1) } != null) { - mainFragment.startActivity(browserIntent) - } +fun showHelpTranslateSnackBar(mainFragment: MainFragment) { + if (!supportedLocales.contains(Locale.getDefault().language)) { + val onClickListener = BannerInterface.OnClickListener { + translateLink(mainFragment) } - popupSnackbar(mainFragment, - message, - 10000, - messageAction, - listener) + showBanner( + mainFragment.banner, + mainFragment.getString( + R.string.help_translate_app, + Locale.getDefault().displayLanguage + ), + R.drawable.help_translate, + mainFragment.getString(R.string.translate), + onClickListener + ) + } +} + +fun translateLink(fragment: Fragment) { + val browserIntent = Intent( + Intent.ACTION_VIEW, + Uri.parse("https://crwd.in/sunnah-assistant") + ) + if (fragment.activity?.packageManager?.let { it1 -> + browserIntent.resolveActivity( + it1 + ) + } != null) { + fragment.startActivity(browserIntent) } } fun showSendFeedbackSnackBar(mainFragment: MainFragment) { - val message = mainFragment.getString(R.string.help_improve_app) - val messageAction = mainFragment.getString(R.string.send_feedback) - val listener = View.OnClickListener { - val browserIntent = Intent(Intent.ACTION_VIEW, - Uri.parse("https://forms.gle/78xZW7hqSE6SS4Ko6")) + val onClickListener = BannerInterface.OnClickListener { + val browserIntent = Intent( + Intent.ACTION_VIEW, + Uri.parse("https://forms.gle/78xZW7hqSE6SS4Ko6") + ) if (mainFragment.activity?.packageManager?.let { it1 -> browserIntent.resolveActivity(it1) } != null) { mainFragment.startActivity(browserIntent) } } - popupSnackbar(mainFragment, - message, - 10000, - messageAction, - listener) + showBanner( + mainFragment.banner, + mainFragment.getString(R.string.help_improve_app), + R.drawable.feedback, + mainFragment.getString(R.string.send_feedback), + onClickListener + ) } fun showShareAppSnackBar(mainFragment: MainFragment) { - val message = mainFragment.getString(R.string.help_us_grow) - val messageAction = mainFragment.getString(R.string.share_app) - val listener = View.OnClickListener { - val intent = Intent(Intent.ACTION_SEND) - intent.type = "text/plain" - intent.putExtra( - Intent.EXTRA_TEXT, - "I invite you to download Sunnah Assistant Android App. The app enables you: \n\n- To set any reminders\n- An option to receive Salah (prayer) time alerts. \n- An option to add Sunnah reminders such as Reminders to fast on Mondays and Thursdays and reading Suratul Kahf on Friday\n- Many more other features \nDownload here for free:- https://play.google.com/store/apps/details?id=com.thesunnahrevival.sunnahassistant ") - mainFragment.startActivity(Intent.createChooser(intent, mainFragment.getString(R.string.share_app))) + val onClickListener = BannerInterface.OnClickListener { + val shareAppIntent = shareAppIntent() + mainFragment.startActivity( + Intent.createChooser( + shareAppIntent, + mainFragment.getString(R.string.share_app) + ) + ) } + showBanner( + mainFragment.banner, + mainFragment.getString(R.string.help_us_grow), + R.drawable.social_media, + mainFragment.getString(R.string.share_app), + onClickListener + ) +} + +fun shareAppIntent(): Intent { + val intent = Intent(Intent.ACTION_SEND) + intent.type = "text/plain" + intent.putExtra( + Intent.EXTRA_TEXT, + "I invite you to download Sunnah Assistant Android App. The app enables you: \n\n- To set any reminders\n- An option to receive Salah (prayer) time alerts. \n- An option to add Sunnah reminders such as Reminders to fast on Mondays and Thursdays and reading Suratul Kahf on Friday\n- Many more other features \n\nDownload here for free:- https://play.google.com/store/apps/details?id=com.thesunnahrevival.sunnahassistant " + ) + return intent +} - popupSnackbar(mainFragment, - message, - 10000, - messageAction, - listener) +private fun showBanner( + banner: Banner, + message: String, + iconId: Int, + rightButtonMessage: String, + rightButtonListener: BannerInterface.OnClickListener, + leftButtonMessage: String? = null, + leftButtonListener: BannerInterface.OnClickListener? = null +) { + banner.setMessage(message) + banner.setIcon(iconId) + banner.setRightButton(rightButtonMessage, rightButtonListener) + if (leftButtonMessage != null && leftButtonListener != null) + banner.setLeftButton(leftButtonMessage, leftButtonListener) + else + banner.setLeftButton(R.string.dismiss) { banner.dismiss() } + banner.visibility = View.VISIBLE } \ No newline at end of file diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/WebViewFragment.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/WebViewFragment.kt new file mode 100644 index 00000000..20f9ab0d --- /dev/null +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/WebViewFragment.kt @@ -0,0 +1,65 @@ +package com.thesunnahrevival.sunnahassistant.views + +import android.content.Intent +import android.graphics.Bitmap +import android.os.Bundle +import android.view.* +import android.webkit.WebView +import android.webkit.WebViewClient +import androidx.fragment.app.Fragment +import com.thesunnahrevival.sunnahassistant.R +import kotlinx.android.synthetic.main.web_view_fragment.* + +open class WebViewFragment : Fragment() { + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + setHasOptionsMenu(true) + // Inflate the layout for this fragment + return inflater.inflate(R.layout.web_view_fragment, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + webview.webViewClient = object : WebViewClient() { + override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { + progress_bar.visibility = View.VISIBLE + webview.visibility = View.GONE + } + + override fun onPageFinished(view: WebView?, url: String?) { + progress_bar.visibility = View.GONE + webview.visibility = View.VISIBLE + } + } + webview.loadUrl(getLink().toString()) + } + + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + inflater.inflate(R.menu.web_view_menu, menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + R.id.share_page -> { + val intent = Intent(Intent.ACTION_SEND) + intent.type = "text/plain" + intent.putExtra( + Intent.EXTRA_TEXT, + "${getLink()} \n\nSent from Sunnah Assistant App.\n\nGet Sunnah Assistant App at https://play.google.com/store/apps/details?id=com.thesunnahrevival.sunnahassistant " + ) + startActivity( + Intent.createChooser( + intent, + getString(R.string.share_message) + ) + ) + return true + } + } + return super.onOptionsItemSelected(item) + } + + open fun getLink() = arguments?.get("link") ?: "https://thesunnahrevival.com" + +} \ No newline at end of file diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/WelcomeFragment.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/WelcomeFragment.kt index 4ac53a2d..a5c33c4c 100644 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/WelcomeFragment.kt +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/WelcomeFragment.kt @@ -2,6 +2,7 @@ package com.thesunnahrevival.sunnahassistant.views import android.media.RingtoneManager import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -10,23 +11,26 @@ import androidx.lifecycle.ViewModelProviders import androidx.navigation.fragment.findNavController import com.thesunnahrevival.sunnahassistant.R import com.thesunnahrevival.sunnahassistant.data.model.AppSettings -import com.thesunnahrevival.sunnahassistant.utilities.createNotificationChannels import com.thesunnahrevival.sunnahassistant.viewmodels.SunnahAssistantViewModel import kotlinx.android.synthetic.main.fragment_welcome.* class WelcomeFragment : Fragment() { - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { return inflater.inflate(R.layout.fragment_welcome, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - context?.let { createNotificationChannels(it) } val myActivity = activity - if (myActivity != null){ - val viewModel = ViewModelProviders.of(myActivity).get(SunnahAssistantViewModel::class.java) - viewModel.getSettings().observe(viewLifecycleOwner, { settings: AppSettings? -> - if (settings?.isFirstLaunch == false){ + if (myActivity != null) { + val viewModel = + ViewModelProviders.of(myActivity).get(SunnahAssistantViewModel::class.java) + viewModel.getSettings().observe(viewLifecycleOwner) { settings: AppSettings? -> + if (settings?.isFirstLaunch == false) { findNavController().navigate(R.id.mainFragment) } @@ -36,15 +40,24 @@ class WelcomeFragment : Fragment() { privacy_policy.visibility = View.INVISIBLE read_privacy_policy.visibility = View.INVISIBLE progress_bar.visibility = View.VISIBLE - settings.notificationToneUri = RingtoneManager.getActualDefaultRingtoneUri( - context, RingtoneManager.TYPE_NOTIFICATION) + try { + settings.notificationToneUri = + RingtoneManager.getActualDefaultRingtoneUri( + context, RingtoneManager.TYPE_NOTIFICATION + ) + } catch (exception: SecurityException) { + Log.i("Info", "Notification tone set to default") + } + settings.isFirstLaunch = false settings.shareAnonymousUsageData = checkbox.isChecked - (myActivity as MainActivity).firebaseAnalytics.setAnalyticsCollectionEnabled(checkbox.isChecked) + (myActivity as MainActivity).firebaseAnalytics.setAnalyticsCollectionEnabled( + checkbox.isChecked + ) viewModel.updateSettings(settings) } } - }) + } read_privacy_policy.setOnClickListener { findNavController().navigate(R.id.privacyPolicyFragment) diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/home/MenuBarFragment.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/home/MenuBarFragment.kt index 160c7dde..489cd75c 100644 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/home/MenuBarFragment.kt +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/home/MenuBarFragment.kt @@ -23,6 +23,8 @@ import com.thesunnahrevival.sunnahassistant.utilities.openPlayStore import com.thesunnahrevival.sunnahassistant.viewmodels.SunnahAssistantViewModel import com.thesunnahrevival.sunnahassistant.views.AboutAppFragment import com.thesunnahrevival.sunnahassistant.views.MainActivity +import com.thesunnahrevival.sunnahassistant.views.shareAppIntent +import com.thesunnahrevival.sunnahassistant.views.translateLink abstract class MenuBarFragment : Fragment(), PopupMenu.OnMenuItemClickListener { @@ -76,20 +78,34 @@ abstract class MenuBarFragment : Fragment(), PopupMenu.OnMenuItemClickListener { fragment.show(myActivity.supportFragmentManager, "about") return true } + R.id.share_app -> { + val shareAppIntent = shareAppIntent() + startActivity( + Intent.createChooser( + shareAppIntent, + getString(R.string.share_app) + ) + ) + return true + } R.id.feedback -> { val intent = generateEmailIntent() if (intent.resolveActivity(myActivity.packageManager) != null) startActivity(intent) else - Toast.makeText(context, getString(R.string.no_email_app_installed), Toast.LENGTH_LONG).show() + Toast.makeText( + context, + getString(R.string.no_email_app_installed), + Toast.LENGTH_LONG + ).show() return true } R.id.rate_this_app -> { context?.let { openPlayStore(it, "com.thesunnahrevival.sunnahassistant") } return true } - R.id.support_developer -> { - context?.let { openPlayStore(it, "com.thesunnahrevival.supportdeveloper") } + R.id.help_translate_app -> { + context?.let { translateLink(this) } return true } R.id.more_apps -> { diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/settings/PrayerTimeSettingsFragment.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/settings/PrayerTimeSettingsFragment.kt index c9ed12f6..264f017f 100644 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/settings/PrayerTimeSettingsFragment.kt +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/settings/PrayerTimeSettingsFragment.kt @@ -22,34 +22,42 @@ import com.thesunnahrevival.sunnahassistant.views.dialogs.ConfirmationDialogFrag import com.thesunnahrevival.sunnahassistant.views.dialogs.EnterLocationDialogFragment import java.lang.Integer.parseInt -class PrayerTimeSettingsFragment: SettingsFragmentWithPopups(), View.OnClickListener { +class PrayerTimeSettingsFragment : SettingsFragmentWithPopups(), View.OnClickListener { private lateinit var mViewModel: SunnahAssistantViewModel - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { val binding: PrayerTimeSettingsBinding = DataBindingUtil.inflate( - inflater, R.layout.prayer_time_settings, container, false) + inflater, R.layout.prayer_time_settings, container, false + ) val myActivity = activity if (myActivity != null) { mViewModel = ViewModelProviders.of(myActivity).get(SunnahAssistantViewModel::class.java) mViewModel.isPrayerSettingsUpdated = false - mViewModel.getSettings().observe(viewLifecycleOwner, { - if (it != null){ + mViewModel.getSettings().observe(viewLifecycleOwner) { + if (it != null) { mViewModel.settingsValue = it binding.settings = it binding.setCalculationMethod(resources.getStringArray(R.array.calculation_methods)[it.calculationMethod.ordinal]) binding.setAsrCalculationMethod( - resources.getStringArray(R.array.asr_juristic_method)[it.asrCalculationMethod.ordinal] + resources.getStringArray(R.array.asr_juristic_method)[it.asrCalculationMethod.ordinal] ) binding.latitudeAdjustmentMethod = - resources.getStringArray(R.array.latitude_options)[it.latitudeAdjustmentMethod] + resources.getStringArray(R.array.latitude_options)[it.latitudeAdjustmentMethod] } - }) + } binding.activatePrayerTimeAlerts.setOnCheckedChangeListener { buttonView, isChecked -> if (buttonView.isPressed) { mViewModel.settingsValue?.isAutomatic = isChecked - mViewModel.settingsValue?.let { mViewModel.updateSettings(it) } + mViewModel.settingsValue?.let { + mViewModel.updateSettings(it) + mViewModel.isPrayerSettingsUpdated = true + } } } @@ -63,23 +71,33 @@ class PrayerTimeSettingsFragment: SettingsFragmentWithPopups(), View.OnClickList } override fun onClick(v: View?) { - when(v?.id) { + when (v?.id) { R.id.location_details -> { val dialogFragment = EnterLocationDialogFragment() fragmentManager?.let { dialogFragment.show(it, "dialog") } } R.id.calculation_details -> - showPopup(resources.getStringArray(R.array.calculation_methods), R.id.calculation_method, R.id.calculation_details) + showPopup( + resources.getStringArray(R.array.calculation_methods), + R.id.calculation_method, + R.id.calculation_details + ) R.id.asr_calculation_details -> - showPopup(resources.getStringArray(R.array.asr_juristic_method), - R.id.asr_calculation_method, R.id.asr_calculation_details) + showPopup( + resources.getStringArray(R.array.asr_juristic_method), + R.id.asr_calculation_method, R.id.asr_calculation_details + ) R.id.higher_latitude_details -> - showPopup(resources.getStringArray(R.array.latitude_options), - R.id.higher_latitude_method, R.id.higher_latitude_details) + showPopup( + resources.getStringArray(R.array.latitude_options), + R.id.higher_latitude_method, R.id.higher_latitude_details + ) R.id.do_not_disturb -> { if (isNotificationPolicyGranted()) - showPopup(resources.getStringArray(R.array.do_not_disturb_minutes), - R.id.do_not_disturb_minutes, R.id.do_not_disturb) + showPopup( + resources.getStringArray(R.array.do_not_disturb_minutes), + R.id.do_not_disturb_minutes, R.id.do_not_disturb + ) } } } @@ -92,14 +110,15 @@ class PrayerTimeSettingsFragment: SettingsFragmentWithPopups(), View.OnClickList when (item?.groupId) { R.id.calculation_details -> { mViewModel.settingsValue?.calculationMethod = - CalculationMethod.values()[calculationMethodsStrings.indexOf(item.title.toString())] + CalculationMethod.values()[calculationMethodsStrings.indexOf(item.title.toString())] } R.id.asr_calculation_details -> { mViewModel.settingsValue?.asrCalculationMethod = - Madhab.values()[asrMethods.indexOf(item.title.toString())] + Madhab.values()[asrMethods.indexOf(item.title.toString())] } R.id.higher_latitude_details -> { - mViewModel.settingsValue?.latitudeAdjustmentMethod = latitudeMethods.indexOf(item.title.toString()) + mViewModel.settingsValue?.latitudeAdjustmentMethod = + latitudeMethods.indexOf(item.title.toString()) } R.id.do_not_disturb -> { mViewModel.settingsValue?.doNotDisturbMinutes = parseInt(item.title.toString()) @@ -114,9 +133,9 @@ class PrayerTimeSettingsFragment: SettingsFragmentWithPopups(), View.OnClickList private fun isNotificationPolicyGranted(): Boolean { val notificationManager = - requireContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + requireContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // Check if the notification policy access has been granted for the app. return if (!notificationManager.isNotificationPolicyAccessGranted) { showConfirmationDialog() diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/settings/PrivacyPolicyFragment.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/settings/PrivacyPolicyFragment.kt index caf297f4..03bd2152 100644 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/settings/PrivacyPolicyFragment.kt +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/settings/PrivacyPolicyFragment.kt @@ -1,26 +1,18 @@ package com.thesunnahrevival.sunnahassistant.views.settings import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.Fragment +import android.view.Menu +import android.view.MenuInflater import com.google.firebase.analytics.FirebaseAnalytics -import com.thesunnahrevival.sunnahassistant.R import com.thesunnahrevival.sunnahassistant.views.MainActivity -import kotlinx.android.synthetic.main.fragment_privacy_policy.* +import com.thesunnahrevival.sunnahassistant.views.WebViewFragment -class PrivacyPolicyFragment : Fragment() { +class PrivacyPolicyFragment : WebViewFragment() { + override fun getLink() = "file:///android_asset/policy.html" - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_privacy_policy, container, false) - } + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - webview.loadUrl("file:///android_asset/policy.html") } override fun onResume() { diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/settings/SettingsListFragment.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/settings/SettingsListFragment.kt index 0eef6b9f..4d59c88b 100644 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/settings/SettingsListFragment.kt +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/views/settings/SettingsListFragment.kt @@ -1,5 +1,7 @@ package com.thesunnahrevival.sunnahassistant.views.settings +import android.content.Intent +import android.net.Uri import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -18,9 +20,55 @@ class SettingsListFragment : Fragment(), AdapterView.OnItemClickListener { val view = inflater.inflate(R.layout.settings_lists, container, false) val listView = view.findViewById(R.id.settings_lists) listView.adapter = - ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, resources.getStringArray(R.array.settings_lists)) + ArrayAdapter( + requireContext(), + android.R.layout.simple_list_item_1, + resources.getStringArray(R.array.settings_lists) + ) listView.onItemClickListener = this - view.findViewById(R.id.version).text = String.format(getString(R.string.version), BuildConfig.VERSION_NAME) + view.findViewById(R.id.version).text = + String.format(getString(R.string.version), BuildConfig.VERSION_NAME) + + view.findViewById(R.id.website).setOnClickListener { + startActivity( + Intent( + Intent.ACTION_VIEW, + Uri.parse("https://www.thesunnahrevival.com") + ) + ) + } + view.findViewById(R.id.facebook).setOnClickListener { + startActivity( + Intent( + Intent.ACTION_VIEW, + Uri.parse("https://www.facebook.com/thesunnahrevival") + ) + ) + } + view.findViewById(R.id.twitter).setOnClickListener { + startActivity( + Intent( + Intent.ACTION_VIEW, + Uri.parse("https://www.twitter.com/thesunahrevival") + ) + ) + } + view.findViewById(R.id.instagram).setOnClickListener { + startActivity( + Intent( + Intent.ACTION_VIEW, + Uri.parse("https://www.instagram.com/thesunnahrevival") + ) + ) + } + view.findViewById(R.id.telegram).setOnClickListener { + startActivity( + Intent( + Intent.ACTION_VIEW, + Uri.parse("https://t.me/thesunnahrevival") + ) + ) + } return view } diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/HijriDateWidget.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/HijriDateWidget.kt index 1514f8c1..4b2442a2 100644 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/HijriDateWidget.kt +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/HijriDateWidget.kt @@ -1,12 +1,16 @@ package com.thesunnahrevival.sunnahassistant.widgets +import android.app.PendingIntent import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetProvider import android.content.Context +import android.content.Intent +import android.view.View import android.widget.RemoteViews import com.thesunnahrevival.sunnahassistant.R import com.thesunnahrevival.sunnahassistant.data.local.SunnahAssistantDatabase import com.thesunnahrevival.sunnahassistant.utilities.* +import com.thesunnahrevival.sunnahassistant.views.MainActivity import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -17,54 +21,103 @@ import kotlinx.coroutines.withContext * App Widget Configuration implemented in [HijriDateWidgetConfigureActivity] */ class HijriDateWidget : AppWidgetProvider() { - override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { + override fun onUpdate( + context: Context, + appWidgetManager: AppWidgetManager, + appWidgetIds: IntArray + ) { CoroutineScope(Dispatchers.IO).launch { fetchDateFromDatabase(context, appWidgetManager, appWidgetIds.toTypedArray()) } } } -internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int, hijriText: String?, reminderName: String?, reminderTime: String?) { +internal fun updateAppWidget( + context: Context, + appWidgetManager: AppWidgetManager, + appWidgetId: Int, + isShowNextReminder: Boolean, + hijriText: String?, + reminderName: String?, + reminderTime: String? +) { // Construct the RemoteViews object val views = RemoteViews(context.packageName, R.layout.hijri_date_widget) - hijriText?.let { views.setTextViewText(R.id.hijri_date_text, hijriText) } - reminderName?.let { - views.setTextViewText(R.id.next_reminder_text, "$reminderTime: $it") + if (hijriText != null) { + views.setViewVisibility(R.id.hijri_date_text, View.VISIBLE) + views.setTextViewText(R.id.hijri_date_text, hijriText) + } else { + views.setViewVisibility(R.id.hijri_date_text, View.GONE) } - if (reminderName == null) - views.setTextViewText(R.id.next_reminder_text, "") + + if (isShowNextReminder) { + views.setViewVisibility(R.id.next_reminder_text, View.VISIBLE) + val next = context.getString(R.string.next_string) + if (reminderName != null) + views.setTextViewText( + R.id.next_reminder_text, + "$next $reminderName at $reminderTime" + ) + else + views.setTextViewText( + R.id.next_reminder_text, + context.getString(R.string.no_upcoming_reminder_today) + ) + } else + views.setViewVisibility(R.id.next_reminder_text, View.GONE) + + val widgetIntent = Intent(context, MainActivity::class.java) + val widgetPendingIntent = PendingIntent.getActivity(context, 0, widgetIntent, 0) + views.setOnClickPendingIntent(R.id.widget, widgetPendingIntent) + // Instruct the widget manager to update the widget appWidgetManager.updateAppWidget(appWidgetId, views) } -internal suspend fun updateWidgetSettings(context: Context, isDisplayHijriDate: Boolean, isDisplayNextReminder: Boolean ){ +internal suspend fun updateWidgetSettings( + context: Context, + isDisplayHijriDate: Boolean, + isDisplayNextReminder: Boolean +) { val reminderDao = SunnahAssistantDatabase.getInstance(context).reminderDao() reminderDao.updateWidgetSettings(isDisplayHijriDate, isDisplayNextReminder) } -internal suspend fun fetchDateFromDatabase(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: Array){ +internal suspend fun fetchDateFromDatabase( + context: Context, + appWidgetManager: AppWidgetManager, + appWidgetIds: Array +) { val reminderDao = SunnahAssistantDatabase.getInstance(context).reminderDao() val appSettings = reminderDao.getAppSettingsValue() val hijriText = if (appSettings?.isShowHijriDateWidget == true) hijriDate else null - - val nextReminder = if (appSettings?.isShowNextReminderWidget == true) reminderDao.getNextScheduledReminderToday( calculateOffsetFromMidnight(), dayOfTheWeek.toString(), getDayDate(System.currentTimeMillis()), getMonthNumber(System.currentTimeMillis()), - getYear(System.currentTimeMillis()).toInt()) else null + getYear(System.currentTimeMillis()).toInt() + ) else null val reminderName = nextReminder?.reminderName - val reminderTime = nextReminder?.timeInMilliseconds?.let { formatTimeInMilliseconds(context, it) } + val reminderTime = + nextReminder?.timeInMilliseconds?.let { formatTimeInMilliseconds(context, it) } - withContext(Dispatchers.Main){ + withContext(Dispatchers.Main) { // There may be multiple widgets active, so update all of them for (appWidgetId in appWidgetIds) { - updateAppWidget(context, appWidgetManager, appWidgetId, hijriText, reminderName, reminderTime) + updateAppWidget( + context, + appWidgetManager, + appWidgetId, + appSettings?.isShowNextReminderWidget ?: false, + hijriText, + reminderName, + reminderTime + ) } } diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/HijriDateWidgetConfigureActivity.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/HijriDateWidgetConfigureActivity.kt index 5859bb4f..84d8bc29 100644 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/HijriDateWidgetConfigureActivity.kt +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/HijriDateWidgetConfigureActivity.kt @@ -1,11 +1,11 @@ package com.thesunnahrevival.sunnahassistant.widgets -import android.app.Activity import android.appwidget.AppWidgetManager import android.content.Intent import android.os.Bundle import android.view.View import android.widget.TextView +import androidx.appcompat.app.AppCompatActivity import com.google.android.material.switchmaterial.SwitchMaterial import com.thesunnahrevival.sunnahassistant.R import kotlinx.coroutines.CoroutineScope @@ -15,18 +15,19 @@ import kotlinx.coroutines.launch /** * The configuration screen for the [HijriDateWidget] AppWidget. */ -class HijriDateWidgetConfigureActivity : Activity(), View.OnClickListener { +class HijriDateWidgetConfigureActivity : AppCompatActivity(), View.OnClickListener { private var appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID - public override fun onCreate(icicle: Bundle?) { - super.onCreate(icicle) + public override fun onCreate(bundle: Bundle?) { + super.onCreate(bundle) // Set the result to CANCELED. This will cause the widget host to cancel // out of the widget placement if the user presses the back button. setResult(RESULT_CANCELED) setContentView(R.layout.hijri_date_widget_configure) + setSupportActionBar(findViewById(R.id.toolbar)) findViewById(R.id.add_button).setOnClickListener(this) // Find the widget id from the intent. @@ -34,7 +35,8 @@ class HijriDateWidgetConfigureActivity : Activity(), View.OnClickListener { val extras = intent.extras if (extras != null) { appWidgetId = extras.getInt( - AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID) + AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID + ) } // If this activity was started with an intent without an app widget ID, finish with an error. @@ -50,23 +52,25 @@ class HijriDateWidgetConfigureActivity : Activity(), View.OnClickListener { // It is the responsibility of the configuration activity to update the app widget val appWidgetManager = AppWidgetManager.getInstance(context) val hijriChecked = findViewById(R.id.display_hijri_date_switch).isChecked - val nextReminderChecked = findViewById(R.id.display_next_reminder_switch).isChecked - if (hijriChecked || nextReminderChecked){ + val nextReminderChecked = + findViewById(R.id.display_next_reminder_switch).isChecked + if (hijriChecked || nextReminderChecked) { findViewById(R.id.error).visibility = View.GONE CoroutineScope(Dispatchers.IO).launch { updateWidgetSettings(context, hijriChecked, nextReminderChecked) val appWidgetIds = arrayOf(appWidgetId) - fetchDateFromDatabase(context, appWidgetManager, appWidgetIds ) + fetchDateFromDatabase(context, appWidgetManager, appWidgetIds) } + // Make sure we pass back the original appWidgetId + val resultValue = Intent() + resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) + setResult(RESULT_OK, resultValue) + finish() } else findViewById(R.id.error).visibility = View.VISIBLE - // Make sure we pass back the original appWidgetId - val resultValue = Intent() - resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) - setResult(RESULT_OK, resultValue) - finish() + } } diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/PrayerTimesWidgetConfigureActivity.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/PrayerTimesWidgetConfigureActivity.kt new file mode 100644 index 00000000..ddc9aa25 --- /dev/null +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/PrayerTimesWidgetConfigureActivity.kt @@ -0,0 +1,44 @@ +package com.thesunnahrevival.sunnahassistant.widgets + +import android.appwidget.AppWidgetManager +import android.graphics.Color +import android.widget.TextView +import com.thesunnahrevival.sunnahassistant.R + +class PrayerTimesWidgetConfigureActivity : SunnahAssistantConfigureWidgetActivity() { + + override fun createWidget(context: SunnahAssistantConfigureWidgetActivity) { + val appWidgetManager = AppWidgetManager.getInstance(context) + val options = resources.getStringArray(R.array.widget_theme_options) + when (findViewById(R.id.theme).text) { + options[1] -> { + updatePrayerAppWidget( + context, + appWidgetManager, + appWidgetId, + Color.BLACK, + Color.WHITE + ) + } + options[2] -> { + updatePrayerAppWidget( + context, + appWidgetManager, + appWidgetId, + Color.TRANSPARENT, + Color.WHITE + ) + } + else -> { + updatePrayerAppWidget( + context, + appWidgetManager, + appWidgetId, + Color.WHITE, + Color.BLACK + ) + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/PrayerTimesWidgetDark.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/PrayerTimesWidgetDark.kt deleted file mode 100644 index 27b0f126..00000000 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/PrayerTimesWidgetDark.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.thesunnahrevival.sunnahassistant.widgets - -import android.appwidget.AppWidgetManager -import android.appwidget.AppWidgetProvider -import android.content.Context -import android.graphics.Color - -class PrayerTimesWidgetDark : AppWidgetProvider() { - override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { - // There may be multiple widgets active, so update all of them - for (appWidgetId in appWidgetIds) { - updatePrayerAppWidget(context, appWidgetManager, appWidgetId, Color.BLACK, Color.WHITE) - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/PrayerTimesWidgetTransparent.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/PrayerTimesWidgetTransparent.kt deleted file mode 100644 index 172fb4d7..00000000 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/PrayerTimesWidgetTransparent.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.thesunnahrevival.sunnahassistant.widgets - -import android.appwidget.AppWidgetManager -import android.appwidget.AppWidgetProvider -import android.content.Context -import android.graphics.Color - -class PrayerTimesWidgetTransparent : AppWidgetProvider() { - override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { - // There may be multiple widgets active, so update all of them - for (appWidgetId in appWidgetIds) { - updatePrayerAppWidget(context, appWidgetManager, appWidgetId, Color.TRANSPARENT, Color.WHITE) - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/SunnahAssistantConfigureWidgetActivity.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/SunnahAssistantConfigureWidgetActivity.kt new file mode 100644 index 00000000..3ccfa6d3 --- /dev/null +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/SunnahAssistantConfigureWidgetActivity.kt @@ -0,0 +1,80 @@ +package com.thesunnahrevival.sunnahassistant.widgets + +import android.appwidget.AppWidgetManager +import android.content.Intent +import android.os.Bundle +import android.view.Menu +import android.view.MenuItem +import android.view.View +import android.widget.PopupMenu +import android.widget.TextView +import androidx.appcompat.app.AppCompatActivity +import com.thesunnahrevival.sunnahassistant.R +import kotlinx.android.synthetic.main.sunnah_assistant_configure_widget.* + +abstract class SunnahAssistantConfigureWidgetActivity : AppCompatActivity(), View.OnClickListener, + PopupMenu.OnMenuItemClickListener { + var appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID + + + public override fun onCreate(bundle: Bundle?) { + super.onCreate(bundle) + + // Set the result to CANCELED. This will cause the widget host to cancel + // out of the widget placement if the user presses the back button. + setResult(RESULT_CANCELED) + + setContentView(R.layout.sunnah_assistant_configure_widget) + setSupportActionBar(findViewById(R.id.toolbar)) + add_button.setOnClickListener(this) + theme_settings.setOnClickListener(this) + + // Find the widget id from the intent. + val intent = intent + val extras = intent.extras + if (extras != null) { + appWidgetId = extras.getInt( + AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID + ) + } + // If this activity was started with an intent without an app widget ID, finish with an error. + if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) { + finish() + return + } + } + + override fun onClick(v: View?) { + val context = this + when (v) { + theme_settings -> { + val popupMenu = PopupMenu(context, findViewById(R.id.theme)) + val options = resources.getStringArray(R.array.widget_theme_options) + for ((index, method) in options.withIndex()) { + popupMenu.menu.add(R.id.theme_settings, Menu.NONE, index, method) + } + popupMenu.setOnMenuItemClickListener(this) + popupMenu.show() + } + add_button -> { + createWidget(context) + val resultValue = Intent() + resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) + setResult(RESULT_OK, resultValue) + finish() + } + } + } + + abstract fun createWidget(context: SunnahAssistantConfigureWidgetActivity) + + override fun onMenuItemClick(item: MenuItem?): Boolean { + when (item?.groupId) { + R.id.theme_settings -> { + findViewById(R.id.theme).text = item.title.toString() + } + } + return true + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/TodayRemindersWidgetConfigureActivity.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/TodayRemindersWidgetConfigureActivity.kt new file mode 100644 index 00000000..d86cc1b6 --- /dev/null +++ b/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/TodayRemindersWidgetConfigureActivity.kt @@ -0,0 +1,42 @@ +package com.thesunnahrevival.sunnahassistant.widgets + +import android.appwidget.AppWidgetManager +import android.graphics.Color +import android.widget.TextView +import com.thesunnahrevival.sunnahassistant.R + +class TodayRemindersWidgetConfigureActivity : SunnahAssistantConfigureWidgetActivity() { + override fun createWidget(context: SunnahAssistantConfigureWidgetActivity) { + val appWidgetManager = AppWidgetManager.getInstance(context) + val options = resources.getStringArray(R.array.widget_theme_options) + when (findViewById(R.id.theme).text) { + options[1] -> { + updateAppWidget( + context, + appWidgetManager, + appWidgetId, + Color.BLACK, + Color.WHITE + ) + } + options[2] -> { + updateAppWidget( + context, + appWidgetManager, + appWidgetId, + Color.TRANSPARENT, + Color.WHITE + ) + } + else -> { + updateAppWidget( + context, + appWidgetManager, + appWidgetId, + Color.WHITE, + Color.BLACK + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/TodaysRemindersWidgetDark.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/TodaysRemindersWidgetDark.kt deleted file mode 100644 index c1d306bd..00000000 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/TodaysRemindersWidgetDark.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.thesunnahrevival.sunnahassistant.widgets - -import android.appwidget.AppWidgetManager -import android.appwidget.AppWidgetProvider -import android.content.Context -import android.graphics.Color - -class TodaysRemindersWidgetDark : AppWidgetProvider() { - override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { - // There may be multiple widgets active, so update all of them - for (appWidgetId in appWidgetIds) { - updateAppWidget(context, appWidgetManager, appWidgetId, Color.BLACK, Color.WHITE) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/TodaysRemindersWidgetTransparent.kt b/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/TodaysRemindersWidgetTransparent.kt deleted file mode 100644 index 175da9ed..00000000 --- a/app/src/main/java/com/thesunnahrevival/sunnahassistant/widgets/TodaysRemindersWidgetTransparent.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.thesunnahrevival.sunnahassistant.widgets - -import android.appwidget.AppWidgetManager -import android.appwidget.AppWidgetProvider -import android.content.Context -import android.graphics.Color - -class TodaysRemindersWidgetTransparent : AppWidgetProvider() { - override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { - // There may be multiple widgets active, so update all of them - for (appWidgetId in appWidgetIds) { - updateAppWidget(context, appWidgetManager, appWidgetId, Color.TRANSPARENT, Color.WHITE) - } - } -} \ No newline at end of file diff --git a/app/src/main/res/drawable-night/ic_share.xml b/app/src/main/res/drawable-night/ic_share.xml new file mode 100644 index 00000000..7522ecdf --- /dev/null +++ b/app/src/main/res/drawable-night/ic_share.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable-night/ic_web.xml b/app/src/main/res/drawable-night/ic_web.xml new file mode 100644 index 00000000..68c94fc2 --- /dev/null +++ b/app/src/main/res/drawable-night/ic_web.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/feedback.png b/app/src/main/res/drawable/feedback.png new file mode 100644 index 00000000..466777c2 Binary files /dev/null and b/app/src/main/res/drawable/feedback.png differ diff --git a/app/src/main/res/drawable/help_translate.png b/app/src/main/res/drawable/help_translate.png new file mode 100644 index 00000000..b1e72aa4 Binary files /dev/null and b/app/src/main/res/drawable/help_translate.png differ diff --git a/app/src/main/res/drawable/ic_share.xml b/app/src/main/res/drawable/ic_share.xml new file mode 100644 index 00000000..4505f477 --- /dev/null +++ b/app/src/main/res/drawable/ic_share.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_web.xml b/app/src/main/res/drawable/ic_web.xml new file mode 100644 index 00000000..5a87677e --- /dev/null +++ b/app/src/main/res/drawable/ic_web.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/prayer_times_dark.png b/app/src/main/res/drawable/prayer_times_dark.png deleted file mode 100755 index a9ecc653..00000000 Binary files a/app/src/main/res/drawable/prayer_times_dark.png and /dev/null differ diff --git a/app/src/main/res/drawable/prayer_times_transparent.png b/app/src/main/res/drawable/prayer_times_transparent.png deleted file mode 100755 index 4b616408..00000000 Binary files a/app/src/main/res/drawable/prayer_times_transparent.png and /dev/null differ diff --git a/app/src/main/res/drawable/social_media.png b/app/src/main/res/drawable/social_media.png new file mode 100644 index 00000000..a86ca587 Binary files /dev/null and b/app/src/main/res/drawable/social_media.png differ diff --git a/app/src/main/res/drawable/today_reminders_dark.png b/app/src/main/res/drawable/today_reminders_dark.png deleted file mode 100755 index c8dabf9c..00000000 Binary files a/app/src/main/res/drawable/today_reminders_dark.png and /dev/null differ diff --git a/app/src/main/res/drawable/today_reminders_transparent.png b/app/src/main/res/drawable/today_reminders_transparent.png deleted file mode 100755 index 831b01c9..00000000 Binary files a/app/src/main/res/drawable/today_reminders_transparent.png and /dev/null differ diff --git a/app/src/main/res/layout/changelog_layout.xml b/app/src/main/res/layout/changelog_layout.xml index 854ce86d..b49f9cd6 100644 --- a/app/src/main/res/layout/changelog_layout.xml +++ b/app/src/main/res/layout/changelog_layout.xml @@ -16,22 +16,16 @@ android:paddingEnd="16dp" android:text="@string/important" android:textStyle="bold" + android:visibility="gone" android:textColor="@android:color/holo_red_dark"/> - - - + + xmlns:tools="http://schemas.android.com/tools" + > - + - + - + - + - - + + - + - + + - - - - - - - - - - - - - - - - - - - - - + android:layout_height="wrap_content" + android:orientation="vertical" + > + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_privacy_policy.xml b/app/src/main/res/layout/fragment_privacy_policy.xml deleted file mode 100644 index 72a7090b..00000000 --- a/app/src/main/res/layout/fragment_privacy_policy.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/hijri_date_widget.xml b/app/src/main/res/layout/hijri_date_widget.xml index 87afcb2e..d2b16ba9 100644 --- a/app/src/main/res/layout/hijri_date_widget.xml +++ b/app/src/main/res/layout/hijri_date_widget.xml @@ -1,4 +1,5 @@ \ No newline at end of file diff --git a/app/src/main/res/layout/hijri_date_widget_configure.xml b/app/src/main/res/layout/hijri_date_widget_configure.xml index 3ad92207..76e0ae32 100644 --- a/app/src/main/res/layout/hijri_date_widget_configure.xml +++ b/app/src/main/res/layout/hijri_date_widget_configure.xml @@ -1,54 +1,80 @@ + > - - - - - + + + + + + + android:layout_height="match_parent" + android:orientation="vertical" + android:padding="@dimen/default_dimen" + > + -