Merge branch 'SimpleMobileTools:master' into attendee_improvements

This commit is contained in:
Naveen Singh 2023-09-28 00:06:13 +05:30 committed by GitHub
commit 8db98217c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 198 additions and 170 deletions

View file

@ -1,14 +1,11 @@
package com.simplemobiletools.calendar.pro.activities
import android.annotation.SuppressLint
import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Intent
import android.content.pm.ShortcutInfo
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Icon
import android.graphics.drawable.LayerDrawable
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.provider.ContactsContract.CommonDataKinds
@ -22,15 +19,12 @@ import com.simplemobiletools.calendar.pro.adapters.EventListAdapter
import com.simplemobiletools.calendar.pro.adapters.QuickFilterEventTypeAdapter
import com.simplemobiletools.calendar.pro.databases.EventsDatabase
import com.simplemobiletools.calendar.pro.databinding.ActivityMainBinding
import com.simplemobiletools.calendar.pro.dialogs.ExportEventsDialog
import com.simplemobiletools.calendar.pro.dialogs.ImportEventsDialog
import com.simplemobiletools.calendar.pro.dialogs.SelectEventTypesDialog
import com.simplemobiletools.calendar.pro.dialogs.SetRemindersDialog
import com.simplemobiletools.calendar.pro.extensions.*
import com.simplemobiletools.calendar.pro.fragments.*
import com.simplemobiletools.calendar.pro.helpers.*
import com.simplemobiletools.calendar.pro.helpers.Formatter
import com.simplemobiletools.calendar.pro.helpers.IcsExporter.ExportResult
import com.simplemobiletools.calendar.pro.helpers.IcsImporter.ImportResult
import com.simplemobiletools.calendar.pro.jobs.CalDAVUpdateListener
import com.simplemobiletools.calendar.pro.models.Event
@ -38,8 +32,6 @@ import com.simplemobiletools.calendar.pro.models.ListEvent
import com.simplemobiletools.calendar.pro.models.ListItem
import com.simplemobiletools.calendar.pro.models.ListSectionDay
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.dialogs.FilePickerDialog
import com.simplemobiletools.commons.dialogs.PermissionRequiredDialog
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.*
@ -52,14 +44,10 @@ import com.simplemobiletools.commons.views.MyLinearLayoutManager
import com.simplemobiletools.commons.views.MyRecyclerView
import org.joda.time.DateTime
import org.joda.time.DateTimeZone
import java.io.FileOutputStream
import java.io.OutputStream
import java.text.SimpleDateFormat
import java.util.*
class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
private val PICK_IMPORT_SOURCE_INTENT = 1
private val PICK_EXPORT_FILE_INTENT = 2
private var showCalDAVRefreshToast = false
private var mShouldFilterBeVisible = false
@ -67,7 +55,6 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
private var shouldGoToTodayBeVisible = false
private var goToTodayButton: MenuItem? = null
private var currentFragments = ArrayList<MyFragmentHolder>()
private var eventTypesToExport = ArrayList<Long>()
private var mStoredTextColor = 0
private var mStoredBackgroundColor = 0
@ -282,8 +269,6 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
R.id.add_holidays -> addHolidays()
R.id.add_birthdays -> tryAddBirthdays()
R.id.add_anniversaries -> tryAddAnniversaries()
R.id.import_events -> tryImportEvents()
R.id.export_events -> tryExportEvents()
R.id.more_apps_from_us -> launchMoreAppsFromUsIntent()
R.id.settings -> launchSettings()
R.id.about -> launchAbout()
@ -314,16 +299,6 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
checkIsViewIntent()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
super.onActivityResult(requestCode, resultCode, resultData)
if (requestCode == PICK_IMPORT_SOURCE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) {
tryImportEventsFromFile(resultData.data!!)
} else if (requestCode == PICK_EXPORT_FILE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) {
val outputStream = contentResolver.openOutputStream(resultData.data!!)
exportEventsTo(eventTypesToExport, outputStream)
}
}
private fun storeStateVariables() {
mStoredTextColor = getProperTextColor()
mStoredPrimaryColor = getProperPrimaryColor()
@ -497,7 +472,14 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
}
} else {
tryImportEventsFromFile(uri!!)
tryImportEventsFromFile(uri!!) {
if (it) {
runOnUiThread {
updateViewPager()
setupQuickFilter()
}
}
}
}
}
}
@ -1066,129 +1048,6 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
}
private fun tryImportEvents() {
if (isQPlus()) {
handleNotificationPermission { granted ->
if (granted) {
hideKeyboard()
Intent(Intent.ACTION_GET_CONTENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "text/calendar"
try {
startActivityForResult(this, PICK_IMPORT_SOURCE_INTENT)
} catch (e: ActivityNotFoundException) {
toast(com.simplemobiletools.commons.R.string.system_service_disabled, Toast.LENGTH_LONG)
} catch (e: Exception) {
showErrorToast(e)
}
}
} else {
PermissionRequiredDialog(this, com.simplemobiletools.commons.R.string.allow_notifications_reminders, { openNotificationSettings() })
}
}
} else {
handlePermission(PERMISSION_READ_STORAGE) {
if (it) {
importEvents()
}
}
}
}
private fun importEvents() {
FilePickerDialog(this) {
showImportEventsDialog(it)
}
}
private fun tryImportEventsFromFile(uri: Uri) {
when (uri.scheme) {
"file" -> showImportEventsDialog(uri.path!!)
"content" -> {
val tempFile = getTempFile()
if (tempFile == null) {
toast(com.simplemobiletools.commons.R.string.unknown_error_occurred)
return
}
try {
val inputStream = contentResolver.openInputStream(uri)
val out = FileOutputStream(tempFile)
inputStream!!.copyTo(out)
showImportEventsDialog(tempFile.absolutePath)
} catch (e: Exception) {
showErrorToast(e)
}
}
else -> toast(com.simplemobiletools.commons.R.string.invalid_file_format)
}
}
private fun showImportEventsDialog(path: String) {
ImportEventsDialog(this, path) {
if (it) {
runOnUiThread {
updateViewPager()
setupQuickFilter()
}
}
}
}
private fun tryExportEvents() {
if (isQPlus()) {
ExportEventsDialog(this, config.lastExportPath, true) { file, eventTypes ->
eventTypesToExport = eventTypes
hideKeyboard()
Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
type = "text/calendar"
putExtra(Intent.EXTRA_TITLE, file.name)
addCategory(Intent.CATEGORY_OPENABLE)
try {
startActivityForResult(this, PICK_EXPORT_FILE_INTENT)
} catch (e: ActivityNotFoundException) {
toast(com.simplemobiletools.commons.R.string.system_service_disabled, Toast.LENGTH_LONG)
} catch (e: Exception) {
showErrorToast(e)
}
}
}
} else {
handlePermission(PERMISSION_WRITE_STORAGE) { granted ->
if (granted) {
ExportEventsDialog(this, config.lastExportPath, false) { file, eventTypes ->
getFileOutputStream(file.toFileDirItem(this), true) {
exportEventsTo(eventTypes, it)
}
}
}
}
}
}
private fun exportEventsTo(eventTypes: ArrayList<Long>, outputStream: OutputStream?) {
ensureBackgroundThread {
val events = eventsHelper.getEventsToExport(eventTypes, config.exportEvents, config.exportTasks, config.exportPastEntries)
if (events.isEmpty()) {
toast(com.simplemobiletools.commons.R.string.no_entries_for_exporting)
} else {
IcsExporter(this).exportEvents(outputStream, events, true) { result ->
toast(
when (result) {
ExportResult.EXPORT_OK -> com.simplemobiletools.commons.R.string.exporting_successful
ExportResult.EXPORT_PARTIAL -> com.simplemobiletools.commons.R.string.exporting_some_entries_failed
else -> com.simplemobiletools.commons.R.string.exporting_failed
}
)
}
}
}
}
private fun launchSettings() {
hideKeyboard()
startActivity(Intent(applicationContext, SettingsActivity::class.java))

View file

@ -12,10 +12,7 @@ import com.google.android.material.timepicker.MaterialTimePicker
import com.google.android.material.timepicker.TimeFormat
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.databinding.ActivitySettingsBinding
import com.simplemobiletools.calendar.pro.dialogs.ManageAutomaticBackupsDialog
import com.simplemobiletools.calendar.pro.dialogs.SelectCalendarsDialog
import com.simplemobiletools.calendar.pro.dialogs.SelectEventTypeDialog
import com.simplemobiletools.calendar.pro.dialogs.SelectEventTypesDialog
import com.simplemobiletools.calendar.pro.dialogs.*
import com.simplemobiletools.calendar.pro.extensions.*
import com.simplemobiletools.calendar.pro.helpers.*
import com.simplemobiletools.calendar.pro.models.EventType
@ -28,6 +25,7 @@ import org.joda.time.DateTime
import org.joda.time.DateTimeConstants
import java.io.File
import java.io.InputStream
import java.io.OutputStream
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
@ -35,10 +33,14 @@ import kotlin.system.exitProcess
class SettingsActivity : SimpleActivity() {
private val GET_RINGTONE_URI = 1
private val PICK_IMPORT_SOURCE_INTENT = 2
private val PICK_SETTINGS_IMPORT_SOURCE_INTENT = 2
private val PICK_EVENTS_IMPORT_SOURCE_INTENT = 3
private val PICK_EVENTS_EXPORT_FILE_INTENT = 4
private var mStoredPrimaryColor = 0
private var eventTypesToExport = listOf<Long>()
private val binding by viewBinding(ActivitySettingsBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) {
@ -105,6 +107,8 @@ class SettingsActivity : SimpleActivity() {
checkPrimaryColor()
setupEnableAutomaticBackups()
setupManageAutomaticBackups()
setupExportEvents()
setupImportEvents()
setupExportSettings()
setupImportSettings()
@ -145,9 +149,14 @@ class SettingsActivity : SimpleActivity() {
if (requestCode == GET_RINGTONE_URI && resultCode == RESULT_OK && resultData != null) {
val newAlarmSound = storeNewYourAlarmSound(resultData)
updateReminderSound(newAlarmSound)
} else if (requestCode == PICK_IMPORT_SOURCE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) {
} else if (requestCode == PICK_SETTINGS_IMPORT_SOURCE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) {
val inputStream = contentResolver.openInputStream(resultData.data!!)
parseFile(inputStream)
} else if (requestCode == PICK_EVENTS_IMPORT_SOURCE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) {
tryImportEventsFromFile(resultData.data!!)
} else if (requestCode == PICK_EVENTS_EXPORT_FILE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) {
val outputStream = contentResolver.openOutputStream(resultData.data!!)
exportEventsTo(eventTypesToExport, outputStream)
}
}
@ -898,6 +907,18 @@ class SettingsActivity : SimpleActivity() {
settingsManageAutomaticBackupsHolder.beVisibleIf(enable)
}
private fun setupExportEvents() {
binding.eventsExportHolder.setOnClickListener {
tryExportEvents()
}
}
private fun setupImportEvents() {
binding.eventsImportHolder.setOnClickListener {
tryImportEvents()
}
}
private fun setupExportSettings() {
binding.settingsExportHolder.setOnClickListener {
val configItems = LinkedHashMap<String, Any>().apply {
@ -959,7 +980,7 @@ class SettingsActivity : SimpleActivity() {
type = "text/plain"
try {
startActivityForResult(this, PICK_IMPORT_SOURCE_INTENT)
startActivityForResult(this, PICK_SETTINGS_IMPORT_SOURCE_INTENT)
} catch (e: ActivityNotFoundException) {
toast(com.simplemobiletools.commons.R.string.system_service_disabled, Toast.LENGTH_LONG)
} catch (e: Exception) {
@ -1072,4 +1093,93 @@ class SettingsActivity : SimpleActivity() {
updateWidgets()
}
}
private fun tryImportEvents() {
if (isQPlus()) {
handleNotificationPermission { granted ->
if (granted) {
hideKeyboard()
Intent(Intent.ACTION_GET_CONTENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "text/calendar"
try {
startActivityForResult(this, PICK_EVENTS_IMPORT_SOURCE_INTENT)
} catch (e: ActivityNotFoundException) {
toast(com.simplemobiletools.commons.R.string.system_service_disabled, Toast.LENGTH_LONG)
} catch (e: Exception) {
showErrorToast(e)
}
}
} else {
PermissionRequiredDialog(this, com.simplemobiletools.commons.R.string.allow_notifications_reminders, { openNotificationSettings() })
}
}
} else {
handlePermission(PERMISSION_READ_STORAGE) {
if (it) {
importEvents()
}
}
}
}
private fun importEvents() {
FilePickerDialog(this) {
showImportEventsDialog(it) {}
}
}
private fun tryExportEvents() {
if (isQPlus()) {
ExportEventsDialog(this, config.lastExportPath, true) { file, eventTypes ->
eventTypesToExport = eventTypes
hideKeyboard()
Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
type = "text/calendar"
putExtra(Intent.EXTRA_TITLE, file.name)
addCategory(Intent.CATEGORY_OPENABLE)
try {
startActivityForResult(this, PICK_EVENTS_EXPORT_FILE_INTENT)
} catch (e: ActivityNotFoundException) {
toast(com.simplemobiletools.commons.R.string.system_service_disabled, Toast.LENGTH_LONG)
} catch (e: Exception) {
showErrorToast(e)
}
}
}
} else {
handlePermission(PERMISSION_WRITE_STORAGE) { granted ->
if (granted) {
ExportEventsDialog(this, config.lastExportPath, false) { file, eventTypes ->
getFileOutputStream(file.toFileDirItem(this), true) {
exportEventsTo(eventTypes, it)
}
}
}
}
}
}
private fun exportEventsTo(eventTypes: List<Long>, outputStream: OutputStream?) {
ensureBackgroundThread {
val events = eventsHelper.getEventsToExport(eventTypes, config.exportEvents, config.exportTasks, config.exportPastEntries)
if (events.isEmpty()) {
toast(com.simplemobiletools.commons.R.string.no_entries_for_exporting)
} else {
IcsExporter(this).exportEvents(outputStream, events, true) { result ->
toast(
when (result) {
IcsExporter.ExportResult.EXPORT_OK -> com.simplemobiletools.commons.R.string.exporting_successful
IcsExporter.ExportResult.EXPORT_PARTIAL -> com.simplemobiletools.commons.R.string.exporting_some_entries_failed
else -> com.simplemobiletools.commons.R.string.exporting_failed
}
)
}
}
}
}
}

View file

@ -40,6 +40,7 @@ class ImportEventsDialog(val activity: SimpleActivity, val path: String, val cal
} else {
config.lastUsedLocalEventTypeId
}
binding.importEventsCheckbox.isChecked = config.lastUsedIgnoreEventTypesState
activity.runOnUiThread {
initDialog()
@ -85,6 +86,7 @@ class ImportEventsDialog(val activity: SimpleActivity, val path: String, val cal
activity.toast(com.simplemobiletools.commons.R.string.importing)
ensureBackgroundThread {
val overrideFileEventTypes = binding.importEventsCheckbox.isChecked
config.lastUsedIgnoreEventTypesState = overrideFileEventTypes
val result = IcsImporter(activity).importEvents(path, currEventTypeId, currEventTypeCalDAVCalendarId, overrideFileEventTypes)
handleParseResult(result)
alertDialog.dismiss()

View file

@ -1,8 +1,11 @@
package com.simplemobiletools.calendar.pro.extensions
import android.app.Activity
import android.net.Uri
import com.simplemobiletools.calendar.pro.BuildConfig
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
import com.simplemobiletools.calendar.pro.dialogs.CustomEventRepeatIntervalDialog
import com.simplemobiletools.calendar.pro.dialogs.ImportEventsDialog
import com.simplemobiletools.calendar.pro.helpers.*
import com.simplemobiletools.calendar.pro.models.Event
import com.simplemobiletools.commons.activities.BaseSimpleActivity
@ -11,6 +14,7 @@ import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.models.RadioItem
import java.io.File
import java.io.FileOutputStream
import java.util.TreeSet
fun BaseSimpleActivity.shareEvents(ids: List<Long>) {
@ -83,3 +87,31 @@ fun Activity.showEventRepeatIntervalDialog(curSeconds: Int, callback: (minutes:
}
}
}
fun SimpleActivity.tryImportEventsFromFile(uri: Uri, callback: (Boolean) -> Unit = {}) {
when (uri.scheme) {
"file" -> showImportEventsDialog(uri.path!!, callback)
"content" -> {
val tempFile = getTempFile()
if (tempFile == null) {
toast(com.simplemobiletools.commons.R.string.unknown_error_occurred)
return
}
try {
val inputStream = contentResolver.openInputStream(uri)
val out = FileOutputStream(tempFile)
inputStream!!.copyTo(out)
showImportEventsDialog(tempFile.absolutePath, callback)
} catch (e: Exception) {
showErrorToast(e)
}
}
else -> toast(com.simplemobiletools.commons.R.string.invalid_file_format)
}
}
fun SimpleActivity.showImportEventsDialog(path: String, callback: (Boolean) -> Unit) {
ImportEventsDialog(this, path, callback)
}

View file

@ -121,6 +121,10 @@ class Config(context: Context) : BaseConfig(context) {
get() = prefs.getLong(LAST_USED_LOCAL_EVENT_TYPE_ID, REGULAR_EVENT_TYPE_ID)
set(lastUsedLocalEventTypeId) = prefs.edit().putLong(LAST_USED_LOCAL_EVENT_TYPE_ID, lastUsedLocalEventTypeId).apply()
var lastUsedIgnoreEventTypesState: Boolean
get() = prefs.getBoolean(LAST_USED_IGNORE_EVENT_TYPES_STATE, false)
set(lastUsedIgnoreEventTypesState) = prefs.edit().putBoolean(LAST_USED_IGNORE_EVENT_TYPES_STATE, lastUsedIgnoreEventTypesState).apply()
var reminderAudioStream: Int
get() = prefs.getInt(REMINDER_AUDIO_STREAM, AudioManager.STREAM_NOTIFICATION)
set(reminderAudioStream) = prefs.edit().putInt(REMINDER_AUDIO_STREAM, reminderAudioStream).apply()

View file

@ -101,6 +101,7 @@ const val CALDAV_SYNC = "caldav_sync"
const val CALDAV_SYNCED_CALENDAR_IDS = "caldav_synced_calendar_ids"
const val LAST_USED_CALDAV_CALENDAR = "last_used_caldav_calendar"
const val LAST_USED_LOCAL_EVENT_TYPE_ID = "last_used_local_event_type_id"
const val LAST_USED_IGNORE_EVENT_TYPES_STATE = "last_used_ignore_event_types_state"
const val DISPLAY_PAST_EVENTS = "display_past_events"
const val DISPLAY_DESCRIPTION = "display_description"
const val REPLACE_DESCRIPTION = "replace_description"

View file

@ -612,10 +612,10 @@ class EventsHelper(val context: Context) {
return events
}
fun getEventsToExport(eventTypes: ArrayList<Long>, exportEvents: Boolean, exportTasks: Boolean, exportPastEntries: Boolean): ArrayList<Event> {
fun getEventsToExport(eventTypes: List<Long>, exportEvents: Boolean, exportTasks: Boolean, exportPastEntries: Boolean): MutableList<Event> {
val currTS = getNowSeconds()
var events = ArrayList<Event>()
val tasks = ArrayList<Event>()
var events = mutableListOf<Event>()
val tasks = mutableListOf<Event>()
if (exportPastEntries) {
if (exportEvents) {
events.addAll(eventsDB.getAllEventsWithTypes(eventTypes))

View file

@ -31,7 +31,7 @@ class IcsExporter(private val context: Context) {
fun exportEvents(
outputStream: OutputStream?,
events: ArrayList<Event>,
events: List<Event>,
showExportingToast: Boolean,
callback: (result: ExportResult) -> Unit
) {

View file

@ -977,6 +977,36 @@
android:layout_height="wrap_content"
android:text="@string/migrating" />
<RelativeLayout
android:id="@+id/events_export_holder"
style="@style/SettingsHolderTextViewOneLinerStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/events_export"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/export_events_to_ics" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/events_import_holder"
style="@style/SettingsHolderTextViewOneLinerStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/events_import"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/import_events_from_ics" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_export_holder"
style="@style/SettingsHolderTextViewOneLinerStyle"

View file

@ -48,16 +48,6 @@
android:showAsAction="never"
android:title="@string/add_anniversaries"
app:showAsAction="never" />
<item
android:id="@+id/import_events"
android:showAsAction="never"
android:title="@string/import_events_from_ics"
app:showAsAction="never" />
<item
android:id="@+id/export_events"
android:showAsAction="never"
android:title="@string/export_events_to_ics"
app:showAsAction="never" />
<item
android:id="@+id/settings"
android:icon="@drawable/ic_settings_cog_vector"