Merge remote-tracking branch 'origin/backup_improve' into backup_improve
# Conflicts: # app/build.gradle # app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/EventActivity.kt # app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/MainActivity.kt # app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/SimpleActivity.kt # app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/TaskActivity.kt # app/src/main/kotlin/com/simplemobiletools/calendar/pro/dialogs/SetRemindersDialog.kt
This commit is contained in:
commit
1edba97270
|
@ -1,6 +1,12 @@
|
||||||
Changelog
|
Changelog
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
Version 6.22.2 *(2023-07-16)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Fixed a couple weekly view related glitches
|
||||||
|
* Added some translation, stability and UX improvements
|
||||||
|
|
||||||
Version 6.22.1 *(2023-07-02)*
|
Version 6.22.1 *(2023-07-02)*
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,8 @@ android {
|
||||||
applicationId "com.simplemobiletools.calendar.pro"
|
applicationId "com.simplemobiletools.calendar.pro"
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
targetSdkVersion 33
|
targetSdkVersion 33
|
||||||
versionCode 237
|
versionCode 238
|
||||||
versionName "6.22.1"
|
versionName "6.22.2"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
setProperty("archivesBaseName", "calendar")
|
setProperty("archivesBaseName", "calendar")
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
@ -78,7 +78,7 @@ dependencies {
|
||||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||||
implementation "androidx.print:print:1.0.0"
|
implementation "androidx.print:print:1.0.0"
|
||||||
|
|
||||||
kapt 'androidx.room:room-compiler:2.5.1'
|
kapt 'androidx.room:room-compiler:2.5.2'
|
||||||
implementation 'androidx.room:room-runtime:2.5.1'
|
implementation 'androidx.room:room-runtime:2.5.2'
|
||||||
annotationProcessor 'androidx.room:room-compiler:2.5.1'
|
annotationProcessor 'androidx.room:room-compiler:2.5.2'
|
||||||
}
|
}
|
||||||
|
|
|
@ -1308,7 +1308,7 @@ class EventActivity : SimpleActivity() {
|
||||||
// recreate the event if it was moved in a different CalDAV calendar
|
// recreate the event if it was moved in a different CalDAV calendar
|
||||||
if (mEvent.id != null && oldSource != newSource && oldSource != SOURCE_IMPORTED_ICS) {
|
if (mEvent.id != null && oldSource != newSource && oldSource != SOURCE_IMPORTED_ICS) {
|
||||||
if (mRepeatInterval > 0 && wasRepeatable) {
|
if (mRepeatInterval > 0 && wasRepeatable) {
|
||||||
applyOriginalStartEndTimes()
|
eventsHelper.applyOriginalStartEndTimes(mEvent, mOriginalStartTS, mOriginalEndTS)
|
||||||
}
|
}
|
||||||
eventsHelper.deleteEvent(mEvent.id!!, true)
|
eventsHelper.deleteEvent(mEvent.id!!, true)
|
||||||
mEvent.id = null
|
mEvent.id = null
|
||||||
|
@ -1321,15 +1321,7 @@ class EventActivity : SimpleActivity() {
|
||||||
storeEvent(wasRepeatable)
|
storeEvent(wasRepeatable)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PermissionRequiredDialog(
|
PermissionRequiredDialog(this, R.string.allow_notifications_reminders, { openNotificationSettings() })
|
||||||
this,
|
|
||||||
R.string.allow_notifications_reminders,
|
|
||||||
positiveActionCallback = {
|
|
||||||
handleNotificationPermission {
|
|
||||||
openNotificationSettings()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1367,70 +1359,31 @@ class EventActivity : SimpleActivity() {
|
||||||
private fun showEditRepeatingEventDialog() {
|
private fun showEditRepeatingEventDialog() {
|
||||||
EditRepeatingEventDialog(this) {
|
EditRepeatingEventDialog(this) {
|
||||||
hideKeyboard()
|
hideKeyboard()
|
||||||
|
if (it == null) {
|
||||||
|
return@EditRepeatingEventDialog
|
||||||
|
}
|
||||||
when (it) {
|
when (it) {
|
||||||
EDIT_SELECTED_OCCURRENCE -> {
|
EDIT_SELECTED_OCCURRENCE -> {
|
||||||
ensureBackgroundThread {
|
eventsHelper.editSelectedOccurrence(mEvent, true) {
|
||||||
mEvent.apply {
|
finish()
|
||||||
parentId = id!!.toLong()
|
|
||||||
id = null
|
|
||||||
repeatRule = 0
|
|
||||||
repeatInterval = 0
|
|
||||||
repeatLimit = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
eventsHelper.insertEvent(mEvent, addToCalDAV = true, showToasts = true) {
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EDIT_FUTURE_OCCURRENCES -> {
|
EDIT_FUTURE_OCCURRENCES -> {
|
||||||
ensureBackgroundThread {
|
eventsHelper.editFutureOccurrences(mEvent, mEventOccurrenceTS, true) {
|
||||||
val eventId = mEvent.id!!
|
finish()
|
||||||
val originalEvent = eventsDB.getEventWithId(eventId) ?: return@ensureBackgroundThread
|
|
||||||
mEvent.maybeAdjustRepeatLimitCount(originalEvent, mEventOccurrenceTS)
|
|
||||||
mEvent.id = null
|
|
||||||
eventsHelper.apply {
|
|
||||||
addEventRepeatLimit(eventId, mEventOccurrenceTS)
|
|
||||||
if (mEventOccurrenceTS == originalEvent.startTS) {
|
|
||||||
deleteEvent(eventId, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
insertEvent(mEvent, addToCalDAV = true, showToasts = true) {
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EDIT_ALL_OCCURRENCES -> {
|
EDIT_ALL_OCCURRENCES -> {
|
||||||
ensureBackgroundThread {
|
eventsHelper.editAllOccurrences(mEvent, mOriginalStartTS, mOriginalEndTS, true) {
|
||||||
applyOriginalStartEndTimes()
|
finish()
|
||||||
eventsHelper.updateEvent(mEvent, updateAtCalDAV = true, showToasts = true) {
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun applyOriginalStartEndTimes() {
|
|
||||||
// Shift the start and end times of the first (original) event based on the changes made
|
|
||||||
val originalEvent = eventsDB.getEventWithId(mEvent.id!!) ?: return
|
|
||||||
val originalStartTS = originalEvent.startTS
|
|
||||||
val originalEndTS = originalEvent.endTS
|
|
||||||
val oldStartTS = mOriginalStartTS
|
|
||||||
val oldEndTS = mOriginalEndTS
|
|
||||||
|
|
||||||
mEvent.apply {
|
|
||||||
val startTSDelta = oldStartTS - startTS
|
|
||||||
val endTSDelta = oldEndTS - endTS
|
|
||||||
startTS = originalStartTS - startTSDelta
|
|
||||||
endTS = originalEndTS - endTSDelta
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateStartTexts() {
|
private fun updateStartTexts() {
|
||||||
updateStartDateText()
|
updateStartDateText()
|
||||||
updateStartTimeText()
|
updateStartTimeText()
|
||||||
|
|
|
@ -618,6 +618,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
||||||
updateViewPager()
|
updateViewPager()
|
||||||
setupQuickFilter()
|
setupQuickFilter()
|
||||||
}
|
}
|
||||||
|
|
||||||
it == -1 -> toast(R.string.no_new_birthdays)
|
it == -1 -> toast(R.string.no_new_birthdays)
|
||||||
else -> toast(R.string.no_birthdays)
|
else -> toast(R.string.no_birthdays)
|
||||||
}
|
}
|
||||||
|
@ -648,6 +649,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
||||||
updateViewPager()
|
updateViewPager()
|
||||||
setupQuickFilter()
|
setupQuickFilter()
|
||||||
}
|
}
|
||||||
|
|
||||||
it == -1 -> toast(R.string.no_new_anniversaries)
|
it == -1 -> toast(R.string.no_new_anniversaries)
|
||||||
else -> toast(R.string.no_anniversaries)
|
else -> toast(R.string.no_anniversaries)
|
||||||
}
|
}
|
||||||
|
@ -1067,15 +1069,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PermissionRequiredDialog(
|
PermissionRequiredDialog(this, R.string.allow_notifications_reminders, { openNotificationSettings() })
|
||||||
this,
|
|
||||||
R.string.allow_notifications_reminders,
|
|
||||||
positiveActionCallback = {
|
|
||||||
handleNotificationPermission {
|
|
||||||
openNotificationSettings()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1112,6 +1106,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
||||||
showErrorToast(e)
|
showErrorToast(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> toast(R.string.invalid_file_format)
|
else -> toast(R.string.invalid_file_format)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,15 +85,7 @@ open class SimpleActivity : BaseSimpleActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PermissionRequiredDialog(
|
PermissionRequiredDialog(this, R.string.allow_notifications_reminders, { openNotificationSettings() })
|
||||||
this,
|
|
||||||
R.string.allow_notifications_reminders,
|
|
||||||
positiveActionCallback = {
|
|
||||||
handleNotificationPermission {
|
|
||||||
openNotificationSettings()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -433,15 +433,7 @@ class TaskActivity : SimpleActivity() {
|
||||||
storeTask(wasRepeatable)
|
storeTask(wasRepeatable)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PermissionRequiredDialog(
|
PermissionRequiredDialog(this, R.string.allow_notifications_reminders, { openNotificationSettings() })
|
||||||
this,
|
|
||||||
R.string.allow_notifications_reminders,
|
|
||||||
positiveActionCallback = {
|
|
||||||
handleNotificationPermission {
|
|
||||||
openNotificationSettings()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -479,55 +471,23 @@ class TaskActivity : SimpleActivity() {
|
||||||
private fun showEditRepeatingTaskDialog() {
|
private fun showEditRepeatingTaskDialog() {
|
||||||
EditRepeatingEventDialog(this, isTask = true) {
|
EditRepeatingEventDialog(this, isTask = true) {
|
||||||
hideKeyboard()
|
hideKeyboard()
|
||||||
|
if (it == null) {
|
||||||
|
return@EditRepeatingEventDialog
|
||||||
|
}
|
||||||
when (it) {
|
when (it) {
|
||||||
EDIT_SELECTED_OCCURRENCE -> {
|
EDIT_SELECTED_OCCURRENCE -> {
|
||||||
ensureBackgroundThread {
|
eventsHelper.editSelectedOccurrence(mTask, true) {
|
||||||
mTask.apply {
|
finish()
|
||||||
parentId = id!!.toLong()
|
|
||||||
id = null
|
|
||||||
repeatRule = 0
|
|
||||||
repeatInterval = 0
|
|
||||||
repeatLimit = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
eventsHelper.insertTask(mTask, showToasts = true) {
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EDIT_FUTURE_OCCURRENCES -> {
|
EDIT_FUTURE_OCCURRENCES -> {
|
||||||
ensureBackgroundThread {
|
eventsHelper.editFutureOccurrences(mTask, mTaskOccurrenceTS, true) {
|
||||||
val taskId = mTask.id!!
|
finish()
|
||||||
val originalTask = eventsDB.getTaskWithId(taskId) ?: return@ensureBackgroundThread
|
|
||||||
mTask.maybeAdjustRepeatLimitCount(originalTask, mTaskOccurrenceTS)
|
|
||||||
mTask.id = null
|
|
||||||
eventsHelper.apply {
|
|
||||||
addEventRepeatLimit(taskId, mTaskOccurrenceTS)
|
|
||||||
if (mTaskOccurrenceTS == originalTask.startTS) {
|
|
||||||
deleteEvent(taskId, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
insertTask(mTask, showToasts = true) {
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EDIT_ALL_OCCURRENCES -> {
|
EDIT_ALL_OCCURRENCES -> {
|
||||||
ensureBackgroundThread {
|
eventsHelper.editAllOccurrences(mTask, mOriginalStartTS, showToasts = true) {
|
||||||
// Shift the start and end times of the first (original) event based on the changes made
|
finish()
|
||||||
val originalEvent = eventsDB.getTaskWithId(mTask.id!!) ?: return@ensureBackgroundThread
|
|
||||||
val originalStartTS = originalEvent.startTS
|
|
||||||
val oldStartTS = mOriginalStartTS
|
|
||||||
|
|
||||||
mTask.apply {
|
|
||||||
val startTSDelta = oldStartTS - startTS
|
|
||||||
startTS = originalStartTS - startTSDelta
|
|
||||||
endTS = startTS
|
|
||||||
}
|
|
||||||
eventsHelper.updateEvent(mTask, updateAtCalDAV = false, showToasts = true) {
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import com.simplemobiletools.commons.extensions.hideKeyboard
|
||||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||||
import kotlinx.android.synthetic.main.dialog_edit_repeating_event.view.*
|
import kotlinx.android.synthetic.main.dialog_edit_repeating_event.view.*
|
||||||
|
|
||||||
class EditRepeatingEventDialog(val activity: SimpleActivity, val isTask: Boolean = false, val callback: (allOccurrences: Int) -> Unit) {
|
class EditRepeatingEventDialog(val activity: SimpleActivity, val isTask: Boolean = false, val callback: (allOccurrences: Int?) -> Unit) {
|
||||||
private var dialog: AlertDialog? = null
|
private var dialog: AlertDialog? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -33,12 +33,15 @@ class EditRepeatingEventDialog(val activity: SimpleActivity, val isTask: Boolean
|
||||||
activity.setupDialogStuff(view, this) { alertDialog ->
|
activity.setupDialogStuff(view, this) { alertDialog ->
|
||||||
dialog = alertDialog
|
dialog = alertDialog
|
||||||
alertDialog.hideKeyboard()
|
alertDialog.hideKeyboard()
|
||||||
|
alertDialog.setOnDismissListener { sendResult(null) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sendResult(allOccurrences: Int) {
|
private fun sendResult(allOccurrences: Int?) {
|
||||||
callback(allOccurrences)
|
callback(allOccurrences)
|
||||||
dialog?.dismiss()
|
if (allOccurrences != null) {
|
||||||
|
dialog?.dismiss()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,15 +36,7 @@ class SetRemindersDialog(val activity: SimpleActivity, val eventType: Int, val c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PermissionRequiredDialog(
|
PermissionRequiredDialog(activity, R.string.allow_notifications_reminders, { activity.openNotificationSettings() })
|
||||||
activity,
|
|
||||||
R.string.allow_notifications_reminders,
|
|
||||||
positiveActionCallback = {
|
|
||||||
activity.handleNotificationPermission {
|
|
||||||
activity.openNotificationSettings()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import android.provider.CalendarContract
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.core.app.AlarmManagerCompat
|
import androidx.core.app.AlarmManagerCompat
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
|
@ -48,7 +47,6 @@ import com.simplemobiletools.commons.helpers.*
|
||||||
import kotlinx.android.synthetic.main.day_monthly_event_view.view.*
|
import kotlinx.android.synthetic.main.day_monthly_event_view.view.*
|
||||||
import org.joda.time.DateTime
|
import org.joda.time.DateTime
|
||||||
import org.joda.time.DateTimeConstants
|
import org.joda.time.DateTimeConstants
|
||||||
import org.joda.time.DateTimeZone
|
|
||||||
import org.joda.time.LocalDate
|
import org.joda.time.LocalDate
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
|
@ -327,7 +325,8 @@ fun Context.notifyEvent(originalEvent: Event) {
|
||||||
val events = eventsHelper.getRepeatableEventsFor(currentSeconds - WEEK_SECONDS, currentSeconds + YEAR_SECONDS, event.id!!)
|
val events = eventsHelper.getRepeatableEventsFor(currentSeconds - WEEK_SECONDS, currentSeconds + YEAR_SECONDS, event.id!!)
|
||||||
for (currEvent in events) {
|
for (currEvent in events) {
|
||||||
eventStartTS = if (currEvent.getIsAllDay()) Formatter.getDayStartTS(Formatter.getDayCodeFromTS(currEvent.startTS)) else currEvent.startTS
|
eventStartTS = if (currEvent.getIsAllDay()) Formatter.getDayStartTS(Formatter.getDayCodeFromTS(currEvent.startTS)) else currEvent.startTS
|
||||||
val firstReminderMinutes = arrayOf(currEvent.reminder3Minutes, currEvent.reminder2Minutes, currEvent.reminder1Minutes).filter { it != REMINDER_OFF }.max()
|
val firstReminderMinutes =
|
||||||
|
arrayOf(currEvent.reminder3Minutes, currEvent.reminder2Minutes, currEvent.reminder1Minutes).filter { it != REMINDER_OFF }.max()
|
||||||
if (eventStartTS - firstReminderMinutes * 60 > currentSeconds) {
|
if (eventStartTS - firstReminderMinutes * 60 > currentSeconds) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -759,7 +758,11 @@ fun Context.editEvent(event: ListEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Context.getFirstDayOfWeek(date: DateTime): String {
|
fun Context.getFirstDayOfWeek(date: DateTime): String {
|
||||||
var startOfWeek = date.withZoneRetainFields(DateTimeZone.UTC).withTimeAtStartOfDay()
|
return getFirstDayOfWeekDt(date).toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Context.getFirstDayOfWeekDt(date: DateTime): DateTime {
|
||||||
|
var startOfWeek = date.withTimeAtStartOfDay()
|
||||||
if (!config.startWeekWithCurrentDay) {
|
if (!config.startWeekWithCurrentDay) {
|
||||||
startOfWeek = if (config.isSundayFirst) {
|
startOfWeek = if (config.isSundayFirst) {
|
||||||
// a workaround for Joda-time's Monday-as-first-day-of-the-week
|
// a workaround for Joda-time's Monday-as-first-day-of-the-week
|
||||||
|
@ -772,7 +775,7 @@ fun Context.getFirstDayOfWeek(date: DateTime): String {
|
||||||
startOfWeek.withDayOfWeek(DateTimeConstants.MONDAY)
|
startOfWeek.withDayOfWeek(DateTimeConstants.MONDAY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return startOfWeek.toString()
|
return startOfWeek
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Context.isTaskCompleted(event: Event): Boolean {
|
fun Context.isTaskCompleted(event: Event): Boolean {
|
||||||
|
|
|
@ -16,6 +16,9 @@ import androidx.collection.LongSparseArray
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.simplemobiletools.calendar.pro.R
|
import com.simplemobiletools.calendar.pro.R
|
||||||
|
import com.simplemobiletools.calendar.pro.activities.MainActivity
|
||||||
|
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
|
||||||
|
import com.simplemobiletools.calendar.pro.dialogs.EditRepeatingEventDialog
|
||||||
import com.simplemobiletools.calendar.pro.extensions.*
|
import com.simplemobiletools.calendar.pro.extensions.*
|
||||||
import com.simplemobiletools.calendar.pro.helpers.*
|
import com.simplemobiletools.calendar.pro.helpers.*
|
||||||
import com.simplemobiletools.calendar.pro.helpers.Formatter
|
import com.simplemobiletools.calendar.pro.helpers.Formatter
|
||||||
|
@ -188,6 +191,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
|
||||||
|
|
||||||
fun updateCalendar() {
|
fun updateCalendar() {
|
||||||
if (context != null) {
|
if (context != null) {
|
||||||
|
currentlyDraggedView = null
|
||||||
WeeklyCalendarImpl(this, requireContext()).updateWeeklyCalendar(weekTimestamp)
|
WeeklyCalendarImpl(this, requireContext()).updateWeeklyCalendar(weekTimestamp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,14 +200,14 @@ class WeekFragment : Fragment(), WeeklyCalendar {
|
||||||
mView.week_events_columns_holder.removeAllViews()
|
mView.week_events_columns_holder.removeAllViews()
|
||||||
(0 until config.weeklyViewDays).forEach {
|
(0 until config.weeklyViewDays).forEach {
|
||||||
val column = inflater.inflate(R.layout.weekly_view_day_column, mView.week_events_columns_holder, false) as RelativeLayout
|
val column = inflater.inflate(R.layout.weekly_view_day_column, mView.week_events_columns_holder, false) as RelativeLayout
|
||||||
column.tag = Formatter.getUTCDayCodeFromTS(weekTimestamp + it * DAY_SECONDS)
|
column.tag = Formatter.getDayCodeFromTS(weekTimestamp + it * DAY_SECONDS)
|
||||||
mView.week_events_columns_holder.addView(column)
|
mView.week_events_columns_holder.addView(column)
|
||||||
dayColumns.add(column)
|
dayColumns.add(column)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupDayLabels() {
|
private fun setupDayLabels() {
|
||||||
var curDay = Formatter.getUTCDateTimeFromTS(weekTimestamp)
|
var curDay = Formatter.getDateTimeFromTS(weekTimestamp)
|
||||||
val todayCode = Formatter.getDayCodeFromDateTime(DateTime())
|
val todayCode = Formatter.getDayCodeFromDateTime(DateTime())
|
||||||
val screenWidth = context?.usableScreenSize?.x ?: return
|
val screenWidth = context?.usableScreenSize?.x ?: return
|
||||||
val dayWidth = screenWidth / config.weeklyViewDays
|
val dayWidth = screenWidth / config.weeklyViewDays
|
||||||
|
@ -269,12 +273,12 @@ class WeekFragment : Fragment(), WeeklyCalendar {
|
||||||
DragEvent.ACTION_DRAG_ENDED -> true
|
DragEvent.ACTION_DRAG_ENDED -> true
|
||||||
DragEvent.ACTION_DROP -> {
|
DragEvent.ACTION_DROP -> {
|
||||||
try {
|
try {
|
||||||
val eventId = dragEvent.clipData.getItemAt(0).text.toString().toLong()
|
val (eventId, originalStartTS, originalEndTS) = dragEvent.clipData.getItemAt(0).text.toString().split(";").map { it.toLong() }
|
||||||
val startHour = (dragEvent.y / rowHeight).toInt()
|
val startHour = (dragEvent.y / rowHeight).toInt()
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
val event = context?.eventsDB?.getEventOrTaskWithId(eventId)
|
val event = context?.eventsDB?.getEventOrTaskWithId(eventId)
|
||||||
event?.let {
|
event?.let { event ->
|
||||||
val currentStartTime = Formatter.getDateTimeFromTS(it.startTS)
|
val currentStartTime = Formatter.getDateTimeFromTS(event.startTS)
|
||||||
val startTime = Formatter.getDateTimeFromTS(weekTimestamp + index * DAY_SECONDS)
|
val startTime = Formatter.getDateTimeFromTS(weekTimestamp + index * DAY_SECONDS)
|
||||||
.withTime(
|
.withTime(
|
||||||
startHour,
|
startHour,
|
||||||
|
@ -284,14 +288,47 @@ class WeekFragment : Fragment(), WeeklyCalendar {
|
||||||
).seconds()
|
).seconds()
|
||||||
val currentEventDuration = event.endTS - event.startTS
|
val currentEventDuration = event.endTS - event.startTS
|
||||||
val endTime = startTime + currentEventDuration
|
val endTime = startTime + currentEventDuration
|
||||||
context?.eventsHelper?.updateEvent(
|
val newEvent = event.copy(
|
||||||
it.copy(
|
startTS = startTime,
|
||||||
startTS = startTime,
|
endTS = endTime,
|
||||||
endTS = endTime,
|
flags = event.flags.removeBit(FLAG_ALL_DAY)
|
||||||
flags = it.flags.removeBit(FLAG_ALL_DAY)
|
)
|
||||||
), updateAtCalDAV = true, showToasts = false
|
if (event.repeatInterval > 0) {
|
||||||
) {
|
val activity = this.activity as SimpleActivity
|
||||||
updateCalendar()
|
activity.runOnUiThread {
|
||||||
|
EditRepeatingEventDialog(activity) {
|
||||||
|
activity.hideKeyboard()
|
||||||
|
when (it) {
|
||||||
|
null -> {
|
||||||
|
revertDraggedEvent()
|
||||||
|
}
|
||||||
|
EDIT_SELECTED_OCCURRENCE -> {
|
||||||
|
context?.eventsHelper?.editSelectedOccurrence(newEvent, false) {
|
||||||
|
updateCalendar()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EDIT_FUTURE_OCCURRENCES -> {
|
||||||
|
context?.eventsHelper?.editFutureOccurrences(newEvent, originalStartTS, false) {
|
||||||
|
// we need to refresh all fragments because they can contain future occurrences
|
||||||
|
(activity as MainActivity).refreshItems()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EDIT_ALL_OCCURRENCES -> {
|
||||||
|
context?.eventsHelper?.editAllOccurrences(newEvent, originalStartTS, originalEndTS, false) {
|
||||||
|
(activity as MainActivity).refreshItems()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (event.startTS == newEvent.startTS && event.endTS == newEvent.endTS) {
|
||||||
|
revertDraggedEvent()
|
||||||
|
} else {
|
||||||
|
context?.eventsHelper?.updateEvent(newEvent, updateAtCalDAV = true, showToasts = false) {
|
||||||
|
updateCalendar()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,6 +343,13 @@ class WeekFragment : Fragment(), WeeklyCalendar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun revertDraggedEvent() {
|
||||||
|
activity?.runOnUiThread {
|
||||||
|
currentlyDraggedView?.beVisible()
|
||||||
|
currentlyDraggedView = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun getViewGestureDetector(view: ViewGroup, index: Int): GestureDetector {
|
private fun getViewGestureDetector(view: ViewGroup, index: Int): GestureDetector {
|
||||||
return GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
|
return GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
|
||||||
override fun onSingleTapUp(event: MotionEvent): Boolean {
|
override fun onSingleTapUp(event: MotionEvent): Boolean {
|
||||||
|
@ -552,7 +596,13 @@ class WeekFragment : Fragment(), WeeklyCalendar {
|
||||||
do {
|
do {
|
||||||
val dayOfWeek = dayColumns.indexOfFirst { it.tag == currentDayCode }
|
val dayOfWeek = dayColumns.indexOfFirst { it.tag == currentDayCode }
|
||||||
if (dayOfWeek == -1 || dayOfWeek >= config.weeklyViewDays) {
|
if (dayOfWeek == -1 || dayOfWeek >= config.weeklyViewDays) {
|
||||||
continue@dayevents
|
if (startDayCode != endDayCode) {
|
||||||
|
currentDateTime = currentDateTime.plusDays(1)
|
||||||
|
currentDayCode = Formatter.getDayCodeFromDateTime(currentDateTime)
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
continue@dayevents
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val dayColumn = dayColumns[dayOfWeek]
|
val dayColumn = dayColumns[dayOfWeek]
|
||||||
|
@ -628,7 +678,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
|
||||||
setOnLongClickListener { view ->
|
setOnLongClickListener { view ->
|
||||||
currentlyDraggedView = view
|
currentlyDraggedView = view
|
||||||
val shadowBuilder = View.DragShadowBuilder(view)
|
val shadowBuilder = View.DragShadowBuilder(view)
|
||||||
val clipData = ClipData.newPlainText(WEEKLY_EVENT_ID_LABEL, event.id.toString())
|
val clipData = ClipData.newPlainText(WEEKLY_EVENT_ID_LABEL, "${event.id};${event.startTS};${event.endTS}")
|
||||||
if (isNougatPlus()) {
|
if (isNougatPlus()) {
|
||||||
view.startDragAndDrop(clipData, shadowBuilder, null, 0)
|
view.startDragAndDrop(clipData, shadowBuilder, null, 0)
|
||||||
} else {
|
} else {
|
||||||
|
@ -892,7 +942,6 @@ class WeekFragment : Fragment(), WeeklyCalendar {
|
||||||
if (!dragEvent.result) {
|
if (!dragEvent.result) {
|
||||||
view.beVisible()
|
view.beVisible()
|
||||||
}
|
}
|
||||||
currentlyDraggedView = null
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
else -> false
|
else -> false
|
||||||
|
|
|
@ -189,22 +189,11 @@ class WeekFragmentsHolder : MyFragmentHolder(), WeekFragmentListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun dateSelected(dateTime: DateTime, datePicker: DatePicker) {
|
private fun dateSelected(dateTime: DateTime, datePicker: DatePicker) {
|
||||||
val isSundayFirst = requireContext().config.isSundayFirst
|
|
||||||
val month = datePicker.month + 1
|
val month = datePicker.month + 1
|
||||||
val year = datePicker.year
|
val year = datePicker.year
|
||||||
val day = datePicker.dayOfMonth
|
val day = datePicker.dayOfMonth
|
||||||
var newDateTime = dateTime.withDate(year, month, day)
|
val newDateTime = dateTime.withDate(year, month, day)
|
||||||
|
currentWeekTS = requireContext().getFirstDayOfWeekDt(newDateTime).seconds()
|
||||||
if (isSundayFirst) {
|
|
||||||
newDateTime = newDateTime.plusDays(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
var selectedWeek = newDateTime.withDayOfWeek(1).withTimeAtStartOfDay().minusDays(if (isSundayFirst) 1 else 0)
|
|
||||||
if (newDateTime.minusDays(7).seconds() > selectedWeek.seconds()) {
|
|
||||||
selectedWeek = selectedWeek.plusDays(7)
|
|
||||||
}
|
|
||||||
|
|
||||||
currentWeekTS = selectedWeek.seconds()
|
|
||||||
setupFragment()
|
setupFragment()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,7 +300,7 @@ class WeekFragmentsHolder : MyFragmentHolder(), WeekFragmentListener {
|
||||||
|
|
||||||
override fun getCurrentDate(): DateTime? {
|
override fun getCurrentDate(): DateTime? {
|
||||||
return if (currentWeekTS != 0L) {
|
return if (currentWeekTS != 0L) {
|
||||||
Formatter.getUTCDateTimeFromTS(currentWeekTS)
|
Formatter.getDateTimeFromTS(currentWeekTS)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,6 +180,66 @@ class EventsHelper(val context: Context) {
|
||||||
callback?.invoke()
|
callback?.invoke()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun applyOriginalStartEndTimes(event: Event, oldStartTS: Long, oldEndTS: Long) {
|
||||||
|
val originalEvent = eventsDB.getEventOrTaskWithId(event.id!!) ?: return
|
||||||
|
val originalStartTS = originalEvent.startTS
|
||||||
|
val originalEndTS = originalEvent.endTS
|
||||||
|
|
||||||
|
event.apply {
|
||||||
|
val startTSDelta = oldStartTS - startTS
|
||||||
|
val endTSDelta = oldEndTS - endTS
|
||||||
|
startTS = originalStartTS - startTSDelta
|
||||||
|
endTS = if (isTask()) startTS else originalEndTS - endTSDelta
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun editSelectedOccurrence(event: Event, showToasts: Boolean, callback: () -> Unit) {
|
||||||
|
ensureBackgroundThread {
|
||||||
|
event.apply {
|
||||||
|
parentId = id!!.toLong()
|
||||||
|
id = null
|
||||||
|
repeatRule = 0
|
||||||
|
repeatInterval = 0
|
||||||
|
repeatLimit = 0
|
||||||
|
}
|
||||||
|
if (event.isTask()) {
|
||||||
|
insertTask(event, showToasts = showToasts, callback = callback)
|
||||||
|
} else {
|
||||||
|
insertEvent(event, addToCalDAV = true, showToasts = showToasts) {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun editFutureOccurrences(event: Event, eventOccurrenceTS: Long, showToasts: Boolean, callback: () -> Unit) {
|
||||||
|
ensureBackgroundThread {
|
||||||
|
val eventId = event.id!!
|
||||||
|
val originalEvent = eventsDB.getEventOrTaskWithId(event.id!!) ?: return@ensureBackgroundThread
|
||||||
|
event.maybeAdjustRepeatLimitCount(originalEvent, eventOccurrenceTS)
|
||||||
|
event.id = null
|
||||||
|
addEventRepeatLimit(eventId, eventOccurrenceTS)
|
||||||
|
if (eventOccurrenceTS == originalEvent.startTS) {
|
||||||
|
deleteEvent(eventId, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.isTask()) {
|
||||||
|
insertTask(event, showToasts = showToasts, callback = callback)
|
||||||
|
} else {
|
||||||
|
insertEvent(event, addToCalDAV = true, showToasts = showToasts) {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun editAllOccurrences(event: Event, originalStartTS: Long, originalEndTS: Long = 0, showToasts: Boolean, callback: () -> Unit) {
|
||||||
|
ensureBackgroundThread {
|
||||||
|
applyOriginalStartEndTimes(event, originalStartTS, originalEndTS)
|
||||||
|
updateEvent(event, updateAtCalDAV = !event.isTask(), showToasts = showToasts, callback = callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun ensureEventTypeVisibility(event: Event, enableEventType: Boolean) {
|
private fun ensureEventTypeVisibility(event: Event, enableEventType: Boolean) {
|
||||||
if (enableEventType) {
|
if (enableEventType) {
|
||||||
val eventType = event.eventType.toString()
|
val eventType = event.eventType.toString()
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/month_day_calendar_holder"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:paddingTop="@dimen/medium_margin">
|
||||||
|
|
||||||
|
<com.simplemobiletools.calendar.pro.views.MonthViewWrapper
|
||||||
|
android:id="@+id/month_day_view_wrapper"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/month_day_list_holder"
|
||||||
|
app:layout_constraintWidth_percent="0.45"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"/>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/month_day_list_holder"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintWidth_percent="0.55"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/month_day_view_wrapper">
|
||||||
|
|
||||||
|
<com.simplemobiletools.commons.views.MyTextView
|
||||||
|
android:id="@+id/month_day_selected_day_label"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:paddingTop="@dimen/normal_margin"
|
||||||
|
android:paddingBottom="@dimen/small_margin"
|
||||||
|
android:textSize="22sp"
|
||||||
|
tools:text="November 19" />
|
||||||
|
|
||||||
|
<com.simplemobiletools.commons.views.MyTextView
|
||||||
|
android:id="@+id/month_day_no_events_placeholder"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/month_day_selected_day_label"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:alpha="0.8"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingStart="@dimen/activity_margin"
|
||||||
|
android:paddingEnd="@dimen/activity_margin"
|
||||||
|
android:text="@string/no_items_found"
|
||||||
|
android:textSize="@dimen/bigger_text_size"
|
||||||
|
android:textStyle="italic"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<com.simplemobiletools.commons.views.MyRecyclerView
|
||||||
|
android:id="@+id/month_day_events_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_below="@+id/month_day_selected_day_label"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:layoutAnimation="@anim/layout_animation"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
app:layoutManager="com.simplemobiletools.commons.views.MyLinearLayoutManager" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -9,7 +9,7 @@
|
||||||
<string name="monthly_daily_view">Месечен и дневен изглед</string>
|
<string name="monthly_daily_view">Месечен и дневен изглед</string>
|
||||||
<string name="yearly_view">Годишен изглед</string>
|
<string name="yearly_view">Годишен изглед</string>
|
||||||
<string name="simple_event_list">Списък със събития</string>
|
<string name="simple_event_list">Списък със събития</string>
|
||||||
<string name="no_upcoming_events">No upcoming events.</string>
|
<string name="no_upcoming_events">Няма предстоящи събития.</string>
|
||||||
<string name="go_to_today">Отидете на днес</string>
|
<string name="go_to_today">Отидете на днес</string>
|
||||||
<string name="go_to_date">Отиди на дата</string>
|
<string name="go_to_date">Отиди на дата</string>
|
||||||
<!-- Widget titles -->
|
<!-- Widget titles -->
|
||||||
|
@ -29,9 +29,9 @@
|
||||||
<string name="filter_events_by_type">Филтриране на събитията по тип</string>
|
<string name="filter_events_by_type">Филтриране на събитията по тип</string>
|
||||||
<string name="please_fill_location">Моля попълнете местоположение за показване на картата</string>
|
<string name="please_fill_location">Моля попълнете местоположение за показване на картата</string>
|
||||||
<string name="public_event_notification_text">Предстоящо събитие</string>
|
<string name="public_event_notification_text">Предстоящо събитие</string>
|
||||||
<string name="everything_filtered_out">You have filtered out all event types</string>
|
<string name="everything_filtered_out">Вие филтрирахте всички типове събития</string>
|
||||||
<string name="event_color">Event color</string>
|
<string name="event_color">Цвят на събитието</string>
|
||||||
<string name="default_calendar_color">Default calendar color</string>
|
<string name="default_calendar_color">Цвят на календара по подразбиране</string>
|
||||||
<!-- Tasks -->
|
<!-- Tasks -->
|
||||||
<string name="task">Задача</string>
|
<string name="task">Задача</string>
|
||||||
<string name="tasks">Задачи</string>
|
<string name="tasks">Задачи</string>
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
<string name="duplicate_task">Дублиране на задача</string>
|
<string name="duplicate_task">Дублиране на задача</string>
|
||||||
<string name="mark_completed">Означете като завършено</string>
|
<string name="mark_completed">Означете като завършено</string>
|
||||||
<string name="mark_incomplete">Означете като незавършено</string>
|
<string name="mark_incomplete">Означете като незавършено</string>
|
||||||
<string name="task_color">Task color</string>
|
<string name="task_color">Цвят на задачата</string>
|
||||||
<!-- Event Repetition -->
|
<!-- Event Repetition -->
|
||||||
<string name="repetition">Повторение</string>
|
<string name="repetition">Повторение</string>
|
||||||
<string name="no_repetition">Без повторение</string>
|
<string name="no_repetition">Без повторение</string>
|
||||||
|
@ -54,8 +54,8 @@
|
||||||
<string name="years_raw">години</string>
|
<string name="years_raw">години</string>
|
||||||
<string name="repeat_till">Повтаряй до</string>
|
<string name="repeat_till">Повтаряй до</string>
|
||||||
<string name="forever">Завинаги</string>
|
<string name="forever">Завинаги</string>
|
||||||
<string name="event_is_repeatable">Събитието се повтаря</string>
|
<string name="event_is_repeatable">Събитието e повтаряемо</string>
|
||||||
<string name="task_is_repeatable">The task is repeatable</string>
|
<string name="task_is_repeatable">Задачата e повтаряема</string>
|
||||||
<string name="selection_contains_repetition">Изборът съдържа само повтарящи се събития</string>
|
<string name="selection_contains_repetition">Изборът съдържа само повтарящи се събития</string>
|
||||||
<string name="delete_one_only">Изтрийте само избраното събитие</string>
|
<string name="delete_one_only">Изтрийте само избраното събитие</string>
|
||||||
<string name="delete_future_occurrences">Изтрийте това събитие и всички бъдещи събития</string>
|
<string name="delete_future_occurrences">Изтрийте това събитие и всички бъдещи събития</string>
|
||||||
|
@ -130,8 +130,8 @@
|
||||||
<string name="export_events_to_ics">Експортиране на събития в .ics файл</string>
|
<string name="export_events_to_ics">Експортиране на събития в .ics файл</string>
|
||||||
<string name="default_event_type">Тип събитие по подразбиране</string>
|
<string name="default_event_type">Тип събитие по подразбиране</string>
|
||||||
<string name="export_past_events_too">Експортиране и на минали събития</string>
|
<string name="export_past_events_too">Експортиране и на минали събития</string>
|
||||||
<string name="export_tasks">Export tasks</string>
|
<string name="export_tasks">Експортиране на задачи</string>
|
||||||
<string name="export_past_entries">Export past entries too</string>
|
<string name="export_past_entries">Експортиране и на минали записи</string>
|
||||||
<string name="include_event_types">Включване на типа събития</string>
|
<string name="include_event_types">Включване на типа събития</string>
|
||||||
<string name="filename_without_ics">Име на файла (без .ics)</string>
|
<string name="filename_without_ics">Име на файла (без .ics)</string>
|
||||||
<string name="ignore_event_types">Игнорирайте типовете събития във файла, винаги използвайте този по подразбиране</string>
|
<string name="ignore_event_types">Игнорирайте типовете събития във файла, винаги използвайте този по подразбиране</string>
|
||||||
|
@ -180,8 +180,8 @@
|
||||||
<string name="replace_description_with_location">Смяна на описанието на събитието с местоположение</string>
|
<string name="replace_description_with_location">Смяна на описанието на събитието с местоположение</string>
|
||||||
<string name="display_description_or_location">Показване на описание или местоположение</string>
|
<string name="display_description_or_location">Показване на описание или местоположение</string>
|
||||||
<string name="delete_all_events">Изтриване на всички събития</string>
|
<string name="delete_all_events">Изтриване на всички събития</string>
|
||||||
<string name="delete_all_events_and_tasks">Delete all events and tasks</string>
|
<string name="delete_all_events_and_tasks">Изтриване на всички събития и задачи</string>
|
||||||
<string name="delete_all_events_confirmation">Сигурни ли сте, че искате да изтриете всички събития\? Това ще остави типовете събития и другите ви настройки непокътнати.</string>
|
<string name="delete_all_events_confirmation">Сигурни ли сте, че искате да изтриете всички събития и задачи\? Това ще остави типовете събития и другите ви настройки непокътнати.</string>
|
||||||
<string name="show_a_grid">Показване на решетка</string>
|
<string name="show_a_grid">Показване на решетка</string>
|
||||||
<string name="loop_reminders">Циклично напомняне до отхвърляне</string>
|
<string name="loop_reminders">Циклично напомняне до отхвърляне</string>
|
||||||
<string name="dim_past_events">Затъмняване на минали събития</string>
|
<string name="dim_past_events">Затъмняване на минали събития</string>
|
||||||
|
@ -227,7 +227,7 @@
|
||||||
<string name="no_synchronized_calendars">Не са намерени календари, които да могат да се синхронизират</string>
|
<string name="no_synchronized_calendars">Не са намерени календари, които да могат да се синхронизират</string>
|
||||||
<string name="status_free">Свободно</string>
|
<string name="status_free">Свободно</string>
|
||||||
<string name="status_busy">Заето</string>
|
<string name="status_busy">Заето</string>
|
||||||
<string name="fetching_event_failed">Fetching event %s failed</string>
|
<string name="fetching_event_failed">Изтегляне на събитие %s е неуспешно</string>
|
||||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||||
<!-- used in repetition, like "Every last Sunday" -->
|
<!-- used in repetition, like "Every last Sunday" -->
|
||||||
<string name="monday_alt">Понеделник</string>
|
<string name="monday_alt">Понеделник</string>
|
||||||
|
@ -267,7 +267,7 @@
|
||||||
<string name="faq_1_title">Как мога да премахна празниците, импортирани чрез бутона \"Добавяне на празници\"\?</string>
|
<string name="faq_1_title">Как мога да премахна празниците, импортирани чрез бутона \"Добавяне на празници\"\?</string>
|
||||||
<string name="faq_1_text">Създадените по този начин празници се вмъкват в нов тип събитие, наречен \"Празници\". Можете да отидете в Настройки -> Управление на типове събития, да натиснете продължително дадения тип събитие и да го изтриете, като изберете кошчето за боклук.</string>
|
<string name="faq_1_text">Създадените по този начин празници се вмъкват в нов тип събитие, наречен \"Празници\". Можете да отидете в Настройки -> Управление на типове събития, да натиснете продължително дадения тип събитие и да го изтриете, като изберете кошчето за боклук.</string>
|
||||||
<string name="faq_2_title">Мога ли да си синхронизирам своите събития с Google Calendar или друга услуга, поддържаща CalDAV\?</string>
|
<string name="faq_2_title">Мога ли да си синхронизирам своите събития с Google Calendar или друга услуга, поддържаща CalDAV\?</string>
|
||||||
<string name="faq_2_title_extra">Maybe even share calendars with other people?</string>
|
<string name="faq_2_title_extra">Може дори да споделяте календари с други хора\?</string>
|
||||||
<string name="faq_2_text">Да, просто превключете \"Синхронизация с CalDAV\" в настройките на приложението и изберете календарите, които искате да синхронизирате. Ще ви е необходимо обаче приложение на трета страна, което да обработва синхронизацията между устройството и сървърите. В случай че искате да синхронизирате календар на Google, тяхното официално приложение \"Календар\" ще свърши тази работа. За други календари ще ви е необходим адаптер за синхронизиране от трета страна, например DAVx5.</string>
|
<string name="faq_2_text">Да, просто превключете \"Синхронизация с CalDAV\" в настройките на приложението и изберете календарите, които искате да синхронизирате. Ще ви е необходимо обаче приложение на трета страна, което да обработва синхронизацията между устройството и сървърите. В случай че искате да синхронизирате календар на Google, тяхното официално приложение \"Календар\" ще свърши тази работа. За други календари ще ви е необходим адаптер за синхронизиране от трета страна, например DAVx5.</string>
|
||||||
<string name="faq_3_title">Виждам напомняния но не чувам звук. Какво мога да направя\?</string>
|
<string name="faq_3_title">Виждам напомняния но не чувам звук. Какво мога да направя\?</string>
|
||||||
<string name="faq_3_text">Системата оказва огромно влияние не само върху показването на действителното напомняне, но и върху възпроизвеждането на звука. Ако не можете да чуете никакъв звук, опитайте да влезете в настройките на приложението, да натиснете опцията \"Аудио поток, използван от напомнянията\" и да я промените на друга стойност. Ако все още не работи, проверете настройките на звука, дали конкретният поток не е заглушен.</string>
|
<string name="faq_3_text">Системата оказва огромно влияние не само върху показването на действителното напомняне, но и върху възпроизвеждането на звука. Ако не можете да чуете никакъв звук, опитайте да влезете в настройките на приложението, да натиснете опцията \"Аудио поток, използван от напомнянията\" и да я промените на друга стойност. Ако все още не работи, проверете настройките на звука, дали конкретният поток не е заглушен.</string>
|
||||||
|
@ -281,4 +281,4 @@
|
||||||
Haven't found some strings? There's more at
|
Haven't found some strings? There's more at
|
||||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||||
-->
|
-->
|
||||||
</resources>
|
</resources>
|
|
@ -41,7 +41,7 @@
|
||||||
<string name="duplicate_task">Дублювати завдання</string>
|
<string name="duplicate_task">Дублювати завдання</string>
|
||||||
<string name="mark_completed">Позначити завершеним</string>
|
<string name="mark_completed">Позначити завершеним</string>
|
||||||
<string name="mark_incomplete">Позначити незавершеним</string>
|
<string name="mark_incomplete">Позначити незавершеним</string>
|
||||||
<string name="task_color">Task color</string>
|
<string name="task_color">Колір завдання</string>
|
||||||
<!-- Event Repetition -->
|
<!-- Event Repetition -->
|
||||||
<string name="repetition">Повторювати</string>
|
<string name="repetition">Повторювати</string>
|
||||||
<string name="no_repetition">Без повторень</string>
|
<string name="no_repetition">Без повторень</string>
|
||||||
|
@ -287,4 +287,4 @@
|
||||||
Haven't found some strings? There's more at
|
Haven't found some strings? There's more at
|
||||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||||
-->
|
-->
|
||||||
</resources>
|
</resources>
|
|
@ -0,0 +1,2 @@
|
||||||
|
* Fixed a couple weekly view related glitches
|
||||||
|
* Added some translation, stability and UX improvements
|
Loading…
Reference in New Issue