Compare commits

...

168 Commits

Author SHA1 Message Date
Tibor Kaputa 1e6b3ec67f
Merge pull request #2254 from Maple-pro/master
fix: error in strings.xml
2023-11-21 08:27:32 +01:00
yangfeng ca3589e76c fix: error in strings.xml 2023-11-06 17:01:33 +08:00
Tibor Kaputa e711d3663d
Merge pull request #2230 from weblate/weblate-simple-mobile-tools-simple-calendar
Translations update from Hosted Weblate
2023-10-18 21:08:33 +02:00
Tibor Kaputa 7971351654
Update strings.xml 2023-10-18 21:08:20 +02:00
Tibor Kaputa caaf328336
Update strings.xml 2023-10-17 10:16:13 +02:00
VfBFan 7407bac512
Translated using Weblate (German)
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/de/
2023-10-17 10:11:06 +02:00
Lionel HANNEQUIN a2d56f63e5
Translated using Weblate (French)
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/fr/
2023-10-11 17:00:57 +02:00
Puppelimies 449c471e1c
Translated using Weblate (Swedish)
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/sv/
2023-10-10 09:16:58 +02:00
NEXI 8071ad19e0
Translated using Weblate (Serbian)
Currently translated at 100.0% (21 of 21 strings)

Translation: Simple Mobile Tools/Simple Calendar metadata
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar-metadata/sr/
2023-10-08 04:18:15 +00:00
NEXI f5a7159140
Translated using Weblate (Serbian)
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/sr/
2023-10-08 04:18:13 +00:00
Tibor Kaputa 53be7f1335
Merge pull request #2226 from naveensingh/task_notification_improvements
Task notification improvements
2023-10-06 13:20:55 +02:00
Tibor Kaputa 6bd80cb9f4
Merge pull request #2223 from weblate/weblate-simple-mobile-tools-simple-calendar
Translations update from Hosted Weblate
2023-10-06 13:16:21 +02:00
Naveen 908e3853d3
Don't schedule reminder for completed tasks 2023-10-05 21:53:57 +05:30
Naveen a67c1c79db
Cancel expired notification when task is completed 2023-10-05 21:31:39 +05:30
spkprs ab1f3f66e6
Translated using Weblate (Greek)
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/el/
2023-10-05 09:15:32 +02:00
Tibor Kaputa 612ea73df5
updating the f-droid icon 2023-10-05 09:15:28 +02:00
tibbi ec81a35828 updating changelog 2023-10-03 08:45:27 +02:00
tibbi 9449e2e8ea update version to 6.23.1 2023-10-03 08:45:19 +02:00
tibbi 108e1e150d updating commons 2023-10-03 08:37:59 +02:00
Tibor Kaputa 32e63a29dd
Merge pull request #2219 from naveensingh/dst_fix_2211
Properly calculate weekly day codes from start week timestamp
2023-10-03 08:10:20 +02:00
Naveen d8d65ed415
Properly calculate weekly day codes from start week timestamp
Because start week timestamp is in local timezone, just adding 86400 is not correct in regions with daylight savings time. See https://github.com/SimpleMobileTools/Simple-Calendar/issues/2211
2023-10-02 17:33:08 +05:30
Tibor Kaputa 5d94efc271
Merge pull request #2217 from weblate/weblate-simple-mobile-tools-simple-calendar
Translations update from Hosted Weblate
2023-09-30 21:33:47 +02:00
Lionel HANNEQUIN b970ea6b05
Translated using Weblate (French)
Currently translated at 100.0% (20 of 20 strings)

Translation: Simple Mobile Tools/Simple Calendar metadata
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar-metadata/fr/
2023-09-30 19:26:22 +00:00
Tibor Kaputa 1843b33d16
Merge pull request #2216 from naveensingh/fix_r8_crash
Fix crash when deserializing attendee class
2023-09-30 21:26:15 +02:00
Naveen b655b8be52
Remove parcelable interface
Because proper proguard rules weren't added for Attendee and Gson, we can not make changes to the Attendee data class without affecting it's obfuscated Json member names. When serialized using Gson, the resulting json still uses the obfuscated member names
2023-09-30 00:01:34 +05:30
tibbi 950feba0bc fixing the french long app description 2023-09-29 09:39:02 +02:00
Tibor Kaputa 1a3aeffa64
Merge pull request #2215 from naveensingh/attendee_improvements
Attendee related improvements
2023-09-28 21:38:36 +02:00
Naveen 106552036e
Return empty list on empty value 2023-09-28 23:32:56 +05:30
Naveen 9f8d59f0d4
Strikethrough events when status is set to "Not going" 2023-09-28 20:58:20 +05:30
Naveen Singh ffa1129d70
Merge branch 'SimpleMobileTools:master' into attendee_improvements 2023-09-28 13:57:53 +05:30
Tibor Kaputa 976d7d1943
Merge pull request #2214 from naveensingh/fix_yearly_view
Use proper day of month to calculate start index in week
2023-09-28 08:56:42 +02:00
Tibor Kaputa 3426399a29
Merge pull request #2212 from weblate/weblate-simple-mobile-tools-simple-calendar
Translations update from Hosted Weblate
2023-09-28 08:56:31 +02:00
Naveen Singh 8db98217c5
Merge branch 'SimpleMobileTools:master' into attendee_improvements 2023-09-28 00:06:13 +05:30
Naveen 3876952f44
Use proper day of month to calculate start index in week
Broke during view-binding migration
2023-09-27 23:58:07 +05:30
Naveen 2929dd147c
Update Attendee.isMe when synchronising 2023-09-27 23:25:08 +05:30
Naveen c779aabfae
Only allow attendee status modification by owner
ACCOUNT_NAME is different from OWNER_ACCOUNT.
2023-09-27 23:22:42 +05:30
Naveen 0241e3beea
Replace manual `attendees` serialization with type converter 2023-09-27 23:19:21 +05:30
Lionel HANNEQUIN 44577f3755
Translated using Weblate (French)
Currently translated at 100.0% (20 of 20 strings)

Translation: Simple Mobile Tools/Simple Calendar metadata
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar-metadata/fr/
2023-09-27 18:07:34 +02:00
Lionel HANNEQUIN 9465020504
Translated using Weblate (French)
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/fr/
2023-09-27 18:07:34 +02:00
Naveen 52c403a7b1
Fix attendee list visibility
Broke during the recent view binding migration
2023-09-27 16:26:30 +05:30
Tibor Kaputa d2e59c2c66
Merge pull request #2209 from esensar/move-migrations-settings
Move migrations into app settings
2023-09-27 08:38:15 +02:00
Ensar Sarajčić 2b0dacae45 Save last used value for ignore event types checkbox when importing 2023-09-25 17:26:45 +02:00
Ensar Sarajčić 07eae3e3f2 Move migrations into app settings 2023-09-25 14:19:55 +02:00
Tibor Kaputa ee70da1d1a
Merge pull request #2205 from weblate/weblate-simple-mobile-tools-simple-calendar
Translations update from Hosted Weblate
2023-09-23 19:04:18 +02:00
Tibor Kaputa 79e39373c5
Update strings.xml 2023-09-23 19:04:08 +02:00
Puppelimies 94b77861c0
Translated using Weblate (Finnish)
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/fi/
2023-09-23 17:53:05 +02:00
gallegonovato bcfd3bea94
Translated using Weblate (Spanish)
Currently translated at 100.0% (20 of 20 strings)

Translation: Simple Mobile Tools/Simple Calendar metadata
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar-metadata/es/
2023-09-22 09:23:43 +02:00
Subham Jena 0c5601ba97
Translated using Weblate (Odia)
Currently translated at 9.7% (24 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/or/
2023-09-22 00:19:38 +02:00
Anonymous 8fe7b26abf
Translated using Weblate (Odia)
Currently translated at 100.0% (0 of 0 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/or/
2023-09-21 17:52:51 +02:00
Subham Jena adabf53c1b
Added translation using Weblate (Odia) 2023-09-21 17:52:31 +02:00
Lionel HANNEQUIN 69c31ee004
Translated using Weblate (French)
Currently translated at 100.0% (20 of 20 strings)

Translation: Simple Mobile Tools/Simple Calendar metadata
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar-metadata/fr/
2023-09-21 11:22:17 +02:00
tibbi 884b6347fc updating changelog 2023-09-19 12:55:45 +02:00
tibbi b103b7862b update version to 6.23.0 2023-09-19 12:55:39 +02:00
tibbi 5dad56a506 updating commons 2023-09-19 12:44:46 +02:00
Tibor Kaputa ed69a8e877
Merge pull request #2182 from Aga-C/fix-opening-search-results
Fixed opening search results (#2180)
2023-09-19 12:41:59 +02:00
Tibor Kaputa 63f920c097
Merge pull request #2201 from weblate/weblate-simple-mobile-tools-simple-calendar
Translations update from Hosted Weblate
2023-09-19 12:39:55 +02:00
Lionel HANNEQUIN cd8cc7eee4
Translated using Weblate (French)
Currently translated at 100.0% (19 of 19 strings)

Translation: Simple Mobile Tools/Simple Calendar metadata
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar-metadata/fr/
2023-09-19 12:39:38 +02:00
Lionel HANNEQUIN 468d2ffc4d
Translated using Weblate (French)
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/fr/
2023-09-19 12:39:38 +02:00
Tibor Kaputa 644c8680c2
Merge pull request #2202 from spkprs/patch-36
Update full_description.txt
2023-09-19 12:39:34 +02:00
Tibor Kaputa 437eb08edb
shortening the full description 2023-09-19 12:39:15 +02:00
spkprs 3dad1aa5e2
Update full_description.txt
The previous description was for the Calculator
2023-09-19 08:31:36 +03:00
tibbi 2608438f1e updating commons 2023-09-13 15:51:11 +02:00
Tibor Kaputa d47a1012ad
Merge pull request #2199 from esensar/gradle-deprecation-warnings
Clean up gradle deprecation warnings
2023-09-13 14:41:19 +02:00
Ensar Sarajčić 2b172d278a Clean up gradle deprecation warnings 2023-09-13 12:42:35 +02:00
Tibor Kaputa a8ec5a3386
Merge pull request #2196 from weblate/weblate-simple-mobile-tools-simple-calendar
Translations update from Hosted Weblate
2023-09-12 10:58:35 +02:00
Josep M. Ferrer 7c2ccc29ec
Translated using Weblate (Catalan)
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/ca/
2023-09-12 10:29:56 +02:00
tibbi 86a8a1b153 updating commons 2023-09-12 10:29:50 +02:00
Tibor Kaputa b1861bb457
Merge pull request #2177 from weblate/weblate-simple-mobile-tools-simple-calendar
Translations update from Hosted Weblate
2023-09-05 16:01:39 +02:00
Komjaunietis Latvijas d8ae034935
Translated using Weblate (Latvian)
Currently translated at 99.5% (244 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/lv/
2023-09-05 16:01:25 +02:00
Komjaunietis Latvijas 613cbb4e15
Translated using Weblate (Latvian)
Currently translated at 99.5% (244 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/lv/
2023-09-05 16:01:24 +02:00
Cleydison Nascimento 96d7f1f63c
Translated using Weblate (Portuguese)
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/pt/
2023-09-05 16:01:24 +02:00
Tibor Kaputa e9e887f1b5
Merge pull request #2189 from naveensingh/sdk_and_viewbinding_migration
Migrate to View binding, SDK 34 and Version catalogs
2023-09-05 16:01:20 +02:00
Naveen a390966228
Update weekly day count color on resume 2023-09-05 18:32:44 +05:30
Tibor Kaputa 3b2a69bdca
Merge pull request #2187 from Usland123/patch-1
Update strings.xml
2023-09-05 14:31:11 +02:00
Naveen cdca6d86c4
Minor readability change 2023-09-05 12:46:40 +05:30
Naveen dc81fddd05
Properly handle exact alarms
- Use `USE_EXACT_ALARM` permission on API 33 and above
 - Degrade to `setAndAllowWhileIdle` just in case `canScheduleExactAlarms()` returns false on some wierd device
2023-09-05 12:28:47 +05:30
Naveen 12837680e1
Target SDK 34 2023-09-05 11:30:14 +05:30
Naveen f791195b2f
Fix month view layout 2023-09-04 16:03:56 +05:30
Naveen 801b4ae9e9
Rename layout to item_autocomplete_title_subtitle.xml 2023-09-04 16:02:06 +05:30
Naveen e2ae8afe10
Migrate to non-transitive R class 2023-09-04 15:43:10 +05:30
Naveen a408323236
Revert accidentally renamed constants 2023-09-04 15:29:26 +05:30
Naveen aac1d60baf
Inflate views using binding 2023-09-04 15:17:16 +05:30
Naveen 76b83a6a46
Remove unused variable 2023-09-04 15:07:20 +05:30
Naveen dfdf816c4e
Use viewBinding extension 2023-09-04 14:52:18 +05:30
Naveen a8d5c1fbb8
Use a simple forEach loop 2023-09-04 14:43:30 +05:30
Naveen a4114bd501
Minor code improvement 2023-09-04 14:26:50 +05:30
Naveen 279bec94cf
Remove useless line 2023-09-04 14:19:05 +05:30
Naveen 95303df5da
Minor code improvement 2023-09-04 14:16:52 +05:30
Naveen 7867e71cde
Migrate from kotlin synthetics to View binding 2023-09-03 18:55:41 +05:30
Naveen 670e5d6a87
Bump jvm heap size to 8192m 2023-09-03 11:34:33 +05:30
Naveen 408cbce9f8
Update kotlin and ksp 2023-09-03 11:32:07 +05:30
Usland c4f5749c1d
Update strings.xml 2023-09-02 20:17:33 +03:00
Naveen 5f41894872
Migrate build scripts to use version catalogs and kts 2023-08-30 19:10:13 +05:30
Agnieszka C 5fc80c2149 Fixed opening search results (#2180) 2023-08-27 13:36:54 +02:00
Tibor Kaputa 030faee892
Merge pull request #2165 from weblate/weblate-simple-mobile-tools-simple-calendar
Translations update from Hosted Weblate
2023-08-14 17:30:03 +02:00
Tibor Kaputa 20aca7e451
Update short_description.txt 2023-08-14 17:29:51 +02:00
Tibor Kaputa 7e603d7ef2
fixing the slovak translation 2023-08-14 17:29:29 +02:00
Milan Šalka 9aeb6c88cd
Translated using Weblate (Slovak)
Currently translated at 100.0% (19 of 19 strings)

Translation: Simple Mobile Tools/Simple Calendar metadata
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar-metadata/sk/
2023-08-11 11:46:50 +02:00
Milan Šalka d4f7bd6c21
Translated using Weblate (Slovak)
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/sk/
2023-08-11 11:46:49 +02:00
Alexander Gabilondo 6b00b5b97d
Translated using Weblate (Basque)
Currently translated at 94.7% (18 of 19 strings)

Translation: Simple Mobile Tools/Simple Calendar metadata
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar-metadata/eu/
2023-08-10 00:52:02 +02:00
Heki 3e3ee9a49c
Translated using Weblate (Slovenian)
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/sl/
2023-08-08 23:51:25 +02:00
Alexander Gabilondo bd03e4f998
Translated using Weblate (Basque)
Currently translated at 94.7% (18 of 19 strings)

Translation: Simple Mobile Tools/Simple Calendar metadata
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar-metadata/eu/
2023-08-08 23:51:24 +02:00
Kingproone 8b28d6512a
Translated using Weblate (Hungarian)
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/hu/
2023-08-01 06:12:15 +02:00
Gabriel Camargo 49910c8629
Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/pt_BR/
2023-07-31 04:02:33 +02:00
Tibor Kaputa 717bae9766
Merge pull request #2159 from naveensingh/start_week_on_any_day
Allow starting week with any day
2023-07-25 08:42:12 +02:00
Naveen a7ced1dd5d
Minor code improvement 2023-07-24 00:31:59 +05:30
Naveen b94c69160f
Avoid unnecessary complication and user locale's first day of week 2023-07-24 00:26:31 +05:30
Naveen bd9fd4879a
Merge remote-tracking branch 'origin/start_week_on_any_day' into start_week_on_any_day 2023-07-23 23:54:54 +05:30
Naveen 7e6ea16dfc
Highlight proper week day in month view 2023-07-23 23:54:37 +05:30
Naveen 59aec074fb
Remove unused variable 2023-07-23 23:40:05 +05:30
Naveen 7a45c38b5d
Migrate user preference from previous version 2023-07-23 23:31:40 +05:30
Naveen Singh f8600fac17
Merge branch 'SimpleMobileTools:master' into start_week_on_any_day 2023-07-23 10:59:08 +05:30
Tibor Kaputa 28bfb7fa21
Merge pull request #2158 from weblate/weblate-simple-mobile-tools-simple-calendar
Translations update from Hosted Weblate
2023-07-22 23:18:28 +02:00
Priit Jõerüüt 3e415f6772
Translated using Weblate (Estonian)
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/et/
2023-07-22 23:18:04 +02:00
Tibor Kaputa 495656a0a0
Merge pull request #2160 from PeterDaveHello/zh_TW
Update & Improve Traditional Chinese translation
2023-07-22 23:17:59 +02:00
Peter Dave Hello c371cead2b Update Traditional Chinese translation 2023-07-23 02:24:43 +08:00
Naveen 2eb2ec398e
Rename preference key 2023-07-22 23:26:30 +05:30
Naveen 400c8003e5
Fix typo 2023-07-22 22:57:08 +05:30
Naveen 5bdd5e8cec
Properly handle "Start week on" preference in all places 2023-07-22 22:44:24 +05:30
Naveen aa1ed30e52
Remove unnecessary variables 2023-07-22 22:38:40 +05:30
Naveen 5d02007e8d
Properly export/import first day of week 2023-07-22 13:47:48 +05:30
Naveen ed39bbfdda
Apply user preferred first day of week in date pickers 2023-07-22 13:45:01 +05:30
Naveen 8229492ae7
Add "Start week on" preference 2023-07-22 13:21:51 +05:30
Tibor Kaputa 38ae6bcb14
Merge pull request #2157 from Merkost/backup_improve
Updated commons for backup
2023-07-19 08:40:34 +02:00
merkost 1edba97270 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
2023-07-19 16:13:30 +10:00
merkost 627938e535 Updated commons and refactored PermissionRequiredDialog 2023-07-19 16:12:13 +10:00
Tibor Kaputa 899ec987f3
Merge pull request #2156 from weblate/weblate-simple-mobile-tools-simple-calendar
Translations update from Hosted Weblate
2023-07-18 07:06:02 +02:00
abc0922001 db2f22f119
Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (19 of 19 strings)

Translation: Simple Mobile Tools/Simple Calendar metadata
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar-metadata/zh_Hant/
2023-07-18 07:03:52 +02:00
abc0922001 b250ead9f5
Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/zh_Hant/
2023-07-18 07:03:52 +02:00
Tibor Kaputa 2131fa1349
Merge pull request #2155 from Merkost/backup_improve
Backup improve
2023-07-18 07:03:47 +02:00
Konstantin Merenkov aad9dbcc50
Merge branch 'master' into backup_improve 2023-07-18 12:14:39 +10:00
merkost 1d9ea4a69b Main backup settings moved to commons 2023-07-18 12:06:12 +10:00
merkost ef65940802 Small gradle refactoring 2023-07-18 11:50:59 +10:00
tibbi f8959bcfd4 updating changelog 2023-07-16 23:29:05 +02:00
tibbi d7fa019583 update version to 6.22.2 2023-07-16 23:28:58 +02:00
tibbi 4591780367 updating commons 2023-07-16 23:25:01 +02:00
Tibor Kaputa 11657e8849
Merge pull request #2152 from Aga-C/weekly-edit-repeating-events
Added editing options for repeating events in weekly view (#2122)
2023-07-16 18:12:09 +02:00
Agnieszka C 33cd18099b Reverting dragged view instead of refreshing calendar 2023-07-16 17:27:40 +02:00
Agnieszka C 1e2ba7d0d5 Merge branch 'master' into weekly-edit-repeating-events 2023-07-16 17:07:56 +02:00
tibbi b2236a2a03 correcting some variable names 2023-07-16 15:08:56 +02:00
Tibor Kaputa 7ab69e974d
Merge pull request #2154 from Naveen3Singh/weekly_view_tz_fix
Use local timezone to configure weekly views
2023-07-16 15:05:24 +02:00
Naveen f06b7864ab
Reuse `getFirstDayOfWeek()` in WeekFragment 2023-07-16 03:07:28 +05:30
Naveen 2ee226d06b
Use local timezone to configure weekly views
This addresses issues like https://github.com/SimpleMobileTools/Simple-Calendar/issues/2143

The weekly view originally used local timezone to configure everything but was modified to use UTC to fix a `Start week with Sunday` issue https://github.com/SimpleMobileTools/Simple-Calendar/issues/1213 where events were created on the wrong day. Since `getFirstDayOfWeek()` was rewritten to handle week preferences properly, there is no need to complicate things using UTC anymore (otherwise we'll have to handle UTC-to-local-timezone conversion in many places)

This also fixes an issue with the drag-and-drop feature where the events were moved by ±1 day because the difference in timezone was not taken care of.
2023-07-16 02:54:51 +05:30
Agnieszka C 8bc0fb0cb7 Added editing options for repeating events in weekly view (#2122) 2023-07-15 09:13:06 +02:00
Tibor Kaputa acc35f791e
Merge pull request #2144 from weblate/weblate-simple-mobile-tools-simple-calendar
Translations update from Hosted Weblate
2023-07-14 14:29:25 +02:00
elgratea 48cfacdace
Translated using Weblate (Bulgarian)
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/bg/
2023-07-14 14:29:10 +02:00
Dan c92a3f4bda
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/uk/
2023-07-14 14:29:10 +02:00
Tibor Kaputa 5547cb48b4
Merge pull request #2145 from edgy-b/month-day-UI-improvements
- Improve UI Monhtly and daily view for landscape
2023-07-14 14:29:06 +02:00
Tibor Kaputa e24b226344
Merge pull request #2138 from Aga-C/fix-long-events
Fixed displaying long events in weekly view (#2135)
2023-07-14 14:27:39 +02:00
Tibor Kaputa c5e9c6f1cb
Merge pull request #2147 from wilsonrc/bugfix/new_alarm_permissions
add Exact alarm permission to fix issues on Android 13-14 targeting
2023-07-13 10:49:57 +02:00
Wilson a851f0475c add USE_EXACT_ALARM to be granted on install. 2023-07-11 13:57:32 -04:00
Edgars Bimbirulis f43f3002e7 - Improve UI Monhtly and daily view for landscape 2023-07-10 02:03:20 +03:00
Tibor Kaputa b01525a240
Merge pull request #2137 from weblate/weblate-simple-mobile-tools-simple-calendar
Translations update from Hosted Weblate
2023-07-08 14:46:09 +02:00
Linerly 809b31f56d
Translated using Weblate (Indonesian)
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/id/
2023-07-08 14:33:22 +02:00
Eric a8d5173ad7
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (245 of 245 strings)

Translation: Simple Mobile Tools/Simple Calendar
Translate-URL: https://hosted.weblate.org/projects/simple-mobile-tools/simple-calendar/zh_Hans/
2023-07-08 14:33:22 +02:00
Tibor Kaputa 244be566e4
Merge pull request #2141 from abc0922001/patch-1
Update Traditional Chinese translation
2023-07-08 14:33:13 +02:00
Tibor Kaputa 14b3afd2ba
Update strings.xml 2023-07-08 14:33:04 +02:00
abc0922001 d2cf79b960
Update Traditional Chinese translation 2023-07-07 15:06:13 +08:00
Agnieszka C 549665e302 Fixed displaying long events in weekly view (#2135) 2023-07-04 20:09:16 +02:00
tibbi dce40291ca updating changelog 2023-07-02 10:51:24 +02:00
tibbi 9e4dcfa306 update version to 6.22.1 2023-07-02 10:51:17 +02:00
tibbi b4e85e4ec3 updating commons 2023-07-02 10:47:12 +02:00
Tibor Kaputa 6deae5cf13
Merge pull request #2132 from Aga-C/change-order
Changed event type and color order (#2131)
2023-07-02 10:40:50 +02:00
Tibor Kaputa d4f320d8b2
Merge pull request #2133 from Naveen3Singh/ensure_event_type_visibility
Ensure event type visibility when a new event or task is created
2023-07-02 10:35:50 +02:00
Naveen d2b40d11e7
Ensure event type visibility when importing ICS 2023-07-01 13:59:23 +05:30
Naveen 4dcce80a7d
Remove unused strings 2023-07-01 00:15:36 +05:30
Naveen 6f0a9e237e
Ensure event type visibility 2023-07-01 00:11:55 +05:30
Agnieszka C 26d96d2ba1 Changed event type and color order (#2131) 2023-06-30 17:36:31 +02:00
171 changed files with 4594 additions and 3781 deletions

View File

@ -1,6 +1,32 @@
Changelog
==========
Version 6.23.1 *(2023-10-03)*
----------------------------
* Fixed a yearly view display issue
* Allow starting the week with any day
* Added some translation, stability and UX improvements
Version 6.23.0 *(2023-09-19)*
----------------------------
* Allow starting the week with any day
* Added some translation, stability and UX improvements
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)*
----------------------------
* Flipped type and color fields at event and task creation screens
* Fixed some repetition issues
* Added some translation, stability and UX improvements
Version 6.22.0 *(2023-06-29)*
----------------------------

View File

@ -61,7 +61,7 @@ Telegram:
https://t.me/SimpleMobileTools
<a href='https://play.google.com/store/apps/details?id=com.simplemobiletools.calendar.pro'><img src='https://simplemobiletools.com/images/button-google-play.svg' alt='Get it on Google Play' height='45' /></a>
<a href='https://f-droid.org/packages/com.simplemobiletools.calendar.pro'><img src='https://simplemobiletools.com/images/button-f-droid.png' alt='Get it on F-Droid' height='45' /></a>
<a href='https://f-droid.org/packages/com.simplemobiletools.calendar.pro'><img src='https://simplemobiletools.com/images/button-fdroid.svg' alt='Get it on F-Droid' height='45' /></a>
<div style="display:flex;">
<img alt="App image" src="fastlane/metadata/android/en-US/images/phoneScreenshots/1_en-US.jpeg" width="30%">

View File

@ -1,82 +0,0 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'de.timfreiheit.resourceplaceholders'
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
compileSdkVersion 33
defaultConfig {
applicationId "com.simplemobiletools.calendar.pro"
minSdkVersion 23
targetSdkVersion 33
versionCode 236
versionName "6.22.0"
multiDexEnabled true
setProperty("archivesBaseName", "calendar")
vectorDrawables.useSupportLibrary = true
}
signingConfigs {
if (keystorePropertiesFile.exists()) {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
}
buildTypes {
debug {
applicationIdSuffix ".debug"
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
if (keystorePropertiesFile.exists()) {
signingConfig signingConfigs.release
}
}
}
flavorDimensions "variants"
productFlavors {
core {}
fdroid {}
prepaid {}
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
checkReleaseBuilds false
abortOnError false
}
resourcePlaceholders {
files = ['xml/shortcuts.xml']
}
}
dependencies {
implementation 'com.github.SimpleMobileTools:Simple-Commons:6f69c8c105'
implementation 'androidx.multidex:multidex:2.0.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation "androidx.print:print:1.0.0"
kapt 'androidx.room:room-compiler:2.5.1'
implementation 'androidx.room:room-runtime:2.5.1'
annotationProcessor 'androidx.room:room-compiler:2.5.1'
}

107
app/build.gradle.kts Normal file
View File

@ -0,0 +1,107 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.konan.properties.Properties
import java.io.FileInputStream
plugins {
alias(libs.plugins.android)
alias(libs.plugins.kotlinAndroid)
alias(libs.plugins.ksp)
base
}
base {
archivesName.set("calendar")
}
val keystorePropertiesFile: File = rootProject.file("keystore.properties")
val keystoreProperties = Properties()
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}
android {
compileSdk = project.libs.versions.app.build.compileSDKVersion.get().toInt()
defaultConfig {
applicationId = libs.versions.app.version.appId.get()
minSdk = project.libs.versions.app.build.minimumSDK.get().toInt()
targetSdk = project.libs.versions.app.build.targetSDK.get().toInt()
versionCode = project.libs.versions.app.version.versionCode.get().toInt()
versionName = project.libs.versions.app.version.versionName.get()
multiDexEnabled = true
vectorDrawables.useSupportLibrary = true
ksp {
arg("room.schemaLocation", "$projectDir/schemas")
}
}
signingConfigs {
if (keystorePropertiesFile.exists()) {
register("release") {
keyAlias = keystoreProperties.getProperty("keyAlias")
keyPassword = keystoreProperties.getProperty("keyPassword")
storeFile = file(keystoreProperties.getProperty("storeFile"))
storePassword = keystoreProperties.getProperty("storePassword")
}
}
}
buildFeatures {
viewBinding = true
buildConfig = true
}
buildTypes {
debug {
applicationIdSuffix = ".debug"
}
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
if (keystorePropertiesFile.exists()) {
signingConfig = signingConfigs.getByName("release")
}
}
}
flavorDimensions.add("variants")
productFlavors {
register("core")
register("fdroid")
register("prepaid")
}
sourceSets {
getByName("main").java.srcDirs("src/main/kotlin")
}
compileOptions {
val currentJavaVersionFromLibs = JavaVersion.valueOf(libs.versions.app.build.javaVersion.get().toString())
sourceCompatibility = currentJavaVersionFromLibs
targetCompatibility = currentJavaVersionFromLibs
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = project.libs.versions.app.build.kotlinJVMTarget.get()
}
namespace = libs.versions.app.version.appId.get()
lint {
checkReleaseBuilds = false
abortOnError = false
}
}
dependencies {
implementation(libs.simple.mobile.tools.commons)
implementation(libs.androidx.multidex)
implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.swiperefreshlayout)
implementation(libs.androidx.print)
implementation(libs.bundles.room)
ksp(libs.androidx.room.compiler)
}

View File

@ -0,0 +1,357 @@
{
"formatVersion": 1,
"database": {
"version": 8,
"identityHash": "1d5b2fddcb258e43f2935820863057a9",
"entities": [
{
"tableName": "events",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `start_ts` INTEGER NOT NULL, `end_ts` INTEGER NOT NULL, `title` TEXT NOT NULL, `location` TEXT NOT NULL, `description` TEXT NOT NULL, `reminder_1_minutes` INTEGER NOT NULL, `reminder_2_minutes` INTEGER NOT NULL, `reminder_3_minutes` INTEGER NOT NULL, `reminder_1_type` INTEGER NOT NULL, `reminder_2_type` INTEGER NOT NULL, `reminder_3_type` INTEGER NOT NULL, `repeat_interval` INTEGER NOT NULL, `repeat_rule` INTEGER NOT NULL, `repeat_limit` INTEGER NOT NULL, `repetition_exceptions` TEXT NOT NULL, `attendees` TEXT NOT NULL, `import_id` TEXT NOT NULL, `time_zone` TEXT NOT NULL, `flags` INTEGER NOT NULL, `event_type` INTEGER NOT NULL, `parent_id` INTEGER NOT NULL, `last_updated` INTEGER NOT NULL, `source` TEXT NOT NULL, `availability` INTEGER NOT NULL, `color` INTEGER NOT NULL, `type` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "startTS",
"columnName": "start_ts",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "endTS",
"columnName": "end_ts",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "location",
"columnName": "location",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "description",
"columnName": "description",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "reminder1Minutes",
"columnName": "reminder_1_minutes",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "reminder2Minutes",
"columnName": "reminder_2_minutes",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "reminder3Minutes",
"columnName": "reminder_3_minutes",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "reminder1Type",
"columnName": "reminder_1_type",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "reminder2Type",
"columnName": "reminder_2_type",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "reminder3Type",
"columnName": "reminder_3_type",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "repeatInterval",
"columnName": "repeat_interval",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "repeatRule",
"columnName": "repeat_rule",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "repeatLimit",
"columnName": "repeat_limit",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "repetitionExceptions",
"columnName": "repetition_exceptions",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "attendees",
"columnName": "attendees",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "importId",
"columnName": "import_id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "timeZone",
"columnName": "time_zone",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "flags",
"columnName": "flags",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "eventType",
"columnName": "event_type",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "parentId",
"columnName": "parent_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "lastUpdated",
"columnName": "last_updated",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "source",
"columnName": "source",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "availability",
"columnName": "availability",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "color",
"columnName": "color",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [
{
"name": "index_events_id",
"unique": true,
"columnNames": [
"id"
],
"orders": [],
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_events_id` ON `${TABLE_NAME}` (`id`)"
}
],
"foreignKeys": []
},
{
"tableName": "event_types",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `title` TEXT NOT NULL, `color` INTEGER NOT NULL, `caldav_calendar_id` INTEGER NOT NULL, `caldav_display_name` TEXT NOT NULL, `caldav_email` TEXT NOT NULL, `type` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "color",
"columnName": "color",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "caldavCalendarId",
"columnName": "caldav_calendar_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "caldavDisplayName",
"columnName": "caldav_display_name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "caldavEmail",
"columnName": "caldav_email",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [
{
"name": "index_event_types_id",
"unique": true,
"columnNames": [
"id"
],
"orders": [],
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_event_types_id` ON `${TABLE_NAME}` (`id`)"
}
],
"foreignKeys": []
},
{
"tableName": "widgets",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `widget_id` INTEGER NOT NULL, `period` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "widgetId",
"columnName": "widget_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "period",
"columnName": "period",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [
{
"name": "index_widgets_widget_id",
"unique": true,
"columnNames": [
"widget_id"
],
"orders": [],
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_widgets_widget_id` ON `${TABLE_NAME}` (`widget_id`)"
}
],
"foreignKeys": []
},
{
"tableName": "tasks",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `task_id` INTEGER NOT NULL, `start_ts` INTEGER NOT NULL, `flags` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "task_id",
"columnName": "task_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "startTS",
"columnName": "start_ts",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "flags",
"columnName": "flags",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [
{
"name": "index_tasks_id_task_id",
"unique": true,
"columnNames": [
"id",
"task_id"
],
"orders": [],
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_tasks_id_task_id` ON `${TABLE_NAME}` (`id`, `task_id`)"
}
],
"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, '1d5b2fddcb258e43f2935820863057a9')"
]
}
}

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.simplemobiletools.calendar.pro"
android:installLocation="auto">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
@ -10,9 +9,13 @@
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission
android:name="android.permission.SCHEDULE_EXACT_ALARM"
android:maxSdkVersion="32" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />

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
@ -21,15 +18,13 @@ import com.simplemobiletools.calendar.pro.R
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.dialogs.ExportEventsDialog
import com.simplemobiletools.calendar.pro.dialogs.ImportEventsDialog
import com.simplemobiletools.calendar.pro.databinding.ActivityMainBinding
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
@ -37,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.*
@ -49,17 +42,12 @@ import com.simplemobiletools.commons.models.Release
import com.simplemobiletools.commons.models.SimpleContact
import com.simplemobiletools.commons.views.MyLinearLayoutManager
import com.simplemobiletools.commons.views.MyRecyclerView
import kotlinx.android.synthetic.main.activity_main.*
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,13 +55,12 @@ 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
private var mStoredPrimaryColor = 0
private var mStoredDayCode = ""
private var mStoredIsSundayFirst = false
private var mStoredFirstDayOfWeek = 0
private var mStoredMidnightSpan = true
private var mStoredUse24HourFormat = false
private var mStoredDimPastEvents = true
@ -88,19 +75,21 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
private var searchResultEvents = ArrayList<Event>()
private var bottomItemAtRefresh: ListItem? = null
private val binding by viewBinding(ActivityMainBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setContentView(binding.root)
appLaunched(BuildConfig.APPLICATION_ID)
setupOptionsMenu()
refreshMenuItems()
updateMaterialActivityViews(main_coordinator, main_holder, useTransparentNavigation = false, useTopSearchMenu = true)
updateMaterialActivityViews(binding.mainCoordinator, binding.mainHolder, useTransparentNavigation = false, useTopSearchMenu = true)
checkWhatsNewDialog()
calendar_fab.beVisibleIf(config.storedView != YEARLY_VIEW && config.storedView != WEEKLY_VIEW)
calendar_fab.setOnClickListener {
binding.calendarFab.beVisibleIf(config.storedView != YEARLY_VIEW && config.storedView != WEEKLY_VIEW)
binding.calendarFab.setOnClickListener {
if (config.allowCreatingTasks) {
if (fab_extended_overlay.isVisible()) {
if (binding.fabExtendedOverlay.isVisible()) {
openNewEvent()
Handler().postDelayed({
@ -113,14 +102,14 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
openNewEvent()
}
}
fab_event_label.setOnClickListener { openNewEvent() }
fab_task_label.setOnClickListener { openNewTask() }
binding.fabEventLabel.setOnClickListener { openNewEvent() }
binding.fabTaskLabel.setOnClickListener { openNewTask() }
fab_extended_overlay.setOnClickListener {
binding.fabExtendedOverlay.setOnClickListener {
hideExtendedFab()
}
fab_task_icon.setOnClickListener {
binding.fabTaskIcon.setOnClickListener {
openNewTask()
Handler().postDelayed({
@ -138,7 +127,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
refreshCalDAVCalendars(false)
}
swipe_refresh_layout.setOnRefreshListener {
binding.swipeRefreshLayout.setOnRefreshListener {
refreshCalDAVCalendars(true)
}
@ -157,7 +146,14 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
addBirthdaysAnniversariesAtStart()
if (isPackageInstalled("com.simplemobiletools.calendar")) {
ConfirmationDialog(this, "", R.string.upgraded_from_free_calendar, R.string.ok, 0, false) {}
ConfirmationDialog(
activity = this,
message = "",
messageId = com.simplemobiletools.commons.R.string.upgraded_from_free_calendar,
positive = com.simplemobiletools.commons.R.string.ok,
negative = 0,
cancelOnTouchOutside = false
) {}
}
addImportIdsToTasks {
@ -183,7 +179,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
if (config.storedView == WEEKLY_VIEW) {
if (mStoredIsSundayFirst != config.isSundayFirst || mStoredUse24HourFormat != config.use24HourFormat
if (mStoredFirstDayOfWeek != config.firstDayOfWeek || mStoredUse24HourFormat != config.use24HourFormat
|| mStoredMidnightSpan != config.showMidnightSpanningEventsAtTop || mStoredStartWeekWithCurrentDay != config.startWeekWithCurrentDay
) {
updateViewPager()
@ -191,23 +187,25 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
updateStatusbarColor(getProperBackgroundColor())
main_menu.updateColors()
storeStateVariables()
updateWidgets()
updateTextColors(calendar_coordinator)
fab_extended_overlay.background = ColorDrawable(getProperBackgroundColor().adjustAlpha(0.8f))
fab_event_label.setTextColor(getProperTextColor())
fab_task_label.setTextColor(getProperTextColor())
binding.apply {
mainMenu.updateColors()
storeStateVariables()
updateWidgets()
updateTextColors(calendarCoordinator)
fabExtendedOverlay.background = ColorDrawable(getProperBackgroundColor().adjustAlpha(0.8f))
fabEventLabel.setTextColor(getProperTextColor())
fabTaskLabel.setTextColor(getProperTextColor())
fab_task_icon.drawable.applyColorFilter(mStoredPrimaryColor.getContrastColor())
fab_task_icon.background.applyColorFilter(mStoredPrimaryColor)
fabTaskIcon.drawable.applyColorFilter(mStoredPrimaryColor.getContrastColor())
fabTaskIcon.background.applyColorFilter(mStoredPrimaryColor)
search_holder.background = ColorDrawable(getProperBackgroundColor())
checkSwipeRefreshAvailability()
checkShortcuts()
searchHolder.background = ColorDrawable(getProperBackgroundColor())
checkSwipeRefreshAvailability()
checkShortcuts()
if (!main_menu.isSearchOpen) {
refreshMenuItems()
if (!mainMenu.isSearchOpen) {
refreshMenuItems()
}
}
setupQuickFilter()
@ -231,33 +229,33 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
fun refreshMenuItems() {
if (fab_extended_overlay.isVisible()) {
if (binding.fabExtendedOverlay.isVisible()) {
hideExtendedFab()
}
shouldGoToTodayBeVisible = currentFragments.lastOrNull()?.shouldGoToTodayBeVisible() ?: false
main_menu.getToolbar().menu.apply {
binding.mainMenu.getToolbar().menu.apply {
goToTodayButton = findItem(R.id.go_to_today)
findItem(R.id.print).isVisible = config.storedView != MONTHLY_DAILY_VIEW
findItem(R.id.filter).isVisible = mShouldFilterBeVisible
findItem(R.id.go_to_today).isVisible = shouldGoToTodayBeVisible && !main_menu.isSearchOpen
findItem(R.id.go_to_today).isVisible = shouldGoToTodayBeVisible && !binding.mainMenu.isSearchOpen
findItem(R.id.go_to_date).isVisible = config.storedView != EVENTS_LIST_VIEW
findItem(R.id.refresh_caldav_calendars).isVisible = config.caldavSync
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(R.bool.hide_google_relations)
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(com.simplemobiletools.commons.R.bool.hide_google_relations)
}
}
private fun setupOptionsMenu() {
main_menu.getToolbar().inflateMenu(R.menu.menu_main)
main_menu.toggleHideOnScroll(false)
main_menu.setupMenu()
private fun setupOptionsMenu() = binding.apply {
mainMenu.getToolbar().inflateMenu(R.menu.menu_main)
mainMenu.toggleHideOnScroll(false)
mainMenu.setupMenu()
main_menu.onSearchTextChangedListener = { text ->
mainMenu.onSearchTextChangedListener = { text ->
searchQueryChanged(text)
}
main_menu.getToolbar().setOnMenuItemClickListener { menuItem ->
if (fab_extended_overlay.isVisible()) {
mainMenu.getToolbar().setOnMenuItemClickListener { menuItem ->
if (fabExtendedOverlay.isVisible()) {
hideExtendedFab()
}
@ -271,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()
@ -283,13 +279,13 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
override fun onBackPressed() {
if (main_menu.isSearchOpen) {
if (binding.mainMenu.isSearchOpen) {
closeSearch()
} else {
swipe_refresh_layout.isRefreshing = false
binding.swipeRefreshLayout.isRefreshing = false
checkSwipeRefreshAvailability()
when {
fab_extended_overlay.isVisible() -> hideExtendedFab()
binding.fabExtendedOverlay.isVisible() -> hideExtendedFab()
currentFragments.size > 1 -> removeTopFragment()
else -> super.onBackPressed()
}
@ -303,22 +299,12 @@ 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()
mStoredBackgroundColor = getProperBackgroundColor()
config.apply {
mStoredIsSundayFirst = isSundayFirst
mStoredFirstDayOfWeek = firstDayOfWeek
mStoredUse24HourFormat = use24HourFormat
mStoredDimPastEvents = dimPastEvents
mStoredDimCompletedTasks = dimCompletedTasks
@ -333,7 +319,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
private fun setupQuickFilter() {
eventsHelper.getEventTypes(this, false) {
val quickFilterEventTypes = config.quickFilterEventTypes
quick_event_type_filter.adapter = QuickFilterEventTypeAdapter(this, it, quickFilterEventTypes) {
binding.quickEventTypeFilter.adapter = QuickFilterEventTypeAdapter(this, it, quickFilterEventTypes) {
if (config.displayEventTypes.isEmpty() && !config.wasFilteredOutWarningShown) {
toast(R.string.everything_filtered_out, Toast.LENGTH_LONG)
config.wasFilteredOutWarningShown = true
@ -346,7 +332,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
private fun closeSearch() {
main_menu.closeSearch()
binding.mainMenu.closeSearch()
minFetchedSearchTS = 0L
maxFetchedSearchTS = 0L
searchResultEvents.clear()
@ -433,7 +419,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
intent.removeExtra(VIEW_TO_OPEN)
intent.removeExtra(DAY_CODE)
if (dayCodeToOpen.isNotEmpty()) {
calendar_fab.beVisible()
binding.calendarFab.beVisible()
if (viewToOpen != LAST_VIEW) {
config.storedView = viewToOpen
}
@ -486,7 +472,14 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
}
} else {
tryImportEventsFromFile(uri!!)
tryImportEventsFromFile(uri!!) {
if (it) {
runOnUiThread {
updateViewPager()
setupQuickFilter()
}
}
}
}
}
}
@ -523,7 +516,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
private fun resetActionBarTitle() {
main_menu.updateHintText(getString(R.string.search))
binding.mainMenu.updateHintText(getString(com.simplemobiletools.commons.R.string.search))
}
private fun showFilterDialog() {
@ -572,7 +565,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
toast(R.string.refreshing_complete)
}
runOnUiThread {
swipe_refresh_layout.isRefreshing = false
binding.swipeRefreshLayout.isRefreshing = false
}
}
@ -581,7 +574,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
RadioGroupDialog(this, items) { selectedHoliday ->
SetRemindersDialog(this, OTHER_EVENT) {
val reminders = it
toast(R.string.importing)
toast(com.simplemobiletools.commons.R.string.importing)
ensureBackgroundThread {
val holidays = getString(R.string.holidays)
var eventTypeId = eventsHelper.getEventTypeIdWithClass(HOLIDAY_EVENT)
@ -618,6 +611,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
updateViewPager()
setupQuickFilter()
}
it == -1 -> toast(R.string.no_new_birthdays)
else -> toast(R.string.no_birthdays)
}
@ -626,7 +620,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
}
} else {
toast(R.string.no_contacts_permission)
toast(com.simplemobiletools.commons.R.string.no_contacts_permission)
}
}
}
@ -648,6 +642,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
updateViewPager()
setupQuickFilter()
}
it == -1 -> toast(R.string.no_new_anniversaries)
else -> toast(R.string.no_anniversaries)
}
@ -656,7 +651,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
}
} else {
toast(R.string.no_contacts_permission)
toast(com.simplemobiletools.commons.R.string.no_contacts_permission)
}
}
}
@ -699,7 +694,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
private fun handleParseResult(result: ImportResult) {
toast(
when (result) {
ImportResult.IMPORT_NOTHING_NEW -> R.string.no_new_items
ImportResult.IMPORT_NOTHING_NEW -> com.simplemobiletools.commons.R.string.no_new_items
ImportResult.IMPORT_OK -> R.string.holidays_imported_successfully
ImportResult.IMPORT_PARTIAL -> R.string.importing_some_holidays_failed
else -> R.string.importing_holidays_failed
@ -867,7 +862,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
private fun updateView(view: Int) {
calendar_fab.beVisibleIf(view != YEARLY_VIEW && view != WEEKLY_VIEW)
binding.calendarFab.beVisibleIf(view != YEARLY_VIEW && view != WEEKLY_VIEW)
val dateCode = getDateCodeToDisplay(view)
config.storedView = view
checkSwipeRefreshAvailability()
@ -929,7 +924,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
fragment.arguments = bundle
supportFragmentManager.beginTransaction().add(R.id.fragments_holder, fragment).commitNow()
main_menu.toggleForceArrowBackIcon(false)
binding.mainMenu.toggleForceArrowBackIcon(false)
}
private fun fixDayCode(dayCode: String? = null): String? = when {
@ -940,26 +935,30 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
private fun showExtendedFab() {
animateFabIcon(false)
arrayOf(fab_event_label, fab_extended_overlay, fab_task_icon, fab_task_label).forEach {
it.fadeIn()
binding.apply {
arrayOf(fabEventLabel, fabExtendedOverlay, fabTaskIcon, fabTaskLabel).forEach {
it.fadeIn()
}
}
}
private fun hideExtendedFab() {
animateFabIcon(true)
arrayOf(fab_event_label, fab_extended_overlay, fab_task_icon, fab_task_label).forEach {
it.fadeOut()
binding.apply {
arrayOf(fabEventLabel, fabExtendedOverlay, fabTaskIcon, fabTaskLabel).forEach {
it.fadeOut()
}
}
}
private fun animateFabIcon(showPlus: Boolean) {
val newDrawableId = if (showPlus) {
R.drawable.ic_plus_vector
com.simplemobiletools.commons.R.drawable.ic_plus_vector
} else {
R.drawable.ic_today_vector
}
val newDrawable = resources.getColoredDrawableWithColor(newDrawableId, getProperPrimaryColor())
calendar_fab.setImageDrawable(newDrawable)
binding.calendarFab.setImageDrawable(newDrawable)
}
private fun openNewEvent() {
@ -988,7 +987,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
fragment.arguments = bundle
supportFragmentManager.beginTransaction().add(R.id.fragments_holder, fragment).commitNow()
resetActionBarTitle()
calendar_fab.beVisible()
binding.calendarFab.beVisible()
showBackNavigationArrow()
}
@ -1026,17 +1025,17 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
refreshEvents()
}
calendar_fab.beGoneIf(currentFragments.size == 1 && config.storedView == YEARLY_VIEW)
binding.calendarFab.beGoneIf(currentFragments.size == 1 && config.storedView == YEARLY_VIEW)
if (currentFragments.size > 1) {
showBackNavigationArrow()
} else {
main_menu.toggleForceArrowBackIcon(false)
binding.mainMenu.toggleForceArrowBackIcon(false)
}
}
private fun showBackNavigationArrow() {
main_menu.toggleForceArrowBackIcon(true)
main_menu.onNavigateBackClickListener = {
binding.mainMenu.toggleForceArrowBackIcon(true)
binding.mainMenu.onNavigateBackClickListener = {
onBackPressed()
}
}
@ -1049,128 +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(R.string.system_service_disabled, Toast.LENGTH_LONG)
} catch (e: Exception) {
showErrorToast(e)
}
}
} else {
PermissionRequiredDialog(this, R.string.allow_notifications_reminders)
}
}
} 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!!)
uri.scheme == "content" -> {
val tempFile = getTempFile()
if (tempFile == null) {
toast(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(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(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(R.string.no_entries_for_exporting)
} else {
IcsExporter(this).exportEvents(outputStream, events, true) { result ->
toast(
when (result) {
ExportResult.EXPORT_OK -> R.string.exporting_successful
ExportResult.EXPORT_PARTIAL -> R.string.exporting_some_entries_failed
else -> R.string.exporting_failed
}
)
}
}
}
}
private fun launchSettings() {
hideKeyboard()
startActivity(Intent(applicationContext, SettingsActivity::class.java))
@ -1185,16 +1062,15 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
FAQItem(R.string.faq_3_title, R.string.faq_3_text),
FAQItem(R.string.faq_6_title, R.string.faq_6_text),
FAQItem(R.string.faq_1_title, R.string.faq_1_text),
FAQItem(R.string.faq_1_title_commons, R.string.faq_1_text_commons),
FAQItem(R.string.faq_4_title_commons, R.string.faq_4_text_commons),
FAQItem(com.simplemobiletools.commons.R.string.faq_1_title_commons, com.simplemobiletools.commons.R.string.faq_1_text_commons),
FAQItem(com.simplemobiletools.commons.R.string.faq_4_title_commons, com.simplemobiletools.commons.R.string.faq_4_text_commons),
FAQItem(R.string.faq_4_title, R.string.faq_4_text)
)
if (!resources.getBoolean(R.bool.hide_google_relations)) {
faqItems.add(FAQItem(R.string.faq_2_title_commons, R.string.faq_2_text_commons))
faqItems.add(FAQItem(R.string.faq_6_title_commons, R.string.faq_6_text_commons))
faqItems.add(FAQItem(R.string.faq_7_title_commons, R.string.faq_7_text_commons))
if (!resources.getBoolean(com.simplemobiletools.commons.R.bool.hide_google_relations)) {
faqItems.add(FAQItem(com.simplemobiletools.commons.R.string.faq_2_title_commons, com.simplemobiletools.commons.R.string.faq_2_text_commons))
faqItems.add(FAQItem(com.simplemobiletools.commons.R.string.faq_6_title_commons, com.simplemobiletools.commons.R.string.faq_6_text_commons))
faqItems.add(FAQItem(com.simplemobiletools.commons.R.string.faq_7_title_commons, com.simplemobiletools.commons.R.string.faq_7_text_commons))
}
startAboutActivity(R.string.app_name, licenses, BuildConfig.VERSION_NAME, faqItems, true)
@ -1203,23 +1079,23 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
private fun searchQueryChanged(text: String) {
mLatestSearchQuery = text
if (text.isNotEmpty() && search_holder.isGone()) {
search_holder.fadeIn()
if (text.isNotEmpty() && binding.searchHolder.isGone()) {
binding.searchHolder.fadeIn()
} else if (text.isEmpty()) {
search_holder.fadeOut()
search_results_list.adapter = null
binding.searchHolder.fadeOut()
binding.searchResultsList.adapter = null
}
val placeholderTextId = if (config.displayEventTypes.isEmpty()) {
R.string.everything_filtered_out
} else {
R.string.no_items_found
com.simplemobiletools.commons.R.string.no_items_found
}
search_placeholder.setText(placeholderTextId)
search_placeholder_2.beVisibleIf(text.length == 1)
binding.searchPlaceholder.setText(placeholderTextId)
binding.searchPlaceholder2.beVisibleIf(text.length == 1)
if (text.length >= 2) {
if (search_results_list.adapter == null) {
if (binding.searchResultsList.adapter == null) {
minFetchedSearchTS = DateTime().minusYears(2).seconds()
maxFetchedSearchTS = DateTime().plusYears(2).seconds()
}
@ -1249,13 +1125,13 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
}
} else if (text.length == 1) {
search_placeholder.beVisible()
search_results_list.beGone()
binding.searchPlaceholder.beVisible()
binding.searchResultsList.beGone()
}
}
private fun showSearchResultEvents(events: ArrayList<Event>, updateStatus: Int) {
val currentSearchQuery = main_menu.getCurrentQuery()
val currentSearchQuery = binding.mainMenu.getCurrentQuery()
val filtered = try {
events.filter {
it.title.contains(currentSearchQuery, true) || it.location.contains(currentSearchQuery, true) || it.description.contains(
@ -1269,24 +1145,25 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
searchResultEvents = filtered.toMutableList() as ArrayList<Event>
runOnUiThread {
search_results_list.beVisibleIf(filtered.isNotEmpty())
search_placeholder.beVisibleIf(filtered.isEmpty())
binding.searchResultsList.beVisibleIf(filtered.isNotEmpty())
binding.searchPlaceholder.beVisibleIf(filtered.isEmpty())
val listItems = getEventListItems(filtered)
val currAdapter = search_results_list.adapter
val currAdapter = binding.searchResultsList.adapter
if (currAdapter == null) {
val eventsAdapter = EventListAdapter(this, listItems, true, this, search_results_list) {
val eventsAdapter = EventListAdapter(this, listItems, true, this, binding.searchResultsList) {
hideKeyboard()
if (it is ListEvent) {
Intent(applicationContext, getActivityToOpen(it.isTask)).apply {
putExtra(EVENT_ID, it.id)
putExtra(EVENT_OCCURRENCE_TS, it.startTS)
startActivity(this)
}
}
}
search_results_list.adapter = eventsAdapter
binding.searchResultsList.adapter = eventsAdapter
search_results_list.endlessScrollListener = object : MyRecyclerView.EndlessScrollListener {
binding.searchResultsList.endlessScrollListener = object : MyRecyclerView.EndlessScrollListener {
override fun updateTop() {
fetchPreviousPeriod()
}
@ -1300,14 +1177,14 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
if (updateStatus == UPDATE_TOP) {
val item = listItems.indexOfFirst { it == bottomItemAtRefresh }
if (item != -1) {
search_results_list.scrollToPosition(item)
binding.searchResultsList.scrollToPosition(item)
}
} else if (updateStatus == UPDATE_BOTTOM) {
search_results_list.smoothScrollBy(0, resources.getDimension(R.dimen.endless_scroll_move_height).toInt())
binding.searchResultsList.smoothScrollBy(0, resources.getDimension(R.dimen.endless_scroll_move_height).toInt())
} else {
val firstNonPastSectionIndex = listItems.indexOfFirst { it is ListSectionDay && !it.isPastSection }
if (firstNonPastSectionIndex != -1) {
search_results_list.scrollToPosition(firstNonPastSectionIndex)
binding.searchResultsList.scrollToPosition(firstNonPastSectionIndex)
}
}
}
@ -1319,8 +1196,8 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
return
}
val lastPosition = (search_results_list.layoutManager as MyLinearLayoutManager).findLastVisibleItemPosition()
bottomItemAtRefresh = (search_results_list.adapter as EventListAdapter).listItems[lastPosition]
val lastPosition = (binding.searchResultsList.layoutManager as MyLinearLayoutManager).findLastVisibleItemPosition()
bottomItemAtRefresh = (binding.searchResultsList.adapter as EventListAdapter).listItems[lastPosition]
val oldMinFetchedTS = minFetchedSearchTS - 1
minFetchedSearchTS -= FETCH_INTERVAL
@ -1360,9 +1237,9 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
private fun checkSwipeRefreshAvailability() {
swipe_refresh_layout.isEnabled = config.caldavSync && config.pullToRefresh && config.storedView != WEEKLY_VIEW
if (!swipe_refresh_layout.isEnabled) {
swipe_refresh_layout.isRefreshing = false
binding.swipeRefreshLayout.isEnabled = config.caldavSync && config.pullToRefresh && config.storedView != WEEKLY_VIEW
if (!binding.swipeRefreshLayout.isEnabled) {
binding.swipeRefreshLayout.isRefreshing = false
}
}
@ -1372,7 +1249,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
private fun openDayAt(timestamp: Long) {
val dayCode = Formatter.getDayCodeFromTS(timestamp / 1000L)
calendar_fab.beVisible()
binding.calendarFab.beVisible()
config.storedView = DAILY_VIEW
updateViewPager(dayCode)
}

View File

@ -3,34 +3,42 @@ package com.simplemobiletools.calendar.pro.activities
import android.os.Bundle
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.adapters.ManageEventTypesAdapter
import com.simplemobiletools.calendar.pro.databinding.ActivityManageEventTypesBinding
import com.simplemobiletools.calendar.pro.dialogs.EditEventTypeDialog
import com.simplemobiletools.calendar.pro.extensions.eventsHelper
import com.simplemobiletools.calendar.pro.interfaces.DeleteEventTypesListener
import com.simplemobiletools.calendar.pro.models.EventType
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.extensions.updateTextColors
import com.simplemobiletools.commons.extensions.viewBinding
import com.simplemobiletools.commons.helpers.NavigationIcon
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import kotlinx.android.synthetic.main.activity_manage_event_types.*
class ManageEventTypesActivity : SimpleActivity(), DeleteEventTypesListener {
private val binding by viewBinding(ActivityManageEventTypesBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_manage_event_types)
setContentView(binding.root)
setupOptionsMenu()
updateMaterialActivityViews(manage_event_types_coordinator, manage_event_types_list, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(manage_event_types_list, manage_event_types_toolbar)
updateMaterialActivityViews(
binding.manageEventTypesCoordinator,
binding.manageEventTypesList,
useTransparentNavigation = true,
useTopSearchMenu = false
)
setupMaterialScrollListener(binding.manageEventTypesList, binding.manageEventTypesToolbar)
getEventTypes()
updateTextColors(manage_event_types_list)
updateTextColors(binding.manageEventTypesList)
}
override fun onResume() {
super.onResume()
setupToolbar(manage_event_types_toolbar, NavigationIcon.Arrow)
setupToolbar(binding.manageEventTypesToolbar, NavigationIcon.Arrow)
}
private fun showEventTypeDialog(eventType: EventType? = null) {
@ -41,15 +49,15 @@ class ManageEventTypesActivity : SimpleActivity(), DeleteEventTypesListener {
private fun getEventTypes() {
eventsHelper.getEventTypes(this, false) {
val adapter = ManageEventTypesAdapter(this, it, this, manage_event_types_list) {
val adapter = ManageEventTypesAdapter(this, it, this, binding.manageEventTypesList) {
showEventTypeDialog(it as EventType)
}
manage_event_types_list.adapter = adapter
binding.manageEventTypesList.adapter = adapter
}
}
private fun setupOptionsMenu() {
manage_event_types_toolbar.setOnMenuItemClickListener { menuItem ->
binding.manageEventTypesToolbar.setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) {
R.id.add_event_type -> showEventTypeDialog()
else -> return@setOnMenuItemClickListener false

View File

@ -10,22 +10,26 @@ import androidx.appcompat.widget.SearchView
import androidx.core.view.MenuItemCompat
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.adapters.SelectTimeZoneAdapter
import com.simplemobiletools.calendar.pro.databinding.ActivitySelectTimeZoneBinding
import com.simplemobiletools.calendar.pro.helpers.CURRENT_TIME_ZONE
import com.simplemobiletools.calendar.pro.helpers.TIME_ZONE
import com.simplemobiletools.calendar.pro.helpers.getAllTimeZones
import com.simplemobiletools.calendar.pro.models.MyTimeZone
import com.simplemobiletools.commons.extensions.hideKeyboard
import com.simplemobiletools.commons.extensions.viewBinding
import com.simplemobiletools.commons.helpers.NavigationIcon
import kotlinx.android.synthetic.main.activity_select_time_zone.*
import java.util.*
import java.util.Locale
import java.util.TimeZone
class SelectTimeZoneActivity : SimpleActivity() {
private var mSearchMenuItem: MenuItem? = null
private val allTimeZones = getAllTimeZones()
private val binding by viewBinding(ActivitySelectTimeZoneBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_select_time_zone)
setContentView(binding.root)
setupOptionsMenu()
SelectTimeZoneAdapter(this, allTimeZones) {
@ -35,23 +39,23 @@ class SelectTimeZoneActivity : SimpleActivity() {
setResult(RESULT_OK, data)
finish()
}.apply {
select_time_zone_list.adapter = this
binding.selectTimeZoneList.adapter = this
}
val currentTimeZone = intent.getStringExtra(CURRENT_TIME_ZONE) ?: TimeZone.getDefault().id
val pos = allTimeZones.indexOfFirst { it.zoneName.equals(currentTimeZone, true) }
if (pos != -1) {
select_time_zone_list.scrollToPosition(pos)
binding.selectTimeZoneList.scrollToPosition(pos)
}
}
override fun onResume() {
super.onResume()
setupToolbar(select_time_zone_toolbar, NavigationIcon.Arrow, searchMenuItem = mSearchMenuItem)
setupToolbar(binding.selectTimeZoneToolbar, NavigationIcon.Arrow, searchMenuItem = mSearchMenuItem)
}
private fun setupOptionsMenu() {
setupSearch(select_time_zone_toolbar.menu)
setupSearch(binding.selectTimeZoneToolbar.menu)
}
private fun setupSearch(menu: Menu) {
@ -89,8 +93,8 @@ class SelectTimeZoneActivity : SimpleActivity() {
private fun searchQueryChanged(text: String) {
val timeZones = allTimeZones.filter {
it.zoneName.toLowerCase(Locale.getDefault()).contains(text.toLowerCase(Locale.getDefault()))
it.zoneName.lowercase(Locale.getDefault()).contains(text.lowercase(Locale.getDefault()))
}.toMutableList() as ArrayList<MyTimeZone>
(select_time_zone_list.adapter as? SelectTimeZoneAdapter)?.updateTimeZones(timeZones)
(binding.selectTimeZoneList.adapter as? SelectTimeZoneAdapter)?.updateTimeZones(timeZones)
}
}

View File

@ -80,12 +80,17 @@ open class SimpleActivity : BaseSimpleActivity() {
if (NotificationManagerCompat.from(this).areNotificationsEnabled()) {
callback()
} else {
ConfirmationDialog(this, messageId = R.string.notifications_disabled, positive = R.string.ok, negative = 0) {
ConfirmationDialog(
activity = this,
messageId = com.simplemobiletools.commons.R.string.notifications_disabled,
positive = com.simplemobiletools.commons.R.string.ok,
negative = 0
) {
callback()
}
}
} else {
PermissionRequiredDialog(this, R.string.allow_notifications_reminders)
PermissionRequiredDialog(this, com.simplemobiletools.commons.R.string.allow_notifications_reminders, { openNotificationSettings() })
}
}
}

View File

@ -10,6 +10,7 @@ import androidx.core.content.ContextCompat
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.ActivityTaskBinding
import com.simplemobiletools.calendar.pro.dialogs.*
import com.simplemobiletools.calendar.pro.extensions.*
import com.simplemobiletools.calendar.pro.helpers.*
@ -23,9 +24,7 @@ import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.RadioItem
import kotlinx.android.synthetic.main.activity_task.*
import org.joda.time.DateTime
import java.util.Calendar
import kotlin.math.pow
class TaskActivity : SimpleActivity() {
@ -49,10 +48,12 @@ class TaskActivity : SimpleActivity() {
private var mIsNewTask = true
private var mEventColor = 0
private val binding by viewBinding(ActivityTaskBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_task)
setContentView(binding.root)
setupOptionsMenu()
refreshMenuItems()
@ -60,8 +61,8 @@ class TaskActivity : SimpleActivity() {
return
}
updateMaterialActivityViews(task_coordinator, task_holder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(task_nested_scrollview, task_toolbar)
updateMaterialActivityViews(binding.taskCoordinator, binding.taskHolder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(binding.taskNestedScrollview, binding.taskToolbar)
val intent = intent ?: return
updateColors()
@ -86,12 +87,12 @@ class TaskActivity : SimpleActivity() {
override fun onResume() {
super.onResume()
setupToolbar(task_toolbar, NavigationIcon.Arrow)
setupToolbar(binding.taskToolbar, NavigationIcon.Arrow)
}
private fun refreshMenuItems() {
if (::mTask.isInitialized) {
task_toolbar.menu.apply {
binding.taskToolbar.menu.apply {
findItem(R.id.delete).isVisible = mTask.id != null
findItem(R.id.share).isVisible = mTask.id != null
findItem(R.id.duplicate).isVisible = mTask.id != null
@ -100,7 +101,7 @@ class TaskActivity : SimpleActivity() {
}
private fun setupOptionsMenu() {
task_toolbar.setOnMenuItemClickListener { menuItem ->
binding.taskToolbar.setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) {
R.id.save -> saveCurrentTask()
R.id.delete -> deleteTask()
@ -126,8 +127,8 @@ class TaskActivity : SimpleActivity() {
val reminders = getReminders()
val originalReminders = mTask.getReminders()
if (task_title.text.toString() != mTask.title ||
task_description.text.toString() != mTask.description ||
if (binding.taskTitle.text.toString() != mTask.title ||
binding.taskDescription.text.toString() != mTask.description ||
reminders != originalReminders ||
mRepeatInterval != mTask.repeatInterval ||
mRepeatRule != mTask.repeatRule ||
@ -144,7 +145,13 @@ class TaskActivity : SimpleActivity() {
override fun onBackPressed() {
if (System.currentTimeMillis() - mLastSavePromptTS > SAVE_DISCARD_PROMPT_INTERVAL && isTaskChanged()) {
mLastSavePromptTS = System.currentTimeMillis()
ConfirmationAdvancedDialog(this, "", R.string.save_before_closing, R.string.save, R.string.discard) {
ConfirmationAdvancedDialog(
activity = this,
message = "",
messageId = com.simplemobiletools.commons.R.string.save_before_closing,
positive = com.simplemobiletools.commons.R.string.save,
negative = com.simplemobiletools.commons.R.string.discard
) {
if (it) {
saveCurrentTask()
} else {
@ -233,7 +240,7 @@ class TaskActivity : SimpleActivity() {
if (intent.getBooleanExtra(IS_DUPLICATE_INTENT, false)) {
mTask.id = null
task_toolbar.title = getString(R.string.new_task)
binding.taskToolbar.title = getString(R.string.new_task)
}
} else {
mTask = Event(null)
@ -248,34 +255,37 @@ class TaskActivity : SimpleActivity() {
}
}
task_all_day.setOnCheckedChangeListener { _, isChecked -> toggleAllDay(isChecked) }
task_all_day_holder.setOnClickListener {
task_all_day.toggle()
}
binding.apply {
taskAllDay.setOnCheckedChangeListener { _, isChecked -> toggleAllDay(isChecked) }
taskAllDayHolder.setOnClickListener {
taskAllDay.toggle()
}
task_date.setOnClickListener { setupDate() }
task_time.setOnClickListener { setupTime() }
task_type_holder.setOnClickListener { showEventTypeDialog() }
task_repetition.setOnClickListener { showRepeatIntervalDialog() }
task_repetition_rule_holder.setOnClickListener { showRepetitionRuleDialog() }
task_repetition_limit_holder.setOnClickListener { showRepetitionTypePicker() }
taskDate.setOnClickListener { setupDate() }
taskTime.setOnClickListener { setupTime() }
taskTypeHolder.setOnClickListener { showEventTypeDialog() }
taskRepetition.setOnClickListener { showRepeatIntervalDialog() }
taskRepetitionRuleHolder.setOnClickListener { showRepetitionRuleDialog() }
taskRepetitionLimitHolder.setOnClickListener { showRepetitionTypePicker() }
task_reminder_1.setOnClickListener {
handleNotificationAvailability {
if (config.wasAlarmWarningShown) {
showReminder1Dialog()
} else {
ReminderWarningDialog(this) {
config.wasAlarmWarningShown = true
taskReminder1.setOnClickListener {
handleNotificationAvailability {
if (config.wasAlarmWarningShown) {
showReminder1Dialog()
} else {
ReminderWarningDialog(this@TaskActivity) {
config.wasAlarmWarningShown = true
showReminder1Dialog()
}
}
}
}
taskReminder2.setOnClickListener { showReminder2Dialog() }
taskReminder3.setOnClickListener { showReminder3Dialog() }
taskColorHolder.setOnClickListener { showTaskColorDialog() }
}
task_reminder_2.setOnClickListener { showReminder2Dialog() }
task_reminder_3.setOnClickListener { showReminder3Dialog() }
task_color_holder.setOnClickListener { showTaskColorDialog() }
refreshMenuItems()
setupMarkCompleteButton()
@ -291,7 +301,7 @@ class TaskActivity : SimpleActivity() {
mOriginalStartTS = realStart
mTaskDateTime = Formatter.getDateTimeFromTS(realStart)
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
task_toolbar.title = getString(R.string.edit_task)
binding.taskToolbar.title = getString(R.string.edit_task)
mEventTypeId = mTask.eventType
mReminder1Minutes = mTask.reminder1Minutes
@ -305,9 +315,9 @@ class TaskActivity : SimpleActivity() {
mRepeatRule = mTask.repeatRule
mEventColor = mTask.color
task_title.setText(mTask.title)
task_description.setText(mTask.description)
task_all_day.isChecked = mTask.getIsAllDay()
binding.taskTitle.setText(mTask.title)
binding.taskDescription.setText(mTask.description)
binding.taskAllDay.isChecked = mTask.getIsAllDay()
toggleAllDay(mTask.getIsAllDay())
checkRepeatTexts(mRepeatInterval)
}
@ -318,8 +328,8 @@ class TaskActivity : SimpleActivity() {
mTaskDateTime = dateTime
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
task_title.requestFocus()
task_toolbar.title = getString(R.string.new_task)
binding.taskTitle.requestFocus()
binding.taskToolbar.title = getString(R.string.new_task)
mTask.apply {
this.startTS = mTaskDateTime.seconds()
@ -350,11 +360,11 @@ class TaskActivity : SimpleActivity() {
}
private fun saveTask() {
val newTitle = task_title.value
val newTitle = binding.taskTitle.value
if (newTitle.isEmpty()) {
toast(R.string.title_empty)
runOnUiThread {
task_title.requestFocus()
binding.taskTitle.requestFocus()
}
return
}
@ -367,7 +377,7 @@ class TaskActivity : SimpleActivity() {
}
val reminders = getReminders()
if (!task_all_day.isChecked) {
if (!binding.taskAllDay.isChecked) {
if ((reminders.getOrNull(2)?.minutes ?: 0) < -1) {
reminders.removeAt(2)
}
@ -398,7 +408,7 @@ class TaskActivity : SimpleActivity() {
startTS = mTaskDateTime.withSecondOfMinute(0).withMillisOfSecond(0).seconds()
endTS = startTS
title = newTitle
description = task_description.value
description = binding.taskDescription.value
// migrate completed task to the new completed tasks db
if (!wasRepeatable && mTask.isTaskCompleted()) {
@ -408,7 +418,7 @@ class TaskActivity : SimpleActivity() {
}
}
importId = newImportId
flags = mTask.flags.addBitIf(task_all_day.isChecked, FLAG_ALL_DAY)
flags = mTask.flags.addBitIf(binding.taskAllDay.isChecked, FLAG_ALL_DAY)
lastUpdated = System.currentTimeMillis()
eventType = mEventTypeId
type = TYPE_TASK
@ -433,7 +443,7 @@ class TaskActivity : SimpleActivity() {
storeTask(wasRepeatable)
}
} else {
PermissionRequiredDialog(this, R.string.allow_notifications_reminders)
PermissionRequiredDialog(this, com.simplemobiletools.commons.R.string.allow_notifications_reminders, { openNotificationSettings() })
}
}
} else {
@ -471,55 +481,25 @@ class TaskActivity : SimpleActivity() {
private fun showEditRepeatingTaskDialog() {
EditRepeatingEventDialog(this, isTask = true) {
hideKeyboard()
if (it == null) {
return@EditRepeatingEventDialog
}
when (it) {
EDIT_SELECTED_OCCURRENCE -> {
ensureBackgroundThread {
mTask.apply {
parentId = id!!.toLong()
id = null
repeatRule = 0
repeatInterval = 0
repeatLimit = 0
}
eventsHelper.insertTask(mTask, showToasts = true) {
finish()
}
eventsHelper.editSelectedOccurrence(mTask, true) {
finish()
}
}
EDIT_FUTURE_OCCURRENCES -> {
ensureBackgroundThread {
val taskId = mTask.id!!
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()
}
}
eventsHelper.editFutureOccurrences(mTask, mTaskOccurrenceTS, true) {
finish()
}
}
EDIT_ALL_OCCURRENCES -> {
ensureBackgroundThread {
// Shift the start and end times of the first (original) event based on the changes made
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()
}
EDIT_ALL_OCCURRENCES -> {
eventsHelper.editAllOccurrences(mTask, mOriginalStartTS, showToasts = true) {
finish()
}
}
}
@ -568,7 +548,7 @@ class TaskActivity : SimpleActivity() {
this, getDatePickerDialogTheme(), dateSetListener, mTaskDateTime.year, mTaskDateTime.monthOfYear - 1, mTaskDateTime.dayOfMonth
)
datePicker.datePicker.firstDayOfWeek = if (config.isSundayFirst) Calendar.SUNDAY else Calendar.MONDAY
datePicker.datePicker.firstDayOfWeek = getJavaDayOfWeekFromJoda(config.firstDayOfWeek)
datePicker.show()
}
@ -646,21 +626,21 @@ class TaskActivity : SimpleActivity() {
}
private fun updateDateText() {
task_date.text = Formatter.getDate(this, mTaskDateTime)
binding.taskDate.text = Formatter.getDate(this, mTaskDateTime)
}
private fun updateTimeText() {
task_time.text = Formatter.getTime(this, mTaskDateTime)
binding.taskTime.text = Formatter.getTime(this, mTaskDateTime)
}
private fun toggleAllDay(isChecked: Boolean) {
hideKeyboard()
task_time.beGoneIf(isChecked)
binding.taskTime.beGoneIf(isChecked)
}
private fun setupMarkCompleteButton() {
toggle_mark_complete.setOnClickListener { toggleCompletion() }
toggle_mark_complete.beVisibleIf(mTask.id != null)
binding.toggleMarkComplete.setOnClickListener { toggleCompletion() }
binding.toggleMarkComplete.beVisibleIf(mTask.id != null)
updateTaskCompletedButton()
ensureBackgroundThread {
// the stored value might be incorrect so update it (e.g. user completed the task via notification action before editing)
@ -673,16 +653,16 @@ class TaskActivity : SimpleActivity() {
private fun updateTaskCompletedButton() {
if (mTaskCompleted) {
toggle_mark_complete.background = ContextCompat.getDrawable(this, R.drawable.button_background_stroke)
toggle_mark_complete.setText(R.string.mark_incomplete)
toggle_mark_complete.setTextColor(getProperTextColor())
binding.toggleMarkComplete.background = ContextCompat.getDrawable(this, com.simplemobiletools.commons.R.drawable.button_background_stroke)
binding.toggleMarkComplete.setText(R.string.mark_incomplete)
binding.toggleMarkComplete.setTextColor(getProperTextColor())
} else {
val markCompleteBgColor = if (isWhiteTheme()) {
Color.WHITE
} else {
getProperPrimaryColor()
}
toggle_mark_complete.setTextColor(markCompleteBgColor.getContrastColor())
binding.toggleMarkComplete.setTextColor(markCompleteBgColor.getContrastColor())
}
}
@ -702,12 +682,12 @@ class TaskActivity : SimpleActivity() {
}
private fun updateReminder1Text() {
task_reminder_1.text = getFormattedMinutes(mReminder1Minutes)
binding.taskReminder1.text = getFormattedMinutes(mReminder1Minutes)
}
private fun updateReminder2Text() {
task_reminder_2.apply {
beGoneIf(task_reminder_2.isGone() && mReminder1Minutes == REMINDER_OFF)
binding.taskReminder2.apply {
beGoneIf(isGone() && mReminder1Minutes == REMINDER_OFF)
if (mReminder2Minutes == REMINDER_OFF) {
text = resources.getString(R.string.add_another_reminder)
alpha = 0.4f
@ -719,8 +699,8 @@ class TaskActivity : SimpleActivity() {
}
private fun updateReminder3Text() {
task_reminder_3.apply {
beGoneIf(task_reminder_3.isGone() && (mReminder2Minutes == REMINDER_OFF || mReminder1Minutes == REMINDER_OFF))
binding.taskReminder3.apply {
beGoneIf(isGone() && (mReminder2Minutes == REMINDER_OFF || mReminder1Minutes == REMINDER_OFF))
if (mReminder3Minutes == REMINDER_OFF) {
text = resources.getString(R.string.add_another_reminder)
alpha = 0.4f
@ -783,13 +763,13 @@ class TaskActivity : SimpleActivity() {
val eventType = eventTypesDB.getEventTypeWithId(mEventTypeId)
if (eventType != null) {
runOnUiThread {
task_type.text = eventType.title
binding.taskType.text = eventType.title
updateTaskColorInfo(eventType.color)
}
}
task_color_image.beVisibleIf(eventType != null)
task_color_holder.beVisibleIf(eventType != null)
task_color_divider.beVisibleIf(eventType != null)
binding.taskColorImage.beVisibleIf(eventType != null)
binding.taskColorHolder.beVisibleIf(eventType != null)
binding.taskColorDivider.beVisibleIf(eventType != null)
}
}
@ -822,16 +802,19 @@ class TaskActivity : SimpleActivity() {
} else {
mEventColor
}
task_color.setFillWithStroke(taskColor, getProperBackgroundColor())
binding.taskColor.setFillWithStroke(taskColor, getProperBackgroundColor())
}
private fun updateColors() {
updateTextColors(task_nested_scrollview)
val textColor = getProperTextColor()
arrayOf(
task_time_image, task_reminder_image, task_type_image, task_repetition_image, task_color_image
).forEach {
it.applyColorFilter(textColor)
binding.apply {
updateTextColors(taskNestedScrollview)
val textColor = getProperTextColor()
arrayOf(
taskTimeImage, taskReminderImage, taskTypeImage, taskRepetitionImage, taskColorImage
).forEach {
it.applyColorFilter(textColor)
}
}
}
@ -854,10 +837,10 @@ class TaskActivity : SimpleActivity() {
}
private fun checkRepeatTexts(limit: Int) {
task_repetition_limit_holder.beGoneIf(limit == 0)
binding.taskRepetitionLimitHolder.beGoneIf(limit == 0)
checkRepetitionLimitText()
task_repetition_rule_holder.beVisibleIf(mRepeatInterval.isXWeeklyRepetition() || mRepeatInterval.isXMonthlyRepetition() || mRepeatInterval.isXYearlyRepetition())
binding.taskRepetitionRuleHolder.beVisibleIf(mRepeatInterval.isXWeeklyRepetition() || mRepeatInterval.isXMonthlyRepetition() || mRepeatInterval.isXYearlyRepetition())
checkRepetitionRuleText()
}
@ -874,18 +857,20 @@ class TaskActivity : SimpleActivity() {
}
private fun checkRepetitionLimitText() {
task_repetition_limit.text = when {
binding.taskRepetitionLimit.text = when {
mRepeatLimit == 0L -> {
task_repetition_limit_label.text = getString(R.string.repeat)
binding.taskRepetitionLimitLabel.text = getString(R.string.repeat)
resources.getString(R.string.forever)
}
mRepeatLimit > 0 -> {
task_repetition_limit_label.text = getString(R.string.repeat_till)
binding.taskRepetitionLimitLabel.text = getString(R.string.repeat_till)
val repeatLimitDateTime = Formatter.getDateTimeFromTS(mRepeatLimit)
Formatter.getFullDate(this, repeatLimitDateTime)
}
else -> {
task_repetition_limit_label.text = getString(R.string.repeat)
binding.taskRepetitionLimitLabel.text = getString(R.string.repeat)
"${-mRepeatLimit} ${getString(R.string.times)}"
}
}
@ -897,12 +882,14 @@ class TaskActivity : SimpleActivity() {
mRepeatInterval.isXWeeklyRepetition() -> RepeatRuleWeeklyDialog(this, mRepeatRule) {
setRepeatRule(it)
}
mRepeatInterval.isXMonthlyRepetition() -> {
val items = getAvailableMonthlyRepetitionRules()
RadioGroupDialog(this, items, mRepeatRule) {
setRepeatRule(it as Int)
}
}
mRepeatInterval.isXYearlyRepetition() -> {
val items = getAvailableYearlyRepetitionRules()
RadioGroupDialog(this, items, mRepeatRule) {
@ -1002,7 +989,7 @@ class TaskActivity : SimpleActivity() {
private fun getRepeatXthDayInMonthString(includeBase: Boolean, repeatRule: Int): String {
val weekDayString = getRepeatXthDayString(includeBase, repeatRule)
val monthString = resources.getStringArray(R.array.in_months)[mTaskDateTime.monthOfYear - 1]
val monthString = resources.getStringArray(com.simplemobiletools.commons.R.array.in_months)[mTaskDateTime.monthOfYear - 1]
return "$weekDayString $monthString"
}
@ -1017,21 +1004,27 @@ class TaskActivity : SimpleActivity() {
private fun checkRepetitionRuleText() {
when {
mRepeatInterval.isXWeeklyRepetition() -> {
task_repetition_rule.text = if (mRepeatRule == EVERY_DAY_BIT) getString(R.string.every_day) else getSelectedDaysString(mRepeatRule)
binding.taskRepetitionRule.text = if (mRepeatRule == EVERY_DAY_BIT) {
getString(com.simplemobiletools.commons.R.string.every_day)
} else {
getShortDaysFromBitmask(mRepeatRule)
}
}
mRepeatInterval.isXMonthlyRepetition() -> {
val repeatString = if (mRepeatRule == REPEAT_ORDER_WEEKDAY_USE_LAST || mRepeatRule == REPEAT_ORDER_WEEKDAY)
R.string.repeat else R.string.repeat_on
task_repetition_rule_label.text = getString(repeatString)
task_repetition_rule.text = getMonthlyRepetitionRuleText()
binding.taskRepetitionRuleLabel.text = getString(repeatString)
binding.taskRepetitionRule.text = getMonthlyRepetitionRuleText()
}
mRepeatInterval.isXYearlyRepetition() -> {
val repeatString = if (mRepeatRule == REPEAT_ORDER_WEEKDAY_USE_LAST || mRepeatRule == REPEAT_ORDER_WEEKDAY)
R.string.repeat else R.string.repeat_on
task_repetition_rule_label.text = getString(repeatString)
task_repetition_rule.text = getYearlyRepetitionRuleText()
binding.taskRepetitionRuleLabel.text = getString(repeatString)
binding.taskRepetitionRule.text = getYearlyRepetitionRuleText()
}
}
}
@ -1048,11 +1041,11 @@ class TaskActivity : SimpleActivity() {
}
private fun updateRepetitionText() {
task_repetition.text = getRepetitionText(mRepeatInterval)
binding.taskRepetition.text = getRepetitionText(mRepeatInterval)
}
private fun updateActionBarTitle() {
task_toolbar.title = if (mIsNewTask) {
binding.taskToolbar.title = if (mIsNewTask) {
getString(R.string.new_task)
} else {
getString(R.string.edit_task)

View File

@ -6,14 +6,13 @@ import android.content.Intent
import android.content.res.ColorStateList
import android.graphics.Color
import android.os.Bundle
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.databinding.WidgetConfigDateBinding
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.helpers.Formatter
import com.simplemobiletools.calendar.pro.helpers.MyWidgetDateProvider
import com.simplemobiletools.commons.dialogs.ColorPickerDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.IS_CUSTOMIZING_COLORS
import kotlinx.android.synthetic.main.widget_config_date.*
class WidgetDateConfigureActivity : SimpleActivity() {
private var mBgAlpha = 0f
@ -22,11 +21,13 @@ class WidgetDateConfigureActivity : SimpleActivity() {
private var mBgColor = 0
private var mTextColor = 0
private val binding by viewBinding(WidgetConfigDateBinding::inflate)
public override fun onCreate(savedInstanceState: Bundle?) {
useDynamicTheme = false
super.onCreate(savedInstanceState)
setResult(Activity.RESULT_CANCELED)
setContentView(R.layout.widget_config_date)
setContentView(binding.root)
initVariables()
val isCustomizingColors = intent.extras?.getBoolean(IS_CUSTOMIZING_COLORS) ?: false
@ -37,12 +38,14 @@ class WidgetDateConfigureActivity : SimpleActivity() {
}
val primaryColor = getProperPrimaryColor()
config_save.setOnClickListener { saveConfig() }
config_bg_color.setOnClickListener { pickBackgroundColor() }
config_text_color.setOnClickListener { pickTextColor() }
config_bg_seekbar.setColors(mTextColor, primaryColor, primaryColor)
widget_date_label.text = Formatter.getTodayDayNumber()
widget_month_label.text = Formatter.getCurrentMonthShort()
binding.apply {
configSave.setOnClickListener { saveConfig() }
configBgColor.setOnClickListener { pickBackgroundColor() }
configTextColor.setOnClickListener { pickTextColor() }
configBgSeekbar.setColors(mTextColor, primaryColor, primaryColor)
widgetDateLabel.text = Formatter.getTodayDayNumber()
widgetMonthLabel.text = Formatter.getCurrentMonthShort()
}
}
private fun initVariables() {
@ -50,7 +53,7 @@ class WidgetDateConfigureActivity : SimpleActivity() {
mBgAlpha = Color.alpha(mBgColor) / 255f
mBgColorWithoutTransparency = Color.rgb(Color.red(mBgColor), Color.green(mBgColor), Color.blue(mBgColor))
config_bg_seekbar.apply {
binding.configBgSeekbar.apply {
progress = (mBgAlpha * 100).toInt()
onSeekBarChangeListener { progress ->
@ -61,8 +64,8 @@ class WidgetDateConfigureActivity : SimpleActivity() {
updateBackgroundColor()
mTextColor = config.widgetTextColor
if (mTextColor == resources.getColor(R.color.default_widget_text_color) && config.isUsingSystemTheme) {
mTextColor = resources.getColor(R.color.you_primary_color, theme)
if (mTextColor == resources.getColor(com.simplemobiletools.commons.R.color.default_widget_text_color) && config.isUsingSystemTheme) {
mTextColor = resources.getColor(com.simplemobiletools.commons.R.color.you_primary_color, theme)
}
updateTextColor()
@ -112,16 +115,20 @@ class WidgetDateConfigureActivity : SimpleActivity() {
}
private fun updateTextColor() {
config_text_color.setFillWithStroke(mTextColor, mTextColor)
widget_date_label.setTextColor(mTextColor)
widget_month_label.setTextColor(mTextColor)
config_save.setTextColor(getProperPrimaryColor().getContrastColor())
binding.apply {
configTextColor.setFillWithStroke(mTextColor, mTextColor)
widgetDateLabel.setTextColor(mTextColor)
widgetMonthLabel.setTextColor(mTextColor)
configSave.setTextColor(getProperPrimaryColor().getContrastColor())
}
}
private fun updateBackgroundColor() {
mBgColor = mBgColorWithoutTransparency.adjustAlpha(mBgAlpha)
config_date_time_wrapper.background.applyColorFilter(mBgColor)
config_bg_color.setFillWithStroke(mBgColor, mBgColor)
config_save.backgroundTintList = ColorStateList.valueOf(getProperPrimaryColor())
binding.apply {
configDateTimeWrapper.background.applyColorFilter(mBgColor)
configBgColor.setFillWithStroke(mBgColor, mBgColor)
configSave.backgroundTintList = ColorStateList.valueOf(getProperPrimaryColor())
}
}
}

View File

@ -9,6 +9,7 @@ import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.adapters.EventListAdapter
import com.simplemobiletools.calendar.pro.databinding.WidgetConfigListBinding
import com.simplemobiletools.calendar.pro.dialogs.CustomPeriodPickerDialog
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.extensions.seconds
@ -26,9 +27,8 @@ import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.RadioItem
import kotlinx.android.synthetic.main.widget_config_list.*
import org.joda.time.DateTime
import java.util.*
import java.util.TreeSet
class WidgetListConfigureActivity : SimpleActivity() {
private var mBgAlpha = 0f
@ -38,11 +38,13 @@ class WidgetListConfigureActivity : SimpleActivity() {
private var mTextColor = 0
private var mSelectedPeriodOption = 0
private val binding by viewBinding(WidgetConfigListBinding::inflate)
public override fun onCreate(savedInstanceState: Bundle?) {
useDynamicTheme = false
super.onCreate(savedInstanceState)
setResult(Activity.RESULT_CANCELED)
setContentView(R.layout.widget_config_list)
setContentView(binding.root)
initVariables()
val isCustomizingColors = intent.extras?.getBoolean(IS_CUSTOMIZING_COLORS) ?: false
@ -52,23 +54,25 @@ class WidgetListConfigureActivity : SimpleActivity() {
finish()
}
EventListAdapter(this, getListItems(), false, null, config_events_list) {}.apply {
updateTextColor(mTextColor)
config_events_list.adapter = this
binding.apply {
EventListAdapter(this@WidgetListConfigureActivity, getListItems(), false, null, configEventsList) {}.apply {
updateTextColor(mTextColor)
configEventsList.adapter = this
}
periodPickerHolder.background = ColorDrawable(getProperBackgroundColor())
periodPickerValue.setOnClickListener { showPeriodSelector() }
configSave.setOnClickListener { saveConfig() }
configBgColor.setOnClickListener { pickBackgroundColor() }
configTextColor.setOnClickListener { pickTextColor() }
periodPickerHolder.beGoneIf(isCustomizingColors)
val primaryColor = getProperPrimaryColor()
configBgSeekbar.setColors(mTextColor, primaryColor, primaryColor)
}
period_picker_holder.background = ColorDrawable(getProperBackgroundColor())
period_picker_value.setOnClickListener { showPeriodSelector() }
config_save.setOnClickListener { saveConfig() }
config_bg_color.setOnClickListener { pickBackgroundColor() }
config_text_color.setOnClickListener { pickTextColor() }
period_picker_holder.beGoneIf(isCustomizingColors)
val primaryColor = getProperPrimaryColor()
config_bg_seekbar.setColors(mTextColor, primaryColor, primaryColor)
updateSelectedPeriod(config.lastUsedEventSpan)
}
@ -77,7 +81,7 @@ class WidgetListConfigureActivity : SimpleActivity() {
mBgAlpha = Color.alpha(mBgColor) / 255f
mBgColorWithoutTransparency = Color.rgb(Color.red(mBgColor), Color.green(mBgColor), Color.blue(mBgColor))
config_bg_seekbar.apply {
binding.configBgSeekbar.apply {
progress = (mBgAlpha * 100).toInt()
onSeekBarChangeListener { progress ->
@ -88,8 +92,8 @@ class WidgetListConfigureActivity : SimpleActivity() {
updateBackgroundColor()
mTextColor = config.widgetTextColor
if (mTextColor == resources.getColor(R.color.default_widget_text_color) && config.isUsingSystemTheme) {
mTextColor = resources.getColor(R.color.you_primary_color, theme)
if (mTextColor == resources.getColor(com.simplemobiletools.commons.R.color.default_widget_text_color) && config.isUsingSystemTheme) {
mTextColor = resources.getColor(com.simplemobiletools.commons.R.color.you_primary_color, theme)
}
updateTextColor()
@ -155,10 +159,11 @@ class WidgetListConfigureActivity : SimpleActivity() {
when (selectedPeriod) {
0 -> {
mSelectedPeriodOption = YEAR_SECONDS
period_picker_value.setText(R.string.within_the_next_one_year)
binding.periodPickerValue.setText(R.string.within_the_next_one_year)
}
EVENT_PERIOD_TODAY -> period_picker_value.setText(R.string.today_only)
else -> period_picker_value.text = getFormattedSeconds(mSelectedPeriodOption)
EVENT_PERIOD_TODAY -> binding.periodPickerValue.setText(R.string.today_only)
else -> binding.periodPickerValue.text = getFormattedSeconds(mSelectedPeriodOption)
}
}
@ -206,16 +211,16 @@ class WidgetListConfigureActivity : SimpleActivity() {
}
private fun updateTextColor() {
(config_events_list.adapter as? EventListAdapter)?.updateTextColor(mTextColor)
config_text_color.setFillWithStroke(mTextColor, mTextColor)
config_save.setTextColor(getProperPrimaryColor().getContrastColor())
(binding.configEventsList.adapter as? EventListAdapter)?.updateTextColor(mTextColor)
binding.configTextColor.setFillWithStroke(mTextColor, mTextColor)
binding.configSave.setTextColor(getProperPrimaryColor().getContrastColor())
}
private fun updateBackgroundColor() {
mBgColor = mBgColorWithoutTransparency.adjustAlpha(mBgAlpha)
config_events_list.background.applyColorFilter(mBgColor)
config_bg_color.setFillWithStroke(mBgColor, mBgColor)
config_save.backgroundTintList = ColorStateList.valueOf(getProperPrimaryColor())
binding.configEventsList.background.applyColorFilter(mBgColor)
binding.configBgColor.setFillWithStroke(mBgColor, mBgColor)
binding.configSave.backgroundTintList = ColorStateList.valueOf(getProperPrimaryColor())
}
private fun getListItems(): ArrayList<ListItem> {
@ -227,36 +232,24 @@ class WidgetListConfigureActivity : SimpleActivity() {
var time = dateTime.withHourOfDay(7)
listItems.add(
ListEvent(
1,
time.seconds(),
time.plusMinutes(30).seconds(),
getString(R.string.sample_title_1),
getString(R.string.sample_description_1),
false,
getProperPrimaryColor(),
"",
false,
false,
false,
false
ListEvent.empty.copy(
id = 1,
startTS = time.seconds(),
endTS = time.plusMinutes(30).seconds(),
title = getString(R.string.sample_title_1),
description = getString(R.string.sample_description_1),
color = getProperPrimaryColor(),
)
)
time = dateTime.withHourOfDay(8)
listItems.add(
ListEvent(
2,
time.seconds(),
time.plusHours(1).seconds(),
getString(R.string.sample_title_2),
getString(R.string.sample_description_2),
false,
getProperPrimaryColor(),
"",
false,
false,
false,
false
ListEvent.empty.copy(
id = 2,
startTS = time.seconds(),
endTS = time.plusHours(1).seconds(),
title = getString(R.string.sample_title_2),
description = getString(R.string.sample_description_2),
color = getProperPrimaryColor(),
)
)
@ -267,53 +260,35 @@ class WidgetListConfigureActivity : SimpleActivity() {
time = dateTime.withHourOfDay(8)
listItems.add(
ListEvent(
3,
time.seconds(),
time.plusHours(1).seconds(),
getString(R.string.sample_title_3),
"",
false,
getProperPrimaryColor(),
"",
false,
false,
false,
false
ListEvent.empty.copy(
id = 3,
startTS = time.seconds(),
endTS = time.plusHours(1).seconds(),
title = getString(R.string.sample_title_3),
description = "",
color = getProperPrimaryColor(),
)
)
time = dateTime.withHourOfDay(13)
listItems.add(
ListEvent(
4,
time.seconds(),
time.plusHours(1).seconds(),
getString(R.string.sample_title_4),
getString(R.string.sample_description_4),
false,
getProperPrimaryColor(),
"",
false,
false,
false,
false
ListEvent.empty.copy(
id = 4,
startTS = time.seconds(),
endTS = time.plusHours(1).seconds(),
title = getString(R.string.sample_title_4),
description = getString(R.string.sample_description_4),
color = getProperPrimaryColor(),
)
)
time = dateTime.withHourOfDay(18)
listItems.add(
ListEvent(
5,
time.seconds(),
time.plusMinutes(10).seconds(),
getString(R.string.sample_title_5),
"",
false,
getProperPrimaryColor(),
"",
false,
false,
false,
false
ListEvent.empty.copy(
id = 5,
startTS = time.seconds(),
endTS = time.plusMinutes(10).seconds(),
title = getString(R.string.sample_title_5),
description = "",
color = getProperPrimaryColor(),
)
)

View File

@ -1,5 +1,6 @@
package com.simplemobiletools.calendar.pro.activities
import android.annotation.SuppressLint
import android.app.Activity
import android.appwidget.AppWidgetManager
import android.content.Context
@ -8,32 +9,26 @@ import android.content.res.ColorStateList
import android.graphics.Color
import android.os.Bundle
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.TextView
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.databinding.DayMonthlyNumberViewBinding
import com.simplemobiletools.calendar.pro.databinding.TopNavigationBinding
import com.simplemobiletools.calendar.pro.databinding.WidgetConfigMonthlyBinding
import com.simplemobiletools.calendar.pro.extensions.addDayEvents
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.extensions.isWeekendIndex
import com.simplemobiletools.calendar.pro.helpers.MonthlyCalendarImpl
import com.simplemobiletools.calendar.pro.helpers.MyWidgetMonthlyProvider
import com.simplemobiletools.calendar.pro.helpers.isWeekend
import com.simplemobiletools.calendar.pro.interfaces.MonthlyCalendar
import com.simplemobiletools.calendar.pro.models.DayMonthly
import com.simplemobiletools.commons.dialogs.ColorPickerDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.IS_CUSTOMIZING_COLORS
import com.simplemobiletools.commons.helpers.LOWER_ALPHA
import kotlinx.android.synthetic.main.day_monthly_number_view.view.*
import kotlinx.android.synthetic.main.first_row.*
import kotlinx.android.synthetic.main.top_navigation.*
import kotlinx.android.synthetic.main.widget_config_monthly.*
import org.joda.time.DateTime
class WidgetMonthlyConfigureActivity : SimpleActivity(), MonthlyCalendar {
private var mDays: List<DayMonthly>? = null
private var dayLabelHeight = 0
private var mBgAlpha = 0f
private var mWidgetId = 0
@ -41,11 +36,14 @@ class WidgetMonthlyConfigureActivity : SimpleActivity(), MonthlyCalendar {
private var mBgColor = 0
private var mTextColor = 0
private val binding by viewBinding(WidgetConfigMonthlyBinding::inflate)
private val topNavigationBinding by lazy { TopNavigationBinding.bind(binding.root) }
public override fun onCreate(savedInstanceState: Bundle?) {
useDynamicTheme = false
super.onCreate(savedInstanceState)
setResult(Activity.RESULT_CANCELED)
setContentView(R.layout.widget_config_monthly)
setContentView(binding.root)
initVariables()
val isCustomizingColors = intent.extras?.getBoolean(IS_CUSTOMIZING_COLORS) ?: false
@ -56,10 +54,12 @@ class WidgetMonthlyConfigureActivity : SimpleActivity(), MonthlyCalendar {
}
val primaryColor = getProperPrimaryColor()
config_save.setOnClickListener { saveConfig() }
config_bg_color.setOnClickListener { pickBackgroundColor() }
config_text_color.setOnClickListener { pickTextColor() }
config_bg_seekbar.setColors(mTextColor, primaryColor, primaryColor)
binding.apply {
configSave.setOnClickListener { saveConfig() }
configBgColor.setOnClickListener { pickBackgroundColor() }
configTextColor.setOnClickListener { pickTextColor() }
configBgSeekbar.setColors(mTextColor, primaryColor, primaryColor)
}
}
private fun initVariables() {
@ -67,7 +67,7 @@ class WidgetMonthlyConfigureActivity : SimpleActivity(), MonthlyCalendar {
mBgAlpha = Color.alpha(mBgColor) / 255f
mBgColorWithoutTransparency = Color.rgb(Color.red(mBgColor), Color.green(mBgColor), Color.blue(mBgColor))
config_bg_seekbar.apply {
binding.configBgSeekbar.apply {
progress = (mBgAlpha * 100).toInt()
onSeekBarChangeListener { progress ->
@ -78,8 +78,8 @@ class WidgetMonthlyConfigureActivity : SimpleActivity(), MonthlyCalendar {
updateBackgroundColor()
mTextColor = config.widgetTextColor
if (mTextColor == resources.getColor(R.color.default_widget_text_color) && config.isUsingSystemTheme) {
mTextColor = resources.getColor(R.color.you_primary_color, theme)
if (mTextColor == resources.getColor(com.simplemobiletools.commons.R.color.default_widget_text_color) && config.isUsingSystemTheme) {
mTextColor = resources.getColor(com.simplemobiletools.commons.R.color.you_primary_color, theme)
}
updateTextColor()
@ -132,75 +132,82 @@ class WidgetMonthlyConfigureActivity : SimpleActivity(), MonthlyCalendar {
}
private fun updateTextColor() {
top_left_arrow.applyColorFilter(mTextColor)
top_right_arrow.applyColorFilter(mTextColor)
top_value.setTextColor(mTextColor)
config_text_color.setFillWithStroke(mTextColor, mTextColor)
topNavigationBinding.topLeftArrow.applyColorFilter(mTextColor)
topNavigationBinding.topRightArrow.applyColorFilter(mTextColor)
topNavigationBinding.topValue.setTextColor(mTextColor)
binding.configTextColor.setFillWithStroke(mTextColor, mTextColor)
binding.configSave.setTextColor(getProperPrimaryColor().getContrastColor())
updateLabels()
config_save.setTextColor(getProperPrimaryColor().getContrastColor())
}
private fun updateBackgroundColor() {
mBgColor = mBgColorWithoutTransparency.adjustAlpha(mBgAlpha)
config_calendar.background.applyColorFilter(mBgColor)
config_bg_color.setFillWithStroke(mBgColor, mBgColor)
config_save.backgroundTintList = ColorStateList.valueOf(getProperPrimaryColor())
binding.configCalendar.root.background.applyColorFilter(mBgColor)
binding.configBgColor.setFillWithStroke(mBgColor, mBgColor)
binding.configSave.backgroundTintList = ColorStateList.valueOf(getProperPrimaryColor())
}
private fun updateDays() {
val len = mDays!!.size
val daysLength = mDays!!.size
binding.configCalendar.apply {
if (config.showWeekNumbers) {
firstRow.weekNum.setTextColor(mTextColor)
firstRow.weekNum.beVisible()
if (config.showWeekNumbers) {
week_num.setTextColor(mTextColor)
week_num.beVisible()
for (i in 0..5) {
findViewById<TextView>(resources.getIdentifier("week_num_$i", "id", packageName)).apply {
text = "${mDays!![i * 7 + 3].weekOfYear}:"
setTextColor(mTextColor)
beVisible()
arrayOf(weekNum0, weekNum1, weekNum2, weekNum3, weekNum4, weekNum5).forEachIndexed { index, textView ->
textView.apply {
@SuppressLint("SetTextI18n")
text = "${mDays!![index * 7 + 3].weekOfYear}:"
setTextColor(mTextColor)
beVisible()
}
}
}
}
val dividerMargin = resources.displayMetrics.density.toInt()
for (i in 0 until len) {
findViewById<LinearLayout>(resources.getIdentifier("day_$i", "id", packageName)).apply {
val dividerMargin = resources.displayMetrics.density.toInt()
val dayViews = arrayOf(
day0, day1, day2, day3, day4, day5, day6, day7, day8, day9, day10, day11, day12, day13,
day14, day15, day16, day17, day18, day19, day20, day21, day22, day23, day24, day25, day26, day27,
day28, day29, day30, day31, day32, day33, day34, day35, day36, day37, day38, day39, day40, day41
)
for (i in 0 until daysLength) {
val day = mDays!![i]
removeAllViews()
val dayTextColor = if (config.highlightWeekends && day.isWeekend) {
config.highlightWeekendsColor
} else {
mTextColor
}
addDayNumber(dayTextColor, day, this, dayLabelHeight) { dayLabelHeight = it }
context.addDayEvents(day, this, resources, dividerMargin)
dayViews[i].apply {
removeAllViews()
addDayNumber(dayTextColor, day, this)
context.addDayEvents(day, this, resources, dividerMargin)
}
}
}
}
private fun addDayNumber(rawTextColor: Int, day: DayMonthly, linearLayout: LinearLayout, dayLabelHeight: Int, callback: (Int) -> Unit) {
private fun addDayNumber(rawTextColor: Int, day: DayMonthly, linearLayout: LinearLayout) {
var textColor = rawTextColor
if (!day.isThisMonth) {
textColor = textColor.adjustAlpha(LOWER_ALPHA)
}
(View.inflate(this, R.layout.day_monthly_number_view, null) as RelativeLayout).apply {
layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
linearLayout.addView(this)
DayMonthlyNumberViewBinding.inflate(layoutInflater).apply {
root.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
linearLayout.addView(root)
day_monthly_number_background.beVisibleIf(day.isToday)
day_monthly_number_id.apply {
dayMonthlyNumberBackground.beVisibleIf(day.isToday)
dayMonthlyNumberId.apply {
setTextColor(textColor)
text = day.value.toString()
gravity = Gravity.TOP or Gravity.CENTER_HORIZONTAL
}
if (day.isToday) {
day_monthly_number_background.setColorFilter(getProperPrimaryColor())
day_monthly_number_id.setTextColor(getProperPrimaryColor().getContrastColor())
dayMonthlyNumberBackground.setColorFilter(getProperPrimaryColor())
dayMonthlyNumberId.setTextColor(getProperPrimaryColor().getContrastColor())
}
}
}
@ -208,22 +215,22 @@ class WidgetMonthlyConfigureActivity : SimpleActivity(), MonthlyCalendar {
override fun updateMonthlyCalendar(context: Context, month: String, days: ArrayList<DayMonthly>, checkedEvents: Boolean, currTargetDate: DateTime) {
runOnUiThread {
mDays = days
top_value.text = month
topNavigationBinding.topValue.text = month
updateDays()
}
}
private fun updateLabels() {
val weekendsTextColor = config.highlightWeekendsColor
for (i in 0..6) {
findViewById<TextView>(resources.getIdentifier("label_$i", "id", packageName)).apply {
val textColor = if (config.highlightWeekends && isWeekend(i, config.isSundayFirst)) {
binding.configCalendar.firstRow.apply {
arrayOf(label0, label1, label2, label3, label4, label5, label6).forEachIndexed { index, textView ->
val textColor = if (config.highlightWeekends && isWeekendIndex(index)) {
weekendsTextColor
} else {
mTextColor
}
setTextColor(textColor)
textView.setTextColor(textColor)
}
}
}

View File

@ -1,42 +1,46 @@
package com.simplemobiletools.calendar.pro.adapters
import android.graphics.drawable.BitmapDrawable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.Filter
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
import com.simplemobiletools.calendar.pro.databinding.ItemAutocompleteTitleSubtitleBinding
import com.simplemobiletools.calendar.pro.models.Attendee
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.extensions.normalizeString
import com.simplemobiletools.commons.helpers.SimpleContactsHelper
import kotlinx.android.synthetic.main.item_autocomplete_email_name.view.*
class AutoCompleteTextViewAdapter(val activity: SimpleActivity, val contacts: ArrayList<Attendee>) : ArrayAdapter<Attendee>(activity, 0, contacts) {
class AutoCompleteTextViewAdapter(val activity: SimpleActivity, val attendees: ArrayList<Attendee>) : ArrayAdapter<Attendee>(activity, 0, attendees) {
var resultList = ArrayList<Attendee>()
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val contact = resultList[position]
val attendee = resultList[position]
val attendeeHasName = attendee.name.isNotEmpty()
var listItem = convertView
if (listItem == null || listItem.tag != contact.name.isNotEmpty()) {
val layout = if (contact.name.isNotEmpty()) R.layout.item_autocomplete_email_name else R.layout.item_autocomplete_email
listItem = LayoutInflater.from(activity).inflate(layout, parent, false)
if (listItem == null || listItem.tag != attendeeHasName) {
listItem = ItemAutocompleteTitleSubtitleBinding.inflate(activity.layoutInflater, parent, false).root
}
val nameToUse = when {
contact.name.isNotEmpty() -> contact.name
contact.email.isNotEmpty() -> contact.email
attendee.name.isNotEmpty() -> attendee.name
attendee.email.isNotEmpty() -> attendee.email
else -> "A"
}
val placeholder = BitmapDrawable(activity.resources, SimpleContactsHelper(context).getContactLetterIcon(nameToUse))
listItem!!.apply {
tag = contact.name.isNotEmpty()
item_autocomplete_name?.text = contact.name
item_autocomplete_email?.text = contact.email
listItem.tag = attendeeHasName
ItemAutocompleteTitleSubtitleBinding.bind(listItem).apply {
itemAutocompleteTitle.text = if (attendeeHasName) {
attendee.name
} else {
attendee.email
}
contact.updateImage(context, item_autocomplete_image, placeholder)
itemAutocompleteSubtitle.text = attendee.email
itemAutocompleteSubtitle.beVisibleIf(attendeeHasName)
attendee.updateImage(context, itemAutocompleteImage, placeholder)
}
return listItem
@ -44,31 +48,35 @@ class AutoCompleteTextViewAdapter(val activity: SimpleActivity, val contacts: Ar
override fun getFilter() = object : Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults {
val filterResults = Filter.FilterResults()
val filterResults = FilterResults()
if (constraint != null) {
resultList.clear()
val results = mutableListOf<Attendee>()
val searchString = constraint.toString().normalizeString()
contacts.forEach {
attendees.forEach {
if (it.email.contains(searchString, true) || it.name.contains(searchString, true)) {
resultList.add(it)
results.add(it)
}
}
resultList.sortWith(compareBy<Attendee>
results.sortWith(compareBy<Attendee>
{ it.name.startsWith(searchString, true) }.thenBy
{ it.email.startsWith(searchString, true) }.thenBy
{ it.name.contains(searchString, true) }.thenBy
{ it.email.contains(searchString, true) })
resultList.reverse()
results.reverse()
filterResults.values = resultList
filterResults.count = resultList.size
filterResults.values = results
filterResults.count = results.size
}
return filterResults
}
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
if (results?.count ?: -1 > 0) {
resultList.clear()
if (results != null && results.count > 0) {
@Suppress("UNCHECKED_CAST")
resultList.addAll(results.values as List<Attendee>)
notifyDataSetChanged()
} else {
notifyDataSetInvalidated()

View File

@ -3,20 +3,18 @@ package com.simplemobiletools.calendar.pro.adapters
import android.app.Activity
import android.content.res.ColorStateList
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.databinding.CheckableColorButtonBinding
import com.simplemobiletools.commons.extensions.applyColorFilter
import kotlinx.android.synthetic.main.checkable_color_button.view.*
class CheckableColorAdapter(private val activity: Activity, private val colors: IntArray, var currentColor: Int, val callback: (color: Int) -> Unit) :
RecyclerView.Adapter<CheckableColorAdapter.CheckableColorViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CheckableColorViewHolder {
val itemView = LayoutInflater.from(activity).inflate(R.layout.checkable_color_button, parent, false)
return CheckableColorViewHolder(itemView)
return CheckableColorViewHolder(
binding = CheckableColorButtonBinding.inflate(activity.layoutInflater, parent, false)
)
}
override fun onBindViewHolder(holder: CheckableColorViewHolder, position: Int) {
@ -31,17 +29,17 @@ class CheckableColorAdapter(private val activity: Activity, private val colors:
callback(color)
}
inner class CheckableColorViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
inner class CheckableColorViewHolder(val binding: CheckableColorButtonBinding) : RecyclerView.ViewHolder(binding.root) {
fun bindView(color: Int, checked: Boolean) {
itemView.checkable_color_button.apply {
binding.checkableColorButton.apply {
backgroundTintList = ColorStateList.valueOf(color)
setOnClickListener {
updateSelection(color)
}
if (checked) {
setImageResource(R.drawable.ic_check_vector)
setImageResource(com.simplemobiletools.commons.R.drawable.ic_check_vector)
applyColorFilter(Color.WHITE)
} else {
setImageDrawable(null)

View File

@ -6,6 +6,7 @@ import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
import com.simplemobiletools.calendar.pro.databinding.EventListItemBinding
import com.simplemobiletools.calendar.pro.dialogs.DeleteEventDialog
import com.simplemobiletools.calendar.pro.extensions.*
import com.simplemobiletools.calendar.pro.helpers.Formatter
@ -18,7 +19,6 @@ import com.simplemobiletools.commons.extensions.getProperTextColor
import com.simplemobiletools.commons.helpers.MEDIUM_ALPHA
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.views.MyRecyclerView
import kotlinx.android.synthetic.main.event_list_item.view.*
class DayEventsAdapter(activity: SimpleActivity, val events: ArrayList<Event>, recyclerView: MyRecyclerView, var dayCode: String, itemClick: (Any) -> Unit) :
MyRecyclerViewAdapter(activity, recyclerView, itemClick) {
@ -29,7 +29,7 @@ class DayEventsAdapter(activity: SimpleActivity, val events: ArrayList<Event>, r
private val dimPastEvents = activity.config.dimPastEvents
private val dimCompletedTasks = activity.config.dimCompletedTasks
private var isPrintVersion = false
private val mediumMargin = activity.resources.getDimension(R.dimen.medium_margin).toInt()
private val mediumMargin = activity.resources.getDimension(com.simplemobiletools.commons.R.dimen.medium_margin).toInt()
init {
setupDragListener(true)
@ -58,11 +58,15 @@ class DayEventsAdapter(activity: SimpleActivity, val events: ArrayList<Event>, r
override fun onActionModeDestroyed() {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.event_list_item, parent)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return createViewHolder(
view = EventListItemBinding.inflate(activity.layoutInflater, parent, false).root
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val event = events[position]
holder.bindView(event, true, true) { itemView, layoutPosition ->
holder.bindView(event, allowSingleClick = true, allowLongClick = true) { itemView, _ ->
setupView(itemView, event)
}
bindViewHolder(holder)
@ -73,7 +77,7 @@ class DayEventsAdapter(activity: SimpleActivity, val events: ArrayList<Event>, r
fun togglePrintMode() {
isPrintVersion = !isPrintVersion
textColor = if (isPrintVersion) {
resources.getColor(R.color.theme_light_text_color)
resources.getColor(com.simplemobiletools.commons.R.color.theme_light_text_color)
} else {
activity.getProperTextColor()
}
@ -82,12 +86,12 @@ class DayEventsAdapter(activity: SimpleActivity, val events: ArrayList<Event>, r
}
private fun setupView(view: View, event: Event) {
view.apply {
event_item_holder.isSelected = selectedKeys.contains(event.id?.toInt())
event_item_holder.background.applyColorFilter(textColor)
event_item_title.text = event.title
event_item_title.checkViewStrikeThrough(event.isTaskCompleted())
event_item_time.text = if (event.getIsAllDay()) allDayString else Formatter.getTimeFromTS(context, event.startTS)
EventListItemBinding.bind(view).apply {
eventItemHolder.isSelected = selectedKeys.contains(event.id?.toInt())
eventItemHolder.background.applyColorFilter(textColor)
eventItemTitle.text = event.title
eventItemTitle.checkViewStrikeThrough(event.shouldStrikeThrough())
eventItemTime.text = if (event.getIsAllDay()) allDayString else Formatter.getTimeFromTS(activity, event.startTS)
if (event.startTS != event.endTS) {
val startDayCode = Formatter.getDayCodeFromTS(event.startTS)
val endDayCode = Formatter.getDayCodeFromTS(event.endTS)
@ -95,19 +99,18 @@ class DayEventsAdapter(activity: SimpleActivity, val events: ArrayList<Event>, r
val endDate = Formatter.getDayTitle(activity, endDayCode, false)
val startDayString = if (startDayCode != dayCode) " ($startDate)" else ""
if (!event.getIsAllDay()) {
val endTimeString = Formatter.getTimeFromTS(context, event.endTS)
val endTimeString = Formatter.getTimeFromTS(activity, event.endTS)
val endDayString = if (endDayCode != dayCode) " ($endDate)" else ""
event_item_time.text = "${event_item_time.text}$startDayString - $endTimeString$endDayString"
}
else {
eventItemTime.text = "${eventItemTime.text}$startDayString - $endTimeString$endDayString"
} else {
val endDayString = if (endDayCode != dayCode) " - ($endDate)" else ""
event_item_time.text = "${event_item_time.text}$startDayString$endDayString"
eventItemTime.text = "${eventItemTime.text}$startDayString$endDayString"
}
}
event_item_description.text = if (replaceDescriptionWithLocation) event.location else event.description.replace("\n", " ")
event_item_description.beVisibleIf(displayDescription && event_item_description.text.isNotEmpty())
event_item_color_bar.background.applyColorFilter(event.color)
eventItemDescription.text = if (replaceDescriptionWithLocation) event.location else event.description.replace("\n", " ")
eventItemDescription.beVisibleIf(displayDescription && eventItemDescription.text.isNotEmpty())
eventItemColorBar.background.applyColorFilter(event.color)
var newTextColor = textColor
@ -121,11 +124,11 @@ class DayEventsAdapter(activity: SimpleActivity, val events: ArrayList<Event>, r
newTextColor = newTextColor.adjustAlpha(MEDIUM_ALPHA)
}
event_item_time.setTextColor(newTextColor)
event_item_title.setTextColor(newTextColor)
event_item_description?.setTextColor(newTextColor)
event_item_task_image.applyColorFilter(newTextColor)
event_item_task_image.beVisibleIf(event.isTask())
eventItemTime.setTextColor(newTextColor)
eventItemTitle.setTextColor(newTextColor)
eventItemDescription.setTextColor(newTextColor)
eventItemTaskImage.applyColorFilter(newTextColor)
eventItemTaskImage.beVisibleIf(event.isTask())
val startMargin = if (event.isTask()) {
0
@ -133,7 +136,7 @@ class DayEventsAdapter(activity: SimpleActivity, val events: ArrayList<Event>, r
mediumMargin
}
(event_item_title.layoutParams as ConstraintLayout.LayoutParams).marginStart = startMargin
(eventItemTitle.layoutParams as ConstraintLayout.LayoutParams).marginStart = startMargin
}
}

View File

@ -6,6 +6,9 @@ import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
import com.simplemobiletools.calendar.pro.databinding.EventListItemBinding
import com.simplemobiletools.calendar.pro.databinding.EventListSectionDayBinding
import com.simplemobiletools.calendar.pro.databinding.EventListSectionMonthBinding
import com.simplemobiletools.calendar.pro.dialogs.DeleteEventDialog
import com.simplemobiletools.calendar.pro.extensions.*
import com.simplemobiletools.calendar.pro.helpers.*
@ -22,8 +25,6 @@ import com.simplemobiletools.commons.helpers.MEDIUM_ALPHA
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
import com.simplemobiletools.commons.views.MyRecyclerView
import kotlinx.android.synthetic.main.event_list_item.view.*
import kotlinx.android.synthetic.main.event_list_section_day.view.*
class EventListAdapter(
activity: SimpleActivity, var listItems: ArrayList<ListItem>, val allowLongClick: Boolean, val listener: RefreshRecyclerViewListener?,
@ -39,7 +40,7 @@ class EventListAdapter(
private var use24HourFormat = activity.config.use24HourFormat
private var currentItemsHash = listItems.hashCode()
private var isPrintVersion = false
private val mediumMargin = activity.resources.getDimension(R.dimen.medium_margin).toInt()
private val mediumMargin = activity.resources.getDimension(com.simplemobiletools.commons.R.dimen.medium_margin).toInt()
init {
setupDragListener(true)
@ -75,17 +76,19 @@ class EventListAdapter(
override fun onActionModeDestroyed() {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyRecyclerViewAdapter.ViewHolder {
val layoutId = when (viewType) {
ITEM_SECTION_DAY -> R.layout.event_list_section_day
ITEM_SECTION_MONTH -> R.layout.event_list_section_month
else -> R.layout.event_list_item
val layoutInflater = activity.layoutInflater
val binding = when (viewType) {
ITEM_SECTION_DAY -> EventListSectionDayBinding.inflate(layoutInflater, parent, false)
ITEM_SECTION_MONTH -> EventListSectionMonthBinding.inflate(layoutInflater, parent, false)
else -> EventListItemBinding.inflate(layoutInflater, parent, false)
}
return createViewHolder(layoutId, parent)
return createViewHolder(binding.root)
}
override fun onBindViewHolder(holder: MyRecyclerViewAdapter.ViewHolder, position: Int) {
val listItem = listItems[position]
holder.bindView(listItem, true, allowLongClick && listItem is ListEvent) { itemView, layoutPosition ->
holder.bindView(listItem, allowSingleClick = true, allowLongClick = allowLongClick && listItem is ListEvent) { itemView, _ ->
when (listItem) {
is ListSectionDay -> setupListSectionDay(itemView, listItem)
is ListEvent -> setupListEvent(itemView, listItem)
@ -121,7 +124,7 @@ class EventListAdapter(
fun togglePrintMode() {
isPrintVersion = !isPrintVersion
textColor = if (isPrintVersion) {
resources.getColor(R.color.theme_light_text_color)
resources.getColor(com.simplemobiletools.commons.R.color.theme_light_text_color)
} else {
activity.getProperTextColor()
}
@ -129,27 +132,27 @@ class EventListAdapter(
}
private fun setupListEvent(view: View, listEvent: ListEvent) {
view.apply {
event_item_holder.isSelected = selectedKeys.contains(listEvent.hashCode())
event_item_holder.background.applyColorFilter(textColor)
event_item_title.text = listEvent.title
event_item_title.checkViewStrikeThrough(listEvent.isTaskCompleted)
event_item_time.text = if (listEvent.isAllDay) allDayString else Formatter.getTimeFromTS(context, listEvent.startTS)
EventListItemBinding.bind(view).apply {
eventItemHolder.isSelected = selectedKeys.contains(listEvent.hashCode())
eventItemHolder.background.applyColorFilter(textColor)
eventItemTitle.text = listEvent.title
eventItemTitle.checkViewStrikeThrough(listEvent.shouldStrikeThrough())
eventItemTime.text = if (listEvent.isAllDay) allDayString else Formatter.getTimeFromTS(activity, listEvent.startTS)
if (listEvent.startTS != listEvent.endTS) {
if (!listEvent.isAllDay) {
event_item_time.text = "${event_item_time.text} - ${Formatter.getTimeFromTS(context, listEvent.endTS)}"
eventItemTime.text = "${eventItemTime.text} - ${Formatter.getTimeFromTS(activity, listEvent.endTS)}"
}
val startCode = Formatter.getDayCodeFromTS(listEvent.startTS)
val endCode = Formatter.getDayCodeFromTS(listEvent.endTS)
if (startCode != endCode) {
event_item_time.text = "${event_item_time.text} (${Formatter.getDateDayTitle(endCode)})"
eventItemTime.text = "${eventItemTime.text} (${Formatter.getDateDayTitle(endCode)})"
}
}
event_item_description.text = if (replaceDescription) listEvent.location else listEvent.description.replace("\n", " ")
event_item_description.beVisibleIf(displayDescription && event_item_description.text.isNotEmpty())
event_item_color_bar.background.applyColorFilter(listEvent.color)
eventItemDescription.text = if (replaceDescription) listEvent.location else listEvent.description.replace("\n", " ")
eventItemDescription.beVisibleIf(displayDescription && eventItemDescription.text.isNotEmpty())
eventItemColorBar.background.applyColorFilter(listEvent.color)
var newTextColor = textColor
if (listEvent.isAllDay || listEvent.startTS <= now && listEvent.endTS <= now) {
@ -169,23 +172,24 @@ class EventListAdapter(
newTextColor = properPrimaryColor
}
event_item_time.setTextColor(newTextColor)
event_item_title.setTextColor(newTextColor)
event_item_description.setTextColor(newTextColor)
event_item_task_image.applyColorFilter(newTextColor)
event_item_task_image.beVisibleIf(listEvent.isTask)
eventItemTime.setTextColor(newTextColor)
eventItemTitle.setTextColor(newTextColor)
eventItemDescription.setTextColor(newTextColor)
eventItemTaskImage.applyColorFilter(newTextColor)
eventItemTaskImage.beVisibleIf(listEvent.isTask)
val startMargin = if (listEvent.isTask) {
0
} else {
mediumMargin
}
(event_item_title.layoutParams as ConstraintLayout.LayoutParams).marginStart = startMargin
(eventItemTitle.layoutParams as ConstraintLayout.LayoutParams).marginStart = startMargin
}
}
private fun setupListSectionDay(view: View, listSectionDay: ListSectionDay) {
view.event_section_title.apply {
EventListSectionDayBinding.bind(view).eventSectionTitle.apply {
text = listSectionDay.title
val dayColor = if (listSectionDay.isToday) properPrimaryColor else textColor
setTextColor(dayColor)
@ -193,7 +197,7 @@ class EventListAdapter(
}
private fun setupListSectionMonth(view: View, listSectionMonth: ListSectionMonth) {
view.event_section_title.apply {
EventListSectionMonthBinding.bind(view).eventSectionTitle.apply {
text = listSectionMonth.title
setTextColor(properPrimaryColor)
}
@ -214,7 +218,7 @@ class EventListAdapter(
listItems.removeAll(eventsToDelete)
ensureBackgroundThread {
val nonRepeatingEventIDs = eventsToDelete.filter { !it.isRepeatable }.mapNotNull { it.id }.toMutableList()
val nonRepeatingEventIDs = eventsToDelete.filter { !it.isRepeatable }.map { it.id }.toMutableList()
activity.eventsHelper.deleteEvents(nonRepeatingEventIDs, true)
val repeatingEventIDs = eventsToDelete.filter { it.isRepeatable }.map { it.id }

View File

@ -6,12 +6,7 @@ import android.graphics.Paint
import android.widget.RemoteViews
import android.widget.RemoteViewsService
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.R.id.event_item_holder
import com.simplemobiletools.calendar.pro.R.id.event_section_title
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.extensions.eventsHelper
import com.simplemobiletools.calendar.pro.extensions.getWidgetFontSize
import com.simplemobiletools.calendar.pro.extensions.seconds
import com.simplemobiletools.calendar.pro.extensions.*
import com.simplemobiletools.calendar.pro.helpers.*
import com.simplemobiletools.calendar.pro.models.*
import com.simplemobiletools.commons.extensions.*
@ -32,8 +27,8 @@ class EventListWidgetAdapter(val context: Context, val intent: Intent) : RemoteV
private var dimPastEvents = context.config.dimPastEvents
private var dimCompletedTasks = context.config.dimCompletedTasks
private var mediumFontSize = context.getWidgetFontSize()
private var smallMargin = context.resources.getDimension(R.dimen.small_margin).toInt()
private var normalMargin = context.resources.getDimension(R.dimen.normal_margin).toInt()
private var smallMargin = context.resources.getDimension(com.simplemobiletools.commons.R.dimen.small_margin).toInt()
private var normalMargin = context.resources.getDimension(com.simplemobiletools.commons.R.dimen.normal_margin).toInt()
init {
initConfigValues()
@ -122,7 +117,7 @@ class EventListWidgetAdapter(val context: Context, val intent: Intent) : RemoteV
setViewPadding(R.id.event_item_title, normalMargin, 0, smallMargin, 0)
}
if (item.isTaskCompleted) {
if (item.shouldStrikeThrough()) {
setInt(R.id.event_item_title, "setPaintFlags", Paint.ANTI_ALIAS_FLAG or Paint.STRIKE_THRU_TEXT_FLAG)
} else {
setInt(R.id.event_item_title, "setPaintFlags", Paint.ANTI_ALIAS_FLAG)
@ -131,7 +126,7 @@ class EventListWidgetAdapter(val context: Context, val intent: Intent) : RemoteV
Intent().apply {
putExtra(EVENT_ID, item.id)
putExtra(EVENT_OCCURRENCE_TS, item.startTS)
setOnClickFillInIntent(event_item_holder, this)
setOnClickFillInIntent(R.id.event_item_holder, this)
}
}
}
@ -143,14 +138,14 @@ class EventListWidgetAdapter(val context: Context, val intent: Intent) : RemoteV
}
remoteView.apply {
setTextColor(event_section_title, curTextColor)
setTextSize(event_section_title, mediumFontSize - 3f)
setText(event_section_title, item.title)
setTextColor(R.id.event_section_title, curTextColor)
setTextSize(R.id.event_section_title, mediumFontSize - 3f)
setText(R.id.event_section_title, item.title)
Intent().apply {
putExtra(DAY_CODE, item.code)
putExtra(VIEW_TO_OPEN, context.config.listWidgetViewToOpen)
setOnClickFillInIntent(event_section_title, this)
setOnClickFillInIntent(R.id.event_section_title, this)
}
}
}
@ -158,9 +153,9 @@ class EventListWidgetAdapter(val context: Context, val intent: Intent) : RemoteV
private fun setupListSectionMonth(remoteView: RemoteViews, item: ListSectionMonth) {
val curTextColor = textColor
remoteView.apply {
setTextColor(event_section_title, curTextColor)
setTextSize(event_section_title, mediumFontSize)
setText(event_section_title, item.title)
setTextColor(R.id.event_section_title, curTextColor)
setTextSize(R.id.event_section_title, mediumFontSize)
setText(R.id.event_section_title, item.title)
}
}
@ -228,18 +223,19 @@ class EventListWidgetAdapter(val context: Context, val intent: Intent) : RemoteV
}
val listEvent = ListEvent(
event.id!!,
event.startTS,
event.endTS,
event.title,
event.description,
event.getIsAllDay(),
event.color,
event.location,
event.isPastEvent,
event.repeatInterval > 0,
event.isTask(),
event.isTaskCompleted()
id = event.id!!,
startTS = event.startTS,
endTS = event.endTS,
title = event.title,
description = event.description,
isAllDay = event.getIsAllDay(),
color = event.color,
location = event.location,
isPastEvent = event.isPastEvent,
isRepeatable = event.repeatInterval > 0,
isTask = event.isTask(),
isTaskCompleted = event.isTaskCompleted(),
isAttendeeInviteDeclined = event.isAttendeeInviteDeclined()
)
listItems.add(listEvent)
}

View File

@ -1,23 +1,21 @@
package com.simplemobiletools.calendar.pro.adapters
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
import com.simplemobiletools.calendar.pro.databinding.FilterEventTypeViewBinding
import com.simplemobiletools.calendar.pro.models.EventType
import com.simplemobiletools.commons.extensions.getProperBackgroundColor
import com.simplemobiletools.commons.extensions.getProperPrimaryColor
import com.simplemobiletools.commons.extensions.getProperTextColor
import com.simplemobiletools.commons.extensions.setFillWithStroke
import kotlinx.android.synthetic.main.filter_event_type_view.view.*
class FilterEventTypeAdapter(val activity: SimpleActivity, val eventTypes: List<EventType>, val displayEventTypes: Set<String>) :
RecyclerView.Adapter<FilterEventTypeAdapter.ViewHolder>() {
RecyclerView.Adapter<FilterEventTypeAdapter.EventTypeViewHolder>() {
private val selectedKeys = HashSet<Long>()
init {
eventTypes.forEachIndexed { index, eventType ->
eventTypes.forEach { eventType ->
if (displayEventTypes.contains(eventType.id.toString())) {
selectedKeys.add(eventType.id!!)
}
@ -36,30 +34,28 @@ class FilterEventTypeAdapter(val activity: SimpleActivity, val eventTypes: List<
fun getSelectedItemsList() = selectedKeys.asSequence().map { it }.toMutableList() as ArrayList<Long>
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = activity.layoutInflater.inflate(R.layout.filter_event_type_view, parent, false)
return ViewHolder(view)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EventTypeViewHolder {
return EventTypeViewHolder(
binding = FilterEventTypeViewBinding.inflate(activity.layoutInflater, parent, false)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val eventType = eventTypes[position]
holder.bindView(eventType)
}
override fun onBindViewHolder(holder: EventTypeViewHolder, position: Int) = holder.bindView(eventType = eventTypes[position])
override fun getItemCount() = eventTypes.size
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bindView(eventType: EventType): View {
inner class EventTypeViewHolder(val binding: FilterEventTypeViewBinding) : RecyclerView.ViewHolder(binding.root) {
fun bindView(eventType: EventType) {
val isSelected = selectedKeys.contains(eventType.id)
itemView.apply {
filter_event_type_checkbox.isChecked = isSelected
filter_event_type_checkbox.setColors(activity.getProperTextColor(), activity.getProperPrimaryColor(), activity.getProperBackgroundColor())
filter_event_type_checkbox.text = eventType.getDisplayTitle()
filter_event_type_color.setFillWithStroke(eventType.color, activity.getProperBackgroundColor())
filter_event_type_holder.setOnClickListener { viewClicked(!isSelected, eventType) }
binding.apply {
filterEventTypeCheckbox.isChecked = isSelected
filterEventTypeCheckbox.setColors(activity.getProperTextColor(), activity.getProperPrimaryColor(), activity.getProperBackgroundColor())
filterEventTypeCheckbox.text = eventType.getDisplayTitle()
filterEventTypeColor.setFillWithStroke(eventType.color, activity.getProperBackgroundColor())
filterEventTypeHolder.setOnClickListener {
viewClicked(!isSelected, eventType)
}
}
return itemView
}
private fun viewClicked(select: Boolean, eventType: EventType) {

View File

@ -4,6 +4,7 @@ import android.view.*
import android.widget.PopupMenu
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
import com.simplemobiletools.calendar.pro.databinding.ItemEventTypeBinding
import com.simplemobiletools.calendar.pro.extensions.eventsHelper
import com.simplemobiletools.calendar.pro.helpers.REGULAR_EVENT_TYPE_ID
import com.simplemobiletools.calendar.pro.interfaces.DeleteEventTypesListener
@ -14,12 +15,14 @@ import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.commons.views.MyRecyclerView
import kotlinx.android.synthetic.main.item_event_type.view.*
class ManageEventTypesAdapter(
activity: SimpleActivity, val eventTypes: ArrayList<EventType>, val listener: DeleteEventTypesListener?, recyclerView: MyRecyclerView,
itemClick: (Any) -> Unit
) : MyRecyclerViewAdapter(activity, recyclerView, itemClick) {
private val MOVE_EVENTS = 0
private val DELETE_EVENTS = 1
init {
setupDragListener(true)
}
@ -55,11 +58,15 @@ class ManageEventTypesAdapter(
override fun onActionModeDestroyed() {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_event_type, parent)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return createViewHolder(
view = ItemEventTypeBinding.inflate(activity.layoutInflater, parent, false).root
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val eventType = eventTypes[position]
holder.bindView(eventType, true, true) { itemView, layoutPosition ->
holder.bindView(eventType, allowSingleClick = true, allowLongClick = true) { itemView, _ ->
setupView(itemView, eventType)
}
bindViewHolder(holder)
@ -72,19 +79,19 @@ class ManageEventTypesAdapter(
private fun getSelectedItems() = eventTypes.filter { selectedKeys.contains(it.id?.toInt()) } as ArrayList<EventType>
private fun setupView(view: View, eventType: EventType) {
view.apply {
event_item_frame.isSelected = selectedKeys.contains(eventType.id?.toInt())
event_type_title.text = eventType.getDisplayTitle()
event_type_color.setFillWithStroke(eventType.color, activity.getProperBackgroundColor())
event_type_title.setTextColor(textColor)
ItemEventTypeBinding.bind(view).apply {
eventItemFrame.isSelected = selectedKeys.contains(eventType.id?.toInt())
eventTypeTitle.text = eventType.getDisplayTitle()
eventTypeColor.setFillWithStroke(eventType.color, activity.getProperBackgroundColor())
eventTypeTitle.setTextColor(textColor)
overflow_menu_icon.drawable.apply {
overflowMenuIcon.drawable.apply {
mutate()
setTint(activity.getProperTextColor())
}
overflow_menu_icon.setOnClickListener {
showPopupMenu(overflow_menu_anchor, eventType)
overflowMenuIcon.setOnClickListener {
showPopupMenu(overflowMenuAnchor, eventType)
}
}
}
@ -104,6 +111,7 @@ class ManageEventTypesAdapter(
itemClick(eventType)
}
}
R.id.cab_delete -> {
executeItemMenuOperation(eventTypeId) {
askConfirmDelete()
@ -133,8 +141,6 @@ class ManageEventTypesAdapter(
activity.eventsHelper.doEventTypesContainEvents(eventTypes) {
activity.runOnUiThread {
if (it) {
val MOVE_EVENTS = 0
val DELETE_EVENTS = 1
val res = activity.resources
val items = ArrayList<RadioItem>().apply {
add(RadioItem(MOVE_EVENTS, res.getString(R.string.move_events_into_default)))

View File

@ -1,24 +1,23 @@
package com.simplemobiletools.calendar.pro.adapters
import android.view.View
import android.view.ViewGroup
import androidx.core.view.updateLayoutParams
import androidx.recyclerview.widget.RecyclerView
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
import com.simplemobiletools.calendar.pro.databinding.QuickFilterEventTypeViewBinding
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.models.EventType
import com.simplemobiletools.commons.extensions.adjustAlpha
import com.simplemobiletools.commons.extensions.getProperTextColor
import com.simplemobiletools.commons.helpers.LOWER_ALPHA
import kotlinx.android.synthetic.main.quick_filter_event_type_view.view.*
class QuickFilterEventTypeAdapter(
val activity: SimpleActivity,
private val allEventTypes: List<EventType>,
private val quickFilterEventTypeIds: Set<String>,
val callback: () -> Unit
) :
RecyclerView.Adapter<QuickFilterEventTypeAdapter.ViewHolder>() {
) : RecyclerView.Adapter<QuickFilterEventTypeAdapter.QuickFilterViewHolder>() {
private val activeKeys = HashSet<Long>()
private val quickFilterEventTypes = ArrayList<EventType>()
private val displayEventTypes = activity.config.displayEventTypes
@ -52,36 +51,42 @@ class QuickFilterEventTypeAdapter(
notifyItemChanged(pos)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QuickFilterViewHolder {
val parentWidth = parent.measuredWidth
val nrOfItems = quickFilterEventTypes.size
val view = activity.layoutInflater.inflate(R.layout.quick_filter_event_type_view, parent, false)
if (nrOfItems * minItemWidth > parentWidth) view.layoutParams.width = minItemWidth
else view.layoutParams.width = parentWidth / nrOfItems
return ViewHolder(view)
val numberOfItems = quickFilterEventTypes.size
val binding = QuickFilterEventTypeViewBinding.inflate(activity.layoutInflater, parent, false)
binding.root.updateLayoutParams<RecyclerView.LayoutParams> {
width = if (numberOfItems * minItemWidth > parentWidth) {
minItemWidth
} else {
parentWidth / numberOfItems
}
}
return QuickFilterViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
override fun onBindViewHolder(holder: QuickFilterViewHolder, position: Int) {
val eventType = quickFilterEventTypes[position]
holder.bindView(eventType)
}
override fun getItemCount() = quickFilterEventTypes.size
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bindView(eventType: EventType): View {
inner class QuickFilterViewHolder(val binding: QuickFilterEventTypeViewBinding) : RecyclerView.ViewHolder(binding.root) {
fun bindView(eventType: EventType) {
val isSelected = activeKeys.contains(eventType.id)
itemView.apply {
quick_filter_event_type.text = eventType.title
binding.apply {
quickFilterEventType.text = eventType.title
val textColor = if (isSelected) textColorActive else textColorInactive
quick_filter_event_type.setTextColor(textColor)
quickFilterEventType.setTextColor(textColor)
val indicatorHeightRes = if (isSelected) R.dimen.quick_filter_active_line_size else R.dimen.quick_filter_inactive_line_size
quick_filter_event_type_color.layoutParams.height = resources.getDimensionPixelSize(indicatorHeightRes)
quick_filter_event_type_color.setBackgroundColor(eventType.color)
quickFilterEventTypeColor.layoutParams.height = root.resources.getDimensionPixelSize(indicatorHeightRes)
quickFilterEventTypeColor.setBackgroundColor(eventType.color)
// avoid too quick clicks, could cause glitches
quick_filter_event_type.setOnClickListener {
quickFilterEventType.setOnClickListener {
if (System.currentTimeMillis() - lastClickTS > 300) {
lastClickTS = System.currentTimeMillis()
viewClicked(!isSelected, eventType)
@ -89,8 +94,6 @@ class QuickFilterEventTypeAdapter(
}
}
}
return itemView
}
private fun viewClicked(select: Boolean, eventType: EventType) {

View File

@ -1,24 +1,23 @@
package com.simplemobiletools.calendar.pro.adapters
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
import com.simplemobiletools.calendar.pro.databinding.ItemSelectTimeZoneBinding
import com.simplemobiletools.calendar.pro.models.MyTimeZone
import com.simplemobiletools.commons.extensions.getProperTextColor
import kotlinx.android.synthetic.main.item_select_time_zone.view.*
class SelectTimeZoneAdapter(val activity: SimpleActivity, var timeZones: ArrayList<MyTimeZone>, val itemClick: (Any) -> Unit) :
RecyclerView.Adapter<SelectTimeZoneAdapter.ViewHolder>() {
RecyclerView.Adapter<SelectTimeZoneAdapter.TimeZoneViewHolder>() {
val textColor = activity.getProperTextColor()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = activity.layoutInflater.inflate(R.layout.item_select_time_zone, parent, false)
return ViewHolder(view)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TimeZoneViewHolder {
return TimeZoneViewHolder(
binding = ItemSelectTimeZoneBinding.inflate(activity.layoutInflater, parent, false)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
override fun onBindViewHolder(holder: TimeZoneViewHolder, position: Int) {
val timeZone = timeZones[position]
holder.bindView(timeZone)
}
@ -30,21 +29,19 @@ class SelectTimeZoneAdapter(val activity: SimpleActivity, var timeZones: ArrayLi
notifyDataSetChanged()
}
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bindView(timeZone: MyTimeZone): View {
itemView.apply {
item_time_zone_title.text = timeZone.zoneName
item_time_zone_shift.text = timeZone.title
inner class TimeZoneViewHolder(val binding: ItemSelectTimeZoneBinding) : RecyclerView.ViewHolder(binding.root) {
fun bindView(timeZone: MyTimeZone) {
binding.apply {
itemTimeZoneTitle.text = timeZone.zoneName
itemTimeZoneShift.text = timeZone.title
item_time_zone_title.setTextColor(textColor)
item_time_zone_shift.setTextColor(textColor)
itemTimeZoneTitle.setTextColor(textColor)
itemTimeZoneShift.setTextColor(textColor)
item_select_time_zone_holder.setOnClickListener {
itemSelectTimeZoneHolder.setOnClickListener {
itemClick(timeZone)
}
}
return itemView
}
}
}

View File

@ -1,38 +1,37 @@
package com.simplemobiletools.calendar.pro.dialogs
import android.app.Activity
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.databinding.DialogCustomEventRepeatIntervalBinding
import com.simplemobiletools.calendar.pro.helpers.DAY
import com.simplemobiletools.calendar.pro.helpers.MONTH
import com.simplemobiletools.calendar.pro.helpers.WEEK
import com.simplemobiletools.calendar.pro.helpers.YEAR
import com.simplemobiletools.commons.extensions.*
import kotlinx.android.synthetic.main.dialog_custom_event_repeat_interval.view.*
class CustomEventRepeatIntervalDialog(val activity: Activity, val callback: (seconds: Int) -> Unit) {
private var dialog: AlertDialog? = null
private var view = activity.layoutInflater.inflate(R.layout.dialog_custom_event_repeat_interval, null) as ViewGroup
private val binding by activity.viewBinding(DialogCustomEventRepeatIntervalBinding::inflate)
init {
view.dialog_radio_view.check(R.id.dialog_radio_days)
binding.dialogRadioView.check(R.id.dialog_radio_days)
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { dialogInterface, i -> confirmRepeatInterval() }
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> confirmRepeatInterval() }
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this) { alertDialog ->
activity.setupDialogStuff(binding.root, this) { alertDialog ->
dialog = alertDialog
alertDialog.showKeyboard(view.dialog_custom_repeat_interval_value)
alertDialog.showKeyboard(binding.dialogCustomRepeatIntervalValue)
}
}
}
private fun confirmRepeatInterval() {
val value = view.dialog_custom_repeat_interval_value.value
val multiplier = getMultiplier(view.dialog_radio_view.checkedRadioButtonId)
val days = Integer.valueOf(if (value.isEmpty()) "0" else value)
val value = binding.dialogCustomRepeatIntervalValue.value
val multiplier = getMultiplier(binding.dialogRadioView.checkedRadioButtonId)
val days = Integer.valueOf(value.ifEmpty { "0" })
callback(days * multiplier)
activity.hideKeyboard()
dialog?.dismiss()

View File

@ -1,29 +1,28 @@
package com.simplemobiletools.calendar.pro.dialogs
import android.app.Activity
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.databinding.DialogCustomPeriodPickerBinding
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.DAY_SECONDS
import com.simplemobiletools.commons.helpers.MONTH_SECONDS
import com.simplemobiletools.commons.helpers.WEEK_SECONDS
import kotlinx.android.synthetic.main.dialog_custom_period_picker.view.*
class CustomPeriodPickerDialog(val activity: Activity, val callback: (value: Int) -> Unit) {
private var dialog: AlertDialog? = null
private var view = (activity.layoutInflater.inflate(R.layout.dialog_custom_period_picker, null) as ViewGroup)
private val binding by activity.viewBinding(DialogCustomPeriodPickerBinding::inflate)
init {
view.dialog_custom_period_value.setText("")
view.dialog_radio_view.check(R.id.dialog_radio_days)
binding.dialogCustomPeriodValue.setText("")
binding.dialogRadioView.check(R.id.dialog_radio_days)
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { dialogInterface, i -> confirmReminder() }
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> confirmReminder() }
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this) { alertDialog ->
activity.setupDialogStuff(binding.root, this) { alertDialog ->
dialog = alertDialog
alertDialog.showKeyboard(view.dialog_custom_period_value)
alertDialog.showKeyboard(binding.dialogCustomPeriodValue)
}
}
}
@ -35,14 +34,9 @@ class CustomPeriodPickerDialog(val activity: Activity, val callback: (value: Int
}
private fun confirmReminder() {
val value = view.dialog_custom_period_value.value
val type = view.dialog_radio_view.checkedRadioButtonId
val periodValue = if (value.isEmpty()) {
"0"
} else {
value
}
val value = binding.dialogCustomPeriodValue.value
val type = binding.dialogRadioView.checkedRadioButtonId
val periodValue = value.ifEmpty { "0" }
val period = calculatePeriod(Integer.valueOf(periodValue), type)
callback(period)
activity.hideKeyboard()

View File

@ -1,18 +1,19 @@
package com.simplemobiletools.calendar.pro.dialogs
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.databinding.DatetimePatternInfoLayoutBinding
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.extensions.viewBinding
class DateTimePatternInfoDialog(activity: BaseSimpleActivity) {
val binding by activity.viewBinding(DatetimePatternInfoLayoutBinding::inflate)
init {
val view = activity.layoutInflater.inflate(R.layout.datetime_pattern_info_layout, null)
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { _, _ -> { } }
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> { } }
.apply {
activity.setupDialogStuff(view, this)
activity.setupDialogStuff(binding.root, this)
}
}
}

View File

@ -1,16 +1,16 @@
package com.simplemobiletools.calendar.pro.dialogs
import android.app.Activity
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.databinding.DialogDeleteEventBinding
import com.simplemobiletools.calendar.pro.helpers.DELETE_ALL_OCCURRENCES
import com.simplemobiletools.calendar.pro.helpers.DELETE_FUTURE_OCCURRENCES
import com.simplemobiletools.calendar.pro.helpers.DELETE_SELECTED_OCCURRENCE
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff
import kotlinx.android.synthetic.main.dialog_delete_event.view.*
import com.simplemobiletools.commons.extensions.viewBinding
class DeleteEventDialog(
val activity: Activity,
@ -20,38 +20,39 @@ class DeleteEventDialog(
val callback: (deleteRule: Int) -> Unit
) {
private var dialog: AlertDialog? = null
private val binding by activity.viewBinding(DialogDeleteEventBinding::inflate)
init {
val view = activity.layoutInflater.inflate(R.layout.dialog_delete_event, null).apply {
delete_event_repeat_description.beVisibleIf(hasRepeatableEvent)
delete_event_radio_view.beVisibleIf(hasRepeatableEvent)
binding.apply {
deleteEventRepeatDescription.beVisibleIf(hasRepeatableEvent)
deleteEventRadioView.beVisibleIf(hasRepeatableEvent)
if (!hasRepeatableEvent) {
delete_event_radio_view.check(R.id.delete_event_all)
deleteEventRadioView.check(R.id.delete_event_all)
}
if (eventIds.size > 1) {
delete_event_repeat_description.setText(R.string.selection_contains_repetition)
deleteEventRepeatDescription.setText(R.string.selection_contains_repetition)
}
if (isTask) {
delete_event_repeat_description.setText(R.string.task_is_repeatable)
deleteEventRepeatDescription.setText(R.string.task_is_repeatable)
} else {
delete_event_repeat_description.setText(R.string.event_is_repeatable)
deleteEventRepeatDescription.setText(R.string.event_is_repeatable)
}
}
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.yes) { dialog, which -> dialogConfirmed(view as ViewGroup) }
.setNegativeButton(R.string.no, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.yes) { _, _ -> dialogConfirmed(binding) }
.setNegativeButton(com.simplemobiletools.commons.R.string.no, null)
.apply {
activity.setupDialogStuff(view, this) { alertDialog ->
activity.setupDialogStuff(binding.root, this) { alertDialog ->
dialog = alertDialog
}
}
}
private fun dialogConfirmed(view: ViewGroup) {
val deleteRule = when (view.delete_event_radio_view.checkedRadioButtonId) {
private fun dialogConfirmed(binding: DialogDeleteEventBinding) {
val deleteRule = when (binding.deleteEventRadioView.checkedRadioButtonId) {
R.id.delete_event_all -> DELETE_ALL_OCCURRENCES
R.id.delete_event_future -> DELETE_FUTURE_OCCURRENCES
else -> DELETE_SELECTED_OCCURRENCE

View File

@ -4,6 +4,7 @@ import android.app.Activity
import android.widget.ImageView
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.databinding.DialogEventTypeBinding
import com.simplemobiletools.calendar.pro.extensions.calDAVHelper
import com.simplemobiletools.calendar.pro.extensions.eventsHelper
import com.simplemobiletools.calendar.pro.helpers.OTHER_EVENT
@ -11,25 +12,25 @@ import com.simplemobiletools.calendar.pro.models.EventType
import com.simplemobiletools.commons.dialogs.ColorPickerDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import kotlinx.android.synthetic.main.dialog_event_type.view.*
class EditEventTypeDialog(val activity: Activity, var eventType: EventType? = null, val callback: (eventType: EventType) -> Unit) {
private var isNewEvent = eventType == null
private val binding by activity.viewBinding(DialogEventTypeBinding::inflate)
init {
if (eventType == null) {
eventType = EventType(null, "", activity.getProperPrimaryColor())
}
val view = activity.layoutInflater.inflate(R.layout.dialog_event_type, null).apply {
setupColor(type_color)
type_title.setText(eventType!!.title)
type_color.setOnClickListener {
binding.apply {
setupColor(typeColor)
typeTitle.setText(eventType!!.title)
typeColor.setOnClickListener {
if (eventType?.caldavCalendarId == 0) {
ColorPickerDialog(activity, eventType!!.color) { wasPositivePressed, color ->
if (wasPositivePressed) {
eventType!!.color = color
setupColor(type_color)
setupColor(typeColor)
}
}
} else {
@ -37,21 +38,21 @@ class EditEventTypeDialog(val activity: Activity, var eventType: EventType? = nu
val colors = activity.calDAVHelper.getAvailableCalDAVCalendarColors(eventType!!).keys.toIntArray()
SelectEventTypeColorDialog(activity, colors = colors, currentColor = currentColor) {
eventType!!.color = it
setupColor(type_color)
setupColor(typeColor)
}
}
}
}
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok, null)
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this, if (isNewEvent) R.string.add_new_type else R.string.edit_type) { alertDialog ->
alertDialog.showKeyboard(view.type_title)
activity.setupDialogStuff(binding.root, this, if (isNewEvent) R.string.add_new_type else R.string.edit_type) { alertDialog ->
alertDialog.showKeyboard(binding.typeTitle)
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
ensureBackgroundThread {
eventTypeConfirmed(view.type_title.value, alertDialog)
eventTypeConfirmed(binding.typeTitle.value, alertDialog)
}
}
}

View File

@ -1,44 +1,48 @@
package com.simplemobiletools.calendar.pro.dialogs
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
import com.simplemobiletools.calendar.pro.databinding.DialogEditRepeatingEventBinding
import com.simplemobiletools.calendar.pro.helpers.EDIT_ALL_OCCURRENCES
import com.simplemobiletools.calendar.pro.helpers.EDIT_FUTURE_OCCURRENCES
import com.simplemobiletools.calendar.pro.helpers.EDIT_SELECTED_OCCURRENCE
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.hideKeyboard
import com.simplemobiletools.commons.extensions.setupDialogStuff
import kotlinx.android.synthetic.main.dialog_edit_repeating_event.view.*
import com.simplemobiletools.commons.extensions.viewBinding
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 val binding by activity.viewBinding(DialogEditRepeatingEventBinding::inflate)
init {
val view = (activity.layoutInflater.inflate(R.layout.dialog_edit_repeating_event, null) as ViewGroup).apply {
edit_repeating_event_one_only.setOnClickListener { sendResult(EDIT_SELECTED_OCCURRENCE) }
edit_repeating_event_this_and_future_occurences.setOnClickListener { sendResult(EDIT_FUTURE_OCCURRENCES) }
edit_repeating_event_all_occurrences.setOnClickListener { sendResult(EDIT_ALL_OCCURRENCES) }
binding.apply {
editRepeatingEventOneOnly.setOnClickListener { sendResult(EDIT_SELECTED_OCCURRENCE) }
editRepeatingEventThisAndFutureOccurences.setOnClickListener { sendResult(EDIT_FUTURE_OCCURRENCES) }
editRepeatingEventAllOccurrences.setOnClickListener { sendResult(EDIT_ALL_OCCURRENCES) }
if (isTask) {
edit_repeating_event_title.setText(R.string.task_is_repeatable)
editRepeatingEventTitle.setText(R.string.task_is_repeatable)
} else {
edit_repeating_event_title.setText(R.string.event_is_repeatable)
editRepeatingEventTitle.setText(R.string.event_is_repeatable)
}
}
activity.getAlertDialogBuilder()
.apply {
activity.setupDialogStuff(view, this) { alertDialog ->
activity.setupDialogStuff(binding.root, this) { alertDialog ->
dialog = alertDialog
alertDialog.hideKeyboard()
alertDialog.setOnDismissListener { sendResult(null) }
}
}
}
private fun sendResult(allOccurrences: Int) {
private fun sendResult(allOccurrences: Int?) {
callback(allOccurrences)
dialog?.dismiss()
if (allOccurrences != null) {
dialog?.dismiss()
}
}
}

View File

@ -1,16 +1,15 @@
package com.simplemobiletools.calendar.pro.dialogs
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
import com.simplemobiletools.calendar.pro.adapters.FilterEventTypeAdapter
import com.simplemobiletools.calendar.pro.databinding.DialogExportEventsBinding
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.extensions.eventsHelper
import com.simplemobiletools.commons.dialogs.FilePickerDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import kotlinx.android.synthetic.main.dialog_export_events.view.*
import java.io.File
class ExportEventsDialog(
@ -19,33 +18,34 @@ class ExportEventsDialog(
) {
private var realPath = path.ifEmpty { activity.internalStoragePath }
private val config = activity.config
private val binding by activity.viewBinding(DialogExportEventsBinding::inflate)
init {
val view = (activity.layoutInflater.inflate(R.layout.dialog_export_events, null) as ViewGroup).apply {
export_events_folder.setText(activity.humanizePath(realPath))
export_events_filename.setText("${activity.getString(R.string.events)}_${activity.getCurrentFormattedDateTime()}")
binding.apply {
exportEventsFolder.setText(activity.humanizePath(realPath))
exportEventsFilename.setText("${activity.getString(R.string.events)}_${activity.getCurrentFormattedDateTime()}")
export_events_checkbox.isChecked = config.exportEvents
export_events_checkbox_holder.setOnClickListener {
export_events_checkbox.toggle()
exportEventsCheckbox.isChecked = config.exportEvents
exportEventsCheckboxHolder.setOnClickListener {
exportEventsCheckbox.toggle()
}
export_tasks_checkbox.isChecked = config.exportTasks
export_tasks_checkbox_holder.setOnClickListener {
export_tasks_checkbox.toggle()
exportTasksCheckbox.isChecked = config.exportTasks
exportTasksCheckboxHolder.setOnClickListener {
exportTasksCheckbox.toggle()
}
export_past_events_checkbox.isChecked = config.exportPastEntries
export_past_events_checkbox_holder.setOnClickListener {
export_past_events_checkbox.toggle()
exportPastEventsCheckbox.isChecked = config.exportPastEntries
exportPastEventsCheckboxHolder.setOnClickListener {
exportPastEventsCheckbox.toggle()
}
if (hidePath) {
export_events_folder_hint.beGone()
export_events_folder.beGone()
exportEventsFolderHint.beGone()
exportEventsFolder.beGone()
} else {
export_events_folder.setOnClickListener {
activity.hideKeyboard(export_events_filename)
exportEventsFolder.setOnClickListener {
activity.hideKeyboard(exportEventsFilename)
FilePickerDialog(activity, realPath, false, showFAB = true) {
export_events_folder.setText(activity.humanizePath(it))
exportEventsFolder.setText(activity.humanizePath(it))
realPath = it
}
}
@ -55,33 +55,33 @@ class ExportEventsDialog(
val eventTypes = HashSet<String>()
it.mapTo(eventTypes) { it.id.toString() }
export_events_types_list.adapter = FilterEventTypeAdapter(activity, it, eventTypes)
exportEventsTypesList.adapter = FilterEventTypeAdapter(activity, it, eventTypes)
if (it.size > 1) {
export_events_pick_types.beVisible()
exportEventsPickTypes.beVisible()
}
}
}
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok, null)
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this, R.string.export_events) { alertDialog ->
activity.setupDialogStuff(binding.root, this, R.string.export_events) { alertDialog ->
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
val filename = view.export_events_filename.value
val filename = binding.exportEventsFilename.value
when {
filename.isEmpty() -> activity.toast(R.string.empty_name)
filename.isEmpty() -> activity.toast(com.simplemobiletools.commons.R.string.empty_name)
filename.isAValidFilename() -> {
val file = File(realPath, "$filename.ics")
if (!hidePath && file.exists()) {
activity.toast(R.string.name_taken)
activity.toast(com.simplemobiletools.commons.R.string.name_taken)
return@setOnClickListener
}
val exportEventsChecked = view.export_events_checkbox.isChecked
val exportTasksChecked = view.export_tasks_checkbox.isChecked
val exportEventsChecked = binding.exportEventsCheckbox.isChecked
val exportTasksChecked = binding.exportTasksCheckbox.isChecked
if (!exportEventsChecked && !exportTasksChecked) {
activity.toast(R.string.no_entries_for_exporting)
activity.toast(com.simplemobiletools.commons.R.string.no_entries_for_exporting)
return@setOnClickListener
}
@ -90,15 +90,16 @@ class ExportEventsDialog(
lastExportPath = file.absolutePath.getParentPath()
exportEvents = exportEventsChecked
exportTasks = exportTasksChecked
exportPastEntries = view.export_past_events_checkbox.isChecked
exportPastEntries = binding.exportPastEventsCheckbox.isChecked
}
val eventTypes = (view.export_events_types_list.adapter as FilterEventTypeAdapter).getSelectedItemsList()
val eventTypes = (binding.exportEventsTypesList.adapter as FilterEventTypeAdapter).getSelectedItemsList()
callback(file, eventTypes)
alertDialog.dismiss()
}
}
else -> activity.toast(R.string.invalid_name)
else -> activity.toast(com.simplemobiletools.commons.R.string.invalid_name)
}
}
}

View File

@ -1,9 +1,9 @@
package com.simplemobiletools.calendar.pro.dialogs
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
import com.simplemobiletools.calendar.pro.databinding.DialogImportEventsBinding
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.extensions.eventTypesDB
import com.simplemobiletools.calendar.pro.extensions.eventsHelper
@ -15,12 +15,12 @@ import com.simplemobiletools.calendar.pro.helpers.IcsImporter.ImportResult.IMPOR
import com.simplemobiletools.calendar.pro.helpers.REGULAR_EVENT_TYPE_ID
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import kotlinx.android.synthetic.main.dialog_import_events.view.*
class ImportEventsDialog(val activity: SimpleActivity, val path: String, val callback: (refreshView: Boolean) -> Unit) {
private var currEventTypeId = REGULAR_EVENT_TYPE_ID
private var currEventTypeCalDAVCalendarId = 0
private val config = activity.config
private val binding by activity.viewBinding(DialogImportEventsBinding::inflate)
init {
ensureBackgroundThread {
@ -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()
@ -48,10 +49,18 @@ class ImportEventsDialog(val activity: SimpleActivity, val path: String, val cal
}
private fun initDialog() {
val view = (activity.layoutInflater.inflate(R.layout.dialog_import_events, null) as ViewGroup).apply {
binding.apply {
updateEventType(this)
import_event_type_title.setOnClickListener {
SelectEventTypeDialog(activity, currEventTypeId, true, true, false, true, false) {
importEventTypeTitle.setOnClickListener {
SelectEventTypeDialog(
activity = activity,
currEventType = currEventTypeId,
showCalDAVCalendars = true,
showNewEventTypeOption = true,
addLastUsedOneAsFirstOption = false,
showOnlyWritable = true,
showManageEventTypes = false
) {
currEventTypeId = it.id!!
currEventTypeCalDAVCalendarId = it.caldavCalendarId
@ -62,21 +71,22 @@ class ImportEventsDialog(val activity: SimpleActivity, val path: String, val cal
}
}
import_events_checkbox_holder.setOnClickListener {
import_events_checkbox.toggle()
importEventsCheckboxHolder.setOnClickListener {
importEventsCheckbox.toggle()
}
}
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok, null)
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this, R.string.import_events) { alertDialog ->
activity.setupDialogStuff(binding.root, this, R.string.import_events) { alertDialog ->
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(null)
activity.toast(R.string.importing)
activity.toast(com.simplemobiletools.commons.R.string.importing)
ensureBackgroundThread {
val overrideFileEventTypes = view.import_events_checkbox.isChecked
val overrideFileEventTypes = binding.importEventsCheckbox.isChecked
config.lastUsedIgnoreEventTypesState = overrideFileEventTypes
val result = IcsImporter(activity).importEvents(path, currEventTypeId, currEventTypeCalDAVCalendarId, overrideFileEventTypes)
handleParseResult(result)
alertDialog.dismiss()
@ -86,12 +96,12 @@ class ImportEventsDialog(val activity: SimpleActivity, val path: String, val cal
}
}
private fun updateEventType(view: ViewGroup) {
private fun updateEventType(binding: DialogImportEventsBinding) {
ensureBackgroundThread {
val eventType = activity.eventTypesDB.getEventTypeWithId(currEventTypeId)
activity.runOnUiThread {
view.import_event_type_title.setText(eventType!!.getDisplayTitle())
view.import_event_type_color.setFillWithStroke(eventType.color, activity.getProperBackgroundColor())
binding.importEventTypeTitle.setText(eventType!!.getDisplayTitle())
binding.importEventTypeColor.setFillWithStroke(eventType.color, activity.getProperBackgroundColor())
}
}
}
@ -99,10 +109,10 @@ class ImportEventsDialog(val activity: SimpleActivity, val path: String, val cal
private fun handleParseResult(result: IcsImporter.ImportResult) {
activity.toast(
when (result) {
IMPORT_NOTHING_NEW -> R.string.no_new_items
IMPORT_OK -> R.string.importing_successful
IMPORT_PARTIAL -> R.string.importing_some_entries_failed
else -> R.string.no_items_found
IMPORT_NOTHING_NEW -> com.simplemobiletools.commons.R.string.no_new_items
IMPORT_OK -> com.simplemobiletools.commons.R.string.importing_successful
IMPORT_PARTIAL -> com.simplemobiletools.commons.R.string.importing_some_entries_failed
else -> com.simplemobiletools.commons.R.string.no_items_found
}
)
callback(result != IMPORT_FAIL)

View File

@ -1,84 +1,83 @@
package com.simplemobiletools.calendar.pro.dialogs
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
import com.simplemobiletools.calendar.pro.databinding.DialogManageAutomaticBackupsBinding
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.commons.dialogs.FilePickerDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import kotlinx.android.synthetic.main.dialog_manage_automatic_backups.view.*
import java.io.File
class ManageAutomaticBackupsDialog(private val activity: SimpleActivity, onSuccess: () -> Unit) {
private val view = (activity.layoutInflater.inflate(R.layout.dialog_manage_automatic_backups, null) as ViewGroup)
private val binding by activity.viewBinding(DialogManageAutomaticBackupsBinding::inflate)
private val config = activity.config
private var backupFolder = config.autoBackupFolder
private var selectedEventTypes = config.autoBackupEventTypes.ifEmpty { config.displayEventTypes }
init {
view.apply {
backup_events_folder.setText(activity.humanizePath(backupFolder))
binding.apply {
backupEventsFolder.setText(activity.humanizePath(backupFolder))
val filename = config.autoBackupFilename.ifEmpty {
"${activity.getString(R.string.events)}_%Y%M%D_%h%m%s"
}
backup_events_filename.setText(filename)
backup_events_filename_hint.setEndIconOnClickListener {
backupEventsFilename.setText(filename)
backupEventsFilenameHint.setEndIconOnClickListener {
DateTimePatternInfoDialog(activity)
}
backup_events_filename_hint.setEndIconOnLongClickListener {
backupEventsFilenameHint.setEndIconOnLongClickListener {
DateTimePatternInfoDialog(activity)
true
}
backup_events_checkbox.isChecked = config.autoBackupEvents
backup_events_checkbox_holder.setOnClickListener {
backup_events_checkbox.toggle()
backupEventsCheckbox.isChecked = config.autoBackupEvents
backupEventsCheckboxHolder.setOnClickListener {
backupEventsCheckbox.toggle()
}
backup_tasks_checkbox.isChecked = config.autoBackupTasks
backup_tasks_checkbox_holder.setOnClickListener {
backup_tasks_checkbox.toggle()
backupTasksCheckbox.isChecked = config.autoBackupTasks
backupTasksCheckboxHolder.setOnClickListener {
backupTasksCheckbox.toggle()
}
backup_past_events_checkbox.isChecked = config.autoBackupPastEntries
backup_past_events_checkbox_holder.setOnClickListener {
backup_past_events_checkbox.toggle()
backupPastEventsCheckbox.isChecked = config.autoBackupPastEntries
backupPastEventsCheckboxHolder.setOnClickListener {
backupPastEventsCheckbox.toggle()
}
backup_events_folder.setOnClickListener {
backupEventsFolder.setOnClickListener {
selectBackupFolder()
}
manage_event_types_holder.setOnClickListener {
manageEventTypesHolder.setOnClickListener {
SelectEventTypesDialog(activity, selectedEventTypes) {
selectedEventTypes = it
}
}
}
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok, null)
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this, R.string.manage_automatic_backups) { dialog ->
activity.setupDialogStuff(binding.root, this, com.simplemobiletools.commons.R.string.manage_automatic_backups) { dialog ->
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
val filename = view.backup_events_filename.value
val filename = binding.backupEventsFilename.value
when {
filename.isEmpty() -> activity.toast(R.string.empty_name)
filename.isEmpty() -> activity.toast(com.simplemobiletools.commons.R.string.empty_name)
filename.isAValidFilename() -> {
val file = File(backupFolder, "$filename.ics")
if (file.exists() && !file.canWrite()) {
activity.toast(R.string.name_taken)
activity.toast(com.simplemobiletools.commons.R.string.name_taken)
return@setOnClickListener
}
val backupEventsChecked = view.backup_events_checkbox.isChecked
val backupTasksChecked = view.backup_tasks_checkbox.isChecked
val backupEventsChecked = binding.backupEventsCheckbox.isChecked
val backupTasksChecked = binding.backupTasksCheckbox.isChecked
if (!backupEventsChecked && !backupTasksChecked || selectedEventTypes.isEmpty()) {
activity.toast(R.string.no_entries_for_exporting)
activity.toast(com.simplemobiletools.commons.R.string.no_entries_for_exporting)
return@setOnClickListener
}
@ -88,7 +87,7 @@ class ManageAutomaticBackupsDialog(private val activity: SimpleActivity, onSucce
autoBackupFilename = filename
autoBackupEvents = backupEventsChecked
autoBackupTasks = backupTasksChecked
autoBackupPastEntries = view.backup_past_events_checkbox.isChecked
autoBackupPastEntries = binding.backupPastEventsCheckbox.isChecked
if (autoBackupEventTypes != selectedEventTypes) {
autoBackupEventTypes = selectedEventTypes
}
@ -101,7 +100,8 @@ class ManageAutomaticBackupsDialog(private val activity: SimpleActivity, onSucce
dialog.dismiss()
}
}
else -> activity.toast(R.string.invalid_name)
else -> activity.toast(com.simplemobiletools.commons.R.string.invalid_name)
}
}
}
@ -109,8 +109,8 @@ class ManageAutomaticBackupsDialog(private val activity: SimpleActivity, onSucce
}
private fun selectBackupFolder() {
activity.hideKeyboard(view.backup_events_filename)
FilePickerDialog(activity, backupFolder, false, showFAB = true) { path ->
activity.hideKeyboard(binding.backupEventsFilename)
FilePickerDialog(activity, backupFolder, pickFile = false, showFAB = true) { path ->
activity.handleSAFDialog(path) { grantedSAF ->
if (!grantedSAF) {
return@handleSAFDialog
@ -122,7 +122,7 @@ class ManageAutomaticBackupsDialog(private val activity: SimpleActivity, onSucce
}
backupFolder = path
view.backup_events_folder.setText(activity.humanizePath(path))
binding.backupEventsFolder.setText(activity.humanizePath(path))
}
}
}

View File

@ -5,23 +5,19 @@ import android.content.Intent
import android.net.Uri
import android.provider.Settings
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.hideKeyboard
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.extensions.showErrorToast
import com.simplemobiletools.calendar.pro.databinding.DialogReminderWarningBinding
import com.simplemobiletools.commons.extensions.*
class ReminderWarningDialog(val activity: Activity, val callback: () -> Unit) {
private var dialog: AlertDialog? = null
private val binding by activity.viewBinding(DialogReminderWarningBinding::inflate)
init {
val view = activity.layoutInflater.inflate(R.layout.dialog_reminder_warning, null)
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { dialog, which -> dialogConfirmed() }
.setNeutralButton(R.string.settings, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> dialogConfirmed() }
.setNeutralButton(com.simplemobiletools.commons.R.string.settings, null)
.apply {
activity.setupDialogStuff(view, this, R.string.disclaimer, cancelOnTouchOutside = false) { alertDialog ->
activity.setupDialogStuff(binding.root, this, com.simplemobiletools.commons.R.string.disclaimer, cancelOnTouchOutside = false) { alertDialog ->
alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener {
redirectToSettings()
}

View File

@ -2,33 +2,32 @@ package com.simplemobiletools.calendar.pro.dialogs
import android.app.Activity
import android.app.DatePickerDialog
import android.view.View
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.databinding.DialogRepeatLimitTypePickerBinding
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.extensions.seconds
import com.simplemobiletools.calendar.pro.helpers.Formatter
import com.simplemobiletools.calendar.pro.helpers.getJavaDayOfWeekFromJoda
import com.simplemobiletools.calendar.pro.helpers.getNowSeconds
import com.simplemobiletools.commons.extensions.*
import kotlinx.android.synthetic.main.dialog_repeat_limit_type_picker.view.*
import org.joda.time.DateTime
import java.util.*
class RepeatLimitTypePickerDialog(val activity: Activity, var repeatLimit: Long, val startTS: Long, val callback: (repeatLimit: Long) -> Unit) {
private var dialog: AlertDialog? = null
private var view: View
private val binding by activity.viewBinding(DialogRepeatLimitTypePickerBinding::inflate)
init {
view = activity.layoutInflater.inflate(R.layout.dialog_repeat_limit_type_picker, null).apply {
repeat_type_date.setOnClickListener { showRepetitionLimitDialog() }
repeat_type_count.setOnClickListener { dialog_radio_view.check(R.id.repeat_type_x_times) }
repeat_type_forever.setOnClickListener {
binding.apply {
repeatTypeDate.setOnClickListener { showRepetitionLimitDialog() }
repeatTypeCount.setOnClickListener { dialogRadioView.check(R.id.repeat_type_x_times) }
repeatTypeForever.setOnClickListener {
callback(0)
dialog?.dismiss()
}
}
view.dialog_radio_view.check(getCheckedItem())
binding.dialogRadioView.check(getCheckedItem())
if (repeatLimit in 1..startTS) {
repeatLimit = startTS
@ -37,15 +36,15 @@ class RepeatLimitTypePickerDialog(val activity: Activity, var repeatLimit: Long,
updateRepeatLimitText()
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { dialogInterface, i -> confirmRepetition() }
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> confirmRepetition() }
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this) { alertDialog ->
activity.setupDialogStuff(binding.root, this) { alertDialog ->
dialog = alertDialog
activity.currentFocus?.clearFocus()
view.repeat_type_count.onTextChangeListener {
view.dialog_radio_view.check(R.id.repeat_type_x_times)
binding.repeatTypeCount.onTextChangeListener {
binding.dialogRadioView.check(R.id.repeat_type_x_times)
}
}
}
@ -54,9 +53,10 @@ class RepeatLimitTypePickerDialog(val activity: Activity, var repeatLimit: Long,
private fun getCheckedItem() = when {
repeatLimit > 0 -> R.id.repeat_type_till_date
repeatLimit < 0 -> {
view.repeat_type_count.setText((-repeatLimit).toString())
binding.repeatTypeCount.setText((-repeatLimit).toString())
R.id.repeat_type_x_times
}
else -> R.id.repeat_type_forever
}
@ -66,15 +66,15 @@ class RepeatLimitTypePickerDialog(val activity: Activity, var repeatLimit: Long,
}
val repeatLimitDateTime = Formatter.getDateTimeFromTS(repeatLimit)
view.repeat_type_date.setText(Formatter.getFullDate(activity, repeatLimitDateTime))
binding.repeatTypeDate.setText(Formatter.getFullDate(activity, repeatLimitDateTime))
}
private fun confirmRepetition() {
when (view.dialog_radio_view.checkedRadioButtonId) {
when (binding.dialogRadioView.checkedRadioButtonId) {
R.id.repeat_type_till_date -> callback(repeatLimit)
R.id.repeat_type_forever -> callback(0)
else -> {
var count = view.repeat_type_count.value
var count = binding.repeatTypeCount.value
count = if (count.isEmpty()) {
"0"
} else {
@ -88,16 +88,16 @@ class RepeatLimitTypePickerDialog(val activity: Activity, var repeatLimit: Long,
private fun showRepetitionLimitDialog() {
val repeatLimitDateTime = Formatter.getDateTimeFromTS(if (repeatLimit != 0L) repeatLimit else getNowSeconds())
val datepicker = DatePickerDialog(
val datePicker = DatePickerDialog(
activity, activity.getDatePickerDialogTheme(), repetitionLimitDateSetListener, repeatLimitDateTime.year,
repeatLimitDateTime.monthOfYear - 1, repeatLimitDateTime.dayOfMonth
)
datepicker.datePicker.firstDayOfWeek = if (activity.config.isSundayFirst) Calendar.SUNDAY else Calendar.MONDAY
datepicker.show()
datePicker.datePicker.firstDayOfWeek = getJavaDayOfWeekFromJoda(activity.config.firstDayOfWeek)
datePicker.show()
}
private val repetitionLimitDateSetListener = DatePickerDialog.OnDateSetListener { v, year, monthOfYear, dayOfMonth ->
private val repetitionLimitDateSetListener = DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
val repeatLimitDateTime = DateTime().withDate(year, monthOfYear + 1, dayOfMonth).withTime(23, 59, 59, 0)
repeatLimit = if (repeatLimitDateTime.seconds() < startTS) {
0
@ -106,6 +106,6 @@ class RepeatLimitTypePickerDialog(val activity: Activity, var repeatLimit: Long,
}
updateRepeatLimitText()
view.dialog_radio_view.check(R.id.repeat_type_till_date)
binding.dialogRadioView.check(R.id.repeat_type_till_date)
}
}

View File

@ -1,22 +1,23 @@
package com.simplemobiletools.calendar.pro.dialogs
import android.app.Activity
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.databinding.DialogVerticalLinearLayoutBinding
import com.simplemobiletools.calendar.pro.databinding.MyCheckboxBinding
import com.simplemobiletools.calendar.pro.extensions.withFirstDayOfWeekToFront
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.extensions.viewBinding
import com.simplemobiletools.commons.views.MyAppCompatCheckbox
import kotlinx.android.synthetic.main.dialog_vertical_linear_layout.view.*
class RepeatRuleWeeklyDialog(val activity: Activity, val curRepeatRule: Int, val callback: (repeatRule: Int) -> Unit) {
private val view = activity.layoutInflater.inflate(R.layout.dialog_vertical_linear_layout, null)
private val binding by activity.viewBinding(DialogVerticalLinearLayoutBinding::inflate)
init {
val days = activity.resources.getStringArray(R.array.week_days)
val checkboxes = ArrayList<MyAppCompatCheckbox>(7)
val days = activity.resources.getStringArray(com.simplemobiletools.commons.R.array.week_days)
var checkboxes = ArrayList<MyAppCompatCheckbox>(7)
for (i in 0..6) {
val pow = Math.pow(2.0, i.toDouble()).toInt()
(activity.layoutInflater.inflate(R.layout.my_checkbox, null) as MyAppCompatCheckbox).apply {
MyCheckboxBinding.inflate(activity.layoutInflater).root.apply {
isChecked = curRepeatRule and pow != 0
text = days[i]
id = pow
@ -24,27 +25,24 @@ class RepeatRuleWeeklyDialog(val activity: Activity, val curRepeatRule: Int, val
}
}
if (activity.config.isSundayFirst) {
checkboxes.add(0, checkboxes.removeAt(6))
}
checkboxes = activity.withFirstDayOfWeekToFront(checkboxes)
checkboxes.forEach {
view.dialog_vertical_linear_layout.addView(it)
binding.dialogVerticalLinearLayout.addView(it)
}
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { dialog, which -> callback(getRepeatRuleSum()) }
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> callback(getRepeatRuleSum()) }
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this)
activity.setupDialogStuff(binding.root, this)
}
}
private fun getRepeatRuleSum(): Int {
var sum = 0
val cnt = view.dialog_vertical_linear_layout.childCount
val cnt = binding.dialogVerticalLinearLayout.childCount
for (i in 0 until cnt) {
val child = view.dialog_vertical_linear_layout.getChildAt(i)
val child = binding.dialogVerticalLinearLayout.getChildAt(i)
if (child is MyAppCompatCheckbox) {
if (child.isChecked)
sum += child.id

View File

@ -1,30 +1,30 @@
package com.simplemobiletools.calendar.pro.dialogs
import android.text.TextUtils
import android.view.ViewGroup
import android.widget.RelativeLayout
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
import com.simplemobiletools.calendar.pro.databinding.CalendarItemAccountBinding
import com.simplemobiletools.calendar.pro.databinding.CalendarItemCalendarBinding
import com.simplemobiletools.calendar.pro.databinding.DialogSelectCalendarsBinding
import com.simplemobiletools.calendar.pro.extensions.calDAVHelper
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.extensions.viewBinding
import com.simplemobiletools.commons.views.MyAppCompatCheckbox
import kotlinx.android.synthetic.main.calendar_item_account.view.*
import kotlinx.android.synthetic.main.calendar_item_calendar.view.*
import kotlinx.android.synthetic.main.dialog_select_calendars.view.*
class SelectCalendarsDialog(val activity: SimpleActivity, val callback: () -> Unit) {
private var prevAccount = ""
private var view = (activity.layoutInflater.inflate(R.layout.dialog_select_calendars, null) as ViewGroup)
private val binding by activity.viewBinding(DialogSelectCalendarsBinding::inflate)
init {
val ids = activity.config.getSyncedCalendarIdsAsList()
val calendars = activity.calDAVHelper.getCalDAVCalendars("", true)
view.apply {
dialog_select_calendars_placeholder.beVisibleIf(calendars.isEmpty())
dialog_select_calendars_holder.beVisibleIf(calendars.isNotEmpty())
binding.apply {
dialogSelectCalendarsPlaceholder.beVisibleIf(calendars.isEmpty())
dialogSelectCalendarsHolder.beVisibleIf(calendars.isNotEmpty())
}
val sorted = calendars.sortedWith(compareBy({ it.accountName }, { it.displayName }))
@ -38,38 +38,37 @@ class SelectCalendarsDialog(val activity: SimpleActivity, val callback: () -> Un
}
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { dialogInterface, i -> confirmSelection() }
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> confirmSelection() }
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this, R.string.select_caldav_calendars)
activity.setupDialogStuff(binding.root, this, R.string.select_caldav_calendars)
}
}
private fun addCalendarItem(isEvent: Boolean, text: String, tag: Int = 0, shouldCheck: Boolean = false) {
val layout = if (isEvent) R.layout.calendar_item_calendar else R.layout.calendar_item_account
val calendarItem = activity.layoutInflater.inflate(layout, view.dialog_select_calendars_holder, false)
if (isEvent) {
calendarItem.calendar_item_calendar_switch.apply {
this.tag = tag
this.text = text
isChecked = shouldCheck
calendarItem.setOnClickListener {
toggle()
val itemBinding = if (isEvent) {
CalendarItemCalendarBinding.inflate(activity.layoutInflater, binding.dialogSelectCalendarsHolder, false).apply {
calendarItemCalendarSwitch.tag = tag
calendarItemCalendarSwitch.text = text
calendarItemCalendarSwitch.isChecked = shouldCheck
root.setOnClickListener {
calendarItemCalendarSwitch.toggle()
}
}
} else {
calendarItem.calendar_item_account.text = text
CalendarItemAccountBinding.inflate(activity.layoutInflater, binding.dialogSelectCalendarsHolder, false).apply {
calendarItemAccount.text = text
}
}
view.dialog_select_calendars_holder.addView(calendarItem)
binding.dialogSelectCalendarsHolder.addView(itemBinding.root)
}
private fun confirmSelection() {
val calendarIds = ArrayList<Int>()
val childCnt = view.dialog_select_calendars_holder.childCount
val childCnt = binding.dialogSelectCalendarsHolder.childCount
for (i in 0..childCnt) {
val child = view.dialog_select_calendars_holder.getChildAt(i)
val child = binding.dialogSelectCalendarsHolder.getChildAt(i)
if (child is RelativeLayout) {
val check = child.getChildAt(0)
if (check is MyAppCompatCheckbox && check.isChecked) {

View File

@ -3,26 +3,25 @@ package com.simplemobiletools.calendar.pro.dialogs
import android.app.Activity
import android.graphics.Color
import android.view.ViewGroup
import android.widget.RadioButton
import android.widget.RadioGroup
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.databinding.DialogSelectRadioGroupBinding
import com.simplemobiletools.calendar.pro.databinding.RadioButtonWithColorBinding
import com.simplemobiletools.calendar.pro.extensions.eventsHelper
import com.simplemobiletools.calendar.pro.helpers.STORED_LOCALLY_ONLY
import com.simplemobiletools.calendar.pro.models.CalDAVCalendar
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import kotlinx.android.synthetic.main.dialog_select_radio_group.view.*
import kotlinx.android.synthetic.main.radio_button_with_color.view.*
class SelectEventCalendarDialog(val activity: Activity, val calendars: List<CalDAVCalendar>, val currCalendarId: Int, val callback: (id: Int) -> Unit) {
private var dialog: AlertDialog? = null
private val radioGroup: RadioGroup
private var wasInit = false
private val binding by activity.viewBinding(DialogSelectRadioGroupBinding::inflate)
init {
val view = activity.layoutInflater.inflate(R.layout.dialog_select_radio_group, null) as ViewGroup
radioGroup = view.dialog_radio_group
radioGroup = binding.dialogRadioGroup
ensureBackgroundThread {
calendars.forEach {
@ -38,32 +37,32 @@ class SelectEventCalendarDialog(val activity: Activity, val calendars: List<CalD
}
addRadioButton(activity.getString(R.string.store_locally_only), STORED_LOCALLY_ONLY, Color.TRANSPARENT)
wasInit = true
activity.updateTextColors(view.dialog_radio_holder)
activity.updateTextColors(binding.dialogRadioHolder)
}
}
activity.getAlertDialogBuilder()
.apply {
activity.setupDialogStuff(view, this) { alertDialog ->
activity.setupDialogStuff(binding.root, this) { alertDialog ->
dialog = alertDialog
}
}
}
private fun addRadioButton(title: String, typeId: Int, color: Int) {
val view = activity.layoutInflater.inflate(R.layout.radio_button_with_color, null)
(view.dialog_radio_button as RadioButton).apply {
val radioBinding = RadioButtonWithColorBinding.inflate(activity.layoutInflater)
radioBinding.dialogRadioButton.apply {
text = title
isChecked = typeId == currCalendarId
id = typeId
}
if (typeId != STORED_LOCALLY_ONLY) {
view.dialog_radio_color.setFillWithStroke(color, activity.getProperBackgroundColor())
radioBinding.dialogRadioColor.setFillWithStroke(color, activity.getProperBackgroundColor())
}
view.setOnClickListener { viewClicked(typeId) }
radioGroup.addView(view, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
radioBinding.root.setOnClickListener { viewClicked(typeId) }
radioGroup.addView(radioBinding.root, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
}
private fun viewClicked(typeId: Int) {

View File

@ -1,28 +1,28 @@
package com.simplemobiletools.calendar.pro.dialogs
import android.app.Activity
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.adapters.CheckableColorAdapter
import com.simplemobiletools.calendar.pro.databinding.DialogSelectColorBinding
import com.simplemobiletools.calendar.pro.views.AutoGridLayoutManager
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff
import kotlinx.android.synthetic.main.dialog_select_color.view.*
import com.simplemobiletools.commons.extensions.viewBinding
class SelectEventColorDialog(val activity: Activity, val colors: IntArray, var currentColor: Int, val callback: (color: Int) -> Unit) {
private var dialog: AlertDialog? = null
private val binding by activity.viewBinding(DialogSelectColorBinding::inflate)
init {
val view = activity.layoutInflater.inflate(R.layout.dialog_select_color, null) as ViewGroup
val colorAdapter = CheckableColorAdapter(activity, colors, currentColor) { color ->
callback(color)
dialog?.dismiss()
}
view.color_grid.apply {
binding.colorGrid.apply {
val width = activity.resources.getDimensionPixelSize(R.dimen.smaller_icon_size)
val spacing = activity.resources.getDimensionPixelSize(R.dimen.small_margin) * 2
val spacing = activity.resources.getDimensionPixelSize(com.simplemobiletools.commons.R.dimen.small_margin) * 2
layoutManager = AutoGridLayoutManager(context = activity, itemWidth = width + spacing)
adapter = colorAdapter
}
@ -34,7 +34,7 @@ class SelectEventColorDialog(val activity: Activity, val colors: IntArray, var c
dialog?.dismiss()
}
activity.setupDialogStuff(view, this, R.string.event_color) {
activity.setupDialogStuff(binding.root, this, R.string.event_color) {
dialog = it
}
}

View File

@ -1,37 +1,37 @@
package com.simplemobiletools.calendar.pro.dialogs
import android.app.Activity
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.adapters.CheckableColorAdapter
import com.simplemobiletools.calendar.pro.databinding.DialogSelectColorBinding
import com.simplemobiletools.calendar.pro.views.AutoGridLayoutManager
import com.simplemobiletools.commons.dialogs.ColorPickerDialog
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff
import kotlinx.android.synthetic.main.dialog_select_color.view.*
import com.simplemobiletools.commons.extensions.viewBinding
class SelectEventTypeColorDialog(val activity: Activity, val colors: IntArray, var currentColor: Int, val callback: (color: Int) -> Unit) {
private var dialog: AlertDialog? = null
private val binding by activity.viewBinding(DialogSelectColorBinding::inflate)
init {
val view = activity.layoutInflater.inflate(R.layout.dialog_select_color, null) as ViewGroup
val colorAdapter = CheckableColorAdapter(activity, colors, currentColor) { color ->
callback(color)
dialog?.dismiss()
}
view.color_grid.apply {
binding.colorGrid.apply {
val width = activity.resources.getDimensionPixelSize(R.dimen.smaller_icon_size)
val spacing = activity.resources.getDimensionPixelSize(R.dimen.small_margin) * 2
val spacing = activity.resources.getDimensionPixelSize(com.simplemobiletools.commons.R.dimen.small_margin) * 2
layoutManager = AutoGridLayoutManager(context = activity, itemWidth = width + spacing)
adapter = colorAdapter
}
activity.getAlertDialogBuilder()
.setNegativeButton(R.string.cancel, null)
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this, R.string.color) {
activity.setupDialogStuff(binding.root, this, R.string.color) {
dialog = it
}

View File

@ -8,12 +8,11 @@ import android.widget.RadioGroup
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.ManageEventTypesActivity
import com.simplemobiletools.calendar.pro.databinding.DialogSelectEventTypeBinding
import com.simplemobiletools.calendar.pro.databinding.RadioButtonWithColorBinding
import com.simplemobiletools.calendar.pro.extensions.eventsHelper
import com.simplemobiletools.calendar.pro.models.EventType
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.views.MyCompatRadioButton
import kotlinx.android.synthetic.main.dialog_select_event_type.view.*
import kotlinx.android.synthetic.main.radio_button_with_color.view.*
class SelectEventTypeDialog(
val activity: Activity, val currEventType: Long, val showCalDAVCalendars: Boolean, val showNewEventTypeOption: Boolean,
@ -27,10 +26,11 @@ class SelectEventTypeDialog(
private var wasInit = false
private var eventTypes = ArrayList<EventType>()
private val binding by activity.viewBinding(DialogSelectEventTypeBinding::inflate)
init {
val view = activity.layoutInflater.inflate(R.layout.dialog_select_event_type, null) as ViewGroup
radioGroup = view.dialog_radio_group
view.dialog_manage_event_types.apply {
radioGroup = binding.dialogRadioGroup
binding.dialogManageEventTypes.apply {
beVisibleIf(showManageEventTypes)
setOnClickListener {
activity.startActivity(Intent(activity, ManageEventTypesActivity::class.java))
@ -38,16 +38,16 @@ class SelectEventTypeDialog(
}
}
view.dialog_radio_divider.beVisibleIf(showManageEventTypes)
binding.dialogRadioDivider.beVisibleIf(showManageEventTypes)
activity.eventsHelper.getEventTypes(activity, showOnlyWritable) {
eventTypes = it
activity.eventsHelper.getEventTypes(activity, showOnlyWritable) { eventTypes ->
this.eventTypes = eventTypes
activity.runOnUiThread {
if (addLastUsedOneAsFirstOption) {
val lastUsedEventType = EventType(LAST_USED_EVENT_TYPE_ID, activity.getString(R.string.last_used_one), Color.TRANSPARENT, 0)
addRadioButton(lastUsedEventType)
}
eventTypes.filter { showCalDAVCalendars || it.caldavCalendarId == 0 }.forEach {
this.eventTypes.filter { showCalDAVCalendars || it.caldavCalendarId == 0 }.forEach {
addRadioButton(it)
}
if (showNewEventTypeOption) {
@ -55,32 +55,32 @@ class SelectEventTypeDialog(
addRadioButton(newEventType)
}
wasInit = true
activity.updateTextColors(view.dialog_radio_holder)
activity.updateTextColors(binding.dialogRadioHolder)
}
}
activity.getAlertDialogBuilder()
.apply {
activity.setupDialogStuff(view, this) { alertDialog ->
activity.setupDialogStuff(binding.root, this) { alertDialog ->
dialog = alertDialog
}
}
}
private fun addRadioButton(eventType: EventType) {
val view = activity.layoutInflater.inflate(R.layout.radio_button_with_color, null)
(view.dialog_radio_button as MyCompatRadioButton).apply {
val radioBinding = RadioButtonWithColorBinding.inflate(activity.layoutInflater)
(radioBinding.dialogRadioButton).apply {
text = eventType.getDisplayTitle()
isChecked = eventType.id == currEventType
id = eventType.id!!.toInt()
}
if (eventType.color != Color.TRANSPARENT) {
view.dialog_radio_color.setFillWithStroke(eventType.color, activity.getProperBackgroundColor())
radioBinding.dialogRadioColor.setFillWithStroke(eventType.color, activity.getProperBackgroundColor())
}
view.setOnClickListener { viewClicked(eventType) }
radioGroup.addView(view, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
radioBinding.root.setOnClickListener { viewClicked(eventType) }
radioGroup.addView(radioBinding.root, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
}
private fun viewClicked(eventType: EventType) {

View File

@ -1,27 +1,27 @@
package com.simplemobiletools.calendar.pro.dialogs
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
import com.simplemobiletools.calendar.pro.adapters.FilterEventTypeAdapter
import com.simplemobiletools.calendar.pro.databinding.DialogFilterEventTypesBinding
import com.simplemobiletools.calendar.pro.extensions.eventsHelper
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff
import kotlinx.android.synthetic.main.dialog_filter_event_types.view.*
import com.simplemobiletools.commons.extensions.viewBinding
class SelectEventTypesDialog(val activity: SimpleActivity, selectedEventTypes: Set<String>, val callback: (HashSet<String>) -> Unit) {
private var dialog: AlertDialog? = null
private val view = activity.layoutInflater.inflate(R.layout.dialog_filter_event_types, null)
private val binding by activity.viewBinding(DialogFilterEventTypesBinding::inflate)
init {
activity.eventsHelper.getEventTypes(activity, false) {
view.filter_event_types_list.adapter = FilterEventTypeAdapter(activity, it, selectedEventTypes)
binding.filterEventTypesList.adapter = FilterEventTypeAdapter(activity, it, selectedEventTypes)
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { _, _ -> confirmEventTypes() }
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> confirmEventTypes() }
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this) { alertDialog ->
activity.setupDialogStuff(binding.root, this) { alertDialog ->
dialog = alertDialog
}
}
@ -29,7 +29,7 @@ class SelectEventTypesDialog(val activity: SimpleActivity, selectedEventTypes: S
}
private fun confirmEventTypes() {
val adapter = view.filter_event_types_list.adapter as FilterEventTypeAdapter
val adapter = binding.filterEventTypesList.adapter as FilterEventTypeAdapter
val selectedItems = adapter.getSelectedItemsList()
.map { it.toString() }
.toHashSet()

View File

@ -3,6 +3,7 @@ package com.simplemobiletools.calendar.pro.dialogs
import android.view.View
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
import com.simplemobiletools.calendar.pro.databinding.DialogSetRemindersBinding
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.helpers.ANNIVERSARY_EVENT
import com.simplemobiletools.calendar.pro.helpers.BIRTHDAY_EVENT
@ -10,7 +11,6 @@ import com.simplemobiletools.calendar.pro.helpers.OTHER_EVENT
import com.simplemobiletools.calendar.pro.helpers.REMINDER_OFF
import com.simplemobiletools.commons.dialogs.PermissionRequiredDialog
import com.simplemobiletools.commons.extensions.*
import kotlinx.android.synthetic.main.dialog_set_reminders.view.*
class SetRemindersDialog(val activity: SimpleActivity, val eventType: Int, val callback: (reminders: ArrayList<Int>) -> Unit) {
private var mReminder1Minutes = REMINDER_OFF
@ -18,47 +18,53 @@ class SetRemindersDialog(val activity: SimpleActivity, val eventType: Int, val c
private var mReminder3Minutes = REMINDER_OFF
private var isAutomatic = false
init {
val view = activity.layoutInflater.inflate(R.layout.dialog_set_reminders, null).apply {
set_reminders_image.applyColorFilter(context.getProperTextColor())
set_reminders_1.text = activity.getFormattedMinutes(mReminder1Minutes)
set_reminders_2.text = activity.getFormattedMinutes(mReminder1Minutes)
set_reminders_3.text = activity.getFormattedMinutes(mReminder1Minutes)
private val binding by activity.viewBinding(DialogSetRemindersBinding::inflate)
set_reminders_1.setOnClickListener {
init {
binding.apply {
setRemindersImage.applyColorFilter(activity.getProperTextColor())
setReminders1.text = activity.getFormattedMinutes(mReminder1Minutes)
setReminders2.text = activity.getFormattedMinutes(mReminder1Minutes)
setReminders3.text = activity.getFormattedMinutes(mReminder1Minutes)
setReminders1.setOnClickListener {
activity.handleNotificationPermission { granted ->
if (granted) {
activity.showPickSecondsDialogHelper(mReminder1Minutes, showDuringDayOption = true) {
mReminder1Minutes = if (it == -1 || it == 0) it else it / 60
set_reminders_1.text = activity.getFormattedMinutes(mReminder1Minutes)
setReminders1.text = activity.getFormattedMinutes(mReminder1Minutes)
if (mReminder1Minutes != REMINDER_OFF) {
set_reminders_2.beVisible()
setReminders2.beVisible()
}
}
} else {
PermissionRequiredDialog(activity, R.string.allow_notifications_reminders)
PermissionRequiredDialog(
activity = activity,
textId = com.simplemobiletools.commons.R.string.allow_notifications_reminders,
positiveActionCallback = { activity.openNotificationSettings() }
)
}
}
}
set_reminders_2.setOnClickListener {
setReminders2.setOnClickListener {
activity.showPickSecondsDialogHelper(mReminder2Minutes, showDuringDayOption = true) {
mReminder2Minutes = if (it == -1 || it == 0) it else it / 60
set_reminders_2.text = activity.getFormattedMinutes(mReminder2Minutes)
setReminders2.text = activity.getFormattedMinutes(mReminder2Minutes)
if (mReminder2Minutes != REMINDER_OFF) {
set_reminders_3.beVisible()
setReminders3.beVisible()
}
}
}
set_reminders_3.setOnClickListener {
setReminders3.setOnClickListener {
activity.showPickSecondsDialogHelper(mReminder3Minutes, showDuringDayOption = true) {
mReminder3Minutes = if (it == -1 || it == 0) it else it / 60
set_reminders_3.text = activity.getFormattedMinutes(mReminder3Minutes)
setReminders3.text = activity.getFormattedMinutes(mReminder3Minutes)
}
}
add_event_automatically_checkbox.apply {
addEventAutomaticallyCheckbox.apply {
visibility = if (eventType == OTHER_EVENT) View.GONE else View.VISIBLE
text = when (eventType) {
BIRTHDAY_EVENT -> activity.getString(R.string.add_birthdays_automatically)
@ -76,10 +82,10 @@ class SetRemindersDialog(val activity: SimpleActivity, val eventType: Int, val c
}
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok) { dialog, which -> dialogConfirmed() }
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> dialogConfirmed() }
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this, R.string.event_reminders)
activity.setupDialogStuff(binding.root, this, R.string.event_reminders)
}
}

View File

@ -1,9 +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.R
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
@ -12,19 +14,20 @@ import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.models.RadioItem
import java.io.File
import java.util.*
import java.io.FileOutputStream
import java.util.TreeSet
fun BaseSimpleActivity.shareEvents(ids: List<Long>) {
ensureBackgroundThread {
val file = getTempFile()
if (file == null) {
toast(R.string.unknown_error_occurred)
toast(com.simplemobiletools.commons.R.string.unknown_error_occurred)
return@ensureBackgroundThread
}
val events = eventsDB.getEventsOrTasksWithIds(ids) as ArrayList<Event>
if (events.isEmpty()) {
toast(R.string.no_items_found)
toast(com.simplemobiletools.commons.R.string.no_items_found)
}
getFileOutputStream(file.toFileDirItem(this), true) {
@ -41,7 +44,7 @@ fun BaseSimpleActivity.getTempFile(): File? {
val folder = File(cacheDir, "events")
if (!folder.exists()) {
if (!folder.mkdir()) {
toast(R.string.unknown_error_occurred)
toast(com.simplemobiletools.commons.R.string.unknown_error_occurred)
return null
}
}
@ -72,7 +75,7 @@ fun Activity.showEventRepeatIntervalDialog(curSeconds: Int, callback: (minutes:
selectedIndex = index
}
items.add(RadioItem(-1, getString(R.string.custom)))
items.add(RadioItem(-1, getString(com.simplemobiletools.commons.R.string.custom)))
RadioGroupDialog(this, items, selectedIndex) {
if (it == -1) {
@ -84,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

@ -17,12 +17,9 @@ import android.media.MediaScannerConnection
import android.net.Uri
import android.os.Bundle
import android.provider.CalendarContract
import android.view.View
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.Toast
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.app.AlarmManagerCompat
import androidx.core.app.NotificationCompat
import androidx.print.PrintHelper
import com.simplemobiletools.calendar.pro.R
@ -31,6 +28,7 @@ import com.simplemobiletools.calendar.pro.activities.EventTypePickerActivity
import com.simplemobiletools.calendar.pro.activities.SnoozeReminderActivity
import com.simplemobiletools.calendar.pro.activities.TaskActivity
import com.simplemobiletools.calendar.pro.databases.EventsDatabase
import com.simplemobiletools.calendar.pro.databinding.DayMonthlyEventViewBinding
import com.simplemobiletools.calendar.pro.helpers.*
import com.simplemobiletools.calendar.pro.helpers.Formatter
import com.simplemobiletools.calendar.pro.interfaces.EventTypesDao
@ -45,10 +43,8 @@ import com.simplemobiletools.calendar.pro.services.MarkCompletedService
import com.simplemobiletools.calendar.pro.services.SnoozeService
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.*
import kotlinx.android.synthetic.main.day_monthly_event_view.view.*
import org.joda.time.DateTime
import org.joda.time.DateTimeConstants
import org.joda.time.DateTimeZone
import org.joda.time.LocalDate
import java.io.File
import java.io.FileOutputStream
@ -114,20 +110,22 @@ fun Context.scheduleNextEventReminder(event: Event, showToasts: Boolean) {
val validReminders = event.getReminders().filter { it.type == REMINDER_NOTIFICATION }
if (validReminders.isEmpty()) {
if (showToasts) {
if (config.displayEventTypes.contains(event.eventType.toString())) {
toast(R.string.saving)
} else {
toast(R.string.saving_filtered_out, Toast.LENGTH_LONG)
}
toast(com.simplemobiletools.commons.R.string.saving)
}
return
}
val now = getNowSeconds()
val reminderSeconds = validReminders.reversed().map { it.minutes * 60 }
val isTask = event.isTask()
eventsHelper.getEvents(now, now + YEAR, event.id!!, false) { events ->
if (events.isNotEmpty()) {
for (curEvent in events) {
if (isTask && curEvent.isTaskCompleted()) {
// skip scheduling reminders for completed tasks
continue
}
for (curReminder in reminderSeconds) {
if (curEvent.getEventStartTS() - curReminder > now) {
scheduleEventIn((curEvent.getEventStartTS() - curReminder) * 1000L, curEvent, showToasts)
@ -138,37 +136,29 @@ fun Context.scheduleNextEventReminder(event: Event, showToasts: Boolean) {
}
if (showToasts) {
toast(R.string.saving)
toast(com.simplemobiletools.commons.R.string.saving)
}
}
}
fun Context.scheduleEventIn(notifTS: Long, event: Event, showToasts: Boolean) {
if (notifTS < System.currentTimeMillis()) {
fun Context.scheduleEventIn(notifyAtMillis: Long, event: Event, showToasts: Boolean) {
val now = System.currentTimeMillis()
if (notifyAtMillis < now) {
if (showToasts) {
toast(R.string.saving)
toast(com.simplemobiletools.commons.R.string.saving)
}
return
}
val newNotifTS = notifTS + 1000
val newNotifyAtMillis = notifyAtMillis + 1000
if (showToasts) {
if (config.displayEventTypes.contains(event.eventType.toString())) {
val secondsTillNotification = (newNotifTS - System.currentTimeMillis()) / 1000
val msg = String.format(getString(R.string.time_remaining), formatSecondsToTimeString(secondsTillNotification.toInt()))
toast(msg)
} else {
toast(R.string.saving_filtered_out, Toast.LENGTH_LONG)
}
val secondsTillNotification = (newNotifyAtMillis - now) / 1000
val msg = String.format(getString(com.simplemobiletools.commons.R.string.time_remaining), formatSecondsToTimeString(secondsTillNotification.toInt()))
toast(msg)
}
val pendingIntent = getNotificationIntent(event)
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
try {
AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, newNotifTS, pendingIntent)
} catch (e: Exception) {
showErrorToast(e)
}
setExactAlarm(newNotifyAtMillis, pendingIntent)
}
// hide the actual notification from the top bar
@ -197,19 +187,11 @@ fun Context.scheduleNextAutomaticBackup() {
if (config.autoBackup) {
val backupAtMillis = getNextAutoBackupTime().millis
val pendingIntent = getAutomaticBackupIntent()
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
try {
AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, backupAtMillis, pendingIntent)
} catch (e: Exception) {
showErrorToast(e)
}
setExactAlarm(backupAtMillis, pendingIntent)
}
}
fun Context.cancelScheduledAutomaticBackup() {
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.cancel(getAutomaticBackupIntent())
}
fun Context.cancelScheduledAutomaticBackup() = getAlarmManager().cancel(getAutomaticBackupIntent())
fun Context.checkAndBackupEventsOnBoot() {
if (config.autoBackup) {
@ -234,7 +216,7 @@ fun Context.backupEventsAndTasks() {
exportPastEntries = config.autoBackupPastEntries
)
if (events.isEmpty()) {
toast(R.string.no_entries_for_exporting)
toast(com.simplemobiletools.commons.R.string.no_entries_for_exporting)
config.lastAutoBackupTime = getNowSeconds()
scheduleNextAutomaticBackup()
return@ensureBackgroundThread
@ -285,8 +267,8 @@ fun Context.backupEventsAndTasks() {
IcsExporter(this).exportEvents(outputStream, events, showExportingToast = false) { result ->
when (result) {
IcsExporter.ExportResult.EXPORT_PARTIAL -> toast(R.string.exporting_some_entries_failed)
IcsExporter.ExportResult.EXPORT_FAIL -> toast(R.string.exporting_failed)
IcsExporter.ExportResult.EXPORT_PARTIAL -> toast(com.simplemobiletools.commons.R.string.exporting_some_entries_failed)
IcsExporter.ExportResult.EXPORT_FAIL -> toast(com.simplemobiletools.commons.R.string.exporting_failed)
else -> {}
}
MediaScannerConnection.scanFile(
@ -309,10 +291,10 @@ fun Context.getRepetitionText(seconds: Int) = when (seconds) {
YEAR -> getString(R.string.yearly)
else -> {
when {
seconds % YEAR == 0 -> resources.getQuantityString(R.plurals.years, seconds / YEAR, seconds / YEAR)
seconds % MONTH == 0 -> resources.getQuantityString(R.plurals.months, seconds / MONTH, seconds / MONTH)
seconds % WEEK == 0 -> resources.getQuantityString(R.plurals.weeks, seconds / WEEK, seconds / WEEK)
else -> resources.getQuantityString(R.plurals.days, seconds / DAY, seconds / DAY)
seconds % YEAR == 0 -> resources.getQuantityString(com.simplemobiletools.commons.R.plurals.years, seconds / YEAR, seconds / YEAR)
seconds % MONTH == 0 -> resources.getQuantityString(com.simplemobiletools.commons.R.plurals.months, seconds / MONTH, seconds / MONTH)
seconds % WEEK == 0 -> resources.getQuantityString(com.simplemobiletools.commons.R.plurals.weeks, seconds / WEEK, seconds / WEEK)
else -> resources.getQuantityString(com.simplemobiletools.commons.R.plurals.days, seconds / DAY, seconds / DAY)
}
}
}
@ -335,7 +317,8 @@ fun Context.notifyEvent(originalEvent: Event) {
val events = eventsHelper.getRepeatableEventsFor(currentSeconds - WEEK_SECONDS, currentSeconds + YEAR_SECONDS, event.id!!)
for (currEvent in events) {
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) {
break
}
@ -351,7 +334,7 @@ fun Context.notifyEvent(originalEvent: Event) {
val displayedStartDate = when (startDate) {
LocalDate.now() -> ""
LocalDate.now().plusDays(1) -> getString(R.string.tomorrow)
LocalDate.now().plusDays(1) -> getString(com.simplemobiletools.commons.R.string.tomorrow)
else -> "${Formatter.getDateFromCode(this, Formatter.getDayCodeFromTS(event.startTS))},"
}
@ -440,7 +423,11 @@ fun Context.getNotification(pendingIntent: PendingIntent, event: Event, content:
if (event.isTask() && !event.isTaskCompleted()) {
addAction(R.drawable.ic_task_vector, getString(R.string.mark_completed), getMarkCompletedPendingIntent(this@getNotification, event))
}
addAction(R.drawable.ic_snooze_vector, getString(R.string.snooze), getSnoozePendingIntent(this@getNotification, event))
addAction(
com.simplemobiletools.commons.R.drawable.ic_snooze_vector,
getString(com.simplemobiletools.commons.R.string.snooze),
getSnoozePendingIntent(this@getNotification, event)
)
}
if (config.vibrateOnReminder) {
@ -541,6 +528,7 @@ fun Context.getNewEventTimestampFromCode(dayCode: String, allowChangingDay: Bool
val currMinutes = calendar.get(Calendar.MINUTE)
dateTime.withMinuteOfHour(currMinutes).seconds()
}
DEFAULT_START_TIME_NEXT_FULL_HOUR -> newDateTime.seconds()
else -> {
val hours = defaultStartTime / 60
@ -573,13 +561,13 @@ fun Context.scheduleCalDAVSync(activate: Boolean) {
syncIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val alarm = getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarm.cancel(pendingIntent)
val alarmManager = getAlarmManager()
alarmManager.cancel(pendingIntent)
if (activate) {
val syncCheckInterval = 2 * AlarmManager.INTERVAL_HOUR
try {
alarm.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + syncCheckInterval, syncCheckInterval, pendingIntent)
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + syncCheckInterval, syncCheckInterval, pendingIntent)
} catch (ignored: Exception) {
}
}
@ -611,21 +599,21 @@ fun Context.addDayEvents(day: DayMonthly, linearLayout: LinearLayout, res: Resou
textColor = textColor.adjustAlpha(0.25f)
}
(View.inflate(applicationContext, R.layout.day_monthly_event_view, null) as ConstraintLayout).apply {
background = backgroundDrawable
layoutParams = eventLayoutParams
linearLayout.addView(this)
DayMonthlyEventViewBinding.inflate(LayoutInflater.from(this)).apply {
root.background = backgroundDrawable
root.layoutParams = eventLayoutParams
linearLayout.addView(root)
day_monthly_event_id.apply {
dayMonthlyEventId.apply {
setTextColor(textColor)
text = it.title.replace(" ", "\u00A0") // allow word break by char
checkViewStrikeThrough(it.isTaskCompleted())
checkViewStrikeThrough(it.shouldStrikeThrough())
contentDescription = it.title
}
day_monthly_task_image.beVisibleIf(it.isTask())
dayMonthlyTaskImage.beVisibleIf(it.isTask())
if (it.isTask()) {
day_monthly_task_image.applyColorFilter(textColor)
dayMonthlyTaskImage.applyColorFilter(textColor)
}
}
}
@ -687,7 +675,8 @@ fun Context.getEventListItems(events: List<Event>, addSectionDays: Boolean = tru
it.isPastEvent,
it.repeatInterval > 0,
it.isTask(),
it.isTaskCompleted()
it.isTaskCompleted(),
it.isAttendeeInviteDeclined()
)
listItems.add(listEvent)
}
@ -701,11 +690,13 @@ fun Context.handleEventDeleting(eventIds: List<Long>, timestamps: List<Long>, ac
eventsHelper.deleteRepeatingEventOccurrence(value, timestamps[index], true)
}
}
DELETE_FUTURE_OCCURRENCES -> {
eventIds.forEachIndexed { index, value ->
eventsHelper.addEventRepeatLimit(value, timestamps[index])
}
}
DELETE_ALL_OCCURRENCES -> {
eventsHelper.deleteEvents(eventIds.toMutableList(), true)
}
@ -723,7 +714,7 @@ fun Context.refreshCalDAVCalendars(ids: String, showToasts: Boolean) {
Bundle().apply {
putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true)
if (showToasts) {
// Assume this is a manual synchronisation when we showToasts to the user (swipe_refresh, MainMenu->refresh_caldav_calendars, ...)
// Assume this is a manual synchronisation when we showToasts to the user (swipe refresh, MainMenu-> refresh caldav calendars, ...)
putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true)
}
accounts.forEach {
@ -767,20 +758,92 @@ fun Context.editEvent(event: ListEvent) {
}
fun Context.getFirstDayOfWeek(date: DateTime): String {
var startOfWeek = date.withZoneRetainFields(DateTimeZone.UTC).withTimeAtStartOfDay()
if (!config.startWeekWithCurrentDay) {
startOfWeek = if (config.isSundayFirst) {
// a workaround for Joda-time's Monday-as-first-day-of-the-week
if (startOfWeek.dayOfWeek == DateTimeConstants.SUNDAY) {
startOfWeek
} else {
startOfWeek.minusWeeks(1).withDayOfWeek(DateTimeConstants.SUNDAY)
}
return getFirstDayOfWeekDt(date).toString()
}
fun Context.getFirstDayOfWeekDt(date: DateTime): DateTime {
val currentDate = date.withTimeAtStartOfDay()
if (config.startWeekWithCurrentDay) {
return currentDate
} else {
val firstDayOfWeek = config.firstDayOfWeek
val currentDayOfWeek = currentDate.dayOfWeek
return if (currentDayOfWeek == firstDayOfWeek) {
currentDate
} else {
startOfWeek.withDayOfWeek(DateTimeConstants.MONDAY)
// Joda-time's weeks always starts on Monday but user preferred firstDayOfWeek could be any week day
if (firstDayOfWeek < currentDayOfWeek) {
currentDate.withDayOfWeek(firstDayOfWeek)
} else {
currentDate.minusWeeks(1).withDayOfWeek(firstDayOfWeek)
}
}
}
return startOfWeek.toString()
}
fun Context.getDayOfWeekString(dayOfWeek: Int): String {
val dayOfWeekResId = when (dayOfWeek) {
DateTimeConstants.MONDAY -> com.simplemobiletools.commons.R.string.monday
DateTimeConstants.TUESDAY -> com.simplemobiletools.commons.R.string.tuesday
DateTimeConstants.WEDNESDAY -> com.simplemobiletools.commons.R.string.wednesday
DateTimeConstants.THURSDAY -> com.simplemobiletools.commons.R.string.thursday
DateTimeConstants.FRIDAY -> com.simplemobiletools.commons.R.string.friday
DateTimeConstants.SATURDAY -> com.simplemobiletools.commons.R.string.saturday
DateTimeConstants.SUNDAY -> com.simplemobiletools.commons.R.string.sunday
else -> throw IllegalArgumentException("Invalid day: $dayOfWeek")
}
return getString(dayOfWeekResId)
}
// format day bits to strings like "Mon, Tue, Wed"
fun Context.getShortDaysFromBitmask(bitMask: Int): String {
val dayBits = withFirstDayOfWeekToFront(listOf(MONDAY_BIT, TUESDAY_BIT, WEDNESDAY_BIT, THURSDAY_BIT, FRIDAY_BIT, SATURDAY_BIT, SUNDAY_BIT))
val weekDays = withFirstDayOfWeekToFront(resources.getStringArray(com.simplemobiletools.commons.R.array.week_days_short).toList())
var days = ""
dayBits.forEachIndexed { index, bit ->
if (bitMask and bit != 0) {
days += "${weekDays[index]}, "
}
}
return days.trim().trimEnd(',')
}
fun <T> Context.withFirstDayOfWeekToFront(weekItems: Collection<T>): ArrayList<T> {
val firstDayOfWeek = config.firstDayOfWeek
if (firstDayOfWeek == DateTimeConstants.MONDAY) {
return weekItems.toMutableList() as ArrayList<T>
}
val firstDayOfWeekIndex = config.firstDayOfWeek - 1
val rotatedWeekItems = weekItems.drop(firstDayOfWeekIndex) + weekItems.take(firstDayOfWeekIndex)
return rotatedWeekItems as ArrayList<T>
}
fun Context.getProperDayIndexInWeek(date: DateTime): Int {
val firstDayOfWeek = config.firstDayOfWeek
val dayOfWeek = date.dayOfWeek
val dayIndex = if (dayOfWeek >= firstDayOfWeek) {
dayOfWeek - firstDayOfWeek
} else {
dayOfWeek + (7 - firstDayOfWeek)
}
return dayIndex
}
fun Context.isWeekendIndex(dayIndex: Int): Boolean {
val firstDayOfWeek = config.firstDayOfWeek
val shiftedIndex = (dayIndex + firstDayOfWeek) % 7
val dayOfWeek = if (shiftedIndex == 0) {
DateTimeConstants.SUNDAY
} else {
shiftedIndex
}
return isWeekend(dayOfWeek)
}
fun Context.isTaskCompleted(event: Event): Boolean {
@ -799,6 +862,12 @@ fun Context.updateTaskCompletion(event: Event, completed: Boolean) {
event.flags = event.flags.removeBit(FLAG_TASK_COMPLETED)
completedTasksDB.deleteTaskWithIdAndTs(event.id!!, event.startTS)
}
// remove existing notification (if any) and schedule a new one if needed
cancelPendingIntent(event.id!!)
cancelNotification(event.id!!)
scheduleNextEventReminder(event, showToasts = false)
// mark event as "incomplete" in the main events db
eventsDB.updateTaskCompletion(event.id!!, event.flags.removeBit(FLAG_TASK_COMPLETED))
}
@ -848,3 +917,18 @@ fun Context.addImportIdsToTasks(callback: () -> Unit) {
}
}
}
fun Context.getAlarmManager() = getSystemService(Context.ALARM_SERVICE) as AlarmManager
fun Context.setExactAlarm(triggerAtMillis: Long, operation: PendingIntent, type: Int = AlarmManager.RTC_WAKEUP) {
val alarmManager = getAlarmManager()
try {
if (isSPlus() && alarmManager.canScheduleExactAlarms() || !isSPlus()) {
alarmManager.setExactAndAllowWhileIdle(type, triggerAtMillis, operation)
} else {
alarmManager.setAndAllowWhileIdle(type, triggerAtMillis, operation)
}
} catch (e: Exception) {
showErrorToast(e)
}
}

View File

@ -40,3 +40,5 @@ fun Event.maybeAdjustRepeatLimitCount(original: Event, occurrenceTS: Long) {
this.repeatLimit = newRepeatLimit
}
}
fun Event.shouldStrikeThrough() = isTaskCompleted() || isAttendeeInviteDeclined()

View File

@ -0,0 +1,5 @@
package com.simplemobiletools.calendar.pro.extensions
import com.simplemobiletools.calendar.pro.models.ListEvent
fun ListEvent.shouldStrikeThrough() = isTaskCompleted || isAttendeeInviteDeclined

View File

@ -0,0 +1,5 @@
package com.simplemobiletools.calendar.pro.extensions
import com.simplemobiletools.calendar.pro.models.MonthViewEvent
fun MonthViewEvent.shouldStrikeThrough() = isTaskCompleted || isAttendeeInviteDeclined

View File

@ -6,12 +6,12 @@ import android.os.Handler
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.RelativeLayout
import androidx.fragment.app.Fragment
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.adapters.DayEventsAdapter
import com.simplemobiletools.calendar.pro.databinding.FragmentDayBinding
import com.simplemobiletools.calendar.pro.databinding.TopNavigationBinding
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.extensions.eventsHelper
import com.simplemobiletools.calendar.pro.extensions.getViewBitmap
@ -20,8 +20,6 @@ import com.simplemobiletools.calendar.pro.helpers.*
import com.simplemobiletools.calendar.pro.interfaces.NavigationListener
import com.simplemobiletools.calendar.pro.models.Event
import com.simplemobiletools.commons.extensions.*
import kotlinx.android.synthetic.main.fragment_day.view.*
import kotlinx.android.synthetic.main.top_navigation.view.*
class DayFragment : Fragment() {
var mListener: NavigationListener? = null
@ -29,15 +27,15 @@ class DayFragment : Fragment() {
private var mDayCode = ""
private var lastHash = 0
private lateinit var mHolder: RelativeLayout
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_day, container, false)
mHolder = view.day_holder
private lateinit var binding: FragmentDayBinding
private lateinit var topNavigationBinding: TopNavigationBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = FragmentDayBinding.inflate(inflater, container, false)
topNavigationBinding = TopNavigationBinding.bind(binding.root)
mDayCode = requireArguments().getString(DAY_CODE)!!
setupButtons()
return view
return binding.root
}
override fun onResume() {
@ -48,32 +46,32 @@ class DayFragment : Fragment() {
private fun setupButtons() {
mTextColor = requireContext().getProperTextColor()
mHolder.top_left_arrow.apply {
topNavigationBinding.topLeftArrow.apply {
applyColorFilter(mTextColor)
background = null
setOnClickListener {
mListener?.goLeft()
}
val pointerLeft = requireContext().getDrawable(R.drawable.ic_chevron_left_vector)
val pointerLeft = requireContext().getDrawable(com.simplemobiletools.commons.R.drawable.ic_chevron_left_vector)
pointerLeft?.isAutoMirrored = true
setImageDrawable(pointerLeft)
}
mHolder.top_right_arrow.apply {
topNavigationBinding.topRightArrow.apply {
applyColorFilter(mTextColor)
background = null
setOnClickListener {
mListener?.goRight()
}
val pointerRight = requireContext().getDrawable(R.drawable.ic_chevron_right_vector)
val pointerRight = requireContext().getDrawable(com.simplemobiletools.commons.R.drawable.ic_chevron_right_vector)
pointerRight?.isAutoMirrored = true
setImageDrawable(pointerRight)
}
val day = Formatter.getDayTitle(requireContext(), mDayCode)
mHolder.top_value.apply {
topNavigationBinding.topValue.apply {
text = day
contentDescription = text
setOnClickListener {
@ -112,14 +110,14 @@ class DayFragment : Fragment() {
if (activity == null)
return
DayEventsAdapter(activity as SimpleActivity, events, mHolder.day_events, mDayCode) {
DayEventsAdapter(activity as SimpleActivity, events, binding.dayEvents, mDayCode) {
editEvent(it as Event)
}.apply {
mHolder.day_events.adapter = this
binding.dayEvents.adapter = this
}
if (requireContext().areSystemAnimationsEnabled) {
mHolder.day_events.scheduleLayoutAnimation()
binding.dayEvents.scheduleLayoutAnimation()
}
}
@ -133,20 +131,20 @@ class DayFragment : Fragment() {
}
fun printCurrentView() {
mHolder.apply {
top_left_arrow.beGone()
top_right_arrow.beGone()
top_value.setTextColor(resources.getColor(R.color.theme_light_text_color))
(day_events.adapter as? DayEventsAdapter)?.togglePrintMode()
topNavigationBinding.apply {
topLeftArrow.beGone()
topRightArrow.beGone()
topValue.setTextColor(resources.getColor(com.simplemobiletools.commons.R.color.theme_light_text_color))
(binding.dayEvents.adapter as? DayEventsAdapter)?.togglePrintMode()
Handler().postDelayed({
requireContext().printBitmap(day_holder.getViewBitmap())
requireContext().printBitmap(binding.dayHolder.getViewBitmap())
Handler().postDelayed({
top_left_arrow.beVisible()
top_right_arrow.beVisible()
top_value.setTextColor(requireContext().getProperTextColor())
(day_events.adapter as? DayEventsAdapter)?.togglePrintMode()
topLeftArrow.beVisible()
topRightArrow.beVisible()
topValue.setTextColor(requireContext().getProperTextColor())
(binding.dayEvents.adapter as? DayEventsAdapter)?.togglePrintMode()
}, 1000)
}, 1000)
}

View File

@ -7,9 +7,9 @@ import android.view.View
import android.view.ViewGroup
import android.widget.DatePicker
import androidx.viewpager.widget.ViewPager
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.MainActivity
import com.simplemobiletools.calendar.pro.adapters.MyDayPagerAdapter
import com.simplemobiletools.calendar.pro.databinding.FragmentDaysHolderBinding
import com.simplemobiletools.calendar.pro.helpers.DAILY_VIEW
import com.simplemobiletools.calendar.pro.helpers.DAY_CODE
import com.simplemobiletools.calendar.pro.helpers.Formatter
@ -18,13 +18,12 @@ import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.getProperBackgroundColor
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.views.MyViewPager
import kotlinx.android.synthetic.main.fragment_days_holder.view.*
import org.joda.time.DateTime
class DayFragmentsHolder : MyFragmentHolder(), NavigationListener {
private val PREFILLED_DAYS = 251
private var viewPager: MyViewPager? = null
private lateinit var viewPager: MyViewPager
private var defaultDailyPage = 0
private var todayDayCode = ""
private var currentDayCode = ""
@ -38,13 +37,13 @@ class DayFragmentsHolder : MyFragmentHolder(), NavigationListener {
todayDayCode = Formatter.getTodayCode()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_days_holder, container, false)
view.background = ColorDrawable(requireContext().getProperBackgroundColor())
viewPager = view.fragment_days_viewpager
viewPager!!.id = (System.currentTimeMillis() % 100000).toInt()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val binding = FragmentDaysHolderBinding.inflate(inflater, container, false)
binding.root.background = ColorDrawable(requireContext().getProperBackgroundColor())
viewPager = binding.fragmentDaysViewpager
viewPager.id = (System.currentTimeMillis() % 100000).toInt()
setupFragment()
return view
return binding.root
}
private fun setupFragment() {
@ -52,8 +51,7 @@ class DayFragmentsHolder : MyFragmentHolder(), NavigationListener {
val dailyAdapter = MyDayPagerAdapter(requireActivity().supportFragmentManager, codes, this)
defaultDailyPage = codes.size / 2
viewPager!!.apply {
viewPager.apply {
adapter = dailyAdapter
addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {
@ -85,11 +83,11 @@ class DayFragmentsHolder : MyFragmentHolder(), NavigationListener {
}
override fun goLeft() {
viewPager!!.currentItem = viewPager!!.currentItem - 1
viewPager.currentItem = viewPager.currentItem - 1
}
override fun goRight() {
viewPager!!.currentItem = viewPager!!.currentItem + 1
viewPager.currentItem = viewPager.currentItem + 1
}
override fun goToDateTime(dateTime: DateTime) {
@ -107,17 +105,15 @@ class DayFragmentsHolder : MyFragmentHolder(), NavigationListener {
return
}
val view = layoutInflater.inflate(getDatePickerDialogStyle(), null)
val datePicker = view.findViewById<DatePicker>(R.id.date_picker)
val datePicker = getDatePickerView()
val dateTime = getCurrentDate()!!
datePicker.init(dateTime.year, dateTime.monthOfYear - 1, dateTime.dayOfMonth, null)
activity?.getAlertDialogBuilder()!!
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.ok) { dialog, which -> dateSelected(dateTime, datePicker) }
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> dateSelected(dateTime, datePicker) }
.apply {
activity?.setupDialogStuff(view, this)
activity?.setupDialogStuff(datePicker, this)
}
}
@ -130,7 +126,7 @@ class DayFragmentsHolder : MyFragmentHolder(), NavigationListener {
}
override fun refreshEvents() {
(viewPager?.adapter as? MyDayPagerAdapter)?.updateCalendars(viewPager?.currentItem ?: 0)
(viewPager.adapter as? MyDayPagerAdapter)?.updateCalendars(viewPager.currentItem)
}
override fun shouldGoToTodayBeVisible() = currentDayCode != todayDayCode
@ -138,7 +134,7 @@ class DayFragmentsHolder : MyFragmentHolder(), NavigationListener {
override fun getNewEventDayCode() = currentDayCode
override fun printView() {
(viewPager?.adapter as? MyDayPagerAdapter)?.printCurrentView(viewPager?.currentItem ?: 0)
(viewPager.adapter as? MyDayPagerAdapter)?.printCurrentView(viewPager.currentItem)
}
override fun getCurrentDate(): DateTime? {

View File

@ -12,6 +12,7 @@ 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.adapters.EventListAdapter
import com.simplemobiletools.calendar.pro.databinding.FragmentEventListBinding
import com.simplemobiletools.calendar.pro.extensions.*
import com.simplemobiletools.calendar.pro.helpers.*
import com.simplemobiletools.calendar.pro.models.Event
@ -22,7 +23,6 @@ import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
import com.simplemobiletools.commons.views.MyLinearLayoutManager
import com.simplemobiletools.commons.views.MyRecyclerView
import kotlinx.android.synthetic.main.fragment_event_list.view.*
import org.joda.time.DateTime
class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener {
@ -35,15 +35,15 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener {
private var use24HourFormat = false
lateinit var mView: View
private lateinit var binding: FragmentEventListBinding
override val viewType = EVENTS_LIST_VIEW
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
mView = inflater.inflate(R.layout.fragment_event_list, container, false)
mView.background = ColorDrawable(requireContext().getProperBackgroundColor())
mView.calendar_events_list_holder?.id = (System.currentTimeMillis() % 100000).toInt()
mView.calendar_empty_list_placeholder_2.apply {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = FragmentEventListBinding.inflate(inflater, container, false)
binding.root.background = ColorDrawable(requireContext().getProperBackgroundColor())
binding.calendarEventsListHolder.id = (System.currentTimeMillis() % 100000).toInt()
binding.calendarEmptyListPlaceholder2.apply {
setTextColor(context.getProperPrimaryColor())
underlineText()
setOnClickListener {
@ -53,7 +53,7 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener {
}
use24HourFormat = requireContext().config.use24HourFormat
return mView
return binding.root
}
override fun onResume() {
@ -62,7 +62,7 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener {
val use24Hour = requireContext().config.use24HourFormat
if (use24Hour != use24HourFormat) {
use24HourFormat = use24Hour
(mView.calendar_events_list.adapter as? EventListAdapter)?.toggle24HourFormat(use24HourFormat)
(binding.calendarEventsList.adapter as? EventListAdapter)?.toggle24HourFormat(use24HourFormat)
}
}
@ -107,21 +107,21 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener {
return@runOnUiThread
}
val currAdapter = mView.calendar_events_list.adapter
val currAdapter = binding.calendarEventsList.adapter
if (currAdapter == null || forceRecreation) {
EventListAdapter(activity as SimpleActivity, listItems, true, this, mView.calendar_events_list) {
EventListAdapter(activity as SimpleActivity, listItems, true, this, binding.calendarEventsList) {
if (it is ListEvent) {
context?.editEvent(it)
}
}.apply {
mView.calendar_events_list.adapter = this
binding.calendarEventsList.adapter = this
}
if (requireContext().areSystemAnimationsEnabled) {
mView.calendar_events_list.scheduleLayoutAnimation()
binding.calendarEventsList.scheduleLayoutAnimation()
}
mView.calendar_events_list.endlessScrollListener = object : MyRecyclerView.EndlessScrollListener {
binding.calendarEventsList.endlessScrollListener = object : MyRecyclerView.EndlessScrollListener {
override fun updateTop() {
fetchPreviousPeriod()
}
@ -131,7 +131,7 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener {
}
}
mView.calendar_events_list.addOnScrollListener(object : RecyclerView.OnScrollListener() {
binding.calendarEventsList.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (!hasBeenScrolled) {
@ -146,10 +146,10 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener {
if (updateStatus == UPDATE_TOP) {
val item = listItems.indexOfFirst { it == bottomItemAtRefresh }
if (item != -1) {
mView.calendar_events_list.scrollToPosition(item)
binding.calendarEventsList.scrollToPosition(item)
}
} else if (updateStatus == UPDATE_BOTTOM) {
mView.calendar_events_list.smoothScrollBy(0, requireContext().resources.getDimension(R.dimen.endless_scroll_move_height).toInt())
binding.calendarEventsList.smoothScrollBy(0, requireContext().resources.getDimension(R.dimen.endless_scroll_move_height).toInt())
}
}
checkPlaceholderVisibility()
@ -157,11 +157,11 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener {
}
private fun checkPlaceholderVisibility() {
mView.calendar_empty_list_placeholder.beVisibleIf(mEvents.isEmpty())
mView.calendar_empty_list_placeholder_2.beVisibleIf(mEvents.isEmpty())
mView.calendar_events_list.beGoneIf(mEvents.isEmpty())
binding.calendarEmptyListPlaceholder.beVisibleIf(mEvents.isEmpty())
binding.calendarEmptyListPlaceholder2.beVisibleIf(mEvents.isEmpty())
binding.calendarEventsList.beGoneIf(mEvents.isEmpty())
if (activity != null) {
mView.calendar_empty_list_placeholder.setTextColor(requireActivity().getProperTextColor())
binding.calendarEmptyListPlaceholder.setTextColor(requireActivity().getProperTextColor())
if (mEvents.isEmpty()) {
val placeholderTextId = if (requireActivity().config.displayEventTypes.isEmpty()) {
R.string.everything_filtered_out
@ -169,14 +169,14 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener {
R.string.no_upcoming_events
}
mView.calendar_empty_list_placeholder.setText(placeholderTextId)
binding.calendarEmptyListPlaceholder.setText(placeholderTextId)
}
}
}
private fun fetchPreviousPeriod() {
val lastPosition = (mView.calendar_events_list.layoutManager as MyLinearLayoutManager).findLastVisibleItemPosition()
bottomItemAtRefresh = (mView.calendar_events_list.adapter as EventListAdapter).listItems[lastPosition]
val lastPosition = (binding.calendarEventsList.layoutManager as MyLinearLayoutManager).findLastVisibleItemPosition()
bottomItemAtRefresh = (binding.calendarEventsList.adapter as EventListAdapter).listItems[lastPosition]
val oldMinFetchedTS = minFetchedTS - 1
minFetchedTS -= FETCH_INTERVAL
@ -213,8 +213,8 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener {
val listItems = requireContext().getEventListItems(mEvents)
val firstNonPastSectionIndex = listItems.indexOfFirst { it is ListSectionDay && !it.isPastSection }
if (firstNonPastSectionIndex != -1) {
(mView.calendar_events_list.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(firstNonPastSectionIndex, 0)
mView.calendar_events_list.onGlobalLayout {
(binding.calendarEventsList.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(firstNonPastSectionIndex, 0)
binding.calendarEventsList.onGlobalLayout {
hasBeenScrolled = false
(activity as? MainActivity)?.refreshItems()
(activity as? MainActivity)?.refreshMenuItems()
@ -233,18 +233,18 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener {
override fun getNewEventDayCode() = Formatter.getTodayCode()
override fun printView() {
mView.apply {
if (calendar_events_list.isGone()) {
context.toast(R.string.no_items_found)
binding.apply {
if (calendarEventsList.isGone()) {
context?.toast(com.simplemobiletools.commons.R.string.no_items_found)
return@apply
}
(calendar_events_list.adapter as? EventListAdapter)?.togglePrintMode()
(calendarEventsList.adapter as? EventListAdapter)?.togglePrintMode()
Handler().postDelayed({
requireContext().printBitmap(calendar_events_list.getViewBitmap())
requireContext().printBitmap(calendarEventsList.getViewBitmap())
Handler().postDelayed({
(calendar_events_list.adapter as? EventListAdapter)?.togglePrintMode()
(calendarEventsList.adapter as? EventListAdapter)?.togglePrintMode()
}, 1000)
}, 1000)
}

View File

@ -6,12 +6,11 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.fragment.app.Fragment
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.adapters.EventListAdapter
import com.simplemobiletools.calendar.pro.databinding.FragmentMonthDayBinding
import com.simplemobiletools.calendar.pro.extensions.*
import com.simplemobiletools.calendar.pro.helpers.Config
import com.simplemobiletools.calendar.pro.helpers.DAY_CODE
@ -27,12 +26,9 @@ import com.simplemobiletools.commons.extensions.areSystemAnimationsEnabled
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.extensions.getProperTextColor
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
import kotlinx.android.synthetic.main.fragment_month_day.*
import kotlinx.android.synthetic.main.fragment_month_day.view.*
import org.joda.time.DateTime
class MonthDayFragment : Fragment(), MonthlyCalendar, RefreshRecyclerViewListener {
private var mSundayFirst = false
private var mShowWeekNumbers = false
private var mDayCode = ""
private var mSelectedDayCode = ""
@ -43,19 +39,18 @@ class MonthDayFragment : Fragment(), MonthlyCalendar, RefreshRecyclerViewListene
var listener: NavigationListener? = null
lateinit var mRes: Resources
lateinit var mHolder: ConstraintLayout
lateinit var mConfig: Config
private lateinit var mRes: Resources
private lateinit var binding: FragmentMonthDayBinding
private lateinit var mConfig: Config
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_month_day, container, false)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = FragmentMonthDayBinding.inflate(inflater, container, false)
mRes = resources
mPackageName = requireActivity().packageName
mHolder = view.month_day_calendar_holder
mDayCode = requireArguments().getString(DAY_CODE)!!
val shownMonthDateTime = Formatter.getDateTimeFromCode(mDayCode)
mHolder.month_day_selected_day_label.apply {
binding.monthDaySelectedDayLabel.apply {
text = getMonthLabel(shownMonthDateTime)
setOnClickListener {
(activity as MainActivity).showGoToDateDialog()
@ -66,7 +61,7 @@ class MonthDayFragment : Fragment(), MonthlyCalendar, RefreshRecyclerViewListene
storeStateVariables()
setupButtons()
mCalendar = MonthlyCalendarImpl(this, requireContext())
return view
return binding.root
}
override fun onPause() {
@ -91,7 +86,6 @@ class MonthDayFragment : Fragment(), MonthlyCalendar, RefreshRecyclerViewListene
private fun storeStateVariables() {
mConfig.apply {
mSundayFirst = isSundayFirst
mShowWeekNumbers = showWeekNumbers
}
}
@ -109,7 +103,7 @@ class MonthDayFragment : Fragment(), MonthlyCalendar, RefreshRecyclerViewListene
mLastHash = newHash
activity?.runOnUiThread {
mHolder.month_day_view_wrapper.updateDays(days, false) {
binding.monthDayViewWrapper.updateDays(days, false) {
mSelectedDayCode = it.code
updateVisibleEvents()
}
@ -138,26 +132,26 @@ class MonthDayFragment : Fragment(), MonthlyCalendar, RefreshRecyclerViewListene
val listItems = requireActivity().getEventListItems(filtered, mSelectedDayCode.isEmpty(), false)
if (mSelectedDayCode.isNotEmpty()) {
mHolder.month_day_selected_day_label.text = Formatter.getDateFromCode(requireActivity(), mSelectedDayCode, false)
binding.monthDaySelectedDayLabel.text = Formatter.getDateFromCode(requireActivity(), mSelectedDayCode, false)
}
activity?.runOnUiThread {
if (activity != null) {
mHolder.month_day_events_list.beVisibleIf(listItems.isNotEmpty())
mHolder.month_day_no_events_placeholder.beVisibleIf(listItems.isEmpty())
binding.monthDayEventsList.beVisibleIf(listItems.isNotEmpty())
binding.monthDayNoEventsPlaceholder.beVisibleIf(listItems.isEmpty())
val currAdapter = mHolder.month_day_events_list.adapter
val currAdapter = binding.monthDayEventsList.adapter
if (currAdapter == null) {
EventListAdapter(activity as SimpleActivity, listItems, true, this, month_day_events_list) {
EventListAdapter(activity as SimpleActivity, listItems, true, this, binding.monthDayEventsList) {
if (it is ListEvent) {
activity?.editEvent(it)
}
}.apply {
month_day_events_list.adapter = this
binding.monthDayEventsList.adapter = this
}
if (requireContext().areSystemAnimationsEnabled) {
month_day_events_list.scheduleLayoutAnimation()
binding.monthDayEventsList.scheduleLayoutAnimation()
}
} else {
(currAdapter as EventListAdapter).updateListItems(listItems)
@ -168,15 +162,15 @@ class MonthDayFragment : Fragment(), MonthlyCalendar, RefreshRecyclerViewListene
private fun setupButtons() {
val textColor = requireContext().getProperTextColor()
mHolder.apply {
month_day_selected_day_label.setTextColor(textColor)
month_day_no_events_placeholder.setTextColor(textColor)
binding.apply {
monthDaySelectedDayLabel.setTextColor(textColor)
monthDayNoEventsPlaceholder.setTextColor(textColor)
}
}
fun printCurrentView() {}
fun getNewEventDayCode() = if (mSelectedDayCode.isEmpty()) null else mSelectedDayCode
fun getNewEventDayCode() = mSelectedDayCode.ifEmpty { null }
private fun getMonthLabel(shownMonthDateTime: DateTime): String {
var month = Formatter.getMonthName(requireActivity(), shownMonthDateTime.monthOfYear)

View File

@ -8,9 +8,9 @@ import android.view.View
import android.view.ViewGroup
import android.widget.DatePicker
import androidx.viewpager.widget.ViewPager
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.MainActivity
import com.simplemobiletools.calendar.pro.adapters.MyMonthDayPagerAdapter
import com.simplemobiletools.calendar.pro.databinding.FragmentMonthsDaysHolderBinding
import com.simplemobiletools.calendar.pro.extensions.getMonthCode
import com.simplemobiletools.calendar.pro.helpers.DAY_CODE
import com.simplemobiletools.calendar.pro.helpers.Formatter
@ -21,13 +21,12 @@ import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.getProperBackgroundColor
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.views.MyViewPager
import kotlinx.android.synthetic.main.fragment_months_days_holder.view.*
import org.joda.time.DateTime
class MonthDayFragmentsHolder : MyFragmentHolder(), NavigationListener {
private val PREFILLED_MONTHS = 251
private var viewPager: MyViewPager? = null
private lateinit var viewPager: MyViewPager
private var defaultMonthlyPage = 0
private var todayDayCode = ""
private var currentDayCode = ""
@ -41,13 +40,13 @@ class MonthDayFragmentsHolder : MyFragmentHolder(), NavigationListener {
todayDayCode = Formatter.getTodayCode()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_months_days_holder, container, false)
view.background = ColorDrawable(requireContext().getProperBackgroundColor())
viewPager = view.fragment_months_days_viewpager
viewPager!!.id = (System.currentTimeMillis() % 100000).toInt()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val binding = FragmentMonthsDaysHolderBinding.inflate(inflater, container, false)
binding.root.background = ColorDrawable(requireContext().getProperBackgroundColor())
viewPager = binding.fragmentMonthsDaysViewpager
viewPager.id = (System.currentTimeMillis() % 100000).toInt()
setupFragment()
return view
return binding.root
}
private fun setupFragment() {
@ -55,14 +54,12 @@ class MonthDayFragmentsHolder : MyFragmentHolder(), NavigationListener {
val monthlyDailyAdapter = MyMonthDayPagerAdapter(requireActivity().supportFragmentManager, codes, this)
defaultMonthlyPage = codes.size / 2
viewPager!!.apply {
viewPager.apply {
adapter = monthlyDailyAdapter
addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {
}
override fun onPageScrollStateChanged(state: Int) {}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
override fun onPageSelected(position: Int) {
currentDayCode = codes[position]
@ -88,11 +85,11 @@ class MonthDayFragmentsHolder : MyFragmentHolder(), NavigationListener {
}
override fun goLeft() {
viewPager!!.currentItem = viewPager!!.currentItem - 1
viewPager.currentItem = viewPager.currentItem - 1
}
override fun goRight() {
viewPager!!.currentItem = viewPager!!.currentItem + 1
viewPager.currentItem = viewPager.currentItem + 1
}
override fun goToDateTime(dateTime: DateTime) {
@ -110,18 +107,17 @@ class MonthDayFragmentsHolder : MyFragmentHolder(), NavigationListener {
return
}
val view = layoutInflater.inflate(getDatePickerDialogStyle(), null)
val datePicker = view.findViewById<DatePicker>(R.id.date_picker)
val datePicker = getDatePickerView()
datePicker.findViewById<View>(Resources.getSystem().getIdentifier("day", "id", "android")).beGone()
val dateTime = getCurrentDate()!!
datePicker.init(dateTime.year, dateTime.monthOfYear - 1, 1, null)
activity?.getAlertDialogBuilder()!!
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.ok) { dialog, which -> datePicked(dateTime, datePicker) }
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> datePicked(dateTime, datePicker) }
.apply {
activity?.setupDialogStuff(view, this)
activity?.setupDialogStuff(datePicker, this)
}
}
@ -133,12 +129,12 @@ class MonthDayFragmentsHolder : MyFragmentHolder(), NavigationListener {
}
override fun refreshEvents() {
(viewPager?.adapter as? MyMonthDayPagerAdapter)?.updateCalendars(viewPager?.currentItem ?: 0)
(viewPager.adapter as? MyMonthDayPagerAdapter)?.updateCalendars(viewPager.currentItem)
}
override fun shouldGoToTodayBeVisible() = currentDayCode.getMonthCode() != todayDayCode.getMonthCode()
override fun getNewEventDayCode() = (viewPager?.adapter as? MyMonthDayPagerAdapter)?.getNewEventDayCode(viewPager?.currentItem ?: 0)
override fun getNewEventDayCode() = (viewPager.adapter as? MyMonthDayPagerAdapter)?.getNewEventDayCode(viewPager.currentItem)
?: if (shouldGoToTodayBeVisible()) {
currentDayCode
} else {

View File

@ -6,10 +6,10 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.RelativeLayout
import androidx.fragment.app.Fragment
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.MainActivity
import com.simplemobiletools.calendar.pro.databinding.FragmentMonthBinding
import com.simplemobiletools.calendar.pro.databinding.TopNavigationBinding
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.extensions.getViewBitmap
import com.simplemobiletools.calendar.pro.extensions.printBitmap
@ -24,13 +24,10 @@ import com.simplemobiletools.commons.extensions.applyColorFilter
import com.simplemobiletools.commons.extensions.beGone
import com.simplemobiletools.commons.extensions.beVisible
import com.simplemobiletools.commons.extensions.getProperTextColor
import kotlinx.android.synthetic.main.fragment_month.view.*
import kotlinx.android.synthetic.main.top_navigation.view.*
import org.joda.time.DateTime
class MonthFragment : Fragment(), MonthlyCalendar {
private var mTextColor = 0
private var mSundayFirst = false
private var mShowWeekNumbers = false
private var mDayCode = ""
private var mPackageName = ""
@ -39,15 +36,16 @@ class MonthFragment : Fragment(), MonthlyCalendar {
var listener: NavigationListener? = null
lateinit var mRes: Resources
lateinit var mHolder: RelativeLayout
lateinit var mConfig: Config
private lateinit var mRes: Resources
private lateinit var mConfig: Config
private lateinit var binding: FragmentMonthBinding
private lateinit var topNavigationBinding: TopNavigationBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_month, container, false)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = FragmentMonthBinding.inflate(inflater, container, false)
topNavigationBinding = TopNavigationBinding.bind(binding.root)
mRes = resources
mPackageName = requireActivity().packageName
mHolder = view.month_calendar_holder
mDayCode = requireArguments().getString(DAY_CODE)!!
mConfig = requireContext().config
storeStateVariables()
@ -55,7 +53,7 @@ class MonthFragment : Fragment(), MonthlyCalendar {
setupButtons()
mCalendar = MonthlyCalendarImpl(this, requireContext())
return view
return binding.root
}
override fun onPause() {
@ -80,7 +78,6 @@ class MonthFragment : Fragment(), MonthlyCalendar {
private fun storeStateVariables() {
mConfig.apply {
mSundayFirst = isSundayFirst
mShowWeekNumbers = showWeekNumbers
}
}
@ -98,7 +95,7 @@ class MonthFragment : Fragment(), MonthlyCalendar {
mLastHash = newHash
activity?.runOnUiThread {
mHolder.top_value.apply {
topNavigationBinding.topValue.apply {
text = month
contentDescription = text
@ -113,31 +110,31 @@ class MonthFragment : Fragment(), MonthlyCalendar {
private fun setupButtons() {
mTextColor = requireContext().getProperTextColor()
mHolder.top_left_arrow.apply {
topNavigationBinding.topLeftArrow.apply {
applyColorFilter(mTextColor)
background = null
setOnClickListener {
listener?.goLeft()
}
val pointerLeft = requireContext().getDrawable(R.drawable.ic_chevron_left_vector)
val pointerLeft = requireContext().getDrawable(com.simplemobiletools.commons.R.drawable.ic_chevron_left_vector)
pointerLeft?.isAutoMirrored = true
setImageDrawable(pointerLeft)
}
mHolder.top_right_arrow.apply {
topNavigationBinding.topRightArrow.apply {
applyColorFilter(mTextColor)
background = null
setOnClickListener {
listener?.goRight()
}
val pointerRight = requireContext().getDrawable(R.drawable.ic_chevron_right_vector)
val pointerRight = requireContext().getDrawable(com.simplemobiletools.commons.R.drawable.ic_chevron_right_vector)
pointerRight?.isAutoMirrored = true
setImageDrawable(pointerRight)
}
mHolder.top_value.apply {
topNavigationBinding.topValue.apply {
setTextColor(requireContext().getProperTextColor())
setOnClickListener {
(activity as MainActivity).showGoToDateDialog()
@ -146,24 +143,24 @@ class MonthFragment : Fragment(), MonthlyCalendar {
}
private fun updateDays(days: ArrayList<DayMonthly>) {
mHolder.month_view_wrapper.updateDays(days, true) {
binding.monthViewWrapper.updateDays(days, true) {
(activity as MainActivity).openDayFromMonthly(Formatter.getDateTimeFromCode(it.code))
}
}
fun printCurrentView() {
mHolder.apply {
top_left_arrow.beGone()
top_right_arrow.beGone()
top_value.setTextColor(resources.getColor(R.color.theme_light_text_color))
month_view_wrapper.togglePrintMode()
topNavigationBinding.apply {
topLeftArrow.beGone()
topRightArrow.beGone()
topValue.setTextColor(resources.getColor(com.simplemobiletools.commons.R.color.theme_light_text_color))
binding.monthViewWrapper.togglePrintMode()
requireContext().printBitmap(month_calendar_holder.getViewBitmap())
requireContext().printBitmap(binding.monthCalendarHolder.getViewBitmap())
top_left_arrow.beVisible()
top_right_arrow.beVisible()
top_value.setTextColor(requireContext().getProperTextColor())
month_view_wrapper.togglePrintMode()
topLeftArrow.beVisible()
topRightArrow.beVisible()
topValue.setTextColor(requireContext().getProperTextColor())
binding.monthViewWrapper.togglePrintMode()
}
}
}

View File

@ -8,9 +8,9 @@ import android.view.View
import android.view.ViewGroup
import android.widget.DatePicker
import androidx.viewpager.widget.ViewPager
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.MainActivity
import com.simplemobiletools.calendar.pro.adapters.MyMonthPagerAdapter
import com.simplemobiletools.calendar.pro.databinding.FragmentMonthsHolderBinding
import com.simplemobiletools.calendar.pro.extensions.getMonthCode
import com.simplemobiletools.calendar.pro.helpers.DAY_CODE
import com.simplemobiletools.calendar.pro.helpers.Formatter
@ -21,13 +21,12 @@ import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.getProperBackgroundColor
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.views.MyViewPager
import kotlinx.android.synthetic.main.fragment_months_holder.view.*
import org.joda.time.DateTime
class MonthFragmentsHolder : MyFragmentHolder(), NavigationListener {
private val PREFILLED_MONTHS = 251
private var viewPager: MyViewPager? = null
private lateinit var viewPager: MyViewPager
private var defaultMonthlyPage = 0
private var todayDayCode = ""
private var currentDayCode = ""
@ -41,13 +40,13 @@ class MonthFragmentsHolder : MyFragmentHolder(), NavigationListener {
todayDayCode = Formatter.getTodayCode()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_months_holder, container, false)
view.background = ColorDrawable(requireContext().getProperBackgroundColor())
viewPager = view.fragment_months_viewpager
viewPager!!.id = (System.currentTimeMillis() % 100000).toInt()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val binding = FragmentMonthsHolderBinding.inflate(inflater, container, false)
binding.root.background = ColorDrawable(requireContext().getProperBackgroundColor())
viewPager = binding.fragmentMonthsViewpager
viewPager.id = (System.currentTimeMillis() % 100000).toInt()
setupFragment()
return view
return binding.root
}
private fun setupFragment() {
@ -55,7 +54,7 @@ class MonthFragmentsHolder : MyFragmentHolder(), NavigationListener {
val monthlyAdapter = MyMonthPagerAdapter(requireActivity().supportFragmentManager, codes, this)
defaultMonthlyPage = codes.size / 2
viewPager!!.apply {
viewPager.apply {
adapter = monthlyAdapter
addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {
@ -88,11 +87,11 @@ class MonthFragmentsHolder : MyFragmentHolder(), NavigationListener {
}
override fun goLeft() {
viewPager!!.currentItem = viewPager!!.currentItem - 1
viewPager.currentItem = viewPager.currentItem - 1
}
override fun goRight() {
viewPager!!.currentItem = viewPager!!.currentItem + 1
viewPager.currentItem = viewPager.currentItem + 1
}
override fun goToDateTime(dateTime: DateTime) {
@ -110,18 +109,17 @@ class MonthFragmentsHolder : MyFragmentHolder(), NavigationListener {
return
}
val view = layoutInflater.inflate(getDatePickerDialogStyle(), null)
val datePicker = view.findViewById<DatePicker>(R.id.date_picker)
val datePicker = getDatePickerView()
datePicker.findViewById<View>(Resources.getSystem().getIdentifier("day", "id", "android")).beGone()
val dateTime = getCurrentDate()!!
datePicker.init(dateTime.year, dateTime.monthOfYear - 1, 1, null)
activity?.getAlertDialogBuilder()!!
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.ok) { dialog, which -> datePicked(dateTime, datePicker) }
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> datePicked(dateTime, datePicker) }
.apply {
activity?.setupDialogStuff(view, this)
activity?.setupDialogStuff(datePicker, this)
}
}
@ -133,7 +131,7 @@ class MonthFragmentsHolder : MyFragmentHolder(), NavigationListener {
}
override fun refreshEvents() {
(viewPager?.adapter as? MyMonthPagerAdapter)?.updateCalendars(viewPager?.currentItem ?: 0)
(viewPager.adapter as? MyMonthPagerAdapter)?.updateCalendars(viewPager.currentItem)
}
override fun shouldGoToTodayBeVisible() = currentDayCode.getMonthCode() != todayDayCode.getMonthCode()
@ -141,7 +139,7 @@ class MonthFragmentsHolder : MyFragmentHolder(), NavigationListener {
override fun getNewEventDayCode() = if (shouldGoToTodayBeVisible()) currentDayCode else todayDayCode
override fun printView() {
(viewPager?.adapter as? MyMonthPagerAdapter)?.printCurrentView(viewPager?.currentItem ?: 0)
(viewPager.adapter as? MyMonthPagerAdapter)?.printCurrentView(viewPager.currentItem)
}
override fun getCurrentDate(): DateTime? {

View File

@ -1,8 +1,10 @@
package com.simplemobiletools.calendar.pro.fragments
import android.graphics.Color
import android.widget.DatePicker
import androidx.fragment.app.Fragment
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.databinding.DatePickerDarkBinding
import com.simplemobiletools.calendar.pro.databinding.DatePickerLightBinding
import com.simplemobiletools.commons.extensions.getContrastColor
import com.simplemobiletools.commons.extensions.getProperBackgroundColor
import org.joda.time.DateTime
@ -24,11 +26,11 @@ abstract class MyFragmentHolder : Fragment() {
abstract fun getCurrentDate(): DateTime?
fun getDatePickerDialogStyle(): Int {
fun getDatePickerView(): DatePicker {
return if (requireActivity().getProperBackgroundColor().getContrastColor() == Color.WHITE) {
R.layout.date_picker_dark
DatePickerDarkBinding.inflate(layoutInflater).datePicker
} else {
R.layout.date_picker_light
DatePickerLightBinding.inflate(layoutInflater).datePicker
}
}
}

View File

@ -13,9 +13,12 @@ import android.view.*
import android.widget.ImageView
import android.widget.RelativeLayout
import androidx.collection.LongSparseArray
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.fragment.app.Fragment
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.databinding.*
import com.simplemobiletools.calendar.pro.dialogs.EditRepeatingEventDialog
import com.simplemobiletools.calendar.pro.extensions.*
import com.simplemobiletools.calendar.pro.helpers.*
import com.simplemobiletools.calendar.pro.helpers.Formatter
@ -28,10 +31,6 @@ import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.commons.views.MyTextView
import kotlinx.android.synthetic.main.fragment_week.*
import kotlinx.android.synthetic.main.fragment_week.view.*
import kotlinx.android.synthetic.main.week_event_marker.view.*
import org.joda.time.DateTime
import org.joda.time.Days
import java.util.*
@ -49,6 +48,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
var listener: WeekFragmentListener? = null
private var weekTimestamp = 0L
private var weekDateTime = DateTime()
private var rowHeight = 0f
private var todayColumnIndex = -1
private var primaryColor = 0
@ -80,8 +80,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
private var eventTimeRanges = LinkedHashMap<String, LinkedHashMap<Long, EventWeeklyView>>()
private var currentlyDraggedView: View? = null
private lateinit var inflater: LayoutInflater
private lateinit var mView: View
private lateinit var binding: FragmentWeekBinding
private lateinit var scrollView: MyScrollView
private lateinit var res: Resources
private lateinit var config: Config
@ -93,6 +92,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
rowHeight = requireContext().getWeeklyViewItemHeight()
defaultRowHeight = res.getDimension(R.dimen.weekly_view_row_height)
weekTimestamp = requireArguments().getLong(WEEK_START_TIMESTAMP)
weekDateTime = Formatter.getDateTimeFromTS(weekTimestamp)
dimPastEvents = config.dimPastEvents
dimCompletedTasks = config.dimCompletedTasks
highlightWeekends = config.highlightWeekends
@ -101,17 +101,15 @@ class WeekFragment : Fragment(), WeeklyCalendar {
}
@SuppressLint("ClickableViewAccessibility")
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
this.inflater = inflater
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val fullHeight = requireContext().getWeeklyViewItemHeight().toInt() * 24
mView = inflater.inflate(R.layout.fragment_week, container, false).apply {
scrollView = week_events_scrollview
week_horizontal_grid_holder.layoutParams.height = fullHeight
week_events_columns_holder.layoutParams.height = fullHeight
binding = FragmentWeekBinding.inflate(inflater, container, false).apply {
scrollView = weekEventsScrollview
weekHorizontalGridHolder.layoutParams.height = fullHeight
weekEventsColumnsHolder.layoutParams.height = fullHeight
val scaleDetector = getViewScaleDetector()
scrollView.setOnTouchListener { view, motionEvent ->
scrollView.setOnTouchListener { _, motionEvent ->
scaleDetector.onTouchEvent(motionEvent)
if (motionEvent.action == MotionEvent.ACTION_UP && wasScaled) {
scrollView.isScrollable = true
@ -132,7 +130,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
scrollView.onGlobalLayout {
if (fullHeight < scrollView.height) {
scrollView.layoutParams.height = fullHeight - res.getDimension(R.dimen.one_dp).toInt()
scrollView.layoutParams.height = fullHeight - res.getDimension(com.simplemobiletools.commons.R.dimen.one_dp).toInt()
}
val initialScrollY = (rowHeight * config.startWeeklyAt).toInt()
@ -140,7 +138,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
}
wasFragmentInit = true
return mView
return binding.root
}
override fun onResume() {
@ -154,7 +152,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
setupDayLabels()
updateCalendar()
if (rowHeight != 0f && mView.width != 0) {
if (rowHeight != 0f && binding.root.width != 0) {
addCurrentTimeIndicator()
}
}
@ -173,11 +171,11 @@ class WeekFragment : Fragment(), WeeklyCalendar {
super.setMenuVisibility(menuVisible)
isFragmentVisible = menuVisible
if (isFragmentVisible && wasFragmentInit) {
listener?.updateHoursTopMargin(mView.week_top_holder.height)
listener?.updateHoursTopMargin(binding.weekTopHolder.height)
checkScrollLimits(scrollView.scrollY)
// fix some glitches like at swiping from a fully scaled out fragment with all-day events to an empty one
val fullFragmentHeight = (listener?.getFullFragmentHeight() ?: 0) - mView.week_top_holder.height
val fullFragmentHeight = (listener?.getFullFragmentHeight() ?: 0) - binding.weekTopHolder.height
if (scrollView.height < fullFragmentHeight) {
config.weeklyViewItemHeightMultiplier = fullFragmentHeight / 24 / defaultRowHeight
updateViewScale()
@ -188,57 +186,58 @@ class WeekFragment : Fragment(), WeeklyCalendar {
fun updateCalendar() {
if (context != null) {
currentlyDraggedView = null
WeeklyCalendarImpl(this, requireContext()).updateWeeklyCalendar(weekTimestamp)
}
}
private fun addDayColumns() {
mView.week_events_columns_holder.removeAllViews()
binding.weekEventsColumnsHolder.removeAllViews()
(0 until config.weeklyViewDays).forEach {
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)
mView.week_events_columns_holder.addView(column)
val column = WeeklyViewDayColumnBinding.inflate(layoutInflater, binding.weekEventsColumnsHolder, false).root
column.tag = Formatter.getDayCodeFromDateTime(weekDateTime.plusDays(it))
binding.weekEventsColumnsHolder.addView(column)
dayColumns.add(column)
}
}
private fun setupDayLabels() {
var curDay = Formatter.getUTCDateTimeFromTS(weekTimestamp)
var curDay = weekDateTime
val todayCode = Formatter.getDayCodeFromDateTime(DateTime())
val screenWidth = context?.usableScreenSize?.x ?: return
val dayWidth = screenWidth / config.weeklyViewDays
val useLongerDayLabels = dayWidth > res.getDimension(R.dimen.weekly_view_min_day_label)
mView.week_letters_holder.removeAllViews()
binding.weekLettersHolder.removeAllViews()
for (i in 0 until config.weeklyViewDays) {
val dayCode = Formatter.getDayCodeFromDateTime(curDay)
val labelIDs = if (useLongerDayLabels) {
R.array.week_days_short
com.simplemobiletools.commons.R.array.week_days_short
} else {
R.array.week_day_letters
com.simplemobiletools.commons.R.array.week_day_letters
}
val dayLetters = res.getStringArray(labelIDs).toMutableList() as ArrayList<String>
val dayLetter = dayLetters[curDay.dayOfWeek - 1]
val textColor = if (isPrintVersion) {
resources.getColor(R.color.theme_light_text_color)
resources.getColor(com.simplemobiletools.commons.R.color.theme_light_text_color)
} else if (todayCode == dayCode) {
primaryColor
} else if (highlightWeekends && isWeekend(curDay.dayOfWeek, true)) {
} else if (highlightWeekends && isWeekend(curDay.dayOfWeek)) {
config.highlightWeekendsColor
} else {
requireContext().getProperTextColor()
}
val label = inflater.inflate(R.layout.weekly_view_day_letter, mView.week_letters_holder, false) as MyTextView
val label = WeeklyViewDayLetterBinding.inflate(layoutInflater, binding.weekLettersHolder, false).root
label.text = "$dayLetter\n${curDay.dayOfMonth}"
label.setTextColor(textColor)
if (todayCode == dayCode) {
todayColumnIndex = i
}
mView.week_letters_holder.addView(label)
binding.weekLettersHolder.addView(label)
curDay = curDay.plusDays(1)
}
}
@ -255,27 +254,28 @@ class WeekFragment : Fragment(), WeeklyCalendar {
layout.removeAllViews()
val gestureDetector = getViewGestureDetector(layout, index)
layout.setOnTouchListener { view, motionEvent ->
layout.setOnTouchListener { _, motionEvent ->
gestureDetector.onTouchEvent(motionEvent)
true
}
layout.setOnDragListener { view, dragEvent ->
layout.setOnDragListener { _, dragEvent ->
when (dragEvent.action) {
DragEvent.ACTION_DRAG_STARTED -> dragEvent.clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)
DragEvent.ACTION_DRAG_ENTERED,
DragEvent.ACTION_DRAG_EXITED,
DragEvent.ACTION_DRAG_LOCATION,
DragEvent.ACTION_DRAG_ENDED -> true
DragEvent.ACTION_DROP -> {
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()
ensureBackgroundThread {
val event = context?.eventsDB?.getEventOrTaskWithId(eventId)
event?.let {
val currentStartTime = Formatter.getDateTimeFromTS(it.startTS)
val startTime = Formatter.getDateTimeFromTS(weekTimestamp + index * DAY_SECONDS)
val currentStartTime = Formatter.getDateTimeFromTS(event.startTS)
val startTime = weekDateTime.plusDays(index)
.withTime(
startHour,
currentStartTime.minuteOfHour,
@ -284,14 +284,50 @@ class WeekFragment : Fragment(), WeeklyCalendar {
).seconds()
val currentEventDuration = event.endTS - event.startTS
val endTime = startTime + currentEventDuration
context?.eventsHelper?.updateEvent(
it.copy(
startTS = startTime,
endTS = endTime,
flags = it.flags.removeBit(FLAG_ALL_DAY)
), updateAtCalDAV = true, showToasts = false
) {
updateCalendar()
val newEvent = event.copy(
startTS = startTime,
endTS = endTime,
flags = event.flags.removeBit(FLAG_ALL_DAY)
)
if (event.repeatInterval > 0) {
val activity = this.activity as SimpleActivity
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()
}
}
}
}
}
@ -300,12 +336,20 @@ class WeekFragment : Fragment(), WeeklyCalendar {
false
}
}
else -> false
}
}
}
}
private fun revertDraggedEvent() {
activity?.runOnUiThread {
currentlyDraggedView?.beVisible()
currentlyDraggedView = null
}
}
private fun getViewGestureDetector(view: ViewGroup, index: Int): GestureDetector {
return GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapUp(event: MotionEvent): Boolean {
@ -313,7 +357,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
selectedGrid?.beGone()
val hour = (event.y / rowHeight).toInt()
selectedGrid = (inflater.inflate(R.layout.week_grid_item, null, false) as ImageView).apply {
selectedGrid = WeekGridItemBinding.inflate(layoutInflater).root.apply {
view.addView(this)
background = ColorDrawable(primaryColor)
layoutParams.width = view.width
@ -322,7 +366,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
applyColorFilter(primaryColor.getContrastColor())
setOnClickListener {
val timestamp = Formatter.getDateTimeFromTS(weekTimestamp + index * DAY_SECONDS).withTime(hour, 0, 0, 0).seconds()
val timestamp = weekDateTime.plusDays(index).withTime(hour, 0, 0, 0).seconds()
if (config.allowCreatingTasks) {
val items = arrayListOf(
RadioItem(TYPE_EVENT, getString(R.string.event)),
@ -425,11 +469,11 @@ class WeekFragment : Fragment(), WeeklyCalendar {
private fun updateViewScale() {
rowHeight = context?.getWeeklyViewItemHeight() ?: return
val oneDp = res.getDimension(R.dimen.one_dp).toInt()
val oneDp = res.getDimension(com.simplemobiletools.commons.R.dimen.one_dp).toInt()
val fullHeight = max(rowHeight.toInt() * 24, scrollView.height + oneDp)
scrollView.layoutParams.height = fullHeight - oneDp
mView.week_horizontal_grid_holder.layoutParams.height = fullHeight
mView.week_events_columns_holder.layoutParams.height = fullHeight
binding.weekHorizontalGridHolder.layoutParams.height = fullHeight
binding.weekEventsColumnsHolder.layoutParams.height = fullHeight
addEvents(currEvents)
}
@ -439,7 +483,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
allDayRows.clear()
eventTimeRanges.clear()
allDayRows.add(HashSet())
week_all_day_holder?.removeAllViews()
binding.weekAllDayHolder.removeAllViews()
addNewLine()
allDayEventToRow.clear()
@ -494,7 +538,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
for ((eventId, eventWeeklyView) in eventDayList) {
if (eventWeeklyView.slot == 0) {
eventWeeklyView.slot = 1
eventWeeklyView.slot_max = 1
eventWeeklyView.slotMax = 1
}
eventsCollisionChecked.add(eventId)
@ -510,8 +554,8 @@ class WeekFragment : Fragment(), WeeklyCalendar {
if (areTouching && doHaveCommonMinutes) {
if (eventWeeklyViewToCheck.slot == 0) {
val nextSlot = eventWeeklyView.slot_max + 1
val slotRange = Array(eventWeeklyView.slot_max) { it + 1 }
val nextSlot = eventWeeklyView.slotMax + 1
val slotRange = Array(eventWeeklyView.slotMax) { it + 1 }
val collisionEventWeeklyViews = eventDayList.filter { eventWeeklyView.collisions.contains(it.key) }
for ((_, collisionEventWeeklyView) in collisionEventWeeklyViews) {
if (collisionEventWeeklyView.range.intersects(eventWeeklyViewToCheck.range)) {
@ -522,13 +566,13 @@ class WeekFragment : Fragment(), WeeklyCalendar {
val slot = slotRange.minOrNull()
eventWeeklyViewToCheck.slot = slot!!
if (slot == nextSlot) {
eventWeeklyViewToCheck.slot_max = nextSlot
eventWeeklyView.slot_max = nextSlot
eventWeeklyViewToCheck.slotMax = nextSlot
eventWeeklyView.slotMax = nextSlot
for ((_, collisionEventWeeklyView) in collisionEventWeeklyViews) {
collisionEventWeeklyView.slot_max++
collisionEventWeeklyView.slotMax++
}
} else {
eventWeeklyViewToCheck.slot_max = eventWeeklyView.slot_max
eventWeeklyViewToCheck.slotMax = eventWeeklyView.slotMax
}
}
eventWeeklyView.collisions.add(toCheckId)
@ -552,11 +596,17 @@ class WeekFragment : Fragment(), WeeklyCalendar {
do {
val dayOfWeek = dayColumns.indexOfFirst { it.tag == currentDayCode }
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]
(inflater.inflate(R.layout.week_event_marker, null, false) as ConstraintLayout).apply {
WeekEventMarkerBinding.inflate(layoutInflater).apply {
var backgroundColor = if (event.color == 0) {
eventTypeColors.get(event.eventType, primaryColor)
} else {
@ -576,19 +626,19 @@ class WeekFragment : Fragment(), WeeklyCalendar {
textColor = textColor.adjustAlpha(HIGHER_ALPHA)
}
background = ColorDrawable(backgroundColor)
dayColumn.addView(this)
y = currentEventWeeklyView!!.range.lower * minuteHeight
root.background = ColorDrawable(backgroundColor)
dayColumn.addView(root)
root.y = currentEventWeeklyView!!.range.lower * minuteHeight
// compensate grid offset
y -= (currentEventWeeklyView.range.lower / 60) / 2
root.y -= (currentEventWeeklyView.range.lower / 60) / 2
week_event_task_image.beVisibleIf(event.isTask())
weekEventTaskImage.beVisibleIf(event.isTask())
if (event.isTask()) {
week_event_task_image.applyColorFilter(textColor)
weekEventTaskImage.applyColorFilter(textColor)
}
week_event_label.apply {
weekEventLabel.apply {
setTextColor(textColor)
maxLines = if (event.isTask() || event.startTS == event.endTS) {
1
@ -597,7 +647,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
}
text = event.title
checkViewStrikeThrough(event.isTaskCompleted())
checkViewStrikeThrough(event.shouldStrikeThrough())
contentDescription = text
minHeight = if (event.startTS == event.endTS) {
@ -607,16 +657,16 @@ class WeekFragment : Fragment(), WeeklyCalendar {
}
}
(layoutParams as RelativeLayout.LayoutParams).apply {
width = (dayColumn.width - 1) / currentEventWeeklyView.slot_max
x = (width * (currentEventWeeklyView.slot - 1)).toFloat()
(root.layoutParams as RelativeLayout.LayoutParams).apply {
width = (dayColumn.width - 1) / currentEventWeeklyView.slotMax
root.x = (width * (currentEventWeeklyView.slot - 1)).toFloat()
if (currentEventWeeklyView.slot > 1) {
x += density
root.x += density
width -= density
}
}
setOnClickListener {
root.setOnClickListener {
Intent(context, getActivityToOpen(event.isTask())).apply {
putExtra(EVENT_ID, event.id!!)
putExtra(EVENT_OCCURRENCE_TS, event.startTS)
@ -625,10 +675,10 @@ class WeekFragment : Fragment(), WeeklyCalendar {
}
}
setOnLongClickListener { view ->
root.setOnLongClickListener { view ->
currentlyDraggedView = 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()) {
view.startDragAndDrop(clipData, shadowBuilder, null, 0)
} else {
@ -637,7 +687,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
true
}
setOnDragListener(DragListener())
root.setOnDragListener(DragListener())
}
currentDateTime = currentDateTime.plusDays(1)
@ -651,8 +701,8 @@ class WeekFragment : Fragment(), WeeklyCalendar {
}
private fun addNewLine() {
val allDaysLine = inflater.inflate(R.layout.all_day_events_holder_line, null, false) as RelativeLayout
week_all_day_holder?.addView(allDaysLine)
val allDaysLine = AllDayEventsHolderLineBinding.inflate(layoutInflater).root
binding.weekAllDayHolder.addView(allDaysLine)
allDayHolders.add(allDaysLine)
}
@ -666,7 +716,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
}
if (currentTimeView != null) {
mView.week_events_holder.removeView(currentTimeView)
binding.weekEventsHolder.removeView(currentTimeView)
}
if (isPrintVersion) {
@ -674,21 +724,21 @@ class WeekFragment : Fragment(), WeeklyCalendar {
}
val weeklyViewDays = config.weeklyViewDays
currentTimeView = (inflater.inflate(R.layout.week_now_marker, null, false) as ImageView).apply {
currentTimeView = WeekNowMarkerBinding.inflate(layoutInflater).root.apply {
applyColorFilter(primaryColor)
mView.week_events_holder.addView(this, 0)
val extraWidth = res.getDimension(R.dimen.activity_margin).toInt()
binding.weekEventsHolder.addView(this, 0)
val extraWidth = res.getDimension(com.simplemobiletools.commons.R.dimen.activity_margin).toInt()
val markerHeight = res.getDimension(R.dimen.weekly_view_now_height).toInt()
val minuteHeight = rowHeight / 60
(layoutParams as RelativeLayout.LayoutParams).apply {
width = (mView.width / weeklyViewDays) + extraWidth
width = (binding.root.width / weeklyViewDays) + extraWidth
height = markerHeight
}
x = if (weeklyViewDays == 1) {
0f
} else {
(mView.width / weeklyViewDays * todayColumnIndex).toFloat() - extraWidth / 2f
(binding.root.width / weeklyViewDays * todayColumnIndex).toFloat() - extraWidth / 2f
}
y = minutes * minuteHeight - markerHeight / 2
@ -697,9 +747,9 @@ class WeekFragment : Fragment(), WeeklyCalendar {
}
private fun checkTopHolderHeight() {
mView.week_top_holder.onGlobalLayout {
binding.weekTopHolder.onGlobalLayout {
if (isFragmentVisible && activity != null && !mWasDestroyed) {
listener?.updateHoursTopMargin(mView.week_top_holder.height)
listener?.updateHoursTopMargin(binding.weekTopHolder.height)
}
}
}
@ -712,7 +762,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
@SuppressLint("NewApi")
private fun addAllDayEvent(event: Event) {
(inflater.inflate(R.layout.week_all_day_event_marker, null, false) as ConstraintLayout).apply {
WeekAllDayEventMarkerBinding.inflate(layoutInflater).apply {
var backgroundColor = if (event.color == 0) {
eventTypeColors.get(event.eventType, primaryColor)
} else {
@ -731,19 +781,19 @@ class WeekFragment : Fragment(), WeeklyCalendar {
textColor = textColor.adjustAlpha(HIGHER_ALPHA)
}
background = ColorDrawable(backgroundColor)
root.background = ColorDrawable(backgroundColor)
week_event_label.apply {
weekEventLabel.apply {
setTextColor(textColor)
maxLines = if (event.isTask()) 1 else 2
text = event.title
checkViewStrikeThrough(event.isTaskCompleted())
checkViewStrikeThrough(event.shouldStrikeThrough())
contentDescription = text
}
week_event_task_image.beVisibleIf(event.isTask())
weekEventTaskImage.beVisibleIf(event.isTask())
if (event.isTask()) {
week_event_task_image.applyColorFilter(textColor)
weekEventTaskImage.applyColorFilter(textColor)
}
val startDateTime = Formatter.getDateTimeFromTS(event.startTS)
@ -820,9 +870,9 @@ class WeekFragment : Fragment(), WeeklyCalendar {
return
}
allDayHolders[drawAtLine].addView(this)
val dayWidth = mView.width / config.weeklyViewDays
(layoutParams as RelativeLayout.LayoutParams).apply {
allDayHolders[drawAtLine].addView(root)
val dayWidth = binding.root.width / config.weeklyViewDays
(root.layoutParams as RelativeLayout.LayoutParams).apply {
leftMargin = dayOfWeek * dayWidth
bottomMargin = 1
width = (dayWidth) * (daysCnt + 1)
@ -830,7 +880,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
calculateExtraHeight()
setOnClickListener {
root.setOnClickListener {
Intent(context, getActivityToOpen(event.isTask())).apply {
putExtra(EVENT_ID, event.id)
putExtra(EVENT_OCCURRENCE_TS, event.startTS)
@ -842,10 +892,10 @@ class WeekFragment : Fragment(), WeeklyCalendar {
}
private fun calculateExtraHeight() {
mView.week_top_holder.onGlobalLayout {
binding.weekTopHolder.onGlobalLayout {
if (activity != null && !mWasDestroyed) {
if (isFragmentVisible) {
listener?.updateHoursTopMargin(mView.week_top_holder.height)
listener?.updateHoursTopMargin(binding.weekTopHolder.height)
}
if (!wasExtraHeightAdded) {
@ -888,13 +938,14 @@ class WeekFragment : Fragment(), WeeklyCalendar {
view.beVisible()
true
}
DragEvent.ACTION_DRAG_ENDED -> {
if (!dragEvent.result) {
view.beVisible()
}
currentlyDraggedView = null
true
}
else -> false
}
}

View File

@ -11,9 +11,10 @@ import android.widget.DatePicker
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.viewpager.widget.ViewPager
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.MainActivity
import com.simplemobiletools.calendar.pro.adapters.MyWeekPagerAdapter
import com.simplemobiletools.calendar.pro.databinding.FragmentWeekHolderBinding
import com.simplemobiletools.calendar.pro.databinding.WeeklyViewHourTextviewBinding
import com.simplemobiletools.calendar.pro.extensions.*
import com.simplemobiletools.calendar.pro.helpers.Formatter
import com.simplemobiletools.calendar.pro.helpers.WEEKLY_VIEW
@ -23,15 +24,14 @@ import com.simplemobiletools.calendar.pro.views.MyScrollView
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.WEEK_SECONDS
import com.simplemobiletools.commons.views.MyViewPager
import kotlinx.android.synthetic.main.fragment_week_holder.view.*
import org.joda.time.DateTime
class WeekFragmentsHolder : MyFragmentHolder(), WeekFragmentListener {
private val PREFILLED_WEEKS = 151
private val MAX_SEEKBAR_VALUE = 14
private var viewPager: MyViewPager? = null
private var weekHolder: ViewGroup? = null
private lateinit var binding: FragmentWeekHolderBinding
private lateinit var viewPager: MyViewPager
private var defaultWeeklyPage = 0
private var thisWeekTS = 0L
private var currentWeekTS = 0L
@ -47,27 +47,27 @@ class WeekFragmentsHolder : MyFragmentHolder(), WeekFragmentListener {
thisWeekTS = DateTime.parse(requireContext().getFirstDayOfWeek(DateTime())).seconds()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val textColor = requireContext().getProperTextColor()
weekHolder = inflater.inflate(R.layout.fragment_week_holder, container, false) as ViewGroup
weekHolder!!.background = ColorDrawable(requireContext().getProperBackgroundColor())
weekHolder!!.week_view_month_label.setTextColor(textColor)
weekHolder!!.week_view_week_number.setTextColor(textColor)
binding = FragmentWeekHolderBinding.inflate(inflater, container, false)
binding.root.background = ColorDrawable(requireContext().getProperBackgroundColor())
binding.weekViewMonthLabel.setTextColor(textColor)
binding.weekViewWeekNumber.setTextColor(textColor)
val itemHeight = requireContext().getWeeklyViewItemHeight().toInt()
weekHolder!!.week_view_hours_holder.setPadding(0, 0, 0, itemHeight)
binding.weekViewHoursHolder.setPadding(0, 0, 0, itemHeight)
viewPager = weekHolder!!.week_view_view_pager
viewPager!!.id = (System.currentTimeMillis() % 100000).toInt()
viewPager = binding.weekViewViewPager
viewPager.id = (System.currentTimeMillis() % 100000).toInt()
setupFragment()
return weekHolder
return binding.root
}
override fun onResume() {
super.onResume()
context?.config?.allowCustomizeDayCount?.let { allow ->
weekHolder!!.week_view_days_count.beVisibleIf(allow)
weekHolder!!.week_view_seekbar.beVisibleIf(allow)
binding.weekViewDaysCount.beVisibleIf(allow)
binding.weekViewSeekbar.beVisibleIf(allow)
}
setupSeekbar()
}
@ -76,9 +76,9 @@ class WeekFragmentsHolder : MyFragmentHolder(), WeekFragmentListener {
addHours()
setupWeeklyViewPager()
weekHolder!!.week_view_hours_scrollview.setOnTouchListener { view, motionEvent -> true }
binding.weekViewHoursScrollview.setOnTouchListener { _, _ -> true }
weekHolder!!.week_view_seekbar.apply {
binding.weekViewSeekbar.apply {
progress = context?.config?.weeklyViewDays ?: 7
max = MAX_SEEKBAR_VALUE
@ -100,7 +100,7 @@ class WeekFragmentsHolder : MyFragmentHolder(), WeekFragmentListener {
defaultWeeklyPage = weekTSs.size / 2
viewPager!!.apply {
viewPager.apply {
adapter = weeklyAdapter
addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {}
@ -121,25 +121,25 @@ class WeekFragmentsHolder : MyFragmentHolder(), WeekFragmentListener {
currentItem = defaultWeeklyPage
}
weekHolder!!.week_view_hours_scrollview.setOnScrollviewListener(object : MyScrollView.ScrollViewListener {
binding.weekViewHoursScrollview.setOnScrollviewListener(object : MyScrollView.ScrollViewListener {
override fun onScrollChanged(scrollView: MyScrollView, x: Int, y: Int, oldx: Int, oldy: Int) {
weekScrollY = y
weeklyAdapter.updateScrollY(viewPager!!.currentItem, y)
weeklyAdapter.updateScrollY(viewPager.currentItem, y)
}
})
}
private fun addHours(textColor: Int = requireContext().getProperTextColor()) {
val itemHeight = requireContext().getWeeklyViewItemHeight().toInt()
weekHolder!!.week_view_hours_holder.removeAllViews()
binding.weekViewHoursHolder.removeAllViews()
val hourDateTime = DateTime().withDate(2000, 1, 1).withTime(0, 0, 0, 0)
for (i in 1..23) {
val formattedHours = Formatter.getTime(requireContext(), hourDateTime.withHourOfDay(i))
(layoutInflater.inflate(R.layout.weekly_view_hour_textview, null, false) as TextView).apply {
WeeklyViewHourTextviewBinding.inflate(layoutInflater).root.apply {
text = formattedHours
setTextColor(textColor)
height = itemHeight
weekHolder!!.week_view_hours_holder.addView(this)
binding.weekViewHoursHolder.addView(this)
}
}
}
@ -159,9 +159,9 @@ class WeekFragmentsHolder : MyFragmentHolder(), WeekFragmentListener {
private fun setupWeeklyActionbarTitle(timestamp: Long) {
val startDateTime = Formatter.getDateTimeFromTS(timestamp)
val month = Formatter.getShortMonthName(requireContext(), startDateTime.monthOfYear)
weekHolder!!.week_view_month_label.text = month
binding.weekViewMonthLabel.text = month
val weekNumber = startDateTime.plusDays(3).weekOfWeekyear
weekHolder!!.week_view_week_number.text = "${getString(R.string.week_number_short)} $weekNumber"
binding.weekViewWeekNumber.text = "${getString(com.simplemobiletools.commons.R.string.week_number_short)} $weekNumber"
}
override fun goToToday() {
@ -174,37 +174,24 @@ class WeekFragmentsHolder : MyFragmentHolder(), WeekFragmentListener {
return
}
val view = layoutInflater.inflate(getDatePickerDialogStyle(), null)
val datePicker = view.findViewById<DatePicker>(R.id.date_picker)
val datePicker = getDatePickerView()
val dateTime = getCurrentDate()!!
datePicker.init(dateTime.year, dateTime.monthOfYear - 1, dateTime.dayOfMonth, null)
activity?.getAlertDialogBuilder()!!
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.ok) { dialog, which -> dateSelected(dateTime, datePicker) }
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> dateSelected(dateTime, datePicker) }
.apply {
activity?.setupDialogStuff(view, this)
activity?.setupDialogStuff(datePicker, this)
}
}
private fun dateSelected(dateTime: DateTime, datePicker: DatePicker) {
val isSundayFirst = requireContext().config.isSundayFirst
val month = datePicker.month + 1
val year = datePicker.year
val day = datePicker.dayOfMonth
var newDateTime = dateTime.withDate(year, month, day)
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()
val newDateTime = dateTime.withDate(year, month, day)
currentWeekTS = requireContext().getFirstDayOfWeekDt(newDateTime).seconds()
setupFragment()
}
@ -214,14 +201,15 @@ class WeekFragmentsHolder : MyFragmentHolder(), WeekFragmentListener {
}
// avoid seekbar width changing if the days count changes to 1, 10 etc
weekHolder!!.week_view_days_count.onGlobalLayout {
if (weekHolder!!.week_view_seekbar.width != 0) {
weekHolder!!.week_view_seekbar.layoutParams.width = weekHolder!!.week_view_seekbar.width
binding.weekViewDaysCount.onGlobalLayout {
if (binding.weekViewSeekbar.width != 0) {
binding.weekViewSeekbar.layoutParams.width = binding.weekViewSeekbar.width
}
(weekHolder!!.week_view_seekbar.layoutParams as RelativeLayout.LayoutParams).removeRule(RelativeLayout.START_OF)
(binding.weekViewSeekbar.layoutParams as RelativeLayout.LayoutParams).removeRule(RelativeLayout.START_OF)
}
updateDaysCount(context?.config?.weeklyViewDays ?: 7)
binding.weekViewDaysCount.setTextColor(requireContext().getProperTextColor())
}
private fun updateWeeklyViewDays(days: Int) {
@ -231,11 +219,11 @@ class WeekFragmentsHolder : MyFragmentHolder(), WeekFragmentListener {
}
private fun updateDaysCount(cnt: Int) {
weekHolder!!.week_view_days_count.text = requireContext().resources.getQuantityString(R.plurals.days, cnt, cnt)
binding.weekViewDaysCount.text = requireContext().resources.getQuantityString(com.simplemobiletools.commons.R.plurals.days, cnt, cnt)
}
override fun refreshEvents() {
(viewPager?.adapter as? MyWeekPagerAdapter)?.updateCalendars(viewPager!!.currentItem)
(viewPager.adapter as? MyWeekPagerAdapter)?.updateCalendars(viewPager.currentItem)
}
override fun shouldGoToTodayBeVisible() = currentWeekTS != thisWeekTS
@ -250,16 +238,16 @@ class WeekFragmentsHolder : MyFragmentHolder(), WeekFragmentListener {
}
override fun scrollTo(y: Int) {
weekHolder!!.week_view_hours_scrollview.scrollY = y
binding.weekViewHoursScrollview.scrollY = y
weekScrollY = y
}
override fun updateHoursTopMargin(margin: Int) {
weekHolder?.apply {
week_view_hours_divider?.layoutParams?.height = margin
week_view_hours_scrollview?.requestLayout()
week_view_hours_scrollview?.onGlobalLayout {
week_view_hours_scrollview.scrollY = weekScrollY
binding.apply {
weekViewHoursDivider.layoutParams?.height = margin
weekViewHoursScrollview.requestLayout()
weekViewHoursScrollview.onGlobalLayout {
weekViewHoursScrollview.scrollY = weekScrollY
}
}
}
@ -267,43 +255,43 @@ class WeekFragmentsHolder : MyFragmentHolder(), WeekFragmentListener {
override fun getCurrScrollY() = weekScrollY
override fun updateRowHeight(rowHeight: Int) {
val childCnt = weekHolder!!.week_view_hours_holder.childCount
val childCnt = binding.weekViewHoursHolder.childCount
for (i in 0..childCnt) {
val textView = weekHolder!!.week_view_hours_holder.getChildAt(i) as? TextView ?: continue
val textView = binding.weekViewHoursHolder.getChildAt(i) as? TextView ?: continue
textView.layoutParams.height = rowHeight
}
weekHolder!!.week_view_hours_holder.setPadding(0, 0, 0, rowHeight)
(viewPager!!.adapter as? MyWeekPagerAdapter)?.updateNotVisibleScaleLevel(viewPager!!.currentItem)
binding.weekViewHoursHolder.setPadding(0, 0, 0, rowHeight)
(viewPager.adapter as? MyWeekPagerAdapter)?.updateNotVisibleScaleLevel(viewPager.currentItem)
}
override fun getFullFragmentHeight() =
weekHolder!!.week_view_holder.height - weekHolder!!.week_view_seekbar.height - weekHolder!!.week_view_days_count_divider.height
binding.weekViewHolder.height - binding.weekViewSeekbar.height - binding.weekViewDaysCountDivider.height
override fun printView() {
val lightTextColor = resources.getColor(R.color.theme_light_text_color)
weekHolder!!.apply {
week_view_days_count_divider.beGone()
week_view_seekbar.beGone()
week_view_days_count.beGone()
val lightTextColor = resources.getColor(com.simplemobiletools.commons.R.color.theme_light_text_color)
binding.apply {
weekViewDaysCountDivider.beGone()
weekViewSeekbar.beGone()
weekViewDaysCount.beGone()
addHours(lightTextColor)
week_view_week_number.setTextColor(lightTextColor)
week_view_month_label.setTextColor(lightTextColor)
background = ColorDrawable(Color.WHITE)
(viewPager?.adapter as? MyWeekPagerAdapter)?.togglePrintMode(viewPager?.currentItem ?: 0)
weekViewWeekNumber.setTextColor(lightTextColor)
weekViewMonthLabel.setTextColor(lightTextColor)
root.background = ColorDrawable(Color.WHITE)
(viewPager.adapter as? MyWeekPagerAdapter)?.togglePrintMode(viewPager.currentItem)
Handler().postDelayed({
requireContext().printBitmap(weekHolder!!.week_view_holder.getViewBitmap())
requireContext().printBitmap(binding.weekViewHolder.getViewBitmap())
Handler().postDelayed({
week_view_days_count_divider.beVisible()
week_view_seekbar.beVisible()
week_view_days_count.beVisible()
week_view_week_number.setTextColor(requireContext().getProperTextColor())
week_view_month_label.setTextColor(requireContext().getProperTextColor())
weekViewDaysCountDivider.beVisible()
weekViewSeekbar.beVisible()
weekViewDaysCount.beVisible()
weekViewWeekNumber.setTextColor(requireContext().getProperTextColor())
weekViewMonthLabel.setTextColor(requireContext().getProperTextColor())
addHours()
background = ColorDrawable(requireContext().getProperBackgroundColor())
(viewPager?.adapter as? MyWeekPagerAdapter)?.togglePrintMode(viewPager?.currentItem ?: 0)
root.background = ColorDrawable(requireContext().getProperBackgroundColor())
(viewPager.adapter as? MyWeekPagerAdapter)?.togglePrintMode(viewPager.currentItem)
}, 1000)
}, 1000)
}
@ -311,7 +299,7 @@ class WeekFragmentsHolder : MyFragmentHolder(), WeekFragmentListener {
override fun getCurrentDate(): DateTime? {
return if (currentWeekTS != 0L) {
Formatter.getUTCDateTimeFromTS(currentWeekTS)
Formatter.getDateTimeFromTS(currentWeekTS)
} else {
null
}

View File

@ -5,11 +5,13 @@ import android.util.SparseArray
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.MainActivity
import com.simplemobiletools.calendar.pro.databinding.FragmentYearBinding
import com.simplemobiletools.calendar.pro.databinding.SmallMonthViewHolderBinding
import com.simplemobiletools.calendar.pro.databinding.TopNavigationBinding
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.extensions.getProperDayIndexInWeek
import com.simplemobiletools.calendar.pro.extensions.getViewBitmap
import com.simplemobiletools.calendar.pro.extensions.printBitmap
import com.simplemobiletools.calendar.pro.helpers.YEAR_LABEL
@ -17,47 +19,71 @@ import com.simplemobiletools.calendar.pro.helpers.YearlyCalendarImpl
import com.simplemobiletools.calendar.pro.interfaces.NavigationListener
import com.simplemobiletools.calendar.pro.interfaces.YearlyCalendar
import com.simplemobiletools.calendar.pro.models.DayYearly
import com.simplemobiletools.calendar.pro.views.SmallMonthView
import com.simplemobiletools.commons.extensions.applyColorFilter
import com.simplemobiletools.commons.extensions.getProperPrimaryColor
import com.simplemobiletools.commons.extensions.getProperTextColor
import com.simplemobiletools.commons.extensions.updateTextColors
import kotlinx.android.synthetic.main.fragment_year.view.*
import kotlinx.android.synthetic.main.top_navigation.view.*
import org.joda.time.DateTime
class YearFragment : Fragment(), YearlyCalendar {
private var mYear = 0
private var mSundayFirst = false
private var mFirstDayOfWeek = 0
private var isPrintVersion = false
private var lastHash = 0
private var mCalendar: YearlyCalendarImpl? = null
var listener: NavigationListener? = null
lateinit var mView: View
private lateinit var binding: FragmentYearBinding
private lateinit var topNavigationBinding: TopNavigationBinding
private lateinit var monthHolders: List<SmallMonthViewHolderBinding>
private val monthResIds = arrayOf(
com.simplemobiletools.commons.R.string.january,
com.simplemobiletools.commons.R.string.february,
com.simplemobiletools.commons.R.string.march,
com.simplemobiletools.commons.R.string.april,
com.simplemobiletools.commons.R.string.may,
com.simplemobiletools.commons.R.string.june,
com.simplemobiletools.commons.R.string.july,
com.simplemobiletools.commons.R.string.august,
com.simplemobiletools.commons.R.string.september,
com.simplemobiletools.commons.R.string.october,
com.simplemobiletools.commons.R.string.november,
com.simplemobiletools.commons.R.string.december
)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = FragmentYearBinding.inflate(inflater, container, false)
topNavigationBinding = TopNavigationBinding.bind(binding.root)
monthHolders = arrayListOf(
binding.month1Holder, binding.month2Holder, binding.month3Holder, binding.month4Holder, binding.month5Holder, binding.month6Holder,
binding.month7Holder, binding.month8Holder, binding.month9Holder, binding.month10Holder, binding.month11Holder, binding.month12Holder
).apply {
forEachIndexed { index, it ->
it.monthLabel.text = getString(monthResIds[index])
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
mView = inflater.inflate(R.layout.fragment_year, container, false)
mYear = requireArguments().getInt(YEAR_LABEL)
requireContext().updateTextColors(mView.calendar_wrapper)
requireContext().updateTextColors(binding.calendarWrapper)
setupMonths()
setupButtons()
mCalendar = YearlyCalendarImpl(this, requireContext(), mYear)
return mView
return binding.root
}
override fun onPause() {
super.onPause()
mSundayFirst = requireContext().config.isSundayFirst
mFirstDayOfWeek = requireContext().config.firstDayOfWeek
}
override fun onResume() {
super.onResume()
val sundayFirst = requireContext().config.isSundayFirst
if (sundayFirst != mSundayFirst) {
mSundayFirst = sundayFirst
val firstDayOfWeek = requireContext().config.firstDayOfWeek
if (firstDayOfWeek != mFirstDayOfWeek) {
mFirstDayOfWeek = firstDayOfWeek
setupMonths()
}
updateCalendar()
@ -68,65 +94,58 @@ class YearFragment : Fragment(), YearlyCalendar {
}
private fun setupMonths() {
val dateTime = DateTime().withDate(mYear, 2, 1).withHourOfDay(12)
val days = dateTime.dayOfMonth().maximumValue
mView.month_2.setDays(days)
val now = DateTime()
for (i in 1..12) {
val monthView = mView.findViewById<SmallMonthView>(resources.getIdentifier("month_$i", "id", requireContext().packageName))
var dayOfWeek = dateTime.withMonthOfYear(i).dayOfWeek().get()
if (!mSundayFirst) {
dayOfWeek--
}
val monthLabel = mView.findViewById<TextView>(resources.getIdentifier("month_${i}_label", "id", requireContext().packageName))
val dateTime = DateTime().withYear(mYear).withHourOfDay(12)
monthHolders.forEachIndexed { index, monthHolder ->
val monthOfYear = index + 1
val monthView = monthHolder.smallMonthView
val curTextColor = when {
isPrintVersion -> resources.getColor(R.color.theme_light_text_color)
isPrintVersion -> resources.getColor(com.simplemobiletools.commons.R.color.theme_light_text_color)
else -> requireContext().getProperTextColor()
}
monthLabel.setTextColor(curTextColor)
monthView.firstDay = dayOfWeek
monthHolder.monthLabel.setTextColor(curTextColor)
val firstDayOfMonth = dateTime.withMonthOfYear(monthOfYear).withDayOfMonth(1)
monthView.firstDay = requireContext().getProperDayIndexInWeek(firstDayOfMonth)
val numberOfDays = dateTime.withMonthOfYear(monthOfYear).dayOfMonth().maximumValue
monthView.setDays(numberOfDays)
monthView.setOnClickListener {
(activity as MainActivity).openMonthFromYearly(DateTime().withDate(mYear, i, 1))
(activity as MainActivity).openMonthFromYearly(DateTime().withDate(mYear, monthOfYear, 1))
}
}
if (!isPrintVersion) {
val now = DateTime()
markCurrentMonth(now)
}
}
private fun setupButtons() {
val textColor = requireContext().getProperTextColor()
mView.top_left_arrow.apply {
topNavigationBinding.topLeftArrow.apply {
applyColorFilter(textColor)
background = null
setOnClickListener {
listener?.goLeft()
}
val pointerLeft = requireContext().getDrawable(R.drawable.ic_chevron_left_vector)
val pointerLeft = requireContext().getDrawable(com.simplemobiletools.commons.R.drawable.ic_chevron_left_vector)
pointerLeft?.isAutoMirrored = true
setImageDrawable(pointerLeft)
}
mView.top_right_arrow.apply {
topNavigationBinding.topRightArrow.apply {
applyColorFilter(textColor)
background = null
setOnClickListener {
listener?.goRight()
}
val pointerRight = requireContext().getDrawable(R.drawable.ic_chevron_right_vector)
val pointerRight = requireContext().getDrawable(com.simplemobiletools.commons.R.drawable.ic_chevron_right_vector)
pointerRight?.isAutoMirrored = true
setImageDrawable(pointerRight)
}
mView.top_value.apply {
topNavigationBinding.topValue.apply {
setTextColor(requireContext().getProperTextColor())
setOnClickListener {
(activity as MainActivity).showGoToDateDialog()
@ -136,11 +155,10 @@ class YearFragment : Fragment(), YearlyCalendar {
private fun markCurrentMonth(now: DateTime) {
if (now.year == mYear) {
val monthLabel = mView.findViewById<TextView>(resources.getIdentifier("month_${now.monthOfYear}_label", "id", requireContext().packageName))
monthLabel.setTextColor(requireContext().getProperPrimaryColor())
val monthView = mView.findViewById<SmallMonthView>(resources.getIdentifier("month_${now.monthOfYear}", "id", requireContext().packageName))
monthView.todaysId = now.dayOfMonth
val monthOfYear = now.monthOfYear
val monthHolder = monthHolders[monthOfYear - 1]
monthHolder.monthLabel.setTextColor(requireContext().getProperPrimaryColor())
monthHolder.smallMonthView.todaysId = now.dayOfMonth
}
}
@ -154,13 +172,14 @@ class YearFragment : Fragment(), YearlyCalendar {
}
lastHash = hashCode
for (i in 1..12) {
val monthView = mView.findViewById<SmallMonthView>(resources.getIdentifier("month_$i", "id", requireContext().packageName))
monthView.setEvents(events.get(i))
monthHolders.forEachIndexed { index, monthHolder ->
val monthView = monthHolder.smallMonthView
val monthOfYear = index + 1
monthView.setEvents(events.get(monthOfYear))
}
mView.top_value.post {
mView.top_value.text = mYear.toString()
topNavigationBinding.topValue.post {
topNavigationBinding.topValue.text = mYear.toString()
}
}
@ -169,7 +188,7 @@ class YearFragment : Fragment(), YearlyCalendar {
setupMonths()
toggleSmallMonthPrintModes()
requireContext().printBitmap(mView.calendar_wrapper.getViewBitmap())
requireContext().printBitmap(binding.calendarWrapper.getViewBitmap())
isPrintVersion = false
setupMonths()
@ -177,9 +196,8 @@ class YearFragment : Fragment(), YearlyCalendar {
}
private fun toggleSmallMonthPrintModes() {
for (i in 1..12) {
val monthView = mView.findViewById<SmallMonthView>(resources.getIdentifier("month_$i", "id", requireContext().packageName))
monthView.togglePrintMode()
monthHolders.forEach {
it.smallMonthView.togglePrintMode()
}
}
}

View File

@ -8,9 +8,9 @@ import android.view.View
import android.view.ViewGroup
import android.widget.DatePicker
import androidx.viewpager.widget.ViewPager
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.MainActivity
import com.simplemobiletools.calendar.pro.adapters.MyYearPagerAdapter
import com.simplemobiletools.calendar.pro.databinding.FragmentYearsHolderBinding
import com.simplemobiletools.calendar.pro.helpers.Formatter
import com.simplemobiletools.calendar.pro.helpers.YEARLY_VIEW
import com.simplemobiletools.calendar.pro.helpers.YEAR_TO_OPEN
@ -20,13 +20,12 @@ import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.getProperBackgroundColor
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.views.MyViewPager
import kotlinx.android.synthetic.main.fragment_years_holder.view.*
import org.joda.time.DateTime
class YearFragmentsHolder : MyFragmentHolder(), NavigationListener {
private val PREFILLED_YEARS = 61
private var viewPager: MyViewPager? = null
private lateinit var viewPager: MyViewPager
private var defaultYearlyPage = 0
private var todayYear = 0
private var currentYear = 0
@ -41,13 +40,13 @@ class YearFragmentsHolder : MyFragmentHolder(), NavigationListener {
todayYear = DateTime().toString(Formatter.YEAR_PATTERN).toInt()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_years_holder, container, false)
view.background = ColorDrawable(requireContext().getProperBackgroundColor())
viewPager = view.fragment_years_viewpager
viewPager!!.id = (System.currentTimeMillis() % 100000).toInt()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val binding = FragmentYearsHolderBinding.inflate(inflater, container, false)
binding.root.background = ColorDrawable(requireContext().getProperBackgroundColor())
viewPager = binding.fragmentYearsViewpager
viewPager.id = (System.currentTimeMillis() % 100000).toInt()
setupFragment()
return view
return binding.root
}
private fun setupFragment() {
@ -55,7 +54,7 @@ class YearFragmentsHolder : MyFragmentHolder(), NavigationListener {
val yearlyAdapter = MyYearPagerAdapter(requireActivity().supportFragmentManager, years, this)
defaultYearlyPage = years.size / 2
viewPager?.apply {
viewPager.apply {
adapter = yearlyAdapter
addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {}
@ -82,11 +81,11 @@ class YearFragmentsHolder : MyFragmentHolder(), NavigationListener {
}
override fun goLeft() {
viewPager!!.currentItem = viewPager!!.currentItem - 1
viewPager.currentItem = viewPager.currentItem - 1
}
override fun goRight() {
viewPager!!.currentItem = viewPager!!.currentItem + 1
viewPager.currentItem = viewPager.currentItem + 1
}
override fun goToDateTime(dateTime: DateTime) {}
@ -101,8 +100,7 @@ class YearFragmentsHolder : MyFragmentHolder(), NavigationListener {
return
}
val view = layoutInflater.inflate(getDatePickerDialogStyle(), null)
val datePicker = view.findViewById<DatePicker>(R.id.date_picker)
val datePicker = getDatePickerView()
datePicker.findViewById<View>(Resources.getSystem().getIdentifier("day", "id", "android")).beGone()
datePicker.findViewById<View>(Resources.getSystem().getIdentifier("month", "id", "android")).beGone()
@ -110,10 +108,10 @@ class YearFragmentsHolder : MyFragmentHolder(), NavigationListener {
datePicker.init(dateTime.year, dateTime.monthOfYear - 1, 1, null)
activity?.getAlertDialogBuilder()!!
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.ok) { dialog, which -> datePicked(datePicker) }
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> datePicked(datePicker) }
.apply {
activity?.setupDialogStuff(view, this)
activity?.setupDialogStuff(datePicker, this)
}
}
@ -126,7 +124,7 @@ class YearFragmentsHolder : MyFragmentHolder(), NavigationListener {
}
override fun refreshEvents() {
(viewPager?.adapter as? MyYearPagerAdapter)?.updateCalendars(viewPager?.currentItem ?: 0)
(viewPager.adapter as? MyYearPagerAdapter)?.updateCalendars(viewPager.currentItem)
}
override fun shouldGoToTodayBeVisible() = currentYear != todayYear
@ -134,7 +132,7 @@ class YearFragmentsHolder : MyFragmentHolder(), NavigationListener {
override fun getNewEventDayCode() = Formatter.getTodayCode()
override fun printView() {
(viewPager?.adapter as? MyYearPagerAdapter)?.printCurrentView(viewPager?.currentItem ?: 0)
(viewPager.adapter as? MyYearPagerAdapter)?.printCurrentView(viewPager.currentItem)
}
override fun getCurrentDate() = null

View File

@ -7,8 +7,6 @@ import android.content.Context
import android.graphics.Color
import android.provider.CalendarContract.*
import android.widget.Toast
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.extensions.*
import com.simplemobiletools.calendar.pro.models.*
@ -46,7 +44,7 @@ class CalDAVHelper(val context: Context) {
}
}
fetchCalDAVCalendarEvents(calendar.id, localEventType.id!!, showToasts)
fetchCalDAVCalendarEvents(calendar, localEventType.id!!, showToasts)
}
if (scheduleNextSync) {
@ -151,7 +149,9 @@ class CalDAVHelper(val context: Context) {
}
@SuppressLint("MissingPermission")
private fun fetchCalDAVCalendarEvents(calendarId: Int, eventTypeId: Long, showToasts: Boolean) {
private fun fetchCalDAVCalendarEvents(calendar: CalDAVCalendar, eventTypeId: Long, showToasts: Boolean) {
val calendarId = calendar.id
val importIdsMap = HashMap<String, Event>()
val fetchedEventIds = ArrayList<String>()
@ -213,7 +213,7 @@ class CalDAVHelper(val context: Context) {
val originalId = cursor.getStringValue(Events.ORIGINAL_ID)
val originalInstanceTime = cursor.getLongValue(Events.ORIGINAL_INSTANCE_TIME)
val reminders = getCalDAVEventReminders(id)
val attendees = Gson().toJson(getCalDAVEventAttendees(id))
val attendees = getCalDAVEventAttendees(id, calendar)
val availability = cursor.getIntValue(Events.AVAILABILITY)
val status = cursor.getIntValue(Events.STATUS)
val color = cursor.getIntValueOrNull(Events.EVENT_COLOR)
@ -261,7 +261,7 @@ class CalDAVHelper(val context: Context) {
// add this event to the parent event's list of exceptions
if (!parentEvent.repetitionExceptions.contains(originalDayCode)) {
parentEvent.addRepetitionException(originalDayCode)
eventsHelper.insertEvent(parentEvent, addToCalDAV = false, showToasts = false)
eventsHelper.insertEvent(parentEvent, addToCalDAV = false, showToasts = false, enableEventType = false)
}
// store the event in the local db only if it is an occurrence that has been modified and not deleted
@ -271,7 +271,7 @@ class CalDAVHelper(val context: Context) {
event.id = storedEventId
}
event.parentId = parentEvent.id!!
eventsHelper.insertEvent(event, addToCalDAV = false, showToasts = false)
eventsHelper.insertEvent(event, addToCalDAV = false, showToasts = false, enableEventType = false)
} else {
// delete the deleted exception event from local db
val storedEventId = context.eventsDB.getEventIdWithImportId(importId)
@ -298,11 +298,11 @@ class CalDAVHelper(val context: Context) {
val offset = DateTimeZone.getDefault().getOffset(System.currentTimeMillis())
val dt = formatter.parseDateTime(it).plusMillis(offset)
val dayCode = Formatter.getDayCodeFromDateTime(dt)
event.repetitionExceptions.add(dayCode)
event.addRepetitionException(dayCode)
} else {
val potentialTS = it.substring(0, 8)
if (potentialTS.areDigitsOnly()) {
event.repetitionExceptions.add(potentialTS)
event.addRepetitionException(potentialTS)
}
}
}
@ -321,12 +321,12 @@ class CalDAVHelper(val context: Context) {
if (existingEvent.hashCode() != event.hashCode() && title.isNotEmpty()) {
event.id = originalEventId
eventsHelper.updateEvent(event, updateAtCalDAV = false, showToasts = false)
eventsHelper.updateEvent(event, updateAtCalDAV = false, showToasts = false, enableEventType = false)
}
} else {
if (title.isNotEmpty()) {
importIdsMap[event.importId] = event
eventsHelper.insertEvent(event, addToCalDAV = false, showToasts = false)
eventsHelper.insertEvent(event, addToCalDAV = false, showToasts = false, enableEventType = false)
}
}
}
@ -387,15 +387,14 @@ class CalDAVHelper(val context: Context) {
try {
context.contentResolver.insert(Reminders.CONTENT_URI, contentValues)
} catch (e: Exception) {
context.toast(R.string.unknown_error_occurred)
context.toast(com.simplemobiletools.commons.R.string.unknown_error_occurred)
}
}
}
private fun setupCalDAVEventAttendees(event: Event) {
clearEventAttendees(event)
val attendees = Gson().fromJson<ArrayList<Attendee>>(event.attendees, object : TypeToken<List<Attendee>>() {}.type) ?: ArrayList()
attendees.forEach {
event.attendees.forEach {
val contentValues = ContentValues().apply {
put(Attendees.ATTENDEE_NAME, it.name)
put(Attendees.ATTENDEE_EMAIL, it.email)
@ -407,7 +406,7 @@ class CalDAVHelper(val context: Context) {
try {
context.contentResolver.insert(Attendees.CONTENT_URI, contentValues)
} catch (e: Exception) {
context.toast(R.string.unknown_error_occurred)
context.toast(com.simplemobiletools.commons.R.string.unknown_error_occurred)
}
}
}
@ -573,7 +572,7 @@ class CalDAVHelper(val context: Context) {
return reminders.sortedBy { it.minutes }
}
private fun getCalDAVEventAttendees(eventId: Long): List<Attendee> {
private fun getCalDAVEventAttendees(eventId: Long, calendar: CalDAVCalendar): List<Attendee> {
val attendees = ArrayList<Attendee>()
val uri = Attendees.CONTENT_URI
val projection = arrayOf(
@ -588,7 +587,7 @@ class CalDAVHelper(val context: Context) {
val email = cursor.getStringValue(Attendees.ATTENDEE_EMAIL) ?: ""
val status = cursor.getIntValue(Attendees.ATTENDEE_STATUS)
val relationship = cursor.getIntValue(Attendees.ATTENDEE_RELATIONSHIP)
val attendee = Attendee(0, name, email, status, "", false, relationship)
val attendee = Attendee(0, name, email, status, "", email == calendar.ownerName, relationship)
attendees.add(attendee)
}

View File

@ -3,8 +3,6 @@ package com.simplemobiletools.calendar.pro.helpers
import android.content.Context
import android.media.AudioManager
import android.media.RingtoneManager
import android.os.Environment
import android.os.Environment.DIRECTORY_DOWNLOADS
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.extensions.scheduleCalDAVSync
@ -31,6 +29,13 @@ class Config(context: Context) : BaseConfig(context) {
get() = prefs.getBoolean(START_WEEK_WITH_CURRENT_DAY, false)
set(startWeekWithCurrentDay) = prefs.edit().putBoolean(START_WEEK_WITH_CURRENT_DAY, startWeekWithCurrentDay).apply()
var firstDayOfWeek: Int
get() {
val defaultFirstDayOfWeek = Calendar.getInstance(Locale.getDefault()).firstDayOfWeek
return prefs.getInt(FIRST_DAY_OF_WEEK, getJodaDayOfWeekFromJava(defaultFirstDayOfWeek))
}
set(firstDayOfWeek) = prefs.edit().putInt(FIRST_DAY_OF_WEEK, firstDayOfWeek).apply()
var showMidnightSpanningEventsAtTop: Boolean
get() = prefs.getBoolean(SHOW_MIDNIGHT_SPANNING_EVENTS_AT_TOP, true)
set(midnightSpanning) = prefs.edit().putBoolean(SHOW_MIDNIGHT_SPANNING_EVENTS_AT_TOP, midnightSpanning).apply()
@ -116,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()
@ -261,18 +270,6 @@ class Config(context: Context) : BaseConfig(context) {
get() = prefs.getBoolean(WAS_FILTERED_OUT_WARNING_SHOWN, false)
set(wasFilteredOutWarningShown) = prefs.edit().putBoolean(WAS_FILTERED_OUT_WARNING_SHOWN, wasFilteredOutWarningShown).apply()
var autoBackup: Boolean
get() = prefs.getBoolean(AUTO_BACKUP, false)
set(enableAutomaticBackups) = prefs.edit().putBoolean(AUTO_BACKUP, enableAutomaticBackups).apply()
var autoBackupFolder: String
get() = prefs.getString(AUTO_BACKUP_FOLDER, Environment.getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS).absolutePath)!!
set(autoBackupPath) = prefs.edit().putString(AUTO_BACKUP_FOLDER, autoBackupPath).apply()
var autoBackupFilename: String
get() = prefs.getString(AUTO_BACKUP_FILENAME, "")!!
set(autoBackupFilename) = prefs.edit().putString(AUTO_BACKUP_FILENAME, autoBackupFilename).apply()
var autoBackupEventTypes: Set<String>
get() = prefs.getStringSet(AUTO_BACKUP_EVENT_TYPES, HashSet())!!
set(autoBackupEventTypes) = prefs.edit().remove(AUTO_BACKUP_EVENT_TYPES).putStringSet(AUTO_BACKUP_EVENT_TYPES, autoBackupEventTypes).apply()
@ -289,7 +286,4 @@ class Config(context: Context) : BaseConfig(context) {
get() = prefs.getBoolean(AUTO_BACKUP_PAST_ENTRIES, true)
set(autoBackupPastEntries) = prefs.edit().putBoolean(AUTO_BACKUP_PAST_ENTRIES, autoBackupPastEntries).apply()
var lastAutoBackupTime: Long
get() = prefs.getLong(LAST_AUTO_BACKUP_TIME, 0L)
set(lastAutoBackupTime) = prefs.edit().putLong(LAST_AUTO_BACKUP_TIME, lastAutoBackupTime).apply()
}

View File

@ -4,7 +4,9 @@ import com.simplemobiletools.calendar.pro.activities.EventActivity
import com.simplemobiletools.calendar.pro.activities.TaskActivity
import com.simplemobiletools.commons.helpers.MONTH_SECONDS
import org.joda.time.DateTime
import java.util.*
import org.joda.time.DateTimeConstants
import java.util.Calendar
import java.util.UUID
const val STORED_LOCALLY_ONLY = 0
const val ROW_COUNT = 6
@ -82,6 +84,7 @@ const val EVENT_LIST_PERIOD = "event_list_period"
const val WEEK_NUMBERS = "week_numbers"
const val START_WEEKLY_AT = "start_weekly_at"
const val START_WEEK_WITH_CURRENT_DAY = "start_week_with_current_day"
const val FIRST_DAY_OF_WEEK = "first_day_of_week"
const val SHOW_MIDNIGHT_SPANNING_EVENTS_AT_TOP = "show_midnight_spanning_events_at_top"
const val ALLOW_CUSTOMIZE_DAY_COUNT = "allow_customise_day_count"
const val VIBRATE = "vibrate"
@ -98,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"
@ -266,12 +270,9 @@ const val ACTION_MARK_COMPLETED = "ACTION_MARK_COMPLETED"
fun getNowSeconds() = System.currentTimeMillis() / 1000L
fun isWeekend(i: Int, isSundayFirst: Boolean): Boolean {
return if (isSundayFirst) {
i == 0 || i == 6 || i == 7 || i == 13
} else {
i == 5 || i == 6 || i == 12 || i == 13
}
fun isWeekend(dayOfWeek: Int): Boolean {
val weekendDays = listOf(DateTimeConstants.SATURDAY, DateTimeConstants.SUNDAY)
return dayOfWeek in weekendDays
}
fun getActivityToOpen(isTask: Boolean) = if (isTask) {
@ -299,3 +300,29 @@ fun getPreviousAutoBackupTime(): DateTime {
val nextBackupTime = getNextAutoBackupTime()
return nextBackupTime.minusDays(AUTO_BACKUP_INTERVAL_IN_DAYS)
}
fun getJodaDayOfWeekFromJava(dayOfWeek: Int): Int {
return when (dayOfWeek) {
Calendar.SUNDAY -> DateTimeConstants.SUNDAY
Calendar.MONDAY -> DateTimeConstants.MONDAY
Calendar.TUESDAY -> DateTimeConstants.TUESDAY
Calendar.WEDNESDAY -> DateTimeConstants.WEDNESDAY
Calendar.THURSDAY -> DateTimeConstants.THURSDAY
Calendar.FRIDAY -> DateTimeConstants.FRIDAY
Calendar.SATURDAY -> DateTimeConstants.SATURDAY
else -> throw IllegalArgumentException("Invalid day: $dayOfWeek")
}
}
fun getJavaDayOfWeekFromJoda(dayOfWeek: Int): Int {
return when (dayOfWeek) {
DateTimeConstants.SUNDAY -> Calendar.SUNDAY
DateTimeConstants.MONDAY -> Calendar.MONDAY
DateTimeConstants.TUESDAY -> Calendar.TUESDAY
DateTimeConstants.WEDNESDAY -> Calendar.WEDNESDAY
DateTimeConstants.THURSDAY -> Calendar.THURSDAY
DateTimeConstants.FRIDAY -> Calendar.FRIDAY
DateTimeConstants.SATURDAY -> Calendar.SATURDAY
else -> throw IllegalArgumentException("Invalid day: $dayOfWeek")
}
}

View File

@ -3,13 +3,15 @@ package com.simplemobiletools.calendar.pro.helpers
import androidx.room.TypeConverter
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.simplemobiletools.calendar.pro.models.Attendee
class Converters {
private val gson = Gson()
private val stringType = object : TypeToken<List<String>>() {}.type
private val attendeeType = object : TypeToken<List<Attendee>>() {}.type
@TypeConverter
fun jsonToStringList(value: String): ArrayList<String> {
fun jsonToStringList(value: String): List<String> {
val newValue = if (value.isNotEmpty() && !value.startsWith("[")) {
"[$value]"
} else {
@ -19,10 +21,26 @@ class Converters {
return try {
gson.fromJson(newValue, stringType)
} catch (e: Exception) {
ArrayList()
emptyList()
}
}
@TypeConverter
fun stringListToJson(list: ArrayList<String>) = gson.toJson(list)
fun stringListToJson(list: List<String>) = gson.toJson(list)
@TypeConverter
fun attendeeListToJson(list: List<Attendee>): String = gson.toJson(list)
@TypeConverter
fun jsonToAttendeeList(value: String): List<Attendee> {
if (value.isEmpty()) {
return emptyList()
}
return try {
gson.fromJson<ArrayList<Attendee>>(value, attendeeType) ?: ArrayList()
} catch (e: Exception) {
emptyList()
}
}
}

View File

@ -110,7 +110,7 @@ class EventsHelper(val context: Context) {
}
}
fun insertEvent(event: Event, addToCalDAV: Boolean, showToasts: Boolean, callback: ((id: Long) -> Unit)? = null) {
fun insertEvent(event: Event, addToCalDAV: Boolean, showToasts: Boolean, enableEventType: Boolean = true, callback: ((id: Long) -> Unit)? = null) {
if (event.startTS > event.endTS) {
callback?.invoke(0)
return
@ -118,7 +118,7 @@ class EventsHelper(val context: Context) {
maybeUpdateParentExceptions(event)
event.id = eventsDB.insertOrUpdate(event)
ensureEventTypeVisibility(event, enableEventType)
context.updateWidgets()
context.scheduleNextEventReminder(event, showToasts)
@ -129,9 +129,10 @@ class EventsHelper(val context: Context) {
callback?.invoke(event.id!!)
}
fun insertTask(task: Event, showToasts: Boolean, callback: () -> Unit) {
fun insertTask(task: Event, showToasts: Boolean, enableEventType: Boolean = true, callback: () -> Unit) {
maybeUpdateParentExceptions(task)
task.id = eventsDB.insertOrUpdate(task)
ensureEventTypeVisibility(task, enableEventType)
context.updateWidgets()
context.scheduleNextEventReminder(task, showToasts)
callback()
@ -157,7 +158,7 @@ class EventsHelper(val context: Context) {
}
event.id = eventsDB.insertOrUpdate(event)
ensureEventTypeVisibility(event, true)
context.scheduleNextEventReminder(event, false)
if (addToCalDAV && event.source != SOURCE_SIMPLE_CALENDAR && event.source != SOURCE_IMPORTED_ICS && config.caldavSync) {
context.calDAVHelper.insertCalDAVEvent(event)
@ -168,9 +169,9 @@ class EventsHelper(val context: Context) {
}
}
fun updateEvent(event: Event, updateAtCalDAV: Boolean, showToasts: Boolean, callback: (() -> Unit)? = null) {
fun updateEvent(event: Event, updateAtCalDAV: Boolean, showToasts: Boolean, enableEventType: Boolean = true, callback: (() -> Unit)? = null) {
eventsDB.insertOrUpdate(event)
ensureEventTypeVisibility(event, enableEventType)
context.updateWidgets()
context.scheduleNextEventReminder(event, showToasts)
if (updateAtCalDAV && event.source != SOURCE_SIMPLE_CALENDAR && config.caldavSync) {
@ -179,6 +180,76 @@ class EventsHelper(val context: Context) {
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) {
if (enableEventType) {
val eventType = event.eventType.toString()
val displayEventTypes = config.displayEventTypes
if (!displayEventTypes.contains(eventType)) {
config.displayEventTypes = displayEventTypes.plus(eventType)
}
}
}
fun deleteAllEvents() {
ensureBackgroundThread {
val eventIds = eventsDB.getEventIds().toMutableList()
@ -541,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

@ -1,7 +1,6 @@
package com.simplemobiletools.calendar.pro.helpers
import android.content.Context
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.extensions.seconds
import org.joda.time.DateTime
@ -108,9 +107,9 @@ object Formatter {
fun getUTCDateTimeFromTS(ts: Long) = DateTime(ts * 1000L, DateTimeZone.UTC)
// use manually translated month names, as DateFormat and Joda have issues with a lot of languages
fun getMonthName(context: Context, id: Int) = context.resources.getStringArray(R.array.months)[id - 1]
fun getMonthName(context: Context, id: Int) = context.resources.getStringArray(com.simplemobiletools.commons.R.array.months)[id - 1]
fun getShortMonthName(context: Context, id: Int) = context.resources.getStringArray(R.array.months_short)[id - 1]
fun getShortMonthName(context: Context, id: Int) = context.resources.getStringArray(com.simplemobiletools.commons.R.array.months_short)[id - 1]
fun getHourPattern(context: Context) = if (context.config.use24HourFormat) PATTERN_HOURS_24 else PATTERN_HOURS_12

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
) {
@ -43,7 +43,7 @@ class IcsExporter(private val context: Context) {
ensureBackgroundThread {
calendars = context.calDAVHelper.getCalDAVCalendars("", false)
if (showExportingToast) {
context.toast(R.string.exporting)
context.toast(com.simplemobiletools.commons.R.string.exporting)
}
object : BufferedWriter(OutputStreamWriter(outputStream, Charsets.UTF_8)) {

View File

@ -1,7 +1,6 @@
package com.simplemobiletools.calendar.pro.helpers
import android.provider.CalendarContract.Events
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
import com.simplemobiletools.calendar.pro.extensions.eventsDB
import com.simplemobiletools.calendar.pro.extensions.eventsHelper
@ -117,7 +116,7 @@ class IcsImporter(val activity: SimpleActivity) {
} else if (line.startsWith(DESCRIPTION) && !isNotificationDescription) {
val match = DESCRIPTION_REGEX.matchEntire(line)
if (match != null) {
curDescription = match.groups[1]!!.value.replace("\\n", "\n").replace("\\,", ",") ?: ""
curDescription = match.groups[1]!!.value.replace("\\n", "\n").replace("\\,", ",")
}
if (curDescription.trim().isEmpty()) {
curDescription = ""
@ -250,7 +249,7 @@ class IcsImporter(val activity: SimpleActivity) {
curRepeatRule,
curRepeatLimit,
curRepeatExceptions,
"",
emptyList(),
curImportId,
DateTimeZone.getDefault().id,
curFlags,
@ -330,6 +329,7 @@ class IcsImporter(val activity: SimpleActivity) {
IMPORT_FAIL
}
}
eventsFailed > 0 -> IMPORT_PARTIAL
else -> IMPORT_OK
}
@ -348,6 +348,7 @@ class IcsImporter(val activity: SimpleActivity) {
Parser().parseDateTimeValue(value)
}
fullString.startsWith(":") -> Parser().parseDateTimeValue(fullString.substring(1).trim())
else -> Parser().parseDateTimeValue(fullString)
}
@ -375,7 +376,12 @@ class IcsImporter(val activity: SimpleActivity) {
val eventId = eventsHelper.getEventTypeIdWithTitle(eventTypeTitle)
curEventTypeId = if (eventId == -1L) {
val newTypeColor = if (curCategoryColor == -2) activity.resources.getColor(R.color.color_primary) else curCategoryColor
val newTypeColor = if (curCategoryColor == -2) {
activity.resources.getColor(com.simplemobiletools.commons.R.color.color_primary)
} else {
curCategoryColor
}
val eventType = EventType(null, eventTypeTitle, newTypeColor)
eventsHelper.insertOrUpdateEventTypeSync(eventType)
} else {

View File

@ -1,8 +1,9 @@
package com.simplemobiletools.calendar.pro.helpers
import android.content.Context
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.extensions.eventsHelper
import com.simplemobiletools.calendar.pro.extensions.getProperDayIndexInWeek
import com.simplemobiletools.calendar.pro.extensions.isWeekendIndex
import com.simplemobiletools.calendar.pro.extensions.seconds
import com.simplemobiletools.calendar.pro.interfaces.MonthlyCalendar
import com.simplemobiletools.calendar.pro.models.DayMonthly
@ -34,13 +35,10 @@ class MonthlyCalendarImpl(val callback: MonthlyCalendar, val context: Context) {
fun getDays(markDaysWithEvents: Boolean) {
val days = ArrayList<DayMonthly>(DAYS_CNT)
val currMonthDays = mTargetDate.dayOfMonth().maximumValue
var firstDayIndex = mTargetDate.withDayOfMonth(1).dayOfWeek
val isSundayFirst = context.config.isSundayFirst
if (!isSundayFirst) {
firstDayIndex -= 1
}
val firstDayOfMonth = mTargetDate.withDayOfMonth(1)
val firstDayIndex = context.getProperDayIndexInWeek(firstDayOfMonth)
val currMonthDays = mTargetDate.dayOfMonth().maximumValue
val prevMonthDays = mTargetDate.minusMonths(1).dayOfMonth().maximumValue
var isThisMonth = false
@ -70,7 +68,7 @@ class MonthlyCalendarImpl(val callback: MonthlyCalendar, val context: Context) {
val newDay = curDay.withDayOfMonth(value)
val dayCode = Formatter.getDayCodeFromDateTime(newDay)
val day = DayMonthly(value, isThisMonth, isToday, dayCode, newDay.weekOfWeekyear, ArrayList(), i, isWeekend(i % 7, isSundayFirst))
val day = DayMonthly(value, isThisMonth, isToday, dayCode, newDay.weekOfWeekyear, ArrayList(), i, context.isWeekendIndex(i))
days.add(day)
value++
}

View File

@ -49,7 +49,12 @@ class MyWidgetListProvider : AppWidgetProvider() {
setTextSize(R.id.widget_event_list_today, fontSize)
}
views.setImageViewBitmap(R.id.widget_event_new_event, context.resources.getColoredBitmap(R.drawable.ic_plus_vector, textColor))
views.setImageViewBitmap(
R.id.widget_event_new_event, context.resources.getColoredBitmap(
resourceId = com.simplemobiletools.commons.R.drawable.ic_plus_vector,
newColor = textColor
)
)
setupIntent(context, views, NEW_EVENT, R.id.widget_event_new_event)
setupIntent(context, views, LAUNCH_CAL, R.id.widget_event_list_today)

View File

@ -12,15 +12,14 @@ import android.view.View
import android.widget.RemoteViews
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.SplashActivity
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.extensions.getWidgetFontSize
import com.simplemobiletools.calendar.pro.extensions.launchNewEventOrTaskActivity
import com.simplemobiletools.calendar.pro.extensions.*
import com.simplemobiletools.calendar.pro.interfaces.MonthlyCalendar
import com.simplemobiletools.calendar.pro.models.DayMonthly
import com.simplemobiletools.calendar.pro.models.Event
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.MEDIUM_ALPHA
import org.joda.time.DateTime
import org.joda.time.DateTimeConstants
class MyWidgetMonthlyProvider : AppWidgetProvider() {
private val PREV = "prev"
@ -153,7 +152,7 @@ class MyWidgetMonthlyProvider : AppWidgetProvider() {
applyColorFilter(R.id.day_monthly_task_image, eventTextColor)
setInt(R.id.day_monthly_event_background, "setColorFilter", it.color)
if (it.isTaskCompleted()) {
if (it.shouldStrikeThrough()) {
setInt(R.id.day_monthly_event_id, "setPaintFlags", Paint.ANTI_ALIAS_FLAG or Paint.STRIKE_THRU_TEXT_FLAG)
} else {
setInt(R.id.day_monthly_event_id, "setPaintFlags", Paint.ANTI_ALIAS_FLAG)
@ -197,16 +196,16 @@ class MyWidgetMonthlyProvider : AppWidgetProvider() {
views.setTextColor(R.id.top_value, textColor)
views.setTextSize(R.id.top_value, largerFontSize)
var bmp = resources.getColoredBitmap(R.drawable.ic_chevron_left_vector, textColor)
var bmp = resources.getColoredBitmap(com.simplemobiletools.commons.R.drawable.ic_chevron_left_vector, textColor)
views.setImageViewBitmap(R.id.top_left_arrow, bmp)
bmp = resources.getColoredBitmap(R.drawable.ic_chevron_right_vector, textColor)
bmp = resources.getColoredBitmap(com.simplemobiletools.commons.R.drawable.ic_chevron_right_vector, textColor)
views.setImageViewBitmap(R.id.top_right_arrow, bmp)
bmp = resources.getColoredBitmap(R.drawable.ic_today_vector, textColor)
views.setImageViewBitmap(R.id.top_go_to_today, bmp)
bmp = resources.getColoredBitmap(R.drawable.ic_plus_vector, textColor)
bmp = resources.getColoredBitmap(com.simplemobiletools.commons.R.drawable.ic_plus_vector, textColor)
views.setImageViewBitmap(R.id.top_new_event, bmp)
val shouldGoToTodayBeVisible = currTargetDate.withTime(0, 0, 0, 0) != DateTime.now().withDayOfMonth(1).withTime(0, 0, 0, 0)
@ -233,14 +232,14 @@ class MyWidgetMonthlyProvider : AppWidgetProvider() {
private fun updateDayLabels(context: Context, views: RemoteViews, resources: Resources, textColor: Int) {
val config = context.config
val sundayFirst = config.isSundayFirst
val firstDayOfWeek = config.firstDayOfWeek
val smallerFontSize = context.getWidgetFontSize()
val packageName = context.packageName
val letters = context.resources.getStringArray(R.array.week_day_letters)
val letters = context.resources.getStringArray(com.simplemobiletools.commons.R.array.week_day_letters)
for (i in 0..6) {
val id = resources.getIdentifier("label_$i", "id", packageName)
val dayTextColor = if (context.config.highlightWeekends && isWeekend(i, sundayFirst)) {
val dayTextColor = if (context.config.highlightWeekends && context.isWeekendIndex(i)) {
context.config.highlightWeekendsColor
} else {
textColor
@ -250,8 +249,8 @@ class MyWidgetMonthlyProvider : AppWidgetProvider() {
views.setTextSize(id, smallerFontSize)
var index = i
if (sundayFirst) {
index = (index + 6) % letters.size
if (firstDayOfWeek != DateTimeConstants.MONDAY) {
index = (index + firstDayOfWeek - 1) % 7
}
views.setText(id, letters[index])

View File

@ -9,29 +9,37 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.request.RequestOptions
data class Attendee(val contactId: Int, var name: String, val email: String, var status: Int, var photoUri: String, var isMe: Boolean, var relationship: Int) {
fun getPublicName() = if (name.isNotEmpty()) name else email
data class Attendee(
val contactId: Int,
var name: String,
val email: String,
var status: Int,
var photoUri: String,
var isMe: Boolean,
var relationship: Int
) {
fun getPublicName() = name.ifEmpty { email }
fun updateImage(context: Context, imageView: ImageView, placeholder: Drawable) {
if (photoUri.isEmpty()) {
imageView.setImageDrawable(placeholder)
} else {
val options = RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.error(placeholder)
.centerCrop()
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.error(placeholder)
.centerCrop()
Glide.with(context)
.load(photoUri)
.transition(DrawableTransitionOptions.withCrossFade())
.placeholder(placeholder)
.apply(options)
.apply(RequestOptions.circleCropTransform())
.into(imageView)
.load(photoUri)
.transition(DrawableTransitionOptions.withCrossFade())
.placeholder(placeholder)
.apply(options)
.apply(RequestOptions.circleCropTransform())
.into(imageView)
}
}
fun showStatusImage() = status == CalendarContract.Attendees.ATTENDEE_STATUS_ACCEPTED ||
status == CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED ||
status == CalendarContract.Attendees.ATTENDEE_STATUS_TENTATIVE
status == CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED ||
status == CalendarContract.Attendees.ATTENDEE_STATUS_TENTATIVE
}

View File

@ -1,5 +1,6 @@
package com.simplemobiletools.calendar.pro.models
import android.provider.CalendarContract.Attendees
import androidx.collection.LongSparseArray
import androidx.room.ColumnInfo
import androidx.room.Entity
@ -29,8 +30,8 @@ data class Event(
@ColumnInfo(name = "repeat_interval") var repeatInterval: Int = 0,
@ColumnInfo(name = "repeat_rule") var repeatRule: Int = 0,
@ColumnInfo(name = "repeat_limit") var repeatLimit: Long = 0L,
@ColumnInfo(name = "repetition_exceptions") var repetitionExceptions: ArrayList<String> = ArrayList(),
@ColumnInfo(name = "attendees") var attendees: String = "",
@ColumnInfo(name = "repetition_exceptions") var repetitionExceptions: List<String> = emptyList(),
@ColumnInfo(name = "attendees") var attendees: List<Attendee> = emptyList(),
@ColumnInfo(name = "import_id") var importId: String = "",
@ColumnInfo(name = "time_zone") var timeZone: String = "",
@ColumnInfo(name = "flags") var flags: Int = 0,
@ -58,16 +59,19 @@ data class Event(
REPEAT_ORDER_WEEKDAY_USE_LAST -> addXthDayInterval(oldStart, original, true)
else -> addYearsWithSameDay(oldStart)
}
repeatInterval % MONTH == 0 -> when (repeatRule) {
REPEAT_SAME_DAY -> addMonthsWithSameDay(oldStart, original)
REPEAT_ORDER_WEEKDAY -> addXthDayInterval(oldStart, original, false)
REPEAT_ORDER_WEEKDAY_USE_LAST -> addXthDayInterval(oldStart, original, true)
else -> oldStart.plusMonths(repeatInterval / MONTH).dayOfMonth().withMaximumValue()
}
repeatInterval % WEEK == 0 -> {
// step through weekly repetition by days too, as events can trigger multiple times a week
oldStart.plusDays(1)
}
else -> oldStart.plusSeconds(repeatInterval)
}
}
@ -186,9 +190,9 @@ data class Event(
isPastEvent = endTSToCheck < getNowSeconds()
}
fun addRepetitionException(daycode: String) {
var newRepetitionExceptions = repetitionExceptions
newRepetitionExceptions.add(daycode)
fun addRepetitionException(dayCode: String) {
var newRepetitionExceptions = repetitionExceptions.toMutableList()
newRepetitionExceptions.add(dayCode)
newRepetitionExceptions = newRepetitionExceptions.distinct().toMutableList() as ArrayList<String>
repetitionExceptions = newRepetitionExceptions
}
@ -206,4 +210,8 @@ data class Event(
DateTimeZone.getDefault().id
}
}
fun isAttendeeInviteDeclined() = attendees.any {
it.isMe && it.status == Attendees.ATTENDEE_STATUS_DECLINED
}
}

View File

@ -2,4 +2,4 @@ package com.simplemobiletools.calendar.pro.models
import android.util.Range
data class EventWeeklyView(val range: Range<Int>, var slot: Int = 0, var slot_max: Int = 0, var collisions: ArrayList<Long> = ArrayList())
data class EventWeeklyView(val range: Range<Int>, var slot: Int = 0, var slotMax: Int = 0, var collisions: ArrayList<Long> = ArrayList())

View File

@ -1,6 +1,36 @@
package com.simplemobiletools.calendar.pro.models
data class ListEvent(
var id: Long, var startTS: Long, var endTS: Long, var title: String, var description: String, var isAllDay: Boolean, var color: Int,
var location: String, var isPastEvent: Boolean, var isRepeatable: Boolean, var isTask: Boolean, var isTaskCompleted: Boolean
) : ListItem()
var id: Long,
var startTS: Long,
var endTS: Long,
var title: String,
var description: String,
var isAllDay: Boolean,
var color: Int,
var location: String,
var isPastEvent: Boolean,
var isRepeatable: Boolean,
var isTask: Boolean,
var isTaskCompleted: Boolean,
var isAttendeeInviteDeclined: Boolean
) : ListItem() {
companion object {
val empty = ListEvent(
id = 0,
startTS = 0,
endTS = 0,
title = "",
description = "",
isAllDay = false,
color = 0,
location = "",
isPastEvent = false,
isRepeatable = false,
isTask = false,
isTaskCompleted = false,
isAttendeeInviteDeclined = false
)
}
}

View File

@ -12,5 +12,6 @@ data class MonthViewEvent(
val isAllDay: Boolean,
val isPastEvent: Boolean,
val isTask: Boolean,
val isTaskCompleted: Boolean
val isTaskCompleted: Boolean,
val isAttendeeInviteDeclined: Boolean,
)

View File

@ -2,8 +2,6 @@ package com.simplemobiletools.calendar.pro.services
import android.app.IntentService
import android.content.Intent
import com.simplemobiletools.calendar.pro.extensions.cancelNotification
import com.simplemobiletools.calendar.pro.extensions.cancelPendingIntent
import com.simplemobiletools.calendar.pro.extensions.eventsDB
import com.simplemobiletools.calendar.pro.extensions.updateTaskCompletion
import com.simplemobiletools.calendar.pro.helpers.ACTION_MARK_COMPLETED
@ -17,9 +15,7 @@ class MarkCompletedService : IntentService("MarkCompleted") {
val taskId = intent.getLongExtra(EVENT_ID, 0L)
val task = eventsDB.getTaskWithId(taskId)
if (task != null) {
updateTaskCompletion(task, true)
cancelPendingIntent(task.id!!)
cancelNotification(task.id!!)
updateTaskCompletion(task, completed = true)
}
}
}

View File

@ -8,12 +8,10 @@ import android.util.AttributeSet
import android.util.SparseIntArray
import android.view.View
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.extensions.seconds
import com.simplemobiletools.calendar.pro.extensions.*
import com.simplemobiletools.calendar.pro.helpers.COLUMN_COUNT
import com.simplemobiletools.calendar.pro.helpers.Formatter
import com.simplemobiletools.calendar.pro.helpers.ROW_COUNT
import com.simplemobiletools.calendar.pro.helpers.isWeekend
import com.simplemobiletools.calendar.pro.models.DayMonthly
import com.simplemobiletools.calendar.pro.models.Event
import com.simplemobiletools.calendar.pro.models.MonthViewEvent
@ -72,7 +70,7 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con
highlightWeekends = config.highlightWeekends
smallPadding = resources.displayMetrics.density.toInt()
val normalTextSize = resources.getDimensionPixelSize(R.dimen.normal_text_size)
val normalTextSize = resources.getDimensionPixelSize(com.simplemobiletools.commons.R.dimen.normal_text_size)
weekDaysLetterHeight = normalTextSize * 2
textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
@ -91,7 +89,7 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con
color = primaryColor
}
val smallerTextSize = resources.getDimensionPixelSize(R.dimen.smaller_text_size)
val smallerTextSize = resources.getDimensionPixelSize(com.simplemobiletools.commons.R.dimen.smaller_text_size)
eventTitleHeight = smallerTextSize
eventTitlePaint = TextPaint(Paint.ANTI_ALIAS_FLAG).apply {
color = textColor
@ -132,8 +130,19 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con
val daysCnt = getEventLastingDaysCount(event)
val monthViewEvent = MonthViewEvent(
event.id!!, event.title, event.startTS, event.endTS, event.color, dayIndexOnMonthView,
daysCnt, dayIndexOnMonthView, event.getIsAllDay(), event.isPastEvent, event.isTask(), event.isTaskCompleted()
id = event.id!!,
title = event.title,
startTS = event.startTS,
endTS = event.endTS,
color = event.color,
startDayIndex = dayIndexOnMonthView,
daysCnt = daysCnt,
originalStartDayIndex = dayIndexOnMonthView,
isAllDay = event.getIsAllDay(),
isPastEvent = event.isPastEvent,
isTask = event.isTask(),
isTaskCompleted = event.isTaskCompleted(),
isAttendeeInviteDeclined = event.isAttendeeInviteDeclined()
)
allEvents.add(monthViewEvent)
}
@ -231,7 +240,7 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con
var weekDayLetterPaint = textPaint
if (i == currDayOfWeek && !isPrintVersion) {
weekDayLetterPaint = getColoredPaint(primaryColor)
} else if (highlightWeekends && isWeekend(i, config.isSundayFirst)) {
} else if (highlightWeekends && context.isWeekendIndex(i)) {
weekDayLetterPaint = getColoredPaint(weekendsTextColor)
}
canvas.drawText(dayLetters[i], xPos, weekDaysLetterHeight * 0.7f, weekDayLetterPaint)
@ -372,7 +381,7 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con
val curPaint = Paint(eventTitlePaint)
curPaint.color = paintColor
curPaint.isStrikeThruText = event.isTaskCompleted
curPaint.isStrikeThruText = event.shouldStrikeThrough()
return curPaint
}
@ -393,10 +402,7 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con
}
private fun initWeekDayLetters() {
dayLetters = context.resources.getStringArray(R.array.week_day_letters).toMutableList() as ArrayList<String>
if (config.isSundayFirst) {
dayLetters.moveLastItemToFront()
}
dayLetters = context.withFirstDayOfWeekToFront(context.resources.getStringArray(com.simplemobiletools.commons.R.array.week_day_letters).toList())
}
private fun setupCurrentDayOfWeekIndex() {
@ -405,12 +411,7 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con
return
}
currDayOfWeek = DateTime().dayOfWeek
if (config.isSundayFirst) {
currDayOfWeek %= 7
} else {
currDayOfWeek--
}
currDayOfWeek = context.getProperDayIndexInWeek(DateTime())
}
// take into account cases when an event starts on the previous screen, subtract those days
@ -440,7 +441,7 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con
fun togglePrintMode() {
isPrintVersion = !isPrintVersion
textColor = if (isPrintVersion) {
resources.getColor(R.color.theme_light_text_color)
resources.getColor(com.simplemobiletools.commons.R.color.theme_light_text_color)
} else {
context.getProperTextColor()
}

View File

@ -4,13 +4,13 @@ import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.FrameLayout
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.databinding.MonthViewBackgroundBinding
import com.simplemobiletools.calendar.pro.databinding.MonthViewBinding
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.helpers.COLUMN_COUNT
import com.simplemobiletools.calendar.pro.helpers.ROW_COUNT
import com.simplemobiletools.calendar.pro.models.DayMonthly
import com.simplemobiletools.commons.extensions.onGlobalLayout
import kotlinx.android.synthetic.main.month_view.view.month_view
// used in the Monthly view fragment, 1 view per screen
class MonthViewWrapper(context: Context, attrs: AttributeSet, defStyle: Int) : FrameLayout(context, attrs, defStyle) {
@ -22,24 +22,24 @@ class MonthViewWrapper(context: Context, attrs: AttributeSet, defStyle: Int) : F
private var isMonthDayView = true
private var days = ArrayList<DayMonthly>()
private var inflater: LayoutInflater
private var monthView: MonthView
private var binding: MonthViewBinding
private var dayClickCallback: ((day: DayMonthly) -> Unit)? = null
constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
init {
val normalTextSize = resources.getDimensionPixelSize(R.dimen.normal_text_size).toFloat()
val normalTextSize = resources.getDimensionPixelSize(com.simplemobiletools.commons.R.dimen.normal_text_size).toFloat()
weekDaysLetterHeight = 2 * normalTextSize.toInt()
inflater = LayoutInflater.from(context)
monthView = inflater.inflate(R.layout.month_view, this).month_view
binding = MonthViewBinding.inflate(inflater, this, true)
setupHorizontalOffset()
onGlobalLayout {
if (!wereViewsAdded && days.isNotEmpty()) {
measureSizes()
addClickableBackgrounds()
monthView.updateDays(days, isMonthDayView)
binding.monthView.updateDays(days, isMonthDayView)
}
}
}
@ -94,11 +94,15 @@ class MonthViewWrapper(context: Context, attrs: AttributeSet, defStyle: Int) : F
}
isMonthDayView = !addEvents
monthView.updateDays(days, isMonthDayView)
binding.monthView.updateDays(days, isMonthDayView)
}
private fun setupHorizontalOffset() {
horizontalOffset = if (context.config.showWeekNumbers) resources.getDimensionPixelSize(R.dimen.smaller_text_size) * 2 else 0
horizontalOffset = if (context.config.showWeekNumbers) {
resources.getDimensionPixelSize(com.simplemobiletools.commons.R.dimen.smaller_text_size) * 2
} else {
0
}
}
private fun measureSizes() {
@ -108,7 +112,7 @@ class MonthViewWrapper(context: Context, attrs: AttributeSet, defStyle: Int) : F
private fun addClickableBackgrounds() {
removeAllViews()
monthView = inflater.inflate(R.layout.month_view, this).month_view
binding = MonthViewBinding.inflate(inflater, this, true)
wereViewsAdded = true
var curId = 0
for (y in 0 until ROW_COUNT) {
@ -126,7 +130,7 @@ class MonthViewWrapper(context: Context, attrs: AttributeSet, defStyle: Int) : F
val xPos = viewX * dayWidth + horizontalOffset
val yPos = viewY * dayHeight + weekDaysLetterHeight
inflater.inflate(R.layout.month_view_background, this, false).apply {
MonthViewBackgroundBinding.inflate(inflater, this, false).root.apply {
if (isMonthDayView) {
background = null
}
@ -139,14 +143,15 @@ class MonthViewWrapper(context: Context, attrs: AttributeSet, defStyle: Int) : F
dayClickCallback?.invoke(day)
if (isMonthDayView) {
monthView.updateCurrentlySelectedDay(viewX, viewY)
binding.monthView.updateCurrentlySelectedDay(viewX, viewY)
}
}
addView(this)
}
}
fun togglePrintMode() {
monthView.togglePrintMode()
binding.monthView.togglePrintMode()
}
}

View File

@ -8,7 +8,7 @@ import android.util.AttributeSet
import android.view.View
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.helpers.isWeekend
import com.simplemobiletools.calendar.pro.extensions.isWeekendIndex
import com.simplemobiletools.calendar.pro.models.DayYearly
import com.simplemobiletools.commons.extensions.adjustAlpha
import com.simplemobiletools.commons.extensions.getProperPrimaryColor
@ -25,7 +25,6 @@ class SmallMonthView(context: Context, attrs: AttributeSet, defStyle: Int) : Vie
private var days = 31
private var isLandscape = false
private var highlightWeekends = false
private var isSundayFirst = false
private var isPrintVersion = false
private var mEvents: ArrayList<DayYearly>? = null
@ -61,7 +60,6 @@ class SmallMonthView(context: Context, attrs: AttributeSet, defStyle: Int) : Vie
textColor = baseColor.adjustAlpha(MEDIUM_ALPHA)
weekendsTextColor = context.config.highlightWeekendsColor.adjustAlpha(MEDIUM_ALPHA)
highlightWeekends = context.config.highlightWeekends
isSundayFirst = context.config.isSundayFirst
paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
color = textColor
@ -107,7 +105,7 @@ class SmallMonthView(context: Context, attrs: AttributeSet, defStyle: Int) : Vie
val curPaint = Paint(paint)
curPaint.color = colors.first()
return curPaint
} else if (highlightWeekends && isWeekend(weekDay - 1, isSundayFirst)) {
} else if (highlightWeekends && context.isWeekendIndex(weekDay - 1)) {
val curPaint = Paint(paint)
curPaint.color = weekendsTextColor
return curPaint
@ -119,7 +117,7 @@ class SmallMonthView(context: Context, attrs: AttributeSet, defStyle: Int) : Vie
fun togglePrintMode() {
isPrintVersion = !isPrintVersion
textColor = if (isPrintVersion) {
resources.getColor(R.color.theme_light_text_color)
resources.getColor(com.simplemobiletools.commons.R.color.theme_light_text_color)
} else {
context.getProperTextColor().adjustAlpha(MEDIUM_ALPHA)
}

View File

@ -5,19 +5,18 @@ import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.extensions.getWeeklyViewItemHeight
class WeeklyViewGrid(context: Context, attrs: AttributeSet, defStyle: Int) : View(context, attrs, defStyle) {
private val ROWS_CNT = 24
private var paint = Paint(Paint.ANTI_ALIAS_FLAG)
var daysCount = context.config.weeklyViewDays
private var daysCount = context.config.weeklyViewDays
constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
init {
paint.color = context.resources.getColor(R.color.divider_grey)
paint.color = context.resources.getColor(com.simplemobiletools.commons.R.color.divider_grey)
}
override fun onDraw(canvas: Canvas) {

View File

@ -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>

View File

@ -1,334 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/calendar_holder"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/top_navigation" />
<TableLayout
<GridLayout
android:id="@+id/calendar_wrapper"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/top_left_arrow"
android:padding="@dimen/yearly_padding_side">
android:columnCount="4"
android:padding="@dimen/yearly_padding_side"
android:rowCount="3">
<TableRow android:layout_weight="1">
<include
android:id="@+id/month_1_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half" />
<RelativeLayout
android:id="@+id/month_1_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/yearly_padding_full"
android:layout_weight="1">
<include
android:id="@+id/month_2_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half" />
<TextView
android:id="@+id/month_1_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/january"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<include
android:id="@+id/month_3_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/month_1_label"
android:layout_marginStart="@dimen/yearly_month_padding" />
<include
android:id="@+id/month_4_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half" />
</RelativeLayout>
<include
android:id="@+id/month_5_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half" />
<RelativeLayout
android:id="@+id/month_2_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half"
android:layout_weight="1">
<include
android:id="@+id/month_6_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half" />
<TextView
android:id="@+id/month_2_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/february"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<include
android:id="@+id/month_7_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/month_2_label"
android:layout_marginStart="@dimen/yearly_month_padding" />
<include
android:id="@+id/month_8_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half" />
</RelativeLayout>
<include
android:id="@+id/month_9_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginTop="0dp"
android:layout_marginEnd="@dimen/yearly_padding_half" />
<RelativeLayout
android:id="@+id/month_3_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/yearly_padding_full"
android:layout_weight="1">
<include
android:id="@+id/month_10_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half" />
<TextView
android:id="@+id/month_3_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/march"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<include
android:id="@+id/month_11_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/month_3_label"
android:layout_marginStart="@dimen/yearly_month_padding" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/month_4_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/yearly_padding_full"
android:layout_weight="1">
<TextView
android:id="@+id/month_4_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/april"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_4"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/month_4_label"
android:layout_marginStart="@dimen/yearly_month_padding"
app:days="30" />
</RelativeLayout>
</TableRow>
<TableRow android:layout_weight="1">
<RelativeLayout
android:id="@+id/month_5_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half"
android:layout_weight="1">
<TextView
android:id="@+id/month_5_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/may"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_5"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/month_5_label"
android:layout_marginStart="@dimen/yearly_month_padding" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/month_6_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/yearly_padding_full"
android:layout_weight="1">
<TextView
android:id="@+id/month_6_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/june"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_6"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/month_6_label"
android:layout_marginStart="@dimen/yearly_month_padding"
app:days="30" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/month_7_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/yearly_padding_full"
android:layout_weight="1">
<TextView
android:id="@+id/month_7_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/july"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_7"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/month_7_label"
android:layout_marginStart="@dimen/yearly_month_padding" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/month_8_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half"
android:layout_weight="1">
<TextView
android:id="@+id/month_8_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/august"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_8"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/month_8_label"
android:layout_marginStart="@dimen/yearly_month_padding" />
</RelativeLayout>
</TableRow>
<TableRow android:layout_weight="1">
<RelativeLayout
android:id="@+id/month_9_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/yearly_padding_full"
android:layout_weight="1">
<TextView
android:id="@+id/month_9_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/september"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_9"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/month_9_label"
android:layout_marginStart="@dimen/yearly_month_padding"
app:days="30" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/month_10_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/yearly_padding_full"
android:layout_weight="1">
<TextView
android:id="@+id/month_10_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/october"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_10"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/month_10_label"
android:layout_marginStart="@dimen/yearly_month_padding" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/month_11_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half"
android:layout_weight="1">
<TextView
android:id="@+id/month_11_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/november"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_11"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/month_11_label"
android:layout_marginStart="@dimen/yearly_month_padding"
app:days="30" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/month_12_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/yearly_padding_full"
android:layout_weight="1">
<TextView
android:id="@+id/month_12_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/december"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_12"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/month_12_label"
android:layout_marginStart="@dimen/yearly_month_padding" />
</RelativeLayout>
</TableRow>
</TableLayout>
<include
android:id="@+id/month_12_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half" />
</GridLayout>
</RelativeLayout>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/yearly_padding_full"
android:layout_weight="1">
<TextView
android:id="@+id/month_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/january"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/small_month_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/month_label"
android:layout_marginStart="@dimen/yearly_month_padding" />
</RelativeLayout>

View File

@ -506,64 +506,11 @@
android:background="@color/divider_grey"
android:importantForAccessibility="no" />
<ImageView
android:id="@+id/event_color_image"
android:layout_width="@dimen/smaller_icon_size"
android:layout_height="@dimen/smaller_icon_size"
android:layout_below="@+id/event_availability_divider"
android:layout_alignTop="@+id/event_color_holder"
android:layout_alignBottom="@+id/event_color_holder"
android:layout_marginStart="@dimen/normal_margin"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_color_vector" />
<RelativeLayout
android:id="@+id/event_color_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/event_availability_divider"
android:layout_marginTop="@dimen/medium_margin"
android:layout_marginBottom="@dimen/medium_margin"
android:layout_toEndOf="@+id/event_color_image"
android:background="?attr/selectableItemBackground">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/event_color_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/small_margin"
android:layout_marginEnd="@dimen/medium_margin"
android:layout_toStartOf="@+id/event_color"
android:paddingTop="@dimen/normal_margin"
android:paddingBottom="@dimen/normal_margin"
android:text="@string/event_color"
android:textSize="@dimen/day_text_size" />
<ImageView
android:id="@+id/event_color"
android:layout_width="@dimen/color_sample_size"
android:layout_height="@dimen/color_sample_size"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="@dimen/activity_margin"
android:clickable="false" />
</RelativeLayout>
<ImageView
android:id="@+id/event_color_divider"
android:layout_width="match_parent"
android:layout_height="@dimen/divider_height"
android:layout_below="@+id/event_color_image"
android:layout_marginTop="@dimen/medium_margin"
android:background="@color/divider_grey"
android:importantForAccessibility="no" />
<ImageView
android:id="@+id/event_caldav_calendar_image"
android:layout_width="@dimen/smaller_icon_size"
android:layout_height="@dimen/smaller_icon_size"
android:layout_below="@+id/event_color_divider"
android:layout_below="@+id/event_availability_divider"
android:layout_alignTop="@+id/event_caldav_calendar_holder"
android:layout_alignEnd="@+id/event_time_image"
android:layout_alignBottom="@+id/event_caldav_calendar_holder"
@ -576,7 +523,7 @@
android:id="@+id/event_caldav_calendar_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/event_color_divider"
android:layout_below="@+id/event_availability_divider"
android:layout_toEndOf="@+id/event_caldav_calendar_image"
android:background="?attr/selectableItemBackground"
android:visibility="gone">
@ -659,6 +606,59 @@
android:background="@color/divider_grey"
android:importantForAccessibility="no" />
<ImageView
android:id="@+id/event_color_image"
android:layout_width="@dimen/smaller_icon_size"
android:layout_height="@dimen/smaller_icon_size"
android:layout_below="@+id/event_type_divider"
android:layout_alignTop="@+id/event_color_holder"
android:layout_alignBottom="@+id/event_color_holder"
android:layout_marginStart="@dimen/normal_margin"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_color_vector" />
<RelativeLayout
android:id="@+id/event_color_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/event_type_divider"
android:layout_marginTop="@dimen/medium_margin"
android:layout_marginBottom="@dimen/medium_margin"
android:layout_toEndOf="@+id/event_color_image"
android:background="?attr/selectableItemBackground">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/event_color_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/small_margin"
android:layout_marginEnd="@dimen/medium_margin"
android:layout_toStartOf="@+id/event_color"
android:paddingTop="@dimen/normal_margin"
android:paddingBottom="@dimen/normal_margin"
android:text="@string/event_color"
android:textSize="@dimen/day_text_size" />
<ImageView
android:id="@+id/event_color"
android:layout_width="@dimen/color_sample_size"
android:layout_height="@dimen/color_sample_size"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="@dimen/activity_margin"
android:clickable="false" />
</RelativeLayout>
<ImageView
android:id="@+id/event_color_divider"
android:layout_width="match_parent"
android:layout_height="@dimen/divider_height"
android:layout_below="@+id/event_color_image"
android:layout_marginTop="@dimen/medium_margin"
android:background="@color/divider_grey"
android:importantForAccessibility="no" />
</RelativeLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -148,6 +148,29 @@
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_start_week_on_holder"
style="@style/SettingsHolderTextViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/settings_start_week_on_label"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/start_week_on" />
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/settings_start_week_on"
style="@style/SettingsTextValueStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/settings_start_week_on_label"
tools:text="@string/monday" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_hour_format_holder"
style="@style/SettingsHolderCheckboxStyle"
@ -163,21 +186,6 @@
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_sunday_first_holder"
style="@style/SettingsHolderCheckboxStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
android:id="@+id/settings_sunday_first"
style="@style/SettingsCheckboxStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/sunday_first" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_highlight_weekends_holder"
style="@style/SettingsHolderCheckboxStyle"
@ -969,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

@ -316,10 +316,51 @@
android:importantForAccessibility="no" />
<ImageView
android:id="@+id/task_color_image"
android:id="@+id/task_type_image"
android:layout_width="@dimen/smaller_icon_size"
android:layout_height="@dimen/smaller_icon_size"
android:layout_below="@+id/task_repetition_divider"
android:layout_alignTop="@+id/task_type_holder"
android:layout_alignBottom="@+id/task_type_holder"
android:layout_marginStart="@dimen/normal_margin"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_category_vector" />
<RelativeLayout
android:id="@+id/task_type_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/task_repetition_divider"
android:layout_marginTop="@dimen/medium_margin"
android:layout_marginBottom="@dimen/medium_margin"
android:layout_toEndOf="@+id/task_type_image"
android:background="?attr/selectableItemBackground">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/task_type"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/small_margin"
android:layout_marginEnd="@dimen/medium_margin"
android:paddingTop="@dimen/normal_margin"
android:paddingBottom="@dimen/normal_margin"
android:textSize="@dimen/day_text_size" />
</RelativeLayout>
<ImageView
android:id="@+id/task_type_divider"
android:layout_width="match_parent"
android:layout_height="@dimen/divider_height"
android:layout_below="@+id/task_type_holder"
android:background="@color/divider_grey"
android:importantForAccessibility="no" />
<ImageView
android:id="@+id/task_color_image"
android:layout_width="@dimen/smaller_icon_size"
android:layout_height="@dimen/smaller_icon_size"
android:layout_below="@+id/task_type_divider"
android:layout_alignTop="@+id/task_color_holder"
android:layout_alignBottom="@+id/task_color_holder"
android:layout_marginStart="@dimen/normal_margin"
@ -330,7 +371,7 @@
android:id="@+id/task_color_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/task_repetition_divider"
android:layout_below="@+id/task_type_divider"
android:layout_marginTop="@dimen/medium_margin"
android:layout_marginBottom="@dimen/medium_margin"
android:layout_toEndOf="@+id/task_color_image"
@ -368,53 +409,12 @@
android:background="@color/divider_grey"
android:importantForAccessibility="no" />
<ImageView
android:id="@+id/task_type_image"
android:layout_width="@dimen/smaller_icon_size"
android:layout_height="@dimen/smaller_icon_size"
android:layout_below="@+id/task_color_divider"
android:layout_alignTop="@+id/task_type_holder"
android:layout_alignBottom="@+id/task_type_holder"
android:layout_marginStart="@dimen/normal_margin"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_category_vector" />
<RelativeLayout
android:id="@+id/task_type_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/task_color_divider"
android:layout_marginTop="@dimen/medium_margin"
android:layout_marginBottom="@dimen/medium_margin"
android:layout_toEndOf="@+id/task_type_image"
android:background="?attr/selectableItemBackground">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/task_type"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/small_margin"
android:layout_marginEnd="@dimen/medium_margin"
android:paddingTop="@dimen/normal_margin"
android:paddingBottom="@dimen/normal_margin"
android:textSize="@dimen/day_text_size" />
</RelativeLayout>
<ImageView
android:id="@+id/task_type_divider"
android:layout_width="match_parent"
android:layout_height="@dimen/divider_height"
android:layout_below="@+id/task_type_holder"
android:background="@color/divider_grey"
android:importantForAccessibility="no" />
<android.widget.TextView
android:id="@+id/toggle_mark_complete"
style="@style/ColoredButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/task_type_divider"
android:layout_below="@+id/task_color_divider"
android:layout_centerHorizontal="true"
android:layout_marginTop="@dimen/activity_margin"
android:layout_marginBottom="@dimen/activity_margin"

View File

@ -1,327 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/calendar_holder"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/top_navigation" />
<TableLayout
<GridLayout
android:id="@+id/calendar_wrapper"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/top_left_arrow"
android:padding="@dimen/yearly_padding_side">
android:columnCount="3"
android:padding="@dimen/yearly_padding_side"
android:rowCount="4">
<TableRow android:layout_weight="1">
<include
android:id="@+id/month_1_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginEnd="@dimen/yearly_padding_full" />
<RelativeLayout
android:id="@+id/month_1_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/yearly_padding_full"
android:layout_weight="1">
<include
android:id="@+id/month_2_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half" />
<TextView
android:id="@+id/month_1_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/january"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<include
android:id="@+id/month_3_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_full" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/month_1_label"
android:layout_centerInParent="true" />
<include
android:id="@+id/month_4_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginEnd="@dimen/yearly_padding_full" />
</RelativeLayout>
<include
android:id="@+id/month_5_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half" />
<RelativeLayout
android:id="@+id/month_2_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half"
android:layout_weight="1">
<include
android:id="@+id/month_6_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_full" />
<TextView
android:id="@+id/month_2_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/february"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<include
android:id="@+id/month_7_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginEnd="@dimen/yearly_padding_full" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/month_2_label" />
<include
android:id="@+id/month_8_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half" />
</RelativeLayout>
<include
android:id="@+id/month_9_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_full" />
<RelativeLayout
android:id="@+id/month_3_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/yearly_padding_full"
android:layout_weight="1">
<include
android:id="@+id/month_10_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginEnd="@dimen/yearly_padding_full" />
<TextView
android:id="@+id/month_3_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/march"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<include
android:id="@+id/month_11_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/month_3_label" />
</RelativeLayout>
</TableRow>
<TableRow android:layout_weight="1">
<RelativeLayout
android:id="@+id/month_4_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/yearly_padding_full"
android:layout_weight="1">
<TextView
android:id="@+id/month_4_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/april"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_4"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/month_4_label"
app:days="30" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/month_5_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half"
android:layout_weight="1">
<TextView
android:id="@+id/month_5_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/may"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_5"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/month_5_label" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/month_6_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/yearly_padding_full"
android:layout_weight="1">
<TextView
android:id="@+id/month_6_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/june"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_6"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/month_6_label"
app:days="30" />
</RelativeLayout>
</TableRow>
<TableRow android:layout_weight="1">
<RelativeLayout
android:id="@+id/month_7_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/yearly_padding_full"
android:layout_weight="1">
<TextView
android:id="@+id/month_7_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/july"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_7"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/month_7_label" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/month_8_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half"
android:layout_weight="1">
<TextView
android:id="@+id/month_8_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/august"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_8"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/month_8_label" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/month_9_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/yearly_padding_full"
android:layout_weight="1">
<TextView
android:id="@+id/month_9_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/september"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_9"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/month_9_label"
app:days="30" />
</RelativeLayout>
</TableRow>
<TableRow android:layout_weight="1">
<RelativeLayout
android:id="@+id/month_10_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/yearly_padding_full"
android:layout_weight="1">
<TextView
android:id="@+id/month_10_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/october"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_10"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/month_10_label" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/month_11_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/yearly_padding_half"
android:layout_marginEnd="@dimen/yearly_padding_half"
android:layout_weight="1">
<TextView
android:id="@+id/month_11_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/november"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_11"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/month_11_label"
android:layout_marginStart="@dimen/yearly_month_padding"
app:days="30" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/month_12_holder"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/yearly_padding_full"
android:layout_weight="1">
<TextView
android:id="@+id/month_12_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/december"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/month_12"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/month_12_label" />
</RelativeLayout>
</TableRow>
</TableLayout>
<include
android:id="@+id/month_12_holder"
layout="@layout/small_month_view_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginStart="@dimen/yearly_padding_full" />
</GridLayout>
</RelativeLayout>

View File

@ -1,38 +0,0 @@
<?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/item_autocomplete_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="@dimen/small_margin"
android:paddingTop="@dimen/medium_margin"
android:paddingEnd="@dimen/medium_margin"
android:paddingBottom="@dimen/medium_margin">
<ImageView
android:id="@+id/item_autocomplete_image"
android:layout_width="@dimen/avatar_size"
android:layout_height="@dimen/avatar_size"
android:layout_margin="@dimen/tiny_margin"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/item_autocomplete_email"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:lines="1"
android:maxLines="1"
android:paddingStart="@dimen/medium_margin"
android:paddingEnd="@dimen/medium_margin"
android:singleLine="true"
android:textSize="@dimen/bigger_text_size"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/item_autocomplete_image"
app:layout_constraintTop_toTopOf="parent"
tools:text="hello@simplemobiletools.com" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -19,7 +19,7 @@
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/item_autocomplete_name"
android:id="@+id/item_autocomplete_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:lines="1"
@ -28,7 +28,7 @@
android:paddingEnd="@dimen/medium_margin"
android:singleLine="true"
android:textSize="@dimen/bigger_text_size"
app:layout_constraintBottom_toTopOf="@+id/item_autocomplete_email"
app:layout_constraintBottom_toTopOf="@+id/item_autocomplete_subtitle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/item_autocomplete_image"
app:layout_constraintTop_toTopOf="parent"
@ -36,10 +36,10 @@
tools:text="Simple Mobile" />
<TextView
android:id="@+id/item_autocomplete_email"
android:id="@+id/item_autocomplete_subtitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_below="@+id/item_autocomplete_name"
android:layout_below="@+id/item_autocomplete_title"
android:layout_marginEnd="8dp"
android:alpha="0.8"
android:lines="1"
@ -51,7 +51,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/item_autocomplete_image"
app:layout_constraintTop_toBottomOf="@+id/item_autocomplete_name"
app:layout_constraintTop_toBottomOf="@+id/item_autocomplete_title"
tools:text="hello@simplemobiletools.com" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/yearly_padding_full"
android:layout_weight="1">
<TextView
android:id="@+id/month_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/january"
android:textAllCaps="true"
android:textSize="@dimen/normal_text_size" />
<com.simplemobiletools.calendar.pro.views.SmallMonthView
android:id="@+id/small_month_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/month_label"
android:layout_centerInParent="true" />
</RelativeLayout>

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"

View File

@ -29,7 +29,6 @@
<string name="filter_events_by_type">تصفية الأحداث حسب النوع</string>
<string name="please_fill_location">أدخل الإحداثية كي يتم عرضها على الخريطة</string>
<string name="public_event_notification_text">اقتراب موعد حدث</string>
<string name="saving_filtered_out">تم الحفظ... ولكن تتم تصفية نوع الحدث المحدد في القائمة العلوية - تصفية</string>
<string name="everything_filtered_out">لقد قمت بتصفية جميع أنواع الأحداث</string>
<string name="event_color">Event color</string>
<string name="default_calendar_color">Default calendar color</string>
@ -294,4 +293,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View File

@ -29,7 +29,6 @@
<string name="filter_events_by_type">Hadisələri yazıya görə sırala</string>
<string name="please_fill_location">Xahiş olunur məkan parametrini doldurun ki hadisədə görünsün</string>
<string name="public_event_notification_text">Bir hadisə günü yaxınlaşır</string>
<string name="saving_filtered_out">Saving… But the selected event type is filtered out in the top Menu - Filter</string>
<string name="everything_filtered_out">You have filtered out all event types</string>
<string name="event_color">Event color</string>
<string name="default_calendar_color">Default calendar color</string>

View File

@ -29,7 +29,6 @@
<string name="filter_events_by_type">Фільтраваць падзеі па тыпу</string>
<string name="please_fill_location">Калі ласка, увядзіце месцазнаходжанне, якое будзе паказана на карце</string>
<string name="public_event_notification_text">Набліжаецца падзея</string>
<string name="saving_filtered_out">Захаванне... Але абраны тып падзеі адфільтраваны ў верхнім меню - Фільтр</string>
<string name="everything_filtered_out">You have filtered out all event types</string>
<string name="event_color">Event color</string>
<string name="default_calendar_color">Default calendar color</string>
@ -288,4 +287,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View File

@ -9,7 +9,7 @@
<string name="monthly_daily_view">Месечен и дневен изглед</string>
<string name="yearly_view">Годишен изглед</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_date">Отиди на дата</string>
<!-- Widget titles -->
@ -29,10 +29,9 @@
<string name="filter_events_by_type">Филтриране на събитията по тип</string>
<string name="please_fill_location">Моля попълнете местоположение за показване на картата</string>
<string name="public_event_notification_text">Предстоящо събитие</string>
<string name="saving_filtered_out">Запазване…Но избраният тип събитие се филтрира от Главно Меню - Филтриране</string>
<string name="everything_filtered_out">You have filtered out all event types</string>
<string name="event_color">Event color</string>
<string name="default_calendar_color">Default calendar color</string>
<string name="everything_filtered_out">Вие филтрирахте всички типове събития</string>
<string name="event_color">Цвят на събитието</string>
<string name="default_calendar_color">Цвят на календара по подразбиране</string>
<!-- Tasks -->
<string name="task">Задача</string>
<string name="tasks">Задачи</string>
@ -42,7 +41,7 @@
<string name="duplicate_task">Дублиране на задача</string>
<string name="mark_completed">Означете като завършено</string>
<string name="mark_incomplete">Означете като незавършено</string>
<string name="task_color">Task color</string>
<string name="task_color">Цвят на задачата</string>
<!-- Event Repetition -->
<string name="repetition">Повторение</string>
<string name="no_repetition">Без повторение</string>
@ -55,8 +54,8 @@
<string name="years_raw">години</string>
<string name="repeat_till">Повтаряй до</string>
<string name="forever">Завинаги</string>
<string name="event_is_repeatable">Събитието се повтаря</string>
<string name="task_is_repeatable">The task is repeatable</string>
<string name="event_is_repeatable">Събитието e повтаряемо</string>
<string name="task_is_repeatable">Задачата e повтаряема</string>
<string name="selection_contains_repetition">Изборът съдържа само повтарящи се събития</string>
<string name="delete_one_only">Изтрийте само избраното събитие</string>
<string name="delete_future_occurrences">Изтрийте това събитие и всички бъдещи събития</string>
@ -131,8 +130,8 @@
<string name="export_events_to_ics">Експортиране на събития в .ics файл</string>
<string name="default_event_type">Тип събитие по подразбиране</string>
<string name="export_past_events_too">Експортиране и на минали събития</string>
<string name="export_tasks">Export tasks</string>
<string name="export_past_entries">Export past entries too</string>
<string name="export_tasks">Експортиране на задачи</string>
<string name="export_past_entries">Експортиране и на минали записи</string>
<string name="include_event_types">Включване на типа събития</string>
<string name="filename_without_ics">Име на файла (без .ics)</string>
<string name="ignore_event_types">Игнорирайте типовете събития във файла, винаги използвайте този по подразбиране</string>
@ -181,8 +180,8 @@
<string name="replace_description_with_location">Смяна на описанието на събитието с местоположение</string>
<string name="display_description_or_location">Показване на описание или местоположение</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_confirmation">Сигурни ли сте, че искате да изтриете всички събития\? Това ще остави типовете събития и другите ви настройки непокътнати.</string>
<string name="delete_all_events_and_tasks">Изтриване на всички събития и задачи</string>
<string name="delete_all_events_confirmation">Сигурни ли сте, че искате да изтриете всички събития и задачи\? Това ще остави типовете събития и другите ви настройки непокътнати.</string>
<string name="show_a_grid">Показване на решетка</string>
<string name="loop_reminders">Циклично напомняне до отхвърляне</string>
<string name="dim_past_events">Затъмняване на минали събития</string>
@ -228,7 +227,7 @@
<string name="no_synchronized_calendars">Не са намерени календари, които да могат да се синхронизират</string>
<string name="status_free">Свободно</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 -->
<!-- used in repetition, like "Every last Sunday" -->
<string name="monday_alt">Понеделник</string>
@ -268,7 +267,7 @@
<string name="faq_1_title">Как мога да премахна празниците, импортирани чрез бутона \"Добавяне на празници\"\?</string>
<string name="faq_1_text">Създадените по този начин празници се вмъкват в нов тип събитие, наречен \"Празници\". Можете да отидете в Настройки -&gt; Управление на типове събития, да натиснете продължително дадения тип събитие и да го изтриете, като изберете кошчето за боклук.</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_3_title">Виждам напомняния но не чувам звук. Какво мога да направя\?</string>
<string name="faq_3_text">Системата оказва огромно влияние не само върху показването на действителното напомняне, но и върху възпроизвеждането на звука. Ако не можете да чуете никакъв звук, опитайте да влезете в настройките на приложението, да натиснете опцията \"Аудио поток, използван от напомнянията\" и да я промените на друга стойност. Ако все още не работи, проверете настройките на звука, дали конкретният поток не е заглушен.</string>
@ -282,4 +281,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View File

@ -29,7 +29,6 @@
<string name="filter_events_by_type">টাইপের মত করে ইভেন্টগুলো ফিল্টার করুন</string>
<string name="please_fill_location">ম্যাপে দেখানোর জন্য লোকেশন পূরণ করুন</string>
<string name="public_event_notification_text">একটি ইভেন্ট আসছে</string>
<string name="saving_filtered_out">Saving… But the selected event type is filtered out in the top Menu - Filter</string>
<string name="everything_filtered_out">You have filtered out all event types</string>
<string name="event_color">Event color</string>
<string name="default_calendar_color">Default calendar color</string>

View File

@ -29,7 +29,6 @@
<string name="filter_events_by_type">Silañ an darvoudoù dre rizh</string>
<string name="please_fill_location">Please fill in a location to be shown on a map</string>
<string name="public_event_notification_text">An event is upcoming</string>
<string name="saving_filtered_out">Saving… But the selected event type is filtered out in the top Menu - Filter</string>
<string name="everything_filtered_out">You have filtered out all event types</string>
<string name="event_color">Event color</string>
<string name="default_calendar_color">Default calendar color</string>

View File

@ -9,7 +9,7 @@
<string name="monthly_daily_view">Vista mensual i diària</string>
<string name="yearly_view">Vista anual</string>
<string name="simple_event_list">Llista d\'esdeveniments senzilla</string>
<string name="no_upcoming_events">No hi ha esdeveniments propers.</string>
<string name="no_upcoming_events">No hi ha esdeveniments pròxims.</string>
<string name="go_to_today">Ves a avui</string>
<string name="go_to_date">Ves a la data</string>
<!-- Widget titles -->
@ -29,7 +29,6 @@
<string name="filter_events_by_type">Filtra els esdeveniments per tipus</string>
<string name="please_fill_location">Ompliu una ubicació que es mostrarà en un mapa</string>
<string name="public_event_notification_text">S\'acosta un esdeveniment</string>
<string name="saving_filtered_out">S\'està desant… Però el tipus d\'esdeveniment seleccionat està filtrat al Menú superior - Filtre</string>
<string name="everything_filtered_out">Heu filtrat tots els tipus d\'esdeveniments</string>
<string name="event_color">Event color</string>
<string name="default_calendar_color">Default calendar color</string>

Some files were not shown because too many files have changed in this diff Show More