commit
1fe5610697
621 changed files with 33286 additions and 19350 deletions
|
@ -15,3 +15,9 @@ root = true
|
|||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
continuation_indent_size = 8
|
||||
|
||||
[*.xml]
|
||||
continuation_indent_size = 4
|
||||
|
|
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
github: [tibbi]
|
||||
patreon: tiborkaputa
|
||||
custom: ["https://www.paypal.me/SimpleMobileTools", "https://www.simplemobiletools.com/donate"]
|
21
.gitignore
vendored
21
.gitignore
vendored
|
@ -1,25 +1,10 @@
|
|||
# Temp files
|
||||
*~
|
||||
*.bak
|
||||
*.backup
|
||||
\#*
|
||||
.\#*
|
||||
*\#
|
||||
*.swp
|
||||
*.swap
|
||||
*.sav
|
||||
*.save
|
||||
*.autosav
|
||||
*.autosave
|
||||
|
||||
*.iml
|
||||
*.aab
|
||||
.gradle
|
||||
/local.properties
|
||||
/gradle.properties
|
||||
/.idea/
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
debug.keystore
|
||||
release.keystore
|
||||
signing.properties
|
||||
keystore.jks
|
||||
keystore.properties
|
||||
|
|
496
CHANGELOG.md
496
CHANGELOG.md
|
@ -1,6 +1,502 @@
|
|||
Changelog
|
||||
==========
|
||||
|
||||
Version 6.9.4 *(2020-05-25)*
|
||||
----------------------------
|
||||
|
||||
* Allow landscape orientation on any device
|
||||
* Use the nicer new app icon on lower Android versions
|
||||
* Some UI, stability and translation improvements
|
||||
|
||||
Version 6.9.3 *(2020-05-05)*
|
||||
----------------------------
|
||||
|
||||
* Added a 1x1 widget showing the current date
|
||||
* Made all widget corners round to make them nicer
|
||||
* Added some translation and other smaller improvements here and there
|
||||
|
||||
Version 6.9.2 *(2020-04-17)*
|
||||
----------------------------
|
||||
|
||||
* Fixed some .ics file importing related glitches
|
||||
* Corrected and added some UK holidays
|
||||
* Added many UI and translation improvements
|
||||
|
||||
Version 6.9.1 *(2020-03-25)*
|
||||
----------------------------
|
||||
|
||||
* Allow zooming the weekly view with vertical gestures
|
||||
* Allow scrolling through the whole weeky view, use Start time only as the default time
|
||||
* Updating the app icon
|
||||
* Other stability, translation and UX improvements
|
||||
|
||||
Version 6.9.0 *(2020-03-18)*
|
||||
----------------------------
|
||||
|
||||
* Remember the last used folder at ics exporting
|
||||
* Do not request the Storage permission on Android 10+, use Scoped Storage
|
||||
|
||||
Version 6.8.5 *(2020-03-08)*
|
||||
----------------------------
|
||||
|
||||
* Added a Go To Today menu button at the event list view too
|
||||
* Some translation and stability improvements
|
||||
|
||||
Version 6.8.4 *(2020-02-07)*
|
||||
----------------------------
|
||||
|
||||
* Added many translation and stability improvements
|
||||
|
||||
Version 6.8.3 *(2019-12-29)*
|
||||
----------------------------
|
||||
|
||||
* Fixed a glitch at events repeating every X weeks
|
||||
* Added an extra check to avoid showing reminders of deleted event repetition instances
|
||||
* Some stability and translation improvements
|
||||
|
||||
Version 6.8.2 *(2019-12-18)*
|
||||
----------------------------
|
||||
|
||||
* Improved some holidays
|
||||
* Added a few stability and translation improvements
|
||||
|
||||
Version 6.8.1 *(2019-12-11)*
|
||||
----------------------------
|
||||
|
||||
* Adding some time zone related crashfixes
|
||||
|
||||
Version 6.8.0 *(2019-12-11)*
|
||||
----------------------------
|
||||
|
||||
* Added time zone support (customization has to be enabled in the app settings)
|
||||
* Some UI improvements here and there
|
||||
* Some stability and translation improvements
|
||||
|
||||
Version 6.7.2 *(2019-12-02)*
|
||||
----------------------------
|
||||
|
||||
* Fixed some glitches at importing events from .ics files
|
||||
* Improved the user experience of Simple Event List view
|
||||
* Added some initial things under the hood for proper timezone support
|
||||
* Couple stability and translation improvements
|
||||
|
||||
Version 6.7.1 *(2019-11-18)*
|
||||
----------------------------
|
||||
|
||||
* Fixed a glitch at rechecking CalDAV synced calendars too often
|
||||
|
||||
Version 6.7.0 *(2019-11-17)*
|
||||
----------------------------
|
||||
|
||||
* Fixed some repeating CalDAV synced events not showing up properly
|
||||
* Improved the event sorting at the monthly widget
|
||||
* Properly refresh CalDAV synced events in the background
|
||||
* Some translation and stability improvements
|
||||
|
||||
Version 6.6.5 *(2019-11-06)*
|
||||
----------------------------
|
||||
|
||||
* Fixed a glitch with small letters in some cases
|
||||
* Some translation improvements
|
||||
|
||||
Version 6.6.4 *(2019-10-27)*
|
||||
----------------------------
|
||||
|
||||
* Never show the Add New Event button over the yearly view
|
||||
* Some stability and translation improvements
|
||||
|
||||
Version 6.6.3 *(2019-10-13)*
|
||||
----------------------------
|
||||
|
||||
* Fixed a glitch with small letters and not being able to force English in some cases
|
||||
|
||||
Version 6.6.2 *(2019-10-09)*
|
||||
----------------------------
|
||||
|
||||
* Added some stability and translation improvements
|
||||
|
||||
Version 6.6.1 *(2019-09-17)*
|
||||
----------------------------
|
||||
|
||||
* Fixed a glitch with syncing all-day events via Radicale (by ddast)
|
||||
* Use better messages at birthday/anniversary importing
|
||||
* Fixed some UK holidays
|
||||
|
||||
Version 6.6.0 *(2019-08-28)*
|
||||
----------------------------
|
||||
|
||||
* Use separate channels per event type reminders for more control
|
||||
* Added some extra German and UK holidays
|
||||
* Apply the Event List past limitation in the in-app view too, not just widget
|
||||
* Fixing some glitches at importing events from .ics files
|
||||
* Added some theming improvements
|
||||
|
||||
Version 6.5.7 *(2019-08-07)*
|
||||
----------------------------
|
||||
|
||||
* Properly use the selected default event calendar, even at CalDAV synced ones
|
||||
* Fixing invisible buttons at the date/time pickers with light theme
|
||||
* Fixed a couple other smaller glitches and added some translation improvements
|
||||
|
||||
Version 6.5.6 *(2019-07-26)*
|
||||
----------------------------
|
||||
|
||||
* Properly handle birthday and anniversary updating
|
||||
* Fixed a widget list related glitch
|
||||
|
||||
Version 6.5.5 *(2019-07-25)*
|
||||
----------------------------
|
||||
|
||||
* Added some dark theme related improvements
|
||||
* Allow customizing the bottom navigation bar color
|
||||
* Added a Go To Today button at the event list widget
|
||||
|
||||
Version 6.5.4 *(2019-07-01)*
|
||||
----------------------------
|
||||
|
||||
* Adding some stability improvements
|
||||
|
||||
Version 6.5.3 *(2019-06-30)*
|
||||
----------------------------
|
||||
|
||||
* Added some translation and stability improvements
|
||||
|
||||
Version 6.5.2 *(2019-06-28)*
|
||||
----------------------------
|
||||
|
||||
* Don't show events that end at 00:00 as multi day event (by archibishop)
|
||||
* Properly handle opening files with type application/ics
|
||||
* Some other stability, translation and performance improvements
|
||||
|
||||
Version 6.5.1 *(2019-06-13)*
|
||||
----------------------------
|
||||
|
||||
* Fixed a glitch related to CalDAV synced events reappearing after deletion
|
||||
* Many translation improvements
|
||||
|
||||
Version 6.5.0 *(2019-05-04)*
|
||||
----------------------------
|
||||
|
||||
* Show a more specific message if no new event has been found at importing
|
||||
* Fixed an Event list widget glitch with overlapping event type indicator colors
|
||||
* Misc smaller improvements
|
||||
|
||||
Version 6.4.3 *(2019-04-10)*
|
||||
----------------------------
|
||||
|
||||
* Fixed some third party intent handling
|
||||
* Some stability and translation improvements
|
||||
|
||||
Version 6.4.2 *(2019-04-03)*
|
||||
----------------------------
|
||||
|
||||
* Added holidays in Taiwan
|
||||
* Added an explanation dialog at upgrading from Free version
|
||||
* Some stability and translation improvements
|
||||
|
||||
Version 6.4.1 *(2019-03-23)*
|
||||
----------------------------
|
||||
|
||||
* Fixed a CalDAV sync related glitch with missing events
|
||||
* Fixed adding reminders to birthdays and anniversaries
|
||||
|
||||
Version 6.4.0 *(2019-03-20)*
|
||||
----------------------------
|
||||
|
||||
* Added email reminders and attendees in CalDAV synced events
|
||||
* Improved CalDAV event syncing in the background
|
||||
* Fixed some sorting related glitches
|
||||
* Some other stability and UX improvements
|
||||
|
||||
Version 6.3.2 *(2019-03-07)*
|
||||
----------------------------
|
||||
|
||||
* Added a "Go to date" to most views for easy jumping between dates
|
||||
* Added an app shortcut for creating new events quickly, from Android 7.1+
|
||||
|
||||
Version 6.3.1 *(2019-02-23)*
|
||||
----------------------------
|
||||
|
||||
* Allow adding event reminders to birthdays/anniversaries
|
||||
* Filled content description of some views to improve the UX of visually impaired people
|
||||
* A few more stability and UX improvements here and there
|
||||
|
||||
Version 6.3.0 *(2019-02-14)*
|
||||
----------------------------
|
||||
|
||||
* Allow setting default start time/duration/event type for new events
|
||||
* Allow exporting/importing settings
|
||||
* Fixed a glitch with repeating events older than from year 2001
|
||||
* Fixed some glitches related to overlapping events on the monthly and weekly view
|
||||
|
||||
Version 6.2.2 *(2019-01-25)*
|
||||
----------------------------
|
||||
|
||||
* Fixed some CalDAV sync glitches
|
||||
* Increase the visibility of dimmed events on the monthly view
|
||||
|
||||
Version 6.2.1 *(2019-01-08)*
|
||||
----------------------------
|
||||
|
||||
* Fixed a CalDAV sync related glitches
|
||||
* Fixed a glitch at showing notifications below Android Oreo
|
||||
|
||||
Version 6.2.0 *(2019-01-07)*
|
||||
----------------------------
|
||||
|
||||
* Fixed a few CalDAV sync related glitches
|
||||
* Properly handle reminder vibrations
|
||||
|
||||
Version 6.1.2 *(2018-12-25)*
|
||||
----------------------------
|
||||
|
||||
* Fixed "Duplicate Event" not working
|
||||
* Fixed a glitch with weekly view sometimes being blank
|
||||
|
||||
Version 6.1.1 *(2018-12-19)*
|
||||
----------------------------
|
||||
|
||||
* Fixed one more case of CalDAV events getting duplicated
|
||||
* Fixed the "New event" button sometimes not working properly
|
||||
* Fixed some cases of empty weekly views at app launch
|
||||
* Few other UX and stability improvements
|
||||
|
||||
Version 6.1.0 *(2018-12-05)*
|
||||
----------------------------
|
||||
|
||||
* Many bugfixed related to CalDAV sync and event importing via .ics files
|
||||
* Fixed a couple weekly view related glitches
|
||||
* Open specific event details on clicking it from Event list widget
|
||||
* Fix a glitch related to events repeating by X weeks for a long time
|
||||
* Many other smaller fixes and performance/stability improvements
|
||||
|
||||
Version 6.0.1 *(2018-11-18)*
|
||||
----------------------------
|
||||
|
||||
* Fixed some crashes and UX glitches
|
||||
|
||||
Version 6.0.0 *(2018-11-16)*
|
||||
----------------------------
|
||||
|
||||
* Initial Pro version
|
||||
* Fully rewrote the database storing events
|
||||
* Fixed some issues related to importing events from .ics files and CalDAV sync
|
||||
|
||||
Version 5.1.3 *(2018-11-29)*
|
||||
----------------------------
|
||||
|
||||
* This version of the app is no longer maintained, please upgrade to the Pro version. You can find the Upgrade button at the top of the app Settings.
|
||||
|
||||
Version 5.1.2 *(2018-11-09)*
|
||||
----------------------------
|
||||
|
||||
* Couple smaller UX improvements
|
||||
|
||||
Version 5.1.1 *(2018-10-25)*
|
||||
----------------------------
|
||||
|
||||
* Fixing a crash related to pull-to-refresh swiping
|
||||
|
||||
Version 5.1.0 *(2018-10-24)*
|
||||
----------------------------
|
||||
|
||||
* Add optional pull-to-refresh for refreshing CalDAV events on some views (by azisuazusa)
|
||||
* Allow setting a default view to be opened from the Event List widget (by knusprjg)
|
||||
* Apply selected filters on all views, including widgets
|
||||
* Allow changing any CalDAV calendars color, even if only locally
|
||||
* Fix some glitches related to saving CalDAV events in a wrong calendar
|
||||
* Some performance improvements related to fetching events
|
||||
* Couple other smaller stability/ux improvements
|
||||
|
||||
Version 5.0.1 *(2018-10-17)*
|
||||
----------------------------
|
||||
|
||||
* Fixed transparent date/time picker backgrounds
|
||||
|
||||
Version 5.0.0 *(2018-10-16)*
|
||||
----------------------------
|
||||
|
||||
* Increased the minimal required Android OS version to 5
|
||||
* Some translation and stability improvements
|
||||
|
||||
Version 4.2.1 *(2018-09-22)*
|
||||
----------------------------
|
||||
|
||||
* Fixed some crashes related to specific invalid times in some timezones
|
||||
* Added some holidays in Malaysia and Australia by youdly
|
||||
* Added a new warning if the app notifications are disabled by the system
|
||||
* Some other translation improvements and bugfixes
|
||||
|
||||
Version 4.2.0 *(2018-09-10)*
|
||||
----------------------------
|
||||
|
||||
* Replaced colored event type dots with bars for better visibility
|
||||
* Fixed some wrong reminder date data
|
||||
* Properly highlight running all-day events
|
||||
* Fix a glitch with CalDAV events being saved in the wrong calendar
|
||||
* Couple other smaller UX and translation improvements
|
||||
|
||||
Version 4.1.3 *(2018-08-06)*
|
||||
----------------------------
|
||||
|
||||
* Added a Go To Today button at the monthly widget
|
||||
* Increase the allowed length of event titles, locations, descriptions
|
||||
* Couple other stability and UX improvements
|
||||
|
||||
Version 4.1.2 *(2018-07-14)*
|
||||
----------------------------
|
||||
|
||||
* Made reminder sounds more reliable on Android Oreo
|
||||
* Properly fetch running events at reboot, notify only if needed
|
||||
* Couple UX and stability improvements
|
||||
|
||||
Version 4.1.1 *(2018-07-04)*
|
||||
----------------------------
|
||||
|
||||
* Allow customizing the audio stream used by reminders
|
||||
* Show the time remaining till the reminder appears
|
||||
* Couple other UX and stability improvements
|
||||
|
||||
Version 4.1.0 *(2018-06-13)*
|
||||
----------------------------
|
||||
|
||||
* Make reminders on Android Oreo more reliable
|
||||
* Allow deleting only future occurrences of repeating events
|
||||
* Fixed some visual glitches at the weekly view
|
||||
* Multiple CalDAV event related improvements
|
||||
|
||||
Version 4.0.4 *(2018-05-27)*
|
||||
----------------------------
|
||||
|
||||
* Make sure the alarm rings properly at DND mode
|
||||
* Improved the UK holidays and added Singapore ones
|
||||
* Make Event list items more compact when possible
|
||||
* Couple other UX improvements and bugfixes
|
||||
|
||||
Version 4.0.3 *(2018-05-15)*
|
||||
----------------------------
|
||||
|
||||
* Fixing some widget related crashes
|
||||
|
||||
Version 4.0.2 *(2018-05-14)*
|
||||
----------------------------
|
||||
|
||||
* Make sure we store the proper calendar ID at events
|
||||
|
||||
Version 4.0.1 *(2018-05-14)*
|
||||
----------------------------
|
||||
|
||||
* Fix app not opening at clicking widgets
|
||||
* Couple stability improvements
|
||||
|
||||
Version 4.0.0 *(2018-05-10)*
|
||||
----------------------------
|
||||
|
||||
* Allow changing the app launcher color
|
||||
* Allow setting reminder looping till dismissed
|
||||
* Added a button in Settings for changing widget colors without recreating them
|
||||
* Added optional dimming of past events
|
||||
* Make Event List view an endless scrollview
|
||||
* Added some more advanced yearly repetition rules
|
||||
* Improved some country holidays
|
||||
* Many CalDAV related improvements
|
||||
* Many other smaller bugfixes and performance/UX improvements
|
||||
|
||||
Version 3.4.2 *(2018-04-13)*
|
||||
----------------------------
|
||||
|
||||
* Hide public notification content if desired so (by fraang)
|
||||
* Added optional grid on the monthly view
|
||||
* Allow exporting events on SD cards
|
||||
* Allow selecting No Sound as a reminder sound
|
||||
* Set default event status for CalDAV events as Confirmed
|
||||
|
||||
Version 3.4.1 *(2018-03-30)*
|
||||
----------------------------
|
||||
|
||||
* Reworked custom notification sound, should be more reliable
|
||||
* Fixed some glitches related to the monthly view
|
||||
* Misc smaller bugfixes and stability improvements
|
||||
|
||||
Version 3.4.0 *(2018-02-28)*
|
||||
----------------------------
|
||||
|
||||
* Rewrote the monthly view
|
||||
* Improved the performance at importing events from ics files
|
||||
* Added many new country holidays
|
||||
* Handle some new third party intents
|
||||
|
||||
Version 3.3.2 *(2018-02-21)*
|
||||
----------------------------
|
||||
|
||||
* Try fixing the off-by-one issue at CalDAV syncing all-day events
|
||||
* Couple stability improvements
|
||||
|
||||
Version 3.3.1 *(2018-02-19)*
|
||||
----------------------------
|
||||
|
||||
* Improved CalDAV all-day event importing (by angelsl)
|
||||
* Added a FAQ section with a couple initial items
|
||||
* Once again fixed some cases of blank or duplicate views
|
||||
|
||||
Version 3.3.0 *(2018-02-10)*
|
||||
----------------------------
|
||||
|
||||
* Fixed blank or duplicate views in some cases (yes, again)
|
||||
* Fixed off-by-one day error at syncing all-day events via Nextcloud
|
||||
* Make default filenames at export more user-friendly
|
||||
* Improved the performance by removing some unnecessary redraws
|
||||
* Added a toggle for switching between default snooze interval or always showing an interval picker
|
||||
|
||||
Version 3.2.4 *(2018-02-05)*
|
||||
----------------------------
|
||||
|
||||
* Fixed blank screens in some cases
|
||||
* Misc smaller improvements
|
||||
|
||||
Version 3.2.3 *(2018-02-01)*
|
||||
----------------------------
|
||||
|
||||
* Fixed blank screens in some cases
|
||||
* Make sure the Add New Event button works when opening the app from a widget
|
||||
* Removed the "Default event reminder" from settings, remember last used values
|
||||
* Allow selecting Snooze interval at pressing Snooze
|
||||
* Allow disabling displaying of What's New
|
||||
* Add a Back button at the actionmenu when opening a subview
|
||||
* Allow deleting all events at once without reseting event types and other settings
|
||||
|
||||
Version 3.2.2 *(2018-01-27)*
|
||||
----------------------------
|
||||
|
||||
* Fixed some cases of reminders not triggering
|
||||
* Properly handle importing events with multiple lines long description
|
||||
* Properly show the New Event button whenever appropriate
|
||||
|
||||
Version 3.2.1 *(2018-01-22)*
|
||||
----------------------------
|
||||
|
||||
* Misc minor fixes
|
||||
|
||||
Version 3.2.0 *(2018-01-22)*
|
||||
----------------------------
|
||||
|
||||
* Added an initial implementation of Search
|
||||
* Fixed an off-by-one issue at syncing all-day CalDAV events
|
||||
* Added a Daily View
|
||||
* Allow importing events from .ics files directly in a CalDAV account
|
||||
* Try parsing latitude and longitude coordinates from the Location field
|
||||
|
||||
Version 3.1.0 *(2018-01-11)*
|
||||
----------------------------
|
||||
|
||||
* Made some CalDAV sync improvements, especially related to repeatable event exceptions
|
||||
* Added a Map button to event location, to display the location in a third party map
|
||||
* Handle INSERT and EDIT intent
|
||||
* Made Dark theme the default
|
||||
* Updated both event list and monthly widget, hopelly making them more reliable
|
||||
* Added holidays in Australia
|
||||
* Hopefully fixed the off-by-one error at importing/syncing all-day events/holidays
|
||||
|
||||
Version 3.0.1 *(2017-12-06)*
|
||||
----------------------------
|
||||
|
||||
|
|
809
LICENSE
809
LICENSE
|
@ -1,201 +1,674 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
1. Definitions.
|
||||
Preamble
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
0. Definitions.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
1. Source Code.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
Copyright 2017 SimpleMobileTools
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
|
|
38
README.md
38
README.md
|
@ -1,37 +1,25 @@
|
|||
# Simple Calendar
|
||||
<img alt="Logo" src="app/src/main/res/mipmap-xxxhdpi/ic_launcher.png" width="80" />
|
||||
<img alt="Logo" src="fastlane/metadata/android/en-US/images/icon.png" width="120" />
|
||||
|
||||
A simple calendar with events and a customizable widget.
|
||||
|
||||
An offline calendar without any other calendar integration. You can easily create recurring events and setup reminders, it can also display week numbers.
|
||||
A simple calendar with optional CalDAV synchronization. You can easily create recurring events and setup reminders, it can also display week numbers.
|
||||
|
||||
Contains a resizable 4x4 widget where you can customize the color of the text, as well as the alpha and the color of the background.
|
||||
Contains a monthly view and an event list widget where you can customize the color of the text, as well as the alpha and the color of the background.
|
||||
|
||||
Contains no ads or unnecessary permissions. It is fully open-source, provides customizable colors.
|
||||
Contains no ads or unnecessary permissions. It is fully opensource, provides customizable colors.
|
||||
|
||||
The Storage permission is needed only for exporting or importing events from .ics files.
|
||||
|
||||
This app is just one piece of a bigger series of apps. You can find the rest of them at http://www.simplemobiletools.com
|
||||
The Contacts permission is used only at importing contact birthdays and anniversaries.
|
||||
|
||||
<a href='https://play.google.com/store/apps/details?id=com.simplemobiletools.calendar'><img src='http://simplemobiletools.github.io/assets/public/google-play.png' alt='Get it on Google Play' height='45' /></a>
|
||||
<a href='https://f-droid.org/app/com.simplemobiletools.calendar'><img src='http://simplemobiletools.github.io/assets/public/f-droid.png' alt='Get it on F-Droid' height='45' /></a>
|
||||
This app is just one piece of a bigger series of apps. You can find the rest of them at https://www.simplemobiletools.com
|
||||
|
||||
<img alt="App image" src="screenshots/app_2.png" width="250" />
|
||||
<img alt="App image" src="screenshots/app_4.png" width="250" />
|
||||
<img alt="App image" src="screenshots/app.png" width="250" />
|
||||
<a href='https://play.google.com/store/apps/details?id=com.simplemobiletools.calendar.pro'><img src='https://simplemobiletools.com/assets/images/google-play.png' 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/assets/images/f-droid.png' alt='Get it on F-Droid' height='45' /></a>
|
||||
|
||||
License
|
||||
-------
|
||||
Copyright 2017 SimpleMobileTools
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
<div style="display:flex;">
|
||||
<img alt="App image" src="fastlane/metadata/android/en-US/images/phoneScreenshots/app_1.jpg" width="30%">
|
||||
<img alt="App image" src="fastlane/metadata/android/en-US/images/phoneScreenshots/app_2.jpg" width="30%">
|
||||
<img alt="App image" src="fastlane/metadata/android/en-US/images/phoneScreenshots/app_3.jpg" width="30%">
|
||||
</div>
|
||||
|
|
|
@ -1,31 +1,53 @@
|
|||
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 27
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "29.0.3"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.simplemobiletools.calendar"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 27
|
||||
versionCode 106
|
||||
versionName "3.0.1"
|
||||
applicationId "com.simplemobiletools.calendar.pro"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
versionCode 177
|
||||
versionName "6.9.4"
|
||||
multiDexEnabled true
|
||||
setProperty("archivesBaseName", "calendar")
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
release
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
|
@ -35,38 +57,19 @@ android {
|
|||
checkReleaseBuilds false
|
||||
abortOnError false
|
||||
}
|
||||
}
|
||||
|
||||
ext {
|
||||
leakCanaryVersion = '1.5.4'
|
||||
resourcePlaceholders {
|
||||
files = ['xml/shortcuts.xml']
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.simplemobiletools:commons:3.4.12'
|
||||
implementation 'joda-time:joda-time:2.9.9'
|
||||
implementation 'com.facebook.stetho:stetho:1.5.0'
|
||||
implementation 'com.android.support:multidex:1.0.2'
|
||||
implementation 'com.google.code.gson:gson:2.8.2'
|
||||
implementation 'com.simplemobiletools:commons:5.28.23'
|
||||
implementation 'joda-time:joda-time:2.10.1'
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
|
||||
|
||||
debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakCanaryVersion"
|
||||
releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$leakCanaryVersion"
|
||||
}
|
||||
|
||||
Properties props = new Properties()
|
||||
def propFile = new File('signing.properties')
|
||||
if (propFile.canRead()) {
|
||||
props.load(new FileInputStream(propFile))
|
||||
|
||||
if (props != null && props.containsKey('STORE_FILE') && props.containsKey('KEY_ALIAS') && props.containsKey('PASSWORD')) {
|
||||
android.signingConfigs.release.storeFile = file(props['STORE_FILE'])
|
||||
android.signingConfigs.release.storePassword = props['PASSWORD']
|
||||
android.signingConfigs.release.keyAlias = props['KEY_ALIAS']
|
||||
android.signingConfigs.release.keyPassword = props['PASSWORD']
|
||||
} else {
|
||||
println 'signing.properties found but some entries are missing'
|
||||
android.buildTypes.release.signingConfig = null
|
||||
}
|
||||
} else {
|
||||
println 'signing.properties not found'
|
||||
android.buildTypes.release.signingConfig = null
|
||||
kapt 'androidx.room:room-compiler:2.2.5'
|
||||
implementation 'androidx.room:room-runtime:2.2.5'
|
||||
annotationProcessor 'androidx.room:room-compiler:2.2.5'
|
||||
}
|
||||
|
|
6
app/proguard-rules.pro
vendored
6
app/proguard-rules.pro
vendored
|
@ -1,7 +1 @@
|
|||
-keep class com.simplemobiletools.calendar.models.** { *; }
|
||||
|
||||
# Joda
|
||||
-dontwarn org.joda.convert.**
|
||||
-dontwarn org.joda.time.**
|
||||
-keep class org.joda.time.** { *; }
|
||||
-keep interface org.joda.time.** { *; }
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 4.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 6.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 8.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 8.6 KiB |
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="leak_canary_display_activity_label">Calendar Leaks</string>
|
||||
<string name="app_launcher_name">Calendar_debug</string>
|
||||
</resources>
|
|
@ -1,40 +1,53 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.simplemobiletools.calendar"
|
||||
package="com.simplemobiletools.calendar.pro"
|
||||
android:installLocation="auto">
|
||||
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<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.WAKE_LOCK" />
|
||||
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="28" />
|
||||
|
||||
<uses-permission
|
||||
android:name="android.permission.USE_FINGERPRINT"
|
||||
tools:node="remove" />
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.faketouch"
|
||||
android:required="false" />
|
||||
|
||||
<application
|
||||
android:name=".App"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_launcher_name"
|
||||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
|
||||
<activity
|
||||
android:name=".activities.SplashActivity"
|
||||
android:theme="@style/SplashTheme">
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/SplashTheme" />
|
||||
|
||||
<activity
|
||||
android:name=".activities.MainActivity"
|
||||
android:launchMode="singleTask">
|
||||
<meta-data
|
||||
android:name="android.app.default_searchable"
|
||||
android:resource="@xml/searchable" />
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
<action android:name="android.intent.action.SEARCH" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
@ -43,6 +56,7 @@
|
|||
<data android:scheme="file" />
|
||||
<data android:mimeType="text/x-vcalendar" />
|
||||
<data android:mimeType="text/calendar" />
|
||||
<data android:mimeType="application/ics" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
|
@ -53,6 +67,12 @@
|
|||
<data android:host="com.android.calendar" />
|
||||
<data android:scheme="content" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="vnd.android.cursor.item/event" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
|
@ -73,6 +93,15 @@
|
|||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".activities.WidgetDateConfigureActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/MyWidgetConfigTheme">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="com.simplemobiletools.commons.activities.AboutActivity"
|
||||
android:label="@string/about"
|
||||
|
@ -89,14 +118,43 @@
|
|||
android:parentActivityName="com.simplemobiletools.commons.activities.AboutActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".activities.DayActivity"
|
||||
android:label="@string/details"
|
||||
android:parentActivityName=".activities.MainActivity"/>
|
||||
android:name="com.simplemobiletools.commons.activities.FAQActivity"
|
||||
android:label="@string/frequently_asked_questions"
|
||||
android:parentActivityName="com.simplemobiletools.commons.activities.AboutActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".activities.EventActivity"
|
||||
android:label="@string/event"
|
||||
android:parentActivityName=".activities.DayActivity"/>
|
||||
android:launchMode="singleTask"
|
||||
android:parentActivityName=".activities.MainActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.EDIT" />
|
||||
<action android:name="android.intent.action.INSERT" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="vnd.android.cursor.item/event" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.EDIT" />
|
||||
<action android:name="android.intent.action.INSERT" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="vnd.android.cursor.dir/event" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".activities.SelectTimeZoneActivity"
|
||||
android:parentActivityName=".activities.EventActivity">
|
||||
<meta-data
|
||||
android:name="android.app.default_searchable"
|
||||
android:resource="@xml/searchable" />
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEARCH" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".activities.SettingsActivity"
|
||||
|
@ -108,6 +166,10 @@
|
|||
android:label="@string/event_types"
|
||||
android:parentActivityName=".activities.SettingsActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".activities.SnoozeReminderActivity"
|
||||
android:theme="@style/Theme.Transparent" />
|
||||
|
||||
<receiver
|
||||
android:name=".helpers.MyWidgetMonthlyProvider"
|
||||
android:icon="@drawable/img_widget_monthly_preview"
|
||||
|
@ -134,12 +196,34 @@
|
|||
android:resource="@xml/widget_list_info" />
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".helpers.MyWidgetDateProvider"
|
||||
android:icon="@drawable/img_widget_date_preview"
|
||||
android:label="@string/widget_todays_date">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/widget_date_info" />
|
||||
</receiver>
|
||||
|
||||
<service
|
||||
android:name=".services.WidgetService"
|
||||
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||
|
||||
<service
|
||||
android:name=".services.WidgetServiceEmpty"
|
||||
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||
|
||||
<service android:name=".services.SnoozeService" />
|
||||
|
||||
<service
|
||||
android:name=".jobs.CalDAVUpdateListener"
|
||||
android:exported="true"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
|
||||
<receiver android:name=".receivers.NotificationReceiver" />
|
||||
|
||||
<receiver android:name=".receivers.CalDAVSyncReceiver" />
|
||||
|
@ -148,11 +232,12 @@
|
|||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
|
||||
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<provider
|
||||
android:name="android.support.v4.content.FileProvider"
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
|
@ -160,5 +245,251 @@
|
|||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/provider_paths" />
|
||||
</provider>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Red"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_red"
|
||||
android:roundIcon="@mipmap/ic_launcher_red"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Pink"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_pink"
|
||||
android:roundIcon="@mipmap/ic_launcher_pink"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Purple"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_purple"
|
||||
android:roundIcon="@mipmap/ic_launcher_purple"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Deep_purple"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_deep_purple"
|
||||
android:roundIcon="@mipmap/ic_launcher_deep_purple"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Indigo"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_indigo"
|
||||
android:roundIcon="@mipmap/ic_launcher_indigo"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Blue"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_blue"
|
||||
android:roundIcon="@mipmap/ic_launcher_blue"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Light_blue"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_light_blue"
|
||||
android:roundIcon="@mipmap/ic_launcher_light_blue"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Cyan"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_cyan"
|
||||
android:roundIcon="@mipmap/ic_launcher_cyan"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Teal"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_teal"
|
||||
android:roundIcon="@mipmap/ic_launcher_teal"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Green"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_green"
|
||||
android:roundIcon="@mipmap/ic_launcher_green"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Light_green"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_light_green"
|
||||
android:roundIcon="@mipmap/ic_launcher_light_green"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Lime"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_lime"
|
||||
android:roundIcon="@mipmap/ic_launcher_lime"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Yellow"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_yellow"
|
||||
android:roundIcon="@mipmap/ic_launcher_yellow"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Amber"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_amber"
|
||||
android:roundIcon="@mipmap/ic_launcher_amber"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Orange"
|
||||
android:enabled="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Deep_orange"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_deep_orange"
|
||||
android:roundIcon="@mipmap/ic_launcher_deep_orange"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Brown"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_brown"
|
||||
android:roundIcon="@mipmap/ic_launcher_brown"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Blue_grey"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_blue_grey"
|
||||
android:roundIcon="@mipmap/ic_launcher_blue_grey"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Grey_black"
|
||||
android:enabled="false"
|
||||
android:icon="@mipmap/ic_launcher_grey_black"
|
||||
android:roundIcon="@mipmap/ic_launcher_grey_black"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
358
app/src/main/assets/australia.ics
Executable file
358
app/src/main/assets/australia.ics
Executable file
|
@ -0,0 +1,358 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
UID:20180101_60o30chhcgo30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:New Year's Day
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180126
|
||||
DTEND;VALUE=DATE:20180127
|
||||
UID:20180126_60o30chhcko30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Australia Day
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180507
|
||||
DTEND;VALUE=DATE:20180508
|
||||
UID:20180507_60o30chicko36e1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=5;BYDAY=1MO
|
||||
SUMMARY:May Day (Northern Territory)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180312
|
||||
DTEND;VALUE=DATE:20180313
|
||||
UID:20180312_60o30chicko3ie1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=3;BYDAY=2MO
|
||||
SUMMARY:Labour Day (Victoria)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180305
|
||||
DTEND;VALUE=DATE:20180306
|
||||
UID:20180305_60o30chicko3ge1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=3;BYDAY=1MO
|
||||
SUMMARY:Labour Day (Western Australia)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181001
|
||||
DTEND;VALUE=DATE:20181002
|
||||
UID:20181001_60o30chicko3ec1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=10;BYDAY=1MO
|
||||
SUMMARY:Labour Day (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180507
|
||||
DTEND;VALUE=DATE:20180508
|
||||
UID:20180507_60o30chicko38e1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=5;BYDAY=1MO
|
||||
SUMMARY:Labour Day (Queensland)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180312
|
||||
DTEND;VALUE=DATE:20180313
|
||||
UID:20180312_60o30chicko62e1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=3;BYDAY=2MO
|
||||
SUMMARY:Eight Hours Day (Tasmania)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180425
|
||||
DTEND;VALUE=DATE:20180426
|
||||
UID:20180425_60o30chi6so32c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:ANZAC Day
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181001
|
||||
DTEND;VALUE=DATE:20181002
|
||||
UID:20181001_60o30chhcoo38c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=10;BYDAY=1MO
|
||||
SUMMARY:Queen's Birthday (Queensland)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180611
|
||||
DTEND;VALUE=DATE:20180612
|
||||
UID:20180611_60o30chhcoo32e1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=6;BYDAY=2MO
|
||||
SUMMARY:Queen's Birthday (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180212
|
||||
DTEND;VALUE=DATE:20180213
|
||||
UID:20180212_60o30e1pcko30e1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=2;BYDAY=2MO
|
||||
SUMMARY:Royal Hobart Regatta (Tasmania)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180312
|
||||
DTEND;VALUE=DATE:20180313
|
||||
UID:20180312_60o30chj64o30e1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=3;BYDAY=2MO
|
||||
SUMMARY:Canberra Day (Australian Capital Territory)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180806
|
||||
DTEND;VALUE=DATE:20180807
|
||||
UID:20180806_60o30chicgo30e1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=8;BYDAY=1MO
|
||||
SUMMARY:Northern Territory Picnic Day (Northern Territory)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180604
|
||||
DTEND;VALUE=DATE:20180605
|
||||
UID:20180604_60o30chj60o30e1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=6;BYDAY=1MO
|
||||
SUMMARY:Western Australia Day (Western Australia)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181105
|
||||
DTEND;VALUE=DATE:20181106
|
||||
UID:20181105_60o30chj6ko30e1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=11;BYDAY=1MO
|
||||
SUMMARY:Recreation Day (Tasmania)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181106
|
||||
DTEND;VALUE=DATE:20181107
|
||||
UID:20181106_60o30chj6oo30e1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=11;BYDAY=1TU
|
||||
SUMMARY:Melbourne Cup Day (Victoria)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180806
|
||||
DTEND;VALUE=DATE:20180807
|
||||
UID:20180806_60o30chicco30e1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=8;BYDAY=1MO
|
||||
SUMMARY:New South Wales Bank Holiday (New South Wales)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180312
|
||||
DTEND;VALUE=DATE:20180313
|
||||
UID:20180312_60o30chicoo30e1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=3;BYDAY=2MO
|
||||
SUMMARY:Adelaide Cup (South Australia)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181007
|
||||
DTEND;VALUE=DATE:20181008
|
||||
UID:20181007_60o30c9o60o30dpl6ooj0dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=10;BYDAY=1SU
|
||||
SUMMARY:Daylight Saving Time starts
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180401
|
||||
DTEND;VALUE=DATE:20180402
|
||||
UID:20180401_60o30c9o64o30dpl6ooj0dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=4;BYDAY=1SU
|
||||
SUMMARY:Daylight Saving Time ends
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180321
|
||||
DTEND;VALUE=DATE:20180322
|
||||
UID:20180321_60o30opo64o30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Harmony Day
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181111
|
||||
DTEND;VALUE=DATE:20181112
|
||||
UID:20181111_60o30chj6so30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Remembrance Day
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181224
|
||||
DTEND;VALUE=DATE:20181225
|
||||
UID:20181224_60o30chi60o30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Christmas Eve
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181225
|
||||
DTEND;VALUE=DATE:20181226
|
||||
UID:20181225_60o30chi64o30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Christmas Day
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181226
|
||||
DTEND;VALUE=DATE:20181227
|
||||
UID:20181226_60o30chi68o30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Boxing Day
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181231
|
||||
DTEND;VALUE=DATE:20190101
|
||||
UID:20181231_60o30chhcco30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:New Year's Eve
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200127
|
||||
DTEND;VALUE=DATE:20200128
|
||||
UID:20200127_60o30chhcko30e1g60o30dr56g@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Australia Day observed
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200412
|
||||
DTEND;VALUE=DATE:20200413
|
||||
UID:20200412_60o30chi6ko36c1g60o30dr56g@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Easter Sunday (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20210404
|
||||
DTEND;VALUE=DATE:20210405
|
||||
UID:20210404_60o30chi6ko3ac1g60o30dr56k@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Easter Sunday (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200413
|
||||
DTEND;VALUE=DATE:20200414
|
||||
UID:20200413_60o30chi6oo30c1g60o30dr56g@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Easter Monday
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20210405
|
||||
DTEND;VALUE=DATE:20210406
|
||||
UID:20210405_60o30chi6oo30c1g60o30dr56k@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Easter Monday
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200414
|
||||
DTEND;VALUE=DATE:20200415
|
||||
UID:20200414_60o30chj6co30c1g60o30dr56g@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Easter Tuesday (Tasmania)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20210406
|
||||
DTEND;VALUE=DATE:20210407
|
||||
UID:20210406_60o30chj6co30c1g60o30dr56k@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Easter Tuesday (Tasmania)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200410
|
||||
DTEND;VALUE=DATE:20200411
|
||||
UID:20200410_60o30chi6co30c1g60o30dr56g@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Good Friday
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20210402
|
||||
DTEND;VALUE=DATE:20210403
|
||||
UID:20210402_60o30chi6co30c1g60o30dr56k@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Good Friday
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200411
|
||||
DTEND;VALUE=DATE:20200412
|
||||
UID:20200411_60o30chi6go32c1g60o30dr56g@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Holy Saturday (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20210403
|
||||
DTEND;VALUE=DATE:20210404
|
||||
UID:20210403_60o30chi6go32c1g60o30dr56k@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Holy Saturday (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200601
|
||||
DTEND;VALUE=DATE:20200602
|
||||
UID:20200601_60o32dr3cgo30e1g60o30dr56g@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Reconciliation Day (Australian Capital Territory)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20210531
|
||||
DTEND;VALUE=DATE:20210601
|
||||
UID:20210531_60o32dr3cgo30e1g60o30dr56k@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Reconciliation Day (Australian Capital Territory)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200812
|
||||
DTEND;VALUE=DATE:20200813
|
||||
UID:20200812_60o30chj6go30c1g60o30dr56g@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Royal National Agricultural Show Day Queensland (Queensland)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20210811
|
||||
DTEND;VALUE=DATE:20210812
|
||||
UID:20210811_60o30chj6go30c1g60o30dr56k@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Royal National Agricultural Show Day Queensland (Queensland)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200928
|
||||
DTEND;VALUE=DATE:20200929
|
||||
UID:20200928_60o30chhcoo36e1g60o30dr56g@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Queen's Birthday (Western Australia)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20210927
|
||||
DTEND;VALUE=DATE:20210928
|
||||
UID:20210927_60o30chhcoo36e1g60o30dr56k@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Queen's Birthday (Western Australia)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20201228
|
||||
DTEND;VALUE=DATE:20201229
|
||||
UID:20201228_60o30chic8o30c1g60o30dr56g@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Christmas/Boxing Day Holiday
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20211227
|
||||
DTEND;VALUE=DATE:20211228
|
||||
UID:20211227_60o30chic4o30c1g60o30dr56k@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Christmas/Boxing Day Holiday
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20211228
|
||||
DTEND;VALUE=DATE:20211229
|
||||
UID:20211228_60o32o9hc4o30e1g60o30dr56k@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Christmas/Boxing Day Holiday
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
File diff suppressed because it is too large
Load diff
149
app/src/main/assets/china.ics
Normal file
149
app/src/main/assets/china.ics
Normal file
|
@ -0,0 +1,149 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20180101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
SUMMARY:元旦
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20180215@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180215
|
||||
DTEND;VALUE=DATE:20180222
|
||||
SUMMARY:春节
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20180405@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180405
|
||||
DTEND;VALUE=DATE:20180408
|
||||
SUMMARY:清明节
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20180429@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180429
|
||||
DTEND;VALUE=DATE:20180502
|
||||
SUMMARY:劳动节
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20180616@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180616
|
||||
DTEND;VALUE=DATE:20180619
|
||||
SUMMARY:端午节
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20180922@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180922
|
||||
DTEND;VALUE=DATE:20180925
|
||||
SUMMARY:中秋节
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20181001@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181001
|
||||
DTEND;VALUE=DATE:20181008
|
||||
SUMMARY:国庆节
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20190101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190101
|
||||
DTEND;VALUE=DATE:20190102
|
||||
SUMMARY:元旦
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20190205@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190205
|
||||
DTEND;VALUE=DATE:20190206
|
||||
SUMMARY:春节
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20190405@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190405
|
||||
DTEND;VALUE=DATE:20190406
|
||||
SUMMARY:清明节
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20190501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190501
|
||||
DTEND;VALUE=DATE:20190502
|
||||
SUMMARY:劳动节
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20190607@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190607
|
||||
DTEND;VALUE=DATE:20190608
|
||||
SUMMARY:端午节
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20190913@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190913
|
||||
DTEND;VALUE=DATE:20190914
|
||||
SUMMARY:中秋节
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20191001@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191001
|
||||
DTEND;VALUE=DATE:20191002
|
||||
SUMMARY:国庆节
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20200101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200101
|
||||
DTEND;VALUE=DATE:20200102
|
||||
SUMMARY:元旦
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20200125@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200125
|
||||
DTEND;VALUE=DATE:20200126
|
||||
SUMMARY:春节
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20200404@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200404
|
||||
DTEND;VALUE=DATE:20200405
|
||||
SUMMARY:清明节
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20200501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200501
|
||||
DTEND;VALUE=DATE:20200502
|
||||
SUMMARY:劳动节
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20200625@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200625
|
||||
DTEND;VALUE=DATE:20200626
|
||||
SUMMARY:端午节
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20201001@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201001
|
||||
DTEND;VALUE=DATE:20201002
|
||||
SUMMARY:国庆节
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-chn-20201001-529562@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201001
|
||||
DTEND;VALUE=DATE:20201002
|
||||
SUMMARY:中秋节
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
422
app/src/main/assets/colombia.ics
Normal file
422
app/src/main/assets/colombia.ics
Normal file
|
@ -0,0 +1,422 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20180101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
SUMMARY:Año Nuevo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20180108@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180108
|
||||
DTEND;VALUE=DATE:20180109
|
||||
SUMMARY:Día de los Reyes Magos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20180319@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180319
|
||||
DTEND;VALUE=DATE:20180320
|
||||
SUMMARY:Día de San José
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20180325@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180325
|
||||
DTEND;VALUE=DATE:20180326
|
||||
SUMMARY:Domingo de Ramos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20180329@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180329
|
||||
DTEND;VALUE=DATE:20180330
|
||||
SUMMARY:Jueves Santo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20180330@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180330
|
||||
DTEND;VALUE=DATE:20180331
|
||||
SUMMARY:Viernes Santo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20180401@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180401
|
||||
DTEND;VALUE=DATE:20180402
|
||||
SUMMARY:Domingo de Pascuas o Resurrección
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20180501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180501
|
||||
DTEND;VALUE=DATE:20180502
|
||||
SUMMARY:Día del Trabajo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20180514@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180514
|
||||
DTEND;VALUE=DATE:20180515
|
||||
SUMMARY:Día de la Ascensión
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20180604@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180604
|
||||
DTEND;VALUE=DATE:20180605
|
||||
SUMMARY:Corpus Christi
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20180611@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180611
|
||||
DTEND;VALUE=DATE:20180612
|
||||
SUMMARY:Sagrado Corazón de Jesús
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20180702@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180702
|
||||
DTEND;VALUE=DATE:20180703
|
||||
SUMMARY:San Pedro y San Pablo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20180720@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180720
|
||||
DTEND;VALUE=DATE:20180721
|
||||
SUMMARY:Declaracion de la Independencia de Colombia
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20180807@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180807
|
||||
DTEND;VALUE=DATE:20180808
|
||||
SUMMARY:Batalla de Boyacá
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20180820@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180820
|
||||
DTEND;VALUE=DATE:20180821
|
||||
SUMMARY:Asunción de la Virgen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20181015@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181015
|
||||
DTEND;VALUE=DATE:20181016
|
||||
SUMMARY:Día de la Raza
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20181105@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181105
|
||||
DTEND;VALUE=DATE:20181106
|
||||
SUMMARY:Día de todos los Santos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20181112@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181112
|
||||
DTEND;VALUE=DATE:20181113
|
||||
SUMMARY:Independencia de Cartagena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20181208@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181208
|
||||
DTEND;VALUE=DATE:20181209
|
||||
SUMMARY:Día de la Inmaculada Concepción
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20181225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181225
|
||||
DTEND;VALUE=DATE:20181226
|
||||
SUMMARY:Navidad
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20190101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190101
|
||||
DTEND;VALUE=DATE:20190102
|
||||
SUMMARY:Año Nuevo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20190107@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190107
|
||||
DTEND;VALUE=DATE:20190108
|
||||
SUMMARY:Día de los Reyes Magos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20190325@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190325
|
||||
DTEND;VALUE=DATE:20190326
|
||||
SUMMARY:Día de San José
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20190414@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190414
|
||||
DTEND;VALUE=DATE:20190415
|
||||
SUMMARY:Domingo de Ramos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20190418@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190418
|
||||
DTEND;VALUE=DATE:20190419
|
||||
SUMMARY:Jueves Santo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20190419@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190419
|
||||
DTEND;VALUE=DATE:20190420
|
||||
SUMMARY:Viernes Santo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20190421@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190421
|
||||
DTEND;VALUE=DATE:20190422
|
||||
SUMMARY:Domingo de Pascuas o Resurrección
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20190501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190501
|
||||
DTEND;VALUE=DATE:20190502
|
||||
SUMMARY:Día del Trabajo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20190603@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190603
|
||||
DTEND;VALUE=DATE:20190604
|
||||
SUMMARY:Día de la Ascensión
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20190624@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190624
|
||||
DTEND;VALUE=DATE:20190625
|
||||
SUMMARY:Corpus Christi
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20190701@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190701
|
||||
DTEND;VALUE=DATE:20190702
|
||||
SUMMARY:Sagrado Corazón de Jesús
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20190701-289927@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190701
|
||||
DTEND;VALUE=DATE:20190702
|
||||
SUMMARY:San Pedro y San Pablo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20190720@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190720
|
||||
DTEND;VALUE=DATE:20190721
|
||||
SUMMARY:Declaracion de la Independencia de Colombia
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20190807@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190807
|
||||
DTEND;VALUE=DATE:20190808
|
||||
SUMMARY:Batalla de Boyacá
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20190819@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190819
|
||||
DTEND;VALUE=DATE:20190820
|
||||
SUMMARY:Asunción de la Virgen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20191014@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191014
|
||||
DTEND;VALUE=DATE:20191015
|
||||
SUMMARY:Día de la Raza
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20191104@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191104
|
||||
DTEND;VALUE=DATE:20191105
|
||||
SUMMARY:Día de todos los Santos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20191111@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191111
|
||||
DTEND;VALUE=DATE:20191112
|
||||
SUMMARY:Independencia de Cartagena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20191208@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191208
|
||||
DTEND;VALUE=DATE:20191209
|
||||
SUMMARY:Día de la Inmaculada Concepción
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20191225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191225
|
||||
DTEND;VALUE=DATE:20191226
|
||||
SUMMARY:Navidad
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20200101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200101
|
||||
DTEND;VALUE=DATE:20200102
|
||||
SUMMARY:Año Nuevo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20200106@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200106
|
||||
DTEND;VALUE=DATE:20200107
|
||||
SUMMARY:Día de los Reyes Magos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20200323@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200323
|
||||
DTEND;VALUE=DATE:20200324
|
||||
SUMMARY:Día de San José
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20200405@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200405
|
||||
DTEND;VALUE=DATE:20200406
|
||||
SUMMARY:Domingo de Ramos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20200409@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200409
|
||||
DTEND;VALUE=DATE:20200410
|
||||
SUMMARY:Jueves Santo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20200410@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200410
|
||||
DTEND;VALUE=DATE:20200411
|
||||
SUMMARY:Viernes Santo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20200412@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200412
|
||||
DTEND;VALUE=DATE:20200413
|
||||
SUMMARY:Domingo de Pascuas o Resurrección
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20200501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200501
|
||||
DTEND;VALUE=DATE:20200502
|
||||
SUMMARY:Día del Trabajo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20200525@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200525
|
||||
DTEND;VALUE=DATE:20200526
|
||||
SUMMARY:Día de la Ascensión
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20200615@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200615
|
||||
DTEND;VALUE=DATE:20200616
|
||||
SUMMARY:Corpus Christi
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20200622@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200622
|
||||
DTEND;VALUE=DATE:20200623
|
||||
SUMMARY:Sagrado Corazón de Jesús
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20200629@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200629
|
||||
DTEND;VALUE=DATE:20200630
|
||||
SUMMARY:San Pedro y San Pablo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20200720@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200720
|
||||
DTEND;VALUE=DATE:20200721
|
||||
SUMMARY:Declaracion de la Independencia de Colombia
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20200807@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200807
|
||||
DTEND;VALUE=DATE:20200808
|
||||
SUMMARY:Batalla de Boyacá
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20200817@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200817
|
||||
DTEND;VALUE=DATE:20200818
|
||||
SUMMARY:Asunción de la Virgen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20201012@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201012
|
||||
DTEND;VALUE=DATE:20201013
|
||||
SUMMARY:Día de la Raza
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20201102@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201102
|
||||
DTEND;VALUE=DATE:20201103
|
||||
SUMMARY:Día de todos los Santos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20201116@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201116
|
||||
DTEND;VALUE=DATE:20201117
|
||||
SUMMARY:Independencia de Cartagena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20201208@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201208
|
||||
DTEND;VALUE=DATE:20201209
|
||||
SUMMARY:Día de la Inmaculada Concepción
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-col-20201225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201225
|
||||
DTEND;VALUE=DATE:20201226
|
||||
SUMMARY:Navidad
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
296
app/src/main/assets/croatia.ics
Normal file
296
app/src/main/assets/croatia.ics
Normal file
|
@ -0,0 +1,296 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20180101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
SUMMARY:Nova Godina
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20180106@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180106
|
||||
DTEND;VALUE=DATE:20180107
|
||||
SUMMARY:Bogojavljanje ili Sveta tri kralja
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20180401@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180401
|
||||
DTEND;VALUE=DATE:20180402
|
||||
SUMMARY:Uskrs
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20180402@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180402
|
||||
DTEND;VALUE=DATE:20180403
|
||||
SUMMARY:Uskrsni ponedjeljak
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20180501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180501
|
||||
DTEND;VALUE=DATE:20180502
|
||||
SUMMARY:Praznik rada
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20180531@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180531
|
||||
DTEND;VALUE=DATE:20180601
|
||||
SUMMARY:Tijelovo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20180622@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180622
|
||||
DTEND;VALUE=DATE:20180623
|
||||
SUMMARY:Dan antifašističke borbe
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20180625@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180625
|
||||
DTEND;VALUE=DATE:20180626
|
||||
SUMMARY:Dan državnosti
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20180805@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180805
|
||||
DTEND;VALUE=DATE:20180806
|
||||
SUMMARY:Dan pobjede i domovinske zahvalnosti i Dan hrvatskih branitelja
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20180815@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180815
|
||||
DTEND;VALUE=DATE:20180816
|
||||
SUMMARY:Velika Gospa
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20181008@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181008
|
||||
DTEND;VALUE=DATE:20181009
|
||||
SUMMARY:Dan neovisnosti
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20181101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181101
|
||||
DTEND;VALUE=DATE:20181102
|
||||
SUMMARY:Svi sveti
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20181225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181225
|
||||
DTEND;VALUE=DATE:20181226
|
||||
SUMMARY:Božić
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20181226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181226
|
||||
DTEND;VALUE=DATE:20181227
|
||||
SUMMARY:Prvi dan po Božiću\, Sveti Stjepan
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20190101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190101
|
||||
DTEND;VALUE=DATE:20190102
|
||||
SUMMARY:Nova Godina
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20190106@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190106
|
||||
DTEND;VALUE=DATE:20190107
|
||||
SUMMARY:Bogojavljanje ili Sveta tri kralja
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20190421@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190421
|
||||
DTEND;VALUE=DATE:20190422
|
||||
SUMMARY:Uskrs
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20190422@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190422
|
||||
DTEND;VALUE=DATE:20190423
|
||||
SUMMARY:Uskrsni ponedjeljak
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20190501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190501
|
||||
DTEND;VALUE=DATE:20190502
|
||||
SUMMARY:Praznik rada
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20190620@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190620
|
||||
DTEND;VALUE=DATE:20190621
|
||||
SUMMARY:Tijelovo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20190622@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190622
|
||||
DTEND;VALUE=DATE:20190623
|
||||
SUMMARY:Dan antifašističke borbe
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20190625@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190625
|
||||
DTEND;VALUE=DATE:20190626
|
||||
SUMMARY:Dan državnosti
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20190805@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190805
|
||||
DTEND;VALUE=DATE:20190806
|
||||
SUMMARY:Dan pobjede i domovinske zahvalnosti i Dan hrvatskih branitelja
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20190815@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190815
|
||||
DTEND;VALUE=DATE:20190816
|
||||
SUMMARY:Velika Gospa
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20191008@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191008
|
||||
DTEND;VALUE=DATE:20191009
|
||||
SUMMARY:Dan neovisnosti
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20191101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191101
|
||||
DTEND;VALUE=DATE:20191102
|
||||
SUMMARY:Svi sveti
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20191225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191225
|
||||
DTEND;VALUE=DATE:20191226
|
||||
SUMMARY:Božić
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20191226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191226
|
||||
DTEND;VALUE=DATE:20191227
|
||||
SUMMARY:Prvi dan po Božiću\, Sveti Stjepan
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20200101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200101
|
||||
DTEND;VALUE=DATE:20200102
|
||||
SUMMARY:Nova Godina
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20200106@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200106
|
||||
DTEND;VALUE=DATE:20200107
|
||||
SUMMARY:Bogojavljanje ili Sveta tri kralja
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20200412@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200412
|
||||
DTEND;VALUE=DATE:20200413
|
||||
SUMMARY:Uskrs
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20200413@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200413
|
||||
DTEND;VALUE=DATE:20200414
|
||||
SUMMARY:Uskrsni ponedjeljak
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20200501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200501
|
||||
DTEND;VALUE=DATE:20200502
|
||||
SUMMARY:Praznik rada
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20200611@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200611
|
||||
DTEND;VALUE=DATE:20200612
|
||||
SUMMARY:Tijelovo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20200622@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200622
|
||||
DTEND;VALUE=DATE:20200623
|
||||
SUMMARY:Dan antifašističke borbe
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20200625@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200625
|
||||
DTEND;VALUE=DATE:20200626
|
||||
SUMMARY:Dan državnosti
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20200805@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200805
|
||||
DTEND;VALUE=DATE:20200806
|
||||
SUMMARY:Dan pobjede i domovinske zahvalnosti i Dan hrvatskih branitelja
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20200815@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200815
|
||||
DTEND;VALUE=DATE:20200816
|
||||
SUMMARY:Velika Gospa
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20201008@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201008
|
||||
DTEND;VALUE=DATE:20201009
|
||||
SUMMARY:Dan neovisnosti
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20201101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201101
|
||||
DTEND;VALUE=DATE:20201102
|
||||
SUMMARY:Svi sveti
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20201225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201225
|
||||
DTEND;VALUE=DATE:20201226
|
||||
SUMMARY:Božić
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-hrv-20201226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201226
|
||||
DTEND;VALUE=DATE:20201227
|
||||
SUMMARY:Prvi dan po Božiću\, Sveti Stjepan
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
254
app/src/main/assets/denmark.ics
Normal file
254
app/src/main/assets/denmark.ics
Normal file
|
@ -0,0 +1,254 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20180101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
SUMMARY:Nytårsdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20180325@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180325
|
||||
DTEND;VALUE=DATE:20180326
|
||||
SUMMARY:Palmesøndag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20180329@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180329
|
||||
DTEND;VALUE=DATE:20180330
|
||||
SUMMARY:Skærtorsdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20180330@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180330
|
||||
DTEND;VALUE=DATE:20180331
|
||||
SUMMARY:Langfredag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20180401@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180401
|
||||
DTEND;VALUE=DATE:20180402
|
||||
SUMMARY:1. Påskedag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20180402@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180402
|
||||
DTEND;VALUE=DATE:20180403
|
||||
SUMMARY:2. Påskedag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20180427@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180427
|
||||
DTEND;VALUE=DATE:20180428
|
||||
SUMMARY:Store Bededag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20180510@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180510
|
||||
DTEND;VALUE=DATE:20180511
|
||||
SUMMARY:Kristi Himmelfartsdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20180520@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180520
|
||||
DTEND;VALUE=DATE:20180521
|
||||
SUMMARY:1. Pinsedag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20180521@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180521
|
||||
DTEND;VALUE=DATE:20180522
|
||||
SUMMARY:2. Pinsedag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20181225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181225
|
||||
DTEND;VALUE=DATE:20181226
|
||||
SUMMARY:1. Juledag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20181226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181226
|
||||
DTEND;VALUE=DATE:20181227
|
||||
SUMMARY:2. Juledag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20190101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190101
|
||||
DTEND;VALUE=DATE:20190102
|
||||
SUMMARY:Nytårsdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20190414@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190414
|
||||
DTEND;VALUE=DATE:20190415
|
||||
SUMMARY:Palmesøndag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20190418@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190418
|
||||
DTEND;VALUE=DATE:20190419
|
||||
SUMMARY:Skærtorsdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20190419@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190419
|
||||
DTEND;VALUE=DATE:20190420
|
||||
SUMMARY:Langfredag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20190421@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190421
|
||||
DTEND;VALUE=DATE:20190422
|
||||
SUMMARY:1. Påskedag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20190422@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190422
|
||||
DTEND;VALUE=DATE:20190423
|
||||
SUMMARY:2. Påskedag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20190517@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190517
|
||||
DTEND;VALUE=DATE:20190518
|
||||
SUMMARY:Store Bededag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20190530@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190530
|
||||
DTEND;VALUE=DATE:20190531
|
||||
SUMMARY:Kristi Himmelfartsdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20190609@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190609
|
||||
DTEND;VALUE=DATE:20190610
|
||||
SUMMARY:1. Pinsedag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20190610@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190610
|
||||
DTEND;VALUE=DATE:20190611
|
||||
SUMMARY:2. Pinsedag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20191225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191225
|
||||
DTEND;VALUE=DATE:20191226
|
||||
SUMMARY:1. Juledag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20191226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191226
|
||||
DTEND;VALUE=DATE:20191227
|
||||
SUMMARY:2. Juledag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20200101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200101
|
||||
DTEND;VALUE=DATE:20200102
|
||||
SUMMARY:Nytårsdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20200405@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200405
|
||||
DTEND;VALUE=DATE:20200406
|
||||
SUMMARY:Palmesøndag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20200409@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200409
|
||||
DTEND;VALUE=DATE:20200410
|
||||
SUMMARY:Skærtorsdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20200410@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200410
|
||||
DTEND;VALUE=DATE:20200411
|
||||
SUMMARY:Langfredag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20200412@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200412
|
||||
DTEND;VALUE=DATE:20200413
|
||||
SUMMARY:1. Påskedag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20200413@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200413
|
||||
DTEND;VALUE=DATE:20200414
|
||||
SUMMARY:2. Påskedag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20200508@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200508
|
||||
DTEND;VALUE=DATE:20200509
|
||||
SUMMARY:Store Bededag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20200521@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200521
|
||||
DTEND;VALUE=DATE:20200522
|
||||
SUMMARY:Kristi Himmelfartsdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20200531@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200531
|
||||
DTEND;VALUE=DATE:20200601
|
||||
SUMMARY:1. Pinsedag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20200601@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200601
|
||||
DTEND;VALUE=DATE:20200602
|
||||
SUMMARY:2. Pinsedag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20201225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201225
|
||||
DTEND;VALUE=DATE:20201226
|
||||
SUMMARY:1. Juledag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-dnk-20201226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201226
|
||||
DTEND;VALUE=DATE:20201227
|
||||
SUMMARY:2. Juledag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
|
@ -1,219 +1,254 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Leheristipäev
|
||||
UID:87aea25e-f592-47eb-b603-81640c074097
|
||||
DTSTART;VALUE=DATE:20170518
|
||||
DTEND;VALUE=DATE:20170519
|
||||
UID:enrico-est-20180101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
SUMMARY:uusaasta
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Taevaminemispüha
|
||||
UID:6e5e0af9-0230-427b-97f3-e799ddad9294
|
||||
DTSTART;VALUE=DATE:20170525
|
||||
DTEND;VALUE=DATE:20170526
|
||||
UID:enrico-est-20180224@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180224
|
||||
DTEND;VALUE=DATE:20180225
|
||||
SUMMARY:iseseisvuspäev
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:1. nelipüha
|
||||
UID:496869e4-af27-425b-ac0d-67c6dcb01adc
|
||||
DTSTART;VALUE=DATE:20170604
|
||||
DTEND;VALUE=DATE:20170605
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:2. nelipüha
|
||||
UID:b70ead8d-fad3-484a-bf67-5a52632c579d
|
||||
DTSTART;VALUE=DATE:20170605
|
||||
DTEND;VALUE=DATE:20170606
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Suve algus kell 07:24
|
||||
UID:328ecee3-576a-44e8-9c1e-2f3a5e357f83
|
||||
DTSTART;VALUE=DATE:20170621
|
||||
DTEND;VALUE=DATE:20170622
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Sügise algus kell 23:02
|
||||
UID:afc4d254-2139-497a-a8d8-38df0bbaea0d
|
||||
DTSTART;VALUE=DATE:20170922
|
||||
DTEND;VALUE=DATE:20170923
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Kohaliku omavalitsuse volikogu valimised
|
||||
UID:8da59f54-176f-446e-a270-c111ea3e18dd
|
||||
DTSTART;VALUE=DATE:20171015
|
||||
DTEND;VALUE=DATE:20171016
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:1. advent
|
||||
UID:47dc3b6a-d95b-44b5-bfc7-1b3a35f7205d
|
||||
DTSTART;VALUE=DATE:20171203
|
||||
DTEND;VALUE=DATE:20171204
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:2. advent
|
||||
UID:4864b353-09b9-4efa-83d0-a972392b84bb
|
||||
DTSTART;VALUE=DATE:20171210
|
||||
DTEND;VALUE=DATE:20171211
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:3. advent
|
||||
UID:329a9209-d449-4bbf-a34c-ad1d5a5c614b
|
||||
DTSTART;VALUE=DATE:20171217
|
||||
DTEND;VALUE=DATE:20171218
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Talve algus kell 18:28
|
||||
UID:8f789507-7ebb-43a0-98c3-7d43e02383ab
|
||||
DTSTART;VALUE=DATE:20171221
|
||||
DTEND;VALUE=DATE:20171222
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:4. advent
|
||||
UID:b2be7f14-42d6-4315-ae41-a8e70cc0389d
|
||||
DTSTART;VALUE=DATE:20171224
|
||||
DTEND;VALUE=DATE:20171225
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Vastlapäev
|
||||
UID:a95dc427-9bc3-42c2-bf73-e28475488119
|
||||
DTSTART;VALUE=DATE:20180213
|
||||
DTEND;VALUE=DATE:20180214
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Tuhkapäev
|
||||
UID:f154d202-d199-47d7-8c9b-2f7e9b6ee566
|
||||
DTSTART;VALUE=DATE:20180214
|
||||
DTEND;VALUE=DATE:20180215
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Kevade algus kell 18:15
|
||||
UID:bf16eef0-f725-4bad-8f08-782b799d3c23
|
||||
DTSTART;VALUE=DATE:20180320
|
||||
DTEND;VALUE=DATE:20180321
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Suur reede
|
||||
UID:c6622440-ffcb-4ac1-b74e-9585bbd4201f
|
||||
UID:enrico-est-20180330@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180330
|
||||
DTEND;VALUE=DATE:20180331
|
||||
SUMMARY:suur reede
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:1. ülestõusmispüha
|
||||
UID:e2b4326b-a759-4139-983c-010e11c00ed6
|
||||
UID:enrico-est-20180401@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180401
|
||||
DTEND;VALUE=DATE:20180402
|
||||
SUMMARY:ülestõusmispühade 1. püha
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:2. ülestõusmispüha
|
||||
UID:7953c329-b375-453d-aa22-3178ab4c8635
|
||||
DTSTART;VALUE=DATE:20180402
|
||||
DTEND;VALUE=DATE:20180403
|
||||
UID:enrico-est-20180501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180501
|
||||
DTEND;VALUE=DATE:20180502
|
||||
SUMMARY:kevadpüha
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Tuuleristipäev
|
||||
UID:3bcd442c-cfb7-4ce2-b094-5c8faa2eb6e3
|
||||
DTSTART;VALUE=DATE:20180419
|
||||
DTEND;VALUE=DATE:20180420
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Linnuristipäev
|
||||
UID:ed690184-a077-404a-9898-526fc30c0edd
|
||||
DTSTART;VALUE=DATE:20180426
|
||||
DTEND;VALUE=DATE:20180427
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Leheristipäev
|
||||
UID:3ee1e9ca-4a0f-4b50-95e2-9d6f0df602b4
|
||||
DTSTART;VALUE=DATE:20180503
|
||||
DTEND;VALUE=DATE:20180504
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Taevaminemispüha
|
||||
UID:77e33601-6e4a-451d-8f05-f0e32aae10e8
|
||||
DTSTART;VALUE=DATE:20180510
|
||||
DTEND;VALUE=DATE:20180511
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:1. nelipüha
|
||||
UID:b1ec19e5-7aad-4c68-9b57-afb2fdc443d7
|
||||
UID:enrico-est-20180520@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180520
|
||||
DTEND;VALUE=DATE:20180521
|
||||
SUMMARY:nelipühade 1. püha
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:2. nelipüha
|
||||
UID:fbd7814f-0b3b-4916-94de-3c20d7a32fae
|
||||
DTSTART;VALUE=DATE:20180521
|
||||
DTEND;VALUE=DATE:20180522
|
||||
UID:enrico-est-20180623@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180623
|
||||
DTEND;VALUE=DATE:20180624
|
||||
SUMMARY:võidupüha
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Suve algus kell 13:07
|
||||
UID:2c96272e-c227-46ba-8219-54e5ae360ffd
|
||||
DTSTART;VALUE=DATE:20180621
|
||||
DTEND;VALUE=DATE:20180622
|
||||
UID:enrico-est-20180624@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180624
|
||||
DTEND;VALUE=DATE:20180625
|
||||
SUMMARY:jaanipäev
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Sügise algus kell 04:54
|
||||
UID:5f22d789-9b4b-4aeb-9691-f813e2a01aa8
|
||||
DTSTART;VALUE=DATE:20180923
|
||||
DTEND;VALUE=DATE:20180924
|
||||
UID:enrico-est-20180820@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180820
|
||||
DTEND;VALUE=DATE:20180821
|
||||
SUMMARY:taasiseseisvumispäev
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:1. advent
|
||||
UID:ec10f2a1-aa5f-44d3-afe1-a6d1cf3e5a9e
|
||||
DTSTART;VALUE=DATE:20181202
|
||||
DTEND;VALUE=DATE:20181203
|
||||
UID:enrico-est-20181224@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181224
|
||||
DTEND;VALUE=DATE:20181225
|
||||
SUMMARY:jõululaupäev
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:2. advent
|
||||
UID:c29c4c4a-6905-4864-9bb9-ebf6c1ed394e
|
||||
DTSTART;VALUE=DATE:20181209
|
||||
DTEND;VALUE=DATE:20181210
|
||||
UID:enrico-est-20181225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181225
|
||||
DTEND;VALUE=DATE:20181226
|
||||
SUMMARY:esimene jõulupüha
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:3. advent
|
||||
UID:fc82eb9d-15b2-4182-9e7c-30096371decc
|
||||
DTSTART;VALUE=DATE:20181216
|
||||
DTEND;VALUE=DATE:20181217
|
||||
UID:enrico-est-20181226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181226
|
||||
DTEND;VALUE=DATE:20181227
|
||||
SUMMARY:teine jõulupüha
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Talve algus kell 00:23
|
||||
UID:89ae6fc6-699f-4189-80db-c118f2aca9c4
|
||||
DTSTART;VALUE=DATE:20181222
|
||||
DTEND;VALUE=DATE:20181223
|
||||
UID:enrico-est-20190101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190101
|
||||
DTEND;VALUE=DATE:20190102
|
||||
SUMMARY:uusaasta
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:4. advent
|
||||
UID:6b3cd6d7-77ab-4d12-97c8-92fbe78264a8
|
||||
DTSTART;VALUE=DATE:20181223
|
||||
DTEND;VALUE=DATE:20181224
|
||||
UID:enrico-est-20190224@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190224
|
||||
DTEND;VALUE=DATE:20190225
|
||||
SUMMARY:iseseisvuspäev
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20190419@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190419
|
||||
DTEND;VALUE=DATE:20190420
|
||||
SUMMARY:suur reede
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20190421@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190421
|
||||
DTEND;VALUE=DATE:20190422
|
||||
SUMMARY:ülestõusmispühade 1. püha
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20190501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190501
|
||||
DTEND;VALUE=DATE:20190502
|
||||
SUMMARY:kevadpüha
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20190609@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190609
|
||||
DTEND;VALUE=DATE:20190610
|
||||
SUMMARY:nelipühade 1. püha
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20190623@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190623
|
||||
DTEND;VALUE=DATE:20190624
|
||||
SUMMARY:võidupüha
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20190624@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190624
|
||||
DTEND;VALUE=DATE:20190625
|
||||
SUMMARY:jaanipäev
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20190820@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190820
|
||||
DTEND;VALUE=DATE:20190821
|
||||
SUMMARY:taasiseseisvumispäev
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20191224@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191224
|
||||
DTEND;VALUE=DATE:20191225
|
||||
SUMMARY:jõululaupäev
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20191225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191225
|
||||
DTEND;VALUE=DATE:20191226
|
||||
SUMMARY:esimene jõulupüha
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20191226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191226
|
||||
DTEND;VALUE=DATE:20191227
|
||||
SUMMARY:teine jõulupüha
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20200101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200101
|
||||
DTEND;VALUE=DATE:20200102
|
||||
SUMMARY:uusaasta
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20200224@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200224
|
||||
DTEND;VALUE=DATE:20200225
|
||||
SUMMARY:iseseisvuspäev
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20200410@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200410
|
||||
DTEND;VALUE=DATE:20200411
|
||||
SUMMARY:suur reede
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20200412@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200412
|
||||
DTEND;VALUE=DATE:20200413
|
||||
SUMMARY:ülestõusmispühade 1. püha
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20200501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200501
|
||||
DTEND;VALUE=DATE:20200502
|
||||
SUMMARY:kevadpüha
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20200531@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200531
|
||||
DTEND;VALUE=DATE:20200601
|
||||
SUMMARY:nelipühade 1. püha
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20200623@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200623
|
||||
DTEND;VALUE=DATE:20200624
|
||||
SUMMARY:võidupüha
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20200624@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200624
|
||||
DTEND;VALUE=DATE:20200625
|
||||
SUMMARY:jaanipäev
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20200820@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200820
|
||||
DTEND;VALUE=DATE:20200821
|
||||
SUMMARY:taasiseseisvumispäev
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20201224@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201224
|
||||
DTEND;VALUE=DATE:20201225
|
||||
SUMMARY:jõululaupäev
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20201225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201225
|
||||
DTEND;VALUE=DATE:20201226
|
||||
SUMMARY:esimene jõulupüha
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-est-20201226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201226
|
||||
DTEND;VALUE=DATE:20201227
|
||||
SUMMARY:teine jõulupüha
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
|
|
|
@ -65,16 +65,16 @@ END:VEVENT
|
|||
BEGIN:VEVENT
|
||||
SUMMARY:Naistenpäivä
|
||||
UID:55954496-9c99-4eeb-871e-b015d0f8ce40
|
||||
DTSTART;VALUE=DATE:19750308
|
||||
DTEND;VALUE=DATE:19750309
|
||||
DTSTART;VALUE=DATE:20170308
|
||||
DTEND;VALUE=DATE:20170309
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ruotsalaisuuden päivä
|
||||
UID:ac081b74-6737-49a2-aeaf-4993eec75d0e
|
||||
DTSTART;VALUE=DATE:19801106
|
||||
DTEND;VALUE=DATE:19801107
|
||||
DTSTART;VALUE=DATE:20171106
|
||||
DTEND;VALUE=DATE:20171107
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
|
|
|
@ -7,13 +7,6 @@ DTEND;VALUE=DATE:20170526
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pfingsten
|
||||
UID:55d7b48b-f4ac-4d4f-9f7a-c750cd836fb9
|
||||
DTSTART;VALUE=DATE:20170604
|
||||
DTEND;VALUE=DATE:20170605
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pfingstmontag
|
||||
UID:0763c01f-245e-4ebf-acff-45597e999a01
|
||||
DTSTART;VALUE=DATE:20170605
|
||||
|
@ -35,13 +28,6 @@ DTEND;VALUE=DATE:20171120
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Buß- und Bettag
|
||||
UID:e2e10823-b9cd-4c10-931c-38f2b0853844
|
||||
DTSTART;VALUE=DATE:20171122
|
||||
DTEND;VALUE=DATE:20171123
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Totensonntag
|
||||
UID:3d292c6c-c482-4a6a-8ec3-18dae2c57aa0
|
||||
DTSTART;VALUE=DATE:20171126
|
||||
|
@ -49,48 +35,6 @@ DTEND;VALUE=DATE:20171127
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Erster Advent
|
||||
UID:f31f4c45-3d27-4992-88b7-8ed6e269069a
|
||||
DTSTART;VALUE=DATE:20171203
|
||||
DTEND;VALUE=DATE:20171204
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Zweiter Advent
|
||||
UID:4f5ceb8a-4fdf-471b-873d-7b6d74ce1527
|
||||
DTSTART;VALUE=DATE:20171210
|
||||
DTEND;VALUE=DATE:20171211
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Dritter Advent
|
||||
UID:13fc6d4f-c378-478e-b4d1-98578060b359
|
||||
DTSTART;VALUE=DATE:20171217
|
||||
DTEND;VALUE=DATE:20171218
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Vierter Advent
|
||||
UID:71807f5d-ea0a-4c85-954d-301490a4db78
|
||||
DTSTART;VALUE=DATE:20171224
|
||||
DTEND;VALUE=DATE:20171225
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Rosenmontag
|
||||
UID:16a1f889-913e-4d6c-ae41-63d05096af02
|
||||
DTSTART;VALUE=DATE:20180212
|
||||
DTEND;VALUE=DATE:20180213
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Aschermittwoch
|
||||
UID:553ebbee-4e98-4979-9fb4-f16de19b78c9
|
||||
DTSTART;VALUE=DATE:20180214
|
||||
DTEND;VALUE=DATE:20180215
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Karfreitag
|
||||
UID:00fa1ea2-c91d-4d5b-89c5-1102259e1d24
|
||||
DTSTART;VALUE=DATE:20180330
|
||||
|
@ -98,13 +42,6 @@ DTEND;VALUE=DATE:20180331
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ostern
|
||||
UID:3a6ff1ad-1215-462e-bc6e-31ff03cab1fe
|
||||
DTSTART;VALUE=DATE:20180401
|
||||
DTEND;VALUE=DATE:20180402
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ostermontag
|
||||
UID:0ab12047-4716-4307-9d41-025db2534867
|
||||
DTSTART;VALUE=DATE:20180402
|
||||
|
@ -119,20 +56,6 @@ DTEND;VALUE=DATE:20180511
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Muttertag
|
||||
UID:01e33d81-7688-4b5f-a448-8f30936d53c5
|
||||
DTSTART;VALUE=DATE:20180513
|
||||
DTEND;VALUE=DATE:20180514
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pfingsten
|
||||
UID:e6891ff2-4e97-4163-8b68-2711a9395a2b
|
||||
DTSTART;VALUE=DATE:20180520
|
||||
DTEND;VALUE=DATE:20180521
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pfingstmontag
|
||||
UID:01da1f59-2a95-4528-84b7-45c420d73130
|
||||
DTSTART;VALUE=DATE:20180521
|
||||
|
@ -154,13 +77,6 @@ DTEND;VALUE=DATE:20181119
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Buß- und Bettag
|
||||
UID:8f011c35-0bc0-4ce7-983c-3f5107105089
|
||||
DTSTART;VALUE=DATE:20181121
|
||||
DTEND;VALUE=DATE:20181122
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Totensonntag
|
||||
UID:5ce3351e-8a46-4a6a-86c1-9d6a4691d69c
|
||||
DTSTART;VALUE=DATE:20181125
|
||||
|
@ -168,55 +84,6 @@ DTEND;VALUE=DATE:20181126
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Erster Advent
|
||||
UID:54af4894-22f2-4d6f-afec-b41a4773a7c1
|
||||
DTSTART;VALUE=DATE:20181202
|
||||
DTEND;VALUE=DATE:20181203
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Zweiter Advent
|
||||
UID:075866e7-e5a4-4e28-9e7b-da1668457f12
|
||||
DTSTART;VALUE=DATE:20181209
|
||||
DTEND;VALUE=DATE:20181210
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Dritter Advent
|
||||
UID:859543e9-8310-4c39-a953-55d01afb95d5
|
||||
DTSTART;VALUE=DATE:20181216
|
||||
DTEND;VALUE=DATE:20181217
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Vierter Advent
|
||||
UID:86472732-c54c-454c-8c46-60dc8d872f22
|
||||
DTSTART;VALUE=DATE:20181223
|
||||
DTEND;VALUE=DATE:20181224
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Rosenmontag
|
||||
UID:d37799d7-4c4e-49a1-8132-3b41ffdc650e
|
||||
DTSTART;VALUE=DATE:20190304
|
||||
DTEND;VALUE=DATE:20190305
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Aschermittwoch
|
||||
UID:59874060-e592-493d-beb3-7710a4c8a4c4
|
||||
DTSTART;VALUE=DATE:20190306
|
||||
DTEND;VALUE=DATE:20190307
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Palmsonntag
|
||||
UID:f69b0d53-6039-4f44-993e-dfed2988dbbb
|
||||
DTSTART;VALUE=DATE:20190414
|
||||
DTEND;VALUE=DATE:20190415
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Karfreitag
|
||||
UID:0aaa7d21-c168-4dbb-a9ca-311c83c0840d
|
||||
DTSTART;VALUE=DATE:20190419
|
||||
|
@ -224,13 +91,6 @@ DTEND;VALUE=DATE:20190420
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ostern
|
||||
UID:c6ae2cd0-f9dc-4936-ac69-7f43a8d5c454
|
||||
DTSTART;VALUE=DATE:20190421
|
||||
DTEND;VALUE=DATE:20190422
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ostermontag
|
||||
UID:b0300aa9-c14b-482c-b9d9-be81d9475123
|
||||
DTSTART;VALUE=DATE:20190422
|
||||
|
@ -238,13 +98,6 @@ DTEND;VALUE=DATE:20190423
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Muttertag
|
||||
UID:1cbb64eb-c8c1-4f49-bc4e-e11190c37f42
|
||||
DTSTART;VALUE=DATE:20190512
|
||||
DTEND;VALUE=DATE:20190513
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Christi Himmelfahrt
|
||||
UID:54b3d09c-99f7-4f27-9253-d1fe8e358c50
|
||||
DTSTART;VALUE=DATE:20190530
|
||||
|
@ -252,13 +105,6 @@ DTEND;VALUE=DATE:20190531
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pfingsten
|
||||
UID:4154d812-6a09-4bb1-9b39-9654af771086
|
||||
DTSTART;VALUE=DATE:20190609
|
||||
DTEND;VALUE=DATE:20190610
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pfingstmontag
|
||||
UID:68095b69-e62a-4a0a-be4a-c9a68844a341
|
||||
DTSTART;VALUE=DATE:20190610
|
||||
|
@ -280,13 +126,6 @@ DTEND;VALUE=DATE:20191118
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Buß- und Bettag
|
||||
UID:29bcda47-bb53-40ef-8d23-5f96e87d7b11
|
||||
DTSTART;VALUE=DATE:20191120
|
||||
DTEND;VALUE=DATE:20191121
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Totensonntag
|
||||
UID:55f73cbf-979c-4947-9245-1f39720f017a
|
||||
DTSTART;VALUE=DATE:20191124
|
||||
|
@ -294,55 +133,6 @@ DTEND;VALUE=DATE:20191125
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Erster Advent
|
||||
UID:f88e5652-cc2c-4e29-8d7a-aaf2b839ca87
|
||||
DTSTART;VALUE=DATE:20191201
|
||||
DTEND;VALUE=DATE:20191202
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Zweiter Advent
|
||||
UID:6a1e6f6b-4a86-45cf-ae59-e73968a4f094
|
||||
DTSTART;VALUE=DATE:20191208
|
||||
DTEND;VALUE=DATE:20191209
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Dritter Advent
|
||||
UID:59ab9870-918f-49ef-a3c5-ac1b79c12e43
|
||||
DTSTART;VALUE=DATE:20191215
|
||||
DTEND;VALUE=DATE:20191216
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Vierter Advent
|
||||
UID:cc5ff7ef-7d49-49ab-ab20-b2fcfb9d5c8a
|
||||
DTSTART;VALUE=DATE:20191222
|
||||
DTEND;VALUE=DATE:20191223
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Rosenmontag
|
||||
UID:f10cb9c7-e9c6-40da-9799-e9f7defc8706
|
||||
DTSTART;VALUE=DATE:20200224
|
||||
DTEND;VALUE=DATE:20200225
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Aschermittwoch
|
||||
UID:d263556d-11f7-41dd-9b87-e7e33b5e0cd7
|
||||
DTSTART;VALUE=DATE:20200226
|
||||
DTEND;VALUE=DATE:20200227
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Palmsonntag
|
||||
UID:e7d82cc8-29d3-4b46-8c64-6d0514ff01a3
|
||||
DTSTART;VALUE=DATE:20200405
|
||||
DTEND;VALUE=DATE:20200406
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Karfreitag
|
||||
UID:84fb596d-f62c-4f0c-be11-7d96e7883e97
|
||||
DTSTART;VALUE=DATE:20200410
|
||||
|
@ -350,8 +140,8 @@ DTEND;VALUE=DATE:20200411
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ostern
|
||||
UID:b65c108f-5eea-4065-a4cd-8f5cc869666b
|
||||
SUMMARY:Ostersonntag
|
||||
UID:84fb596d-f62c-4f0c-be11-7d96e7884567
|
||||
DTSTART;VALUE=DATE:20200412
|
||||
DTEND;VALUE=DATE:20200413
|
||||
STATUS:CONFIRMED
|
||||
|
@ -364,13 +154,6 @@ DTEND;VALUE=DATE:20200414
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Muttertag
|
||||
UID:b3a25d49-3ae0-4941-a0a3-605a0aa013a3
|
||||
DTSTART;VALUE=DATE:20200510
|
||||
DTEND;VALUE=DATE:20200511
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Christi Himmelfahrt
|
||||
UID:20b3805d-d325-478b-bcee-c8f1f87f7e2d
|
||||
DTSTART;VALUE=DATE:20200521
|
||||
|
@ -378,8 +161,8 @@ DTEND;VALUE=DATE:20200522
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pfingsten
|
||||
UID:b394de73-9c84-425c-8f43-acb3f08988fb
|
||||
SUMMARY:Pfingstsonntag
|
||||
UID:12013b62-6924-4457-89ff-3a8ba947778
|
||||
DTSTART;VALUE=DATE:20200531
|
||||
DTEND;VALUE=DATE:20200601
|
||||
STATUS:CONFIRMED
|
||||
|
@ -406,13 +189,6 @@ DTEND;VALUE=DATE:20201116
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Buß- und Bettag
|
||||
UID:fbda2175-0043-463e-9559-75846f246604
|
||||
DTSTART;VALUE=DATE:20201118
|
||||
DTEND;VALUE=DATE:20201119
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Totensonntag
|
||||
UID:0cc4f56c-7eb8-4de7-ae2a-99b293b25f97
|
||||
DTSTART;VALUE=DATE:20201122
|
||||
|
@ -420,48 +196,6 @@ DTEND;VALUE=DATE:20201123
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Erster Advent
|
||||
UID:af547b9d-c9fb-4b2c-a9ee-1883a246fb4a
|
||||
DTSTART;VALUE=DATE:20201129
|
||||
DTEND;VALUE=DATE:20201130
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Zweiter Advent
|
||||
UID:9be17f09-8386-4d4a-b611-ea5b8aaca4d1
|
||||
DTSTART;VALUE=DATE:20201206
|
||||
DTEND;VALUE=DATE:20201207
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Dritter Advent
|
||||
UID:7b494bd1-ed8b-4278-985e-f974481b1574
|
||||
DTSTART;VALUE=DATE:20201213
|
||||
DTEND;VALUE=DATE:20201214
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Vierter Advent
|
||||
UID:1b11acb7-0340-4958-9225-cfc14f4a478f
|
||||
DTSTART;VALUE=DATE:20201220
|
||||
DTEND;VALUE=DATE:20201221
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Rosenmontag
|
||||
UID:2a024898-6e15-448b-83f5-c994fb1e4aa1
|
||||
DTSTART;VALUE=DATE:20210215
|
||||
DTEND;VALUE=DATE:20210216
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Aschermittwoch
|
||||
UID:82dc191a-e513-407e-99e3-9cb98483715d
|
||||
DTSTART;VALUE=DATE:20210217
|
||||
DTEND;VALUE=DATE:20210218
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Karfreitag
|
||||
UID:4c8899f1-6694-4804-bdaf-dd13f837c8d5
|
||||
DTSTART;VALUE=DATE:20210402
|
||||
|
@ -469,13 +203,6 @@ DTEND;VALUE=DATE:20210403
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ostern
|
||||
UID:7de1ada4-4e88-417e-91a1-86a219184830
|
||||
DTSTART;VALUE=DATE:20210404
|
||||
DTEND;VALUE=DATE:20210405
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ostermontag
|
||||
UID:3ab2214a-92e4-4fca-87b6-77d92c142631
|
||||
DTSTART;VALUE=DATE:20210405
|
||||
|
@ -483,13 +210,6 @@ DTEND;VALUE=DATE:20210406
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Muttertag
|
||||
UID:d6cfc602-b0ec-4cb7-a066-4fed1804dc2e
|
||||
DTSTART;VALUE=DATE:20210509
|
||||
DTEND;VALUE=DATE:20210510
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Christi Himmelfahrt
|
||||
UID:65fd8793-c12f-4c51-b392-a40b8b434fee
|
||||
DTSTART;VALUE=DATE:20210513
|
||||
|
@ -497,13 +217,6 @@ DTEND;VALUE=DATE:20210514
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pfingsten
|
||||
UID:6b058d52-a7c5-40e4-9c49-9b2cf6994053
|
||||
DTSTART;VALUE=DATE:20210523
|
||||
DTEND;VALUE=DATE:20210524
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pfingstmontag
|
||||
UID:8a560aec-1ad3-4116-b0c0-f345345f8112
|
||||
DTSTART;VALUE=DATE:20210524
|
||||
|
@ -525,13 +238,6 @@ DTEND;VALUE=DATE:20211115
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Buß- und Bettag
|
||||
UID:b495650e-002d-4c02-b9d3-52c26b204bf0
|
||||
DTSTART;VALUE=DATE:20211117
|
||||
DTEND;VALUE=DATE:20211118
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Totensonntag
|
||||
UID:f0a7eadd-30e7-46c1-bce0-37616e68ac13
|
||||
DTSTART;VALUE=DATE:20211121
|
||||
|
@ -539,55 +245,6 @@ DTEND;VALUE=DATE:20211122
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Erster Advent
|
||||
UID:03e79870-f2e5-414e-ac71-a41f73acd5c8
|
||||
DTSTART;VALUE=DATE:20211128
|
||||
DTEND;VALUE=DATE:20211129
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Zweiter Advent
|
||||
UID:79ba8671-3780-461a-a884-c23a64cf7930
|
||||
DTSTART;VALUE=DATE:20211205
|
||||
DTEND;VALUE=DATE:20211206
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Dritter Advent
|
||||
UID:7128bd77-e61e-48ec-baca-adc12c869c87
|
||||
DTSTART;VALUE=DATE:20211212
|
||||
DTEND;VALUE=DATE:20211213
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Vierter Advent
|
||||
UID:b73f7d0d-0d10-4d42-96d7-d3256415d1b9
|
||||
DTSTART;VALUE=DATE:20211219
|
||||
DTEND;VALUE=DATE:20211220
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Rosenmontag
|
||||
UID:28273646-1658-430a-836f-90b3079ab56c
|
||||
DTSTART;VALUE=DATE:20220228
|
||||
DTEND;VALUE=DATE:20220301
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Aschermittwoch
|
||||
UID:642134b6-db26-4c84-9055-88f1e350ef4e
|
||||
DTSTART;VALUE=DATE:20220302
|
||||
DTEND;VALUE=DATE:20220303
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Palmsonntag
|
||||
UID:70683648-440f-45aa-9460-10d1ffced6e1
|
||||
DTSTART;VALUE=DATE:20220410
|
||||
DTEND;VALUE=DATE:20220411
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Karfreitag
|
||||
UID:018fdbdd-e2c5-48aa-bf6e-4f802d757d52
|
||||
DTSTART;VALUE=DATE:20220415
|
||||
|
@ -595,13 +252,6 @@ DTEND;VALUE=DATE:20220416
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ostern
|
||||
UID:fca22c3c-3e5a-4aec-b1f8-14b146ec71ef
|
||||
DTSTART;VALUE=DATE:20220417
|
||||
DTEND;VALUE=DATE:20220418
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ostermontag
|
||||
UID:402857cd-1eb5-48ef-9b8c-fd0eb188dec6
|
||||
DTSTART;VALUE=DATE:20220418
|
||||
|
@ -609,13 +259,6 @@ DTEND;VALUE=DATE:20220419
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Muttertag
|
||||
UID:ff344166-2d62-43c5-9ded-53a300f684b9
|
||||
DTSTART;VALUE=DATE:20220508
|
||||
DTEND;VALUE=DATE:20220509
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Christi Himmelfahrt
|
||||
UID:c90fd01f-5521-4973-b0bb-11c3b16dd9ff
|
||||
DTSTART;VALUE=DATE:20220526
|
||||
|
@ -623,13 +266,6 @@ DTEND;VALUE=DATE:20220527
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pfingsten
|
||||
UID:0d0106e9-1335-464e-b463-5cb142db5f1a
|
||||
DTSTART;VALUE=DATE:20220605
|
||||
DTEND;VALUE=DATE:20220606
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pfingstmontag
|
||||
UID:a22fa187-185b-4cf1-93c1-82bdca14fd0e
|
||||
DTSTART;VALUE=DATE:20220606
|
||||
|
@ -651,13 +287,6 @@ DTEND;VALUE=DATE:20221114
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Buß- und Bettag
|
||||
UID:590b067f-31f8-4c6f-bafb-accf22a6cf89
|
||||
DTSTART;VALUE=DATE:20221116
|
||||
DTEND;VALUE=DATE:20221117
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Totensonntag
|
||||
UID:f3b740a9-5fe6-42f8-8ea1-0a24c3b7947c
|
||||
DTSTART;VALUE=DATE:20221120
|
||||
|
@ -665,55 +294,6 @@ DTEND;VALUE=DATE:20221121
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Erster Advent
|
||||
UID:9b5a13c3-6abe-458e-bcbe-f1d6cdcdd02d
|
||||
DTSTART;VALUE=DATE:20221127
|
||||
DTEND;VALUE=DATE:20221128
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Zweiter Advent
|
||||
UID:1a7f91ae-5850-4e72-bdd1-1108c812d6fb
|
||||
DTSTART;VALUE=DATE:20221204
|
||||
DTEND;VALUE=DATE:20221205
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Dritter Advent
|
||||
UID:a7d53387-8173-4a44-8d67-b64563dff278
|
||||
DTSTART;VALUE=DATE:20221211
|
||||
DTEND;VALUE=DATE:20221212
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Vierter Advent
|
||||
UID:220094a1-08c4-4a0d-bd30-40d071682395
|
||||
DTSTART;VALUE=DATE:20221218
|
||||
DTEND;VALUE=DATE:20221219
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Rosenmontag
|
||||
UID:5f7513bd-0978-4ed8-8022-7280645c3186
|
||||
DTSTART;VALUE=DATE:20230220
|
||||
DTEND;VALUE=DATE:20230221
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Aschermittwoch
|
||||
UID:956d4b66-1b2c-418e-ae7d-3cffad30eae7
|
||||
DTSTART;VALUE=DATE:20230222
|
||||
DTEND;VALUE=DATE:20230223
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Palmsonntag
|
||||
UID:0b5571a1-a813-4f47-bef7-dc28569de753
|
||||
DTSTART;VALUE=DATE:20230402
|
||||
DTEND;VALUE=DATE:20230403
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Karfreitag
|
||||
UID:ffaf8199-f853-45c8-b635-5f0e302f13fe
|
||||
DTSTART;VALUE=DATE:20230407
|
||||
|
@ -721,13 +301,6 @@ DTEND;VALUE=DATE:20230408
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ostern
|
||||
UID:a379dcf3-85eb-401f-b8cf-7f02da344d11
|
||||
DTSTART;VALUE=DATE:20230409
|
||||
DTEND;VALUE=DATE:20230410
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ostermontag
|
||||
UID:bb40c59f-7f00-44b7-98fc-e5fd5e0c9c27
|
||||
DTSTART;VALUE=DATE:20230410
|
||||
|
@ -735,13 +308,6 @@ DTEND;VALUE=DATE:20230411
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Muttertag
|
||||
UID:8a0d77ba-30f9-4238-83b5-adcab7a3badb
|
||||
DTSTART;VALUE=DATE:20230514
|
||||
DTEND;VALUE=DATE:20230515
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Christi Himmelfahrt
|
||||
UID:f91d0e50-3550-46f4-959e-4c0837d122b3
|
||||
DTSTART;VALUE=DATE:20230518
|
||||
|
@ -749,13 +315,6 @@ DTEND;VALUE=DATE:20230519
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pfingsten
|
||||
UID:888f86d6-9809-4b2c-948b-1443edac5e8e
|
||||
DTSTART;VALUE=DATE:20230528
|
||||
DTEND;VALUE=DATE:20230529
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pfingstmontag
|
||||
UID:4eebf391-9bab-4c47-9828-9f102779600a
|
||||
DTSTART;VALUE=DATE:20230529
|
||||
|
@ -777,13 +336,6 @@ DTEND;VALUE=DATE:20231120
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Buß- und Bettag
|
||||
UID:ba67b1dd-5db8-4536-af86-5ac01e6db382
|
||||
DTSTART;VALUE=DATE:20231122
|
||||
DTEND;VALUE=DATE:20231123
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Totensonntag
|
||||
UID:0eae032b-ae56-42ba-9d9b-42893d74dfb2
|
||||
DTSTART;VALUE=DATE:20231126
|
||||
|
@ -791,55 +343,6 @@ DTEND;VALUE=DATE:20231127
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Erster Advent
|
||||
UID:42a5ae0f-030c-4e61-a16a-168e3644c61a
|
||||
DTSTART;VALUE=DATE:20231203
|
||||
DTEND;VALUE=DATE:20231204
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Zweiter Advent
|
||||
UID:3568cc04-205f-43ce-981f-5f695f0ffb89
|
||||
DTSTART;VALUE=DATE:20231210
|
||||
DTEND;VALUE=DATE:20231211
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Dritter Advent
|
||||
UID:c706891d-2560-4b11-b165-01b1810f36a3
|
||||
DTSTART;VALUE=DATE:20231217
|
||||
DTEND;VALUE=DATE:20231218
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Vierter Advent
|
||||
UID:966f4e2f-a485-4617-be7b-fc1bfed38d05
|
||||
DTSTART;VALUE=DATE:20231224
|
||||
DTEND;VALUE=DATE:20231225
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Rosenmontag
|
||||
UID:28ff27ae-6c43-4241-8e19-b859d3bacbbd
|
||||
DTSTART;VALUE=DATE:20240212
|
||||
DTEND;VALUE=DATE:20240213
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Aschermittwoch
|
||||
UID:99af362f-b9b1-4452-896d-648906ae4920
|
||||
DTSTART;VALUE=DATE:20240214
|
||||
DTEND;VALUE=DATE:20240215
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Palmsonntag
|
||||
UID:aabf87df-8b3b-469d-b731-fd8ee5c851da
|
||||
DTSTART;VALUE=DATE:20240324
|
||||
DTEND;VALUE=DATE:20240325
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Karfreitag
|
||||
UID:179a8a7f-6ebc-427f-89c8-dfd87f770bf9
|
||||
DTSTART;VALUE=DATE:20240329
|
||||
|
@ -861,20 +364,6 @@ DTEND;VALUE=DATE:20240510
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Muttertag
|
||||
UID:23fa06d1-ccfe-40bf-81e8-d558ed1bf420
|
||||
DTSTART;VALUE=DATE:20240512
|
||||
DTEND;VALUE=DATE:20240513
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pfingsten
|
||||
UID:7075eb28-7dde-4b96-8aad-76083ac8682b
|
||||
DTSTART;VALUE=DATE:20240519
|
||||
DTEND;VALUE=DATE:20240520
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pfingstmontag
|
||||
UID:aa76019e-b3b6-4488-8bbf-31dc09fb1764
|
||||
DTSTART;VALUE=DATE:20240520
|
||||
|
@ -896,13 +385,6 @@ DTEND;VALUE=DATE:20241118
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Buß- und Bettag
|
||||
UID:dcf3f9a7-086c-4e3e-805f-adaaec6fda2e
|
||||
DTSTART;VALUE=DATE:20241120
|
||||
DTEND;VALUE=DATE:20241121
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Totensonntag
|
||||
UID:546e46fb-ec99-4ddd-aa9d-6ec619b96dc0
|
||||
DTSTART;VALUE=DATE:20241124
|
||||
|
@ -910,55 +392,6 @@ DTEND;VALUE=DATE:20241125
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Erster Advent
|
||||
UID:0b6285cb-89f9-4b85-8de0-a42bd18589c9
|
||||
DTSTART;VALUE=DATE:20241201
|
||||
DTEND;VALUE=DATE:20241202
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Zweiter Advent
|
||||
UID:4ad38de2-8fce-4344-a208-979f1916b835
|
||||
DTSTART;VALUE=DATE:20241208
|
||||
DTEND;VALUE=DATE:20241209
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Dritter Advent
|
||||
UID:b49431ca-7be4-4b79-bbb2-5f6a1248ef93
|
||||
DTSTART;VALUE=DATE:20241215
|
||||
DTEND;VALUE=DATE:20241216
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Vierter Advent
|
||||
UID:6b46edc1-b54b-430b-9028-759a11d582c7
|
||||
DTSTART;VALUE=DATE:20241222
|
||||
DTEND;VALUE=DATE:20241223
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Rosenmontag
|
||||
UID:749e7d53-b90e-4e4c-8375-10bc41996985
|
||||
DTSTART;VALUE=DATE:20250303
|
||||
DTEND;VALUE=DATE:20250304
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Aschermittwoch
|
||||
UID:0c4a90fc-4651-4a12-886c-0659eb26d299
|
||||
DTSTART;VALUE=DATE:20250305
|
||||
DTEND;VALUE=DATE:20250306
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Palmsonntag
|
||||
UID:1c33e111-bb08-4f3d-992e-4e4712ab7118
|
||||
DTSTART;VALUE=DATE:20250413
|
||||
DTEND;VALUE=DATE:20250414
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Karfreitag
|
||||
UID:e9a51e52-0956-4d0f-be18-c5ce39dae024
|
||||
DTSTART;VALUE=DATE:20250418
|
||||
|
@ -966,13 +399,6 @@ DTEND;VALUE=DATE:20250419
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ostern
|
||||
UID:efacb91a-6c19-4f00-bda9-cd6b8cfc4ce0
|
||||
DTSTART;VALUE=DATE:20250420
|
||||
DTEND;VALUE=DATE:20250421
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ostermontag
|
||||
UID:457982d2-a038-49d2-9b27-6f9708a16206
|
||||
DTSTART;VALUE=DATE:20250421
|
||||
|
@ -980,13 +406,6 @@ DTEND;VALUE=DATE:20250422
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Muttertag
|
||||
UID:1b9ecb65-b7ff-4388-b20c-64a5f90ff83f
|
||||
DTSTART;VALUE=DATE:20250511
|
||||
DTEND;VALUE=DATE:20250512
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Christi Himmelfahrt
|
||||
UID:0705f107-eef7-4929-ac93-a9d7a645e7f8
|
||||
DTSTART;VALUE=DATE:20250529
|
||||
|
@ -994,13 +413,6 @@ DTEND;VALUE=DATE:20250530
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pfingsten
|
||||
UID:49fa3924-037e-46aa-985b-29f0f886ef8c
|
||||
DTSTART;VALUE=DATE:20250608
|
||||
DTEND;VALUE=DATE:20250609
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pfingstmontag
|
||||
UID:082092fe-3345-4652-b5f9-d5aeee66328f
|
||||
DTSTART;VALUE=DATE:20250609
|
||||
|
@ -1022,13 +434,6 @@ DTEND;VALUE=DATE:20251117
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Buß- und Bettag
|
||||
UID:b2e0c62b-d371-414a-9f14-bdd0fa5a3eb9
|
||||
DTSTART;VALUE=DATE:20251119
|
||||
DTEND;VALUE=DATE:20251120
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Totensonntag
|
||||
UID:54c731a4-2052-44f7-be17-7976de70f144
|
||||
DTSTART;VALUE=DATE:20251123
|
||||
|
@ -1080,14 +485,6 @@ STATUS:CONFIRMED
|
|||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Valentinstag
|
||||
UID:959125914
|
||||
DTSTART;VALUE=DATE:20060214
|
||||
DTEND;VALUE=DATE:20060215
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Tag der Arbeit
|
||||
UID:999463355
|
||||
DTSTART;VALUE=DATE:20060501
|
||||
|
@ -1104,7 +501,7 @@ STATUS:CONFIRMED
|
|||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Mariä Himmelfahrt
|
||||
SUMMARY:Maria Himmelfahrt
|
||||
UID:948278340
|
||||
DTSTART;VALUE=DATE:20060815
|
||||
DTEND;VALUE=DATE:20060816
|
||||
|
@ -1120,14 +517,6 @@ STATUS:CONFIRMED
|
|||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Reformationstag
|
||||
UID:996398531
|
||||
DTSTART;VALUE=DATE:20061031
|
||||
DTEND;VALUE=DATE:20061101
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Allerheiligen
|
||||
UID:970745861
|
||||
DTSTART;VALUE=DATE:20061101
|
||||
|
@ -1136,22 +525,6 @@ STATUS:CONFIRMED
|
|||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Nikolaus
|
||||
UID:915905148
|
||||
DTSTART;VALUE=DATE:20061206
|
||||
DTEND;VALUE=DATE:20061207
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Heiliger Abend
|
||||
UID:031bd550-c8d9-11da-9d0c-a4805e40b203
|
||||
DTSTART;VALUE=DATE:20061224
|
||||
DTEND;VALUE=DATE:20061225
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:1. Weihnachtstag
|
||||
UID:982967580
|
||||
DTSTART;VALUE=DATE:20061225
|
||||
|
@ -1175,4 +548,62 @@ DTEND;VALUE=DATE:20070101
|
|||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Internationaler Frauentag
|
||||
UID:4694f46a-aef0-49a0-a8eb-asdasd
|
||||
DTSTART;VALUE=DATE:20170308
|
||||
DTEND;VALUE=DATE:20170309
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Reformationstag
|
||||
UID:4694f46a-aef0-49a0-a8eb-reform
|
||||
DTSTART;VALUE=DATE:20171031
|
||||
DTEND;VALUE=DATE:20171101
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Buß- und Bettag
|
||||
UID:4694f46a-aef0-49a0-a8eb-b1
|
||||
DTSTART;VALUE=DATE:20181121
|
||||
DTEND;VALUE=DATE:20181122
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Buß- und Bettag
|
||||
UID:4694f46a-aef0-49a0-a8eb-b2
|
||||
DTSTART;VALUE=DATE:20191120
|
||||
DTEND;VALUE=DATE:20191121
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Buß- und Bettag
|
||||
UID:4694f46a-aef0-49a0-a8eb-b3
|
||||
DTSTART;VALUE=DATE:20201118
|
||||
DTEND;VALUE=DATE:20201119
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Buß- und Bettag
|
||||
UID:4694f46a-aef0-49a0-a8eb-b4
|
||||
DTSTART;VALUE=DATE:20211117
|
||||
DTEND;VALUE=DATE:20211118
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Buß- und Bettag
|
||||
UID:4694f46a-aef0-49a0-a8eb-b5
|
||||
DTSTART;VALUE=DATE:20221116
|
||||
DTEND;VALUE=DATE:20221117
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Buß- und Bettag
|
||||
UID:4694f46a-aef0-49a0-a8eb-b6
|
||||
DTSTART;VALUE=DATE:20231122
|
||||
DTEND;VALUE=DATE:20231123
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
|
|
|
@ -300,8 +300,8 @@ END:VEVENT
|
|||
BEGIN:VEVENT
|
||||
SUMMARY:ID-I-Milad-un-Nabi [Barah-Wafat]
|
||||
UID:2002-05-25-1
|
||||
DTSTART;VALUE=DATE:20161213
|
||||
DTEND;VALUE=DATE:20161214
|
||||
DTSTART;VALUE=DATE:20161110
|
||||
DTEND;VALUE=DATE:20161111
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
|
|
300
app/src/main/assets/indonesia.ics
Normal file
300
app/src/main/assets/indonesia.ics
Normal file
|
@ -0,0 +1,300 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-268948299@marudot.com
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180101
|
||||
SUMMARY:New Year's Day 2018
|
||||
DESCRIPTION:Tahun Baru 2018
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-601964501@marudot.com
|
||||
DTSTART;VALUE=DATE:20180216
|
||||
DTEND;VALUE=DATE:20180216
|
||||
SUMMARY:Chinese New Year
|
||||
DESCRIPTION:Tahun Baru Imlek 2569
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-417357037@marudot.com
|
||||
DTSTART;VALUE=DATE:20180228
|
||||
DTEND;VALUE=DATE:20180228
|
||||
SUMMARY:Coming to Indonesia-Cross Cultural Training
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-578292563@marudot.com
|
||||
DTSTART;VALUE=DATE:20180301
|
||||
DTEND;VALUE=DATE:20180301
|
||||
SUMMARY:Working in Indonesia-Cross Cultural Workshop for Expats
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-1099619811@marudot.com
|
||||
DTSTART;VALUE=DATE:20180313
|
||||
DTEND;VALUE=DATE:20180313
|
||||
SUMMARY:Living in Indonesia-Cross Cultural Workshop for Spouses
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-894503703@marudot.com
|
||||
DTSTART;VALUE=DATE:20180314
|
||||
DTEND;VALUE=DATE:20180314
|
||||
SUMMARY:Management in Indonesia-Cross Cultural Workshop
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-791851244@marudot.com
|
||||
DTSTART;VALUE=DATE:20180317
|
||||
DTEND;VALUE=DATE:20180317
|
||||
SUMMARY:Balinese New Year
|
||||
DESCRIPTION:Hari Raya Nyepi 1940
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-329618688@marudot.com
|
||||
DTSTART;VALUE=DATE:20180330
|
||||
DTEND;VALUE=DATE:20180330
|
||||
SUMMARY:Good Friday
|
||||
DESCRIPTION:Wafat Isa Al-Masih
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-190146881@marudot.com
|
||||
DTSTART;VALUE=DATE:20180414
|
||||
DTEND;VALUE=DATE:20180414
|
||||
SUMMARY:Ascension of Prophet Muhammad SAW
|
||||
DESCRIPTION:Isra’ Mi’raj Nabi Muhammad SAW
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-435386496@marudot.com
|
||||
DTSTART;VALUE=DATE:20180501
|
||||
DTEND;VALUE=DATE:20180501
|
||||
SUMMARY:Labor Day
|
||||
DESCRIPTION:Hari Buruh Internasional
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-418653428@marudot.com
|
||||
DTSTART;VALUE=DATE:20180510
|
||||
DTEND;VALUE=DATE:20180510
|
||||
SUMMARY:Waisak Day (“Buddhas Birthday” 2562)
|
||||
DESCRIPTION:Hari Waisak 2562
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-2110293750@marudot.com
|
||||
DTSTART;VALUE=DATE:20180510
|
||||
DTEND;VALUE=DATE:20180510
|
||||
SUMMARY:Ascension Day of Jesus Christ
|
||||
DESCRIPTION:Kenaikan Isa Almasih
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-119842090@marudot.com
|
||||
DTSTART;VALUE=DATE:20180601
|
||||
DTEND;VALUE=DATE:20180601
|
||||
SUMMARY:Birthday of Pancasila
|
||||
DESCRIPTION:Hari Lahir Pancasila
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-1166612864@marudot.com
|
||||
DTSTART;VALUE=DATE:20180615
|
||||
DTEND;VALUE=DATE:20180615
|
||||
SUMMARY:End of Ramadan – Eid-al-Fitr 1439H (1st of Shawwal)
|
||||
DESCRIPTION:Hari Raya Idul Fitri 1439H
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-640873938@marudot.com
|
||||
DTSTART;VALUE=DATE:20180616
|
||||
DTEND;VALUE=DATE:20180616
|
||||
SUMMARY:End of Ramadan – Eid-al-Fitr 1439H (2nd of Shawwal)
|
||||
DESCRIPTION:Hari Raya Idul Fitri 1439H
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-1948724575@marudot.com
|
||||
DTSTART;VALUE=DATE:20180808
|
||||
DTEND;VALUE=DATE:20180808
|
||||
SUMMARY:Working in Indonesia-Cross Cultural Workshop for Expats
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-1926764224@marudot.com
|
||||
DTSTART;VALUE=DATE:20180814
|
||||
DTEND;VALUE=DATE:20180814
|
||||
SUMMARY:Management in Indonesia-Cross Cultural Workshop
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-828431129@marudot.com
|
||||
DTSTART;VALUE=DATE:20180817
|
||||
DTEND;VALUE=DATE:20180817
|
||||
SUMMARY:Indonesia Independence Day
|
||||
DESCRIPTION:Hari Kemerdekaan Republik Indonesia ke-73
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-1713949044@marudot.com
|
||||
DTSTART;VALUE=DATE:20180822
|
||||
DTEND;VALUE=DATE:20180822
|
||||
SUMMARY:Islamic feast of Sacrifice (Bakr-Eid) 1439H
|
||||
DESCRIPTION:Hari Raya Idul Adha 1439H
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-1202137034@marudot.com
|
||||
DTSTART;VALUE=DATE:20180911
|
||||
DTEND;VALUE=DATE:20180911
|
||||
SUMMARY:Islamic New Year (1st Muharram 1440H)
|
||||
DESCRIPTION:Tahun Baru Islam 1440H
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-209129850@marudot.com
|
||||
DTSTART;VALUE=DATE:20181120
|
||||
DTEND;VALUE=DATE:20181120
|
||||
SUMMARY:Birth of the Prophet Muhammad SAW
|
||||
DESCRIPTION:Maulid Nabi
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-946856460@marudot.com
|
||||
DTSTART;VALUE=DATE:20181225
|
||||
DTEND;VALUE=DATE:20181225
|
||||
SUMMARY:Christmas Day
|
||||
DESCRIPTION:Hari Raya Natal
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-2689482992@marudot.com
|
||||
DTSTART;VALUE=DATE:20190101
|
||||
DTEND;VALUE=DATE:20190101
|
||||
SUMMARY:New Year's Day 2019
|
||||
DESCRIPTION:Tahun Baru 2019
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-6019645012@marudot.com
|
||||
DTSTART;VALUE=DATE:20190205
|
||||
DTEND;VALUE=DATE:20190205
|
||||
SUMMARY:Chinese New Year
|
||||
DESCRIPTION:Tahun Baru Imlek 2569
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-7918512442@marudot.com
|
||||
DTSTART;VALUE=DATE:20190307
|
||||
DTEND;VALUE=DATE:20190307
|
||||
SUMMARY:Balinese New Year
|
||||
DESCRIPTION:Hari Raya Nyepi 1940
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-3296186882@marudot.com
|
||||
DTSTART;VALUE=DATE:20190419
|
||||
DTEND;VALUE=DATE:20190419
|
||||
SUMMARY:Good Friday
|
||||
DESCRIPTION:Wafat Isa Al-Masih
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-1901468812@marudot.com
|
||||
DTSTART;VALUE=DATE:20190530
|
||||
DTEND;VALUE=DATE:20190530
|
||||
SUMMARY:Ascension of Prophet Muhammad SAW
|
||||
DESCRIPTION:Isra’ Mi’raj Nabi Muhammad SAW
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-4353864962@marudot.com
|
||||
DTSTART;VALUE=DATE:20190501
|
||||
DTEND;VALUE=DATE:20190501
|
||||
SUMMARY:Labor Day
|
||||
DESCRIPTION:Hari Buruh Internasional
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-4186534282@marudot.com
|
||||
DTSTART;VALUE=DATE:20190519
|
||||
DTEND;VALUE=DATE:20190519
|
||||
SUMMARY:Waisak Day (“Buddhas Birthday” 2562)
|
||||
DESCRIPTION:Hari Waisak 2562
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-21102937502@marudot.com
|
||||
DTSTART;VALUE=DATE:20190530
|
||||
DTEND;VALUE=DATE:20190530
|
||||
SUMMARY:Ascension Day of Jesus Christ
|
||||
DESCRIPTION:Kenaikan Isa Almasih
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-1198420902@marudot.com
|
||||
DTSTART;VALUE=DATE:20190601
|
||||
DTEND;VALUE=DATE:20190601
|
||||
SUMMARY:Birthday of Pancasila
|
||||
DESCRIPTION:Hari Lahir Pancasila
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-11666128642@marudot.com
|
||||
DTSTART;VALUE=DATE:20180605
|
||||
DTEND;VALUE=DATE:20180605
|
||||
SUMMARY:End of Ramadan – Eid-al-Fitr 1439H (1st of Shawwal)
|
||||
DESCRIPTION:Hari Raya Idul Fitri 1439H
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-6408739382@marudot.com
|
||||
DTSTART;VALUE=DATE:20180606
|
||||
DTEND;VALUE=DATE:20180606
|
||||
SUMMARY:End of Ramadan – Eid-al-Fitr 1439H (2nd of Shawwal)
|
||||
DESCRIPTION:Hari Raya Idul Fitri 1439H
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-8284311292@marudot.com
|
||||
DTSTART;VALUE=DATE:20190817
|
||||
DTEND;VALUE=DATE:20190817
|
||||
SUMMARY:Indonesia Independence Day
|
||||
DESCRIPTION:Hari Kemerdekaan Republik Indonesia ke-73
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-17139490442@marudot.com
|
||||
DTSTART;VALUE=DATE:20180812
|
||||
DTEND;VALUE=DATE:20180812
|
||||
SUMMARY:Islamic feast of Sacrifice (Bakr-Eid) 1439H
|
||||
DESCRIPTION:Hari Raya Idul Adha 1439H
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-12021370342@marudot.com
|
||||
DTSTART;VALUE=DATE:20180901
|
||||
DTEND;VALUE=DATE:20180901
|
||||
SUMMARY:Islamic New Year (1st Muharram 1440H)
|
||||
DESCRIPTION:Tahun Baru Islam 1440H
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-2091298502@marudot.com
|
||||
DTSTART;VALUE=DATE:20181110
|
||||
DTEND;VALUE=DATE:20181110
|
||||
SUMMARY:Birth of the Prophet Muhammad SAW
|
||||
DESCRIPTION:Maulid Nabi
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20171212T045342Z-9468564602@marudot.com
|
||||
DTSTART;VALUE=DATE:20181225
|
||||
DTEND;VALUE=DATE:20181225
|
||||
SUMMARY:Christmas Day
|
||||
DESCRIPTION:Hari Raya Natal
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
|
@ -152,10 +152,10 @@ STATUS:CONFIRMED
|
|||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:天皇誕生日 / Tennō tanjōbi / Emperor Akihito's Birthday
|
||||
SUMMARY:天皇誕生日 / Tennō tanjōbi / The Emperor Naruhito's Birthday
|
||||
UID:0f5a4799-4082-4921-95e5-183652982b2d
|
||||
DTSTART;VALUE=DATE:20071223
|
||||
DTEND;VALUE=DATE:20071224
|
||||
DTSTART;VALUE=DATE:20190223
|
||||
DTEND;VALUE=DATE:20190224
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
|
|
326
app/src/main/assets/latvia.ics
Normal file
326
app/src/main/assets/latvia.ics
Normal file
|
@ -0,0 +1,326 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20180101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
SUMMARY:Jaungada dienu
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20180330@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180330
|
||||
DTEND;VALUE=DATE:20180331
|
||||
SUMMARY:Lielo Piektdienu
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20180401@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180401
|
||||
DTEND;VALUE=DATE:20180402
|
||||
SUMMARY:Pirmās Lieldienas
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20180402@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180402
|
||||
DTEND;VALUE=DATE:20180403
|
||||
SUMMARY:Otro Lieldienu dienu
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20180430@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180430
|
||||
DTEND;VALUE=DATE:20180501
|
||||
SUMMARY:Darba svētkus
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20180501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180501
|
||||
DTEND;VALUE=DATE:20180502
|
||||
SUMMARY:Darba svētkus
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20180504@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180504
|
||||
DTEND;VALUE=DATE:20180505
|
||||
SUMMARY:Latvijas Republikas Neatkarības atjaunošanas dienu
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20180513@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180513
|
||||
DTEND;VALUE=DATE:20180514
|
||||
SUMMARY:Mātes diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20180520@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180520
|
||||
DTEND;VALUE=DATE:20180521
|
||||
SUMMARY:Vasarsvētkus
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20180623@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180623
|
||||
DTEND;VALUE=DATE:20180624
|
||||
SUMMARY:Līgo dienu
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20180624@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180624
|
||||
DTEND;VALUE=DATE:20180625
|
||||
SUMMARY:Jāņu dienu
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20181119@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181119
|
||||
DTEND;VALUE=DATE:20181120
|
||||
SUMMARY:Latvijas Republikas proklamēšanas diena
|
||||
DESCRIPTION:Holiday in lieu of 18 Nov 2018
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20181224@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181224
|
||||
DTEND;VALUE=DATE:20181225
|
||||
SUMMARY:Ziemassvētku vakars
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20181225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181225
|
||||
DTEND;VALUE=DATE:20181226
|
||||
SUMMARY:Ziemassvētki
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20181226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181226
|
||||
DTEND;VALUE=DATE:20181227
|
||||
SUMMARY:2. Ziemassvētki
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20181231@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181231
|
||||
DTEND;VALUE=DATE:20190101
|
||||
SUMMARY:Vecgada vakars
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20190101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190101
|
||||
DTEND;VALUE=DATE:20190102
|
||||
SUMMARY:Jaungada dienu
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20190419@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190419
|
||||
DTEND;VALUE=DATE:20190420
|
||||
SUMMARY:Lielo Piektdienu
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20190421@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190421
|
||||
DTEND;VALUE=DATE:20190422
|
||||
SUMMARY:Pirmās Lieldienas
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20190422@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190422
|
||||
DTEND;VALUE=DATE:20190423
|
||||
SUMMARY:Otro Lieldienu dienu
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20190501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190501
|
||||
DTEND;VALUE=DATE:20190502
|
||||
SUMMARY:Darba svētkus
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20190506@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190506
|
||||
DTEND;VALUE=DATE:20190507
|
||||
SUMMARY:Latvijas Republikas Neatkarības atjaunošanas dienu
|
||||
DESCRIPTION:Holiday in lieu of 4 May 2019
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20190512@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190512
|
||||
DTEND;VALUE=DATE:20190513
|
||||
SUMMARY:Mātes diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20190609@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190609
|
||||
DTEND;VALUE=DATE:20190610
|
||||
SUMMARY:Vasarsvētkus
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20190623@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190623
|
||||
DTEND;VALUE=DATE:20190624
|
||||
SUMMARY:Līgo dienu
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20190624@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190624
|
||||
DTEND;VALUE=DATE:20190625
|
||||
SUMMARY:Jāņu dienu
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20191118@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191118
|
||||
DTEND;VALUE=DATE:20191119
|
||||
SUMMARY:Latvijas Republikas proklamēšanas diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20191224@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191224
|
||||
DTEND;VALUE=DATE:20191225
|
||||
SUMMARY:Ziemassvētku vakars
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20191225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191225
|
||||
DTEND;VALUE=DATE:20191226
|
||||
SUMMARY:Ziemassvētki
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20191226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191226
|
||||
DTEND;VALUE=DATE:20191227
|
||||
SUMMARY:2. Ziemassvētki
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20191231@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191231
|
||||
DTEND;VALUE=DATE:20200101
|
||||
SUMMARY:Vecgada vakars
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20200101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200101
|
||||
DTEND;VALUE=DATE:20200102
|
||||
SUMMARY:Jaungada dienu
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20200410@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200410
|
||||
DTEND;VALUE=DATE:20200411
|
||||
SUMMARY:Lielo Piektdienu
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20200412@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200412
|
||||
DTEND;VALUE=DATE:20200413
|
||||
SUMMARY:Pirmās Lieldienas
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20200413@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200413
|
||||
DTEND;VALUE=DATE:20200414
|
||||
SUMMARY:Otro Lieldienu dienu
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20200501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200501
|
||||
DTEND;VALUE=DATE:20200502
|
||||
SUMMARY:Darba svētkus
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20200504@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200504
|
||||
DTEND;VALUE=DATE:20200505
|
||||
SUMMARY:Latvijas Republikas Neatkarības atjaunošanas dienu
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20200510@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200510
|
||||
DTEND;VALUE=DATE:20200511
|
||||
SUMMARY:Mātes diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20200531@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200531
|
||||
DTEND;VALUE=DATE:20200601
|
||||
SUMMARY:Vasarsvētkus
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20200623@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200623
|
||||
DTEND;VALUE=DATE:20200624
|
||||
SUMMARY:Līgo dienu
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20200624@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200624
|
||||
DTEND;VALUE=DATE:20200625
|
||||
SUMMARY:Jāņu dienu
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20201118@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201118
|
||||
DTEND;VALUE=DATE:20201119
|
||||
SUMMARY:Latvijas Republikas proklamēšanas diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20201224@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201224
|
||||
DTEND;VALUE=DATE:20201225
|
||||
SUMMARY:Ziemassvētku vakars
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20201225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201225
|
||||
DTEND;VALUE=DATE:20201226
|
||||
SUMMARY:Ziemassvētki
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20201226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201226
|
||||
DTEND;VALUE=DATE:20201227
|
||||
SUMMARY:2. Ziemassvētki
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lva-20201231@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201231
|
||||
DTEND;VALUE=DATE:20210101
|
||||
SUMMARY:Vecgada vakars
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
317
app/src/main/assets/lithuania.ics
Normal file
317
app/src/main/assets/lithuania.ics
Normal file
|
@ -0,0 +1,317 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20180101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
SUMMARY:Naujieji metai
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20180216@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180216
|
||||
DTEND;VALUE=DATE:20180217
|
||||
SUMMARY:Lietuvos valstybės atkūrimo diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20180311@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180311
|
||||
DTEND;VALUE=DATE:20180312
|
||||
SUMMARY:Lietuvos nepriklausomybės atkūrimo diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20180401@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180401
|
||||
DTEND;VALUE=DATE:20180402
|
||||
SUMMARY:Velykos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20180402@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180402
|
||||
DTEND;VALUE=DATE:20180403
|
||||
SUMMARY:Velykos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20180501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180501
|
||||
DTEND;VALUE=DATE:20180502
|
||||
SUMMARY:Tarptautinė darbo diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20180506@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180506
|
||||
DTEND;VALUE=DATE:20180507
|
||||
SUMMARY:Motinos diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20180603@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180603
|
||||
DTEND;VALUE=DATE:20180604
|
||||
SUMMARY:Tėvo diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20180624@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180624
|
||||
DTEND;VALUE=DATE:20180625
|
||||
SUMMARY:Rasos (Joninės)
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20180706@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180706
|
||||
DTEND;VALUE=DATE:20180707
|
||||
SUMMARY:Valstybės (Lietuvos karaliaus Mindaugo karūnavimo) diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20180815@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180815
|
||||
DTEND;VALUE=DATE:20180816
|
||||
SUMMARY:Žolinė (Švč. Mergelės Marijos ėmimo į dangų diena)
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20181101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181101
|
||||
DTEND;VALUE=DATE:20181102
|
||||
SUMMARY:Visų šventųjų diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20181224@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181224
|
||||
DTEND;VALUE=DATE:20181225
|
||||
SUMMARY:Šv. Kalėdos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20181225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181225
|
||||
DTEND;VALUE=DATE:20181226
|
||||
SUMMARY:Šv. Kalėdos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20181226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181226
|
||||
DTEND;VALUE=DATE:20181227
|
||||
SUMMARY:Šv. Kalėdos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20190101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190101
|
||||
DTEND;VALUE=DATE:20190102
|
||||
SUMMARY:Naujieji metai
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20190216@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190216
|
||||
DTEND;VALUE=DATE:20190217
|
||||
SUMMARY:Lietuvos valstybės atkūrimo diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20190311@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190311
|
||||
DTEND;VALUE=DATE:20190312
|
||||
SUMMARY:Lietuvos nepriklausomybės atkūrimo diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20190421@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190421
|
||||
DTEND;VALUE=DATE:20190422
|
||||
SUMMARY:Velykos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20190422@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190422
|
||||
DTEND;VALUE=DATE:20190423
|
||||
SUMMARY:Velykos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20190501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190501
|
||||
DTEND;VALUE=DATE:20190502
|
||||
SUMMARY:Tarptautinė darbo diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20190505@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190505
|
||||
DTEND;VALUE=DATE:20190506
|
||||
SUMMARY:Motinos diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20190602@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190602
|
||||
DTEND;VALUE=DATE:20190603
|
||||
SUMMARY:Tėvo diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20190624@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190624
|
||||
DTEND;VALUE=DATE:20190625
|
||||
SUMMARY:Rasos (Joninės)
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20190706@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190706
|
||||
DTEND;VALUE=DATE:20190707
|
||||
SUMMARY:Valstybės (Lietuvos karaliaus Mindaugo karūnavimo) diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20190815@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190815
|
||||
DTEND;VALUE=DATE:20190816
|
||||
SUMMARY:Žolinė (Švč. Mergelės Marijos ėmimo į dangų diena)
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20191101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191101
|
||||
DTEND;VALUE=DATE:20191102
|
||||
SUMMARY:Visų šventųjų diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20191224@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191224
|
||||
DTEND;VALUE=DATE:20191225
|
||||
SUMMARY:Šv. Kalėdos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20191225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191225
|
||||
DTEND;VALUE=DATE:20191226
|
||||
SUMMARY:Šv. Kalėdos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20191226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191226
|
||||
DTEND;VALUE=DATE:20191227
|
||||
SUMMARY:Šv. Kalėdos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20200101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200101
|
||||
DTEND;VALUE=DATE:20200102
|
||||
SUMMARY:Naujieji metai
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20200216@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200216
|
||||
DTEND;VALUE=DATE:20200217
|
||||
SUMMARY:Lietuvos valstybės atkūrimo diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20200311@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200311
|
||||
DTEND;VALUE=DATE:20200312
|
||||
SUMMARY:Lietuvos nepriklausomybės atkūrimo diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20200412@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200412
|
||||
DTEND;VALUE=DATE:20200413
|
||||
SUMMARY:Velykos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20200413@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200413
|
||||
DTEND;VALUE=DATE:20200414
|
||||
SUMMARY:Velykos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20200501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200501
|
||||
DTEND;VALUE=DATE:20200502
|
||||
SUMMARY:Tarptautinė darbo diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20200503@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200503
|
||||
DTEND;VALUE=DATE:20200504
|
||||
SUMMARY:Motinos diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20200607@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200607
|
||||
DTEND;VALUE=DATE:20200608
|
||||
SUMMARY:Tėvo diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20200624@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200624
|
||||
DTEND;VALUE=DATE:20200625
|
||||
SUMMARY:Rasos (Joninės)
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20200706@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200706
|
||||
DTEND;VALUE=DATE:20200707
|
||||
SUMMARY:Valstybės (Lietuvos karaliaus Mindaugo karūnavimo) diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20200815@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200815
|
||||
DTEND;VALUE=DATE:20200816
|
||||
SUMMARY:Žolinė (Švč. Mergelės Marijos ėmimo į dangų diena)
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20201101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201101
|
||||
DTEND;VALUE=DATE:20201102
|
||||
SUMMARY:Visų šventųjų diena
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20201224@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201224
|
||||
DTEND;VALUE=DATE:20201225
|
||||
SUMMARY:Šv. Kalėdos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20201225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201225
|
||||
DTEND;VALUE=DATE:20201226
|
||||
SUMMARY:Šv. Kalėdos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ltu-20201226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201226
|
||||
DTEND;VALUE=DATE:20201227
|
||||
SUMMARY:Šv. Kalėdos
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
212
app/src/main/assets/luxembourg.ics
Normal file
212
app/src/main/assets/luxembourg.ics
Normal file
|
@ -0,0 +1,212 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20180101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
SUMMARY:Neijoerschdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20180402@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180402
|
||||
DTEND;VALUE=DATE:20180403
|
||||
SUMMARY:Ouschterméindeg
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20180501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180501
|
||||
DTEND;VALUE=DATE:20180502
|
||||
SUMMARY:Dag vun der Aarbecht
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20180510@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180510
|
||||
DTEND;VALUE=DATE:20180511
|
||||
SUMMARY:Christi Himmelfaart
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20180521@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180521
|
||||
DTEND;VALUE=DATE:20180522
|
||||
SUMMARY:Péngschtméindeg
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20180623@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180623
|
||||
DTEND;VALUE=DATE:20180624
|
||||
SUMMARY:Nationalfeierdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20180815@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180815
|
||||
DTEND;VALUE=DATE:20180816
|
||||
SUMMARY:Mariä Himmelfaart
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20181101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181101
|
||||
DTEND;VALUE=DATE:20181102
|
||||
SUMMARY:Allerhellgen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20181225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181225
|
||||
DTEND;VALUE=DATE:20181226
|
||||
SUMMARY:Chrëschtdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20181226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181226
|
||||
DTEND;VALUE=DATE:20181227
|
||||
SUMMARY:Stiefesdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20190101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190101
|
||||
DTEND;VALUE=DATE:20190102
|
||||
SUMMARY:Neijoerschdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20190422@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190422
|
||||
DTEND;VALUE=DATE:20190423
|
||||
SUMMARY:Ouschterméindeg
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20190501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190501
|
||||
DTEND;VALUE=DATE:20190502
|
||||
SUMMARY:Dag vun der Aarbecht
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20190530@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190530
|
||||
DTEND;VALUE=DATE:20190531
|
||||
SUMMARY:Christi Himmelfaart
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20190610@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190610
|
||||
DTEND;VALUE=DATE:20190611
|
||||
SUMMARY:Péngschtméindeg
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20190623@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190623
|
||||
DTEND;VALUE=DATE:20190624
|
||||
SUMMARY:Nationalfeierdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20190815@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190815
|
||||
DTEND;VALUE=DATE:20190816
|
||||
SUMMARY:Mariä Himmelfaart
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20191101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191101
|
||||
DTEND;VALUE=DATE:20191102
|
||||
SUMMARY:Allerhellgen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20191225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191225
|
||||
DTEND;VALUE=DATE:20191226
|
||||
SUMMARY:Chrëschtdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20191226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191226
|
||||
DTEND;VALUE=DATE:20191227
|
||||
SUMMARY:Stiefesdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20200101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200101
|
||||
DTEND;VALUE=DATE:20200102
|
||||
SUMMARY:Neijoerschdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20200413@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200413
|
||||
DTEND;VALUE=DATE:20200414
|
||||
SUMMARY:Ouschterméindeg
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20200501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200501
|
||||
DTEND;VALUE=DATE:20200502
|
||||
SUMMARY:Dag vun der Aarbecht
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20200521@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200521
|
||||
DTEND;VALUE=DATE:20200522
|
||||
SUMMARY:Christi Himmelfaart
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20200601@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200601
|
||||
DTEND;VALUE=DATE:20200602
|
||||
SUMMARY:Péngschtméindeg
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20200623@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200623
|
||||
DTEND;VALUE=DATE:20200624
|
||||
SUMMARY:Nationalfeierdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20200815@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200815
|
||||
DTEND;VALUE=DATE:20200816
|
||||
SUMMARY:Mariä Himmelfaart
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20201101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201101
|
||||
DTEND;VALUE=DATE:20201102
|
||||
SUMMARY:Allerhellgen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20201225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201225
|
||||
DTEND;VALUE=DATE:20201226
|
||||
SUMMARY:Chrëschtdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-lux-20201226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201226
|
||||
DTEND;VALUE=DATE:20201227
|
||||
SUMMARY:Stiefesdag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
239
app/src/main/assets/macedonia.ics
Normal file
239
app/src/main/assets/macedonia.ics
Normal file
|
@ -0,0 +1,239 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20180101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
SUMMARY:Нова Година\, Nova Godina
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20180108@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180108
|
||||
DTEND;VALUE=DATE:20180109
|
||||
SUMMARY:Прв ден Божик\, Prv den Božik
|
||||
DESCRIPTION:Holiday in lieu of 7 Jan 2018
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20180409@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180409
|
||||
DTEND;VALUE=DATE:20180410
|
||||
SUMMARY:Втор ден Велигден\, Vtor den Veligden
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20180501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180501
|
||||
DTEND;VALUE=DATE:20180502
|
||||
SUMMARY:Ден на трудот\, Den na trudot
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20180524@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180524
|
||||
DTEND;VALUE=DATE:20180525
|
||||
SUMMARY:Св. Кирил и Методиј\, Ден на сèсловенските просветители; Sv. Kiril i Metodij\, Den na sèslovenskite prosvetiteli
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20180615@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180615
|
||||
DTEND;VALUE=DATE:20180616
|
||||
SUMMARY:Рамазан Бајрам\, Ramazan Bajram
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20180802@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180802
|
||||
DTEND;VALUE=DATE:20180803
|
||||
SUMMARY:Ден на Републиката\, Den na Republikata
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20180908@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180908
|
||||
DTEND;VALUE=DATE:20180909
|
||||
SUMMARY:Ден на независноста\, Den na nezavisnosta
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20181011@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181011
|
||||
DTEND;VALUE=DATE:20181012
|
||||
SUMMARY:Ден на востанието\, Den na vostanieto
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20181023@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181023
|
||||
DTEND;VALUE=DATE:20181024
|
||||
SUMMARY:Ден на македонската револуционерна борба\, Den na makedonskata revolucionarna borba
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20181208@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181208
|
||||
DTEND;VALUE=DATE:20181209
|
||||
SUMMARY:Св. Климент Охридски\, Sv. Kliment Ohridski
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20190101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190101
|
||||
DTEND;VALUE=DATE:20190102
|
||||
SUMMARY:Нова Година\, Nova Godina
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20190107@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190107
|
||||
DTEND;VALUE=DATE:20190108
|
||||
SUMMARY:Прв ден Божик\, Prv den Božik
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20190429@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190429
|
||||
DTEND;VALUE=DATE:20190430
|
||||
SUMMARY:Втор ден Велигден\, Vtor den Veligden
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20190501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190501
|
||||
DTEND;VALUE=DATE:20190502
|
||||
SUMMARY:Ден на трудот\, Den na trudot
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20190524@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190524
|
||||
DTEND;VALUE=DATE:20190525
|
||||
SUMMARY:Св. Кирил и Методиј\, Ден на сèсловенските просветители; Sv. Kiril i Metodij\, Den na sèslovenskite prosvetiteli
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20190604@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190604
|
||||
DTEND;VALUE=DATE:20190605
|
||||
SUMMARY:Рамазан Бајрам\, Ramazan Bajram
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20190802@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190802
|
||||
DTEND;VALUE=DATE:20190803
|
||||
SUMMARY:Ден на Републиката\, Den na Republikata
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20190909@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190909
|
||||
DTEND;VALUE=DATE:20190910
|
||||
SUMMARY:Ден на независноста\, Den na nezavisnosta
|
||||
DESCRIPTION:Holiday in lieu of 8 Sep 2019
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20191011@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191011
|
||||
DTEND;VALUE=DATE:20191012
|
||||
SUMMARY:Ден на востанието\, Den na vostanieto
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20191023@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191023
|
||||
DTEND;VALUE=DATE:20191024
|
||||
SUMMARY:Ден на македонската револуционерна борба\, Den na makedonskata revolucionarna borba
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20191209@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191209
|
||||
DTEND;VALUE=DATE:20191210
|
||||
SUMMARY:Св. Климент Охридски\, Sv. Kliment Ohridski
|
||||
DESCRIPTION:Holiday in lieu of 8 Dec 2019
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20200101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200101
|
||||
DTEND;VALUE=DATE:20200102
|
||||
SUMMARY:Нова Година\, Nova Godina
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20200107@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200107
|
||||
DTEND;VALUE=DATE:20200108
|
||||
SUMMARY:Прв ден Божик\, Prv den Božik
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20200420@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200420
|
||||
DTEND;VALUE=DATE:20200421
|
||||
SUMMARY:Втор ден Велигден\, Vtor den Veligden
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20200501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200501
|
||||
DTEND;VALUE=DATE:20200502
|
||||
SUMMARY:Ден на трудот\, Den na trudot
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20200524@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200524
|
||||
DTEND;VALUE=DATE:20200525
|
||||
SUMMARY:Рамазан Бајрам\, Ramazan Bajram
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20200525@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200525
|
||||
DTEND;VALUE=DATE:20200526
|
||||
SUMMARY:Св. Кирил и Методиј\, Ден на сèсловенските просветители; Sv. Kiril i Metodij\, Den na sèslovenskite prosvetiteli
|
||||
DESCRIPTION:Holiday in lieu of 24 May 2020
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20200803@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200803
|
||||
DTEND;VALUE=DATE:20200804
|
||||
SUMMARY:Ден на Републиката\, Den na Republikata
|
||||
DESCRIPTION:Holiday in lieu of 2 Aug 2020
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20200908@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200908
|
||||
DTEND;VALUE=DATE:20200909
|
||||
SUMMARY:Ден на независноста\, Den na nezavisnosta
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20201012@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201012
|
||||
DTEND;VALUE=DATE:20201013
|
||||
SUMMARY:Ден на востанието\, Den na vostanieto
|
||||
DESCRIPTION:Holiday in lieu of 11 Oct 2020
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20201023@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201023
|
||||
DTEND;VALUE=DATE:20201024
|
||||
SUMMARY:Ден на македонската револуционерна борба\, Den na makedonskata revolucionarna borba
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mkd-20201208@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201208
|
||||
DTEND;VALUE=DATE:20201209
|
||||
SUMMARY:Св. Климент Охридски\, Sv. Kliment Ohridski
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
429
app/src/main/assets/malaysia.ics
Normal file
429
app/src/main/assets/malaysia.ics
Normal file
|
@ -0,0 +1,429 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190713
|
||||
DTEND;VALUE=DATE:20190714
|
||||
UID:20190713_60o30pb3cgo30e1g60o30dr56c@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Penang Governor's Birthday (Penang)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
UID:20180101_60o30db16oo30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:New Year's Day (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180531
|
||||
DTEND;VALUE=DATE:20180601
|
||||
UID:20180531_60o30p9k6oo30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Harvest Festival Day 2 (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190605
|
||||
DTEND;VALUE=DATE:20190606
|
||||
UID:20190605_60o30db260o30c1g60o30db160@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Hari Raya Puasa
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190419
|
||||
DTEND;VALUE=DATE:20190420
|
||||
UID:20190419_60o30db26so30c1g60o30dr56c@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Good Friday (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180707
|
||||
DTEND;VALUE=DATE:20180708
|
||||
UID:20180707_60o30pb3cco30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:George Town World Heritage City Day (Penang)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20191027
|
||||
DTEND;VALUE=DATE:20191028
|
||||
UID:20191027_60o30db268o30c1g60o30dr56c@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Diwali/Deepavali (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190506
|
||||
DTEND;VALUE=DATE:20190507
|
||||
UID:20190506_60o30ob5c4o30c1g60o30db160@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Ramadan begins (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180530
|
||||
DTEND;VALUE=DATE:20180531
|
||||
UID:20180530_60o30p9k6ko30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Harvest Festival (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181015
|
||||
DTEND;VALUE=DATE:20181016
|
||||
UID:20181015_60o32e1icgo30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Almarhum Sultan Iskandar Hol Day (Johor)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190603
|
||||
DTEND;VALUE=DATE:20190604
|
||||
UID:20190603_60o32e1i64o30e1g60o30dr56c@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Gawai Dayak Holiday observed (Sarawak)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181211
|
||||
DTEND;VALUE=DATE:20181212
|
||||
UID:20181211_60o32e1j68o30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Birthday of the Sultan of Selangor (Selangor)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181024
|
||||
DTEND;VALUE=DATE:20181025
|
||||
UID:20181024_60o32e1icko30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Birthday of the Sultan of Pahang (Pahang)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181111
|
||||
DTEND;VALUE=DATE:20181112
|
||||
UID:20181111_60o32e1j60o30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Birthday of the Sultan of Kelantan (Kelantan)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180323
|
||||
DTEND;VALUE=DATE:20180324
|
||||
UID:20180323_60o32e1i6go30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Birthday of the Sultan of Johor (Johor)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181013
|
||||
DTEND;VALUE=DATE:20181014
|
||||
UID:20181013_60o32e1icco30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Birthday of the Governor of Sarawak (Sarawak)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20191007
|
||||
DTEND;VALUE=DATE:20191008
|
||||
UID:20191007_60o32e1ic4o30e1g60o30dr56c@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Birthday of the Governor of Sabah observed (Sabah)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180507
|
||||
DTEND;VALUE=DATE:20180508
|
||||
UID:20180507_60o32e1i6oo30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Pahang State Holiday (Pahang)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190522
|
||||
DTEND;VALUE=DATE:20190523
|
||||
UID:20190522_60o30ob5c8o30c1g60o30db160@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Nuzul Al-Quran (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190403
|
||||
DTEND;VALUE=DATE:20190404
|
||||
UID:20190403_60o30ob574o30c1g60o30db160@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Isra and Mi'raj (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180415
|
||||
DTEND;VALUE=DATE:20180416
|
||||
UID:20180415_60o32e1i6so30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Declaration of Malacca as Historical City (Malacca)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180114
|
||||
DTEND;VALUE=DATE:20180115
|
||||
UID:20180114_60o32e1i6co30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Birthday of Yang di-Pertuan Besar (Negeri Sembilan)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180426
|
||||
DTEND;VALUE=DATE:20180427
|
||||
UID:20180426_60o32e1i70o30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Birthday of the Sultan of Terengganu (Terengganu)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180517
|
||||
DTEND;VALUE=DATE:20180518
|
||||
UID:20180517_60o32e1i68o30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Birthday of the Raja of Perlis (Perlis)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181012
|
||||
DTEND;VALUE=DATE:20181013
|
||||
UID:20181012_60o32e1ic8o30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Birthday of the Governor of Malacca (Malacca)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180304
|
||||
DTEND;VALUE=DATE:20180305
|
||||
UID:20180304_60o32e1i6ko30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Anniversary of the coronation of the Sultan of Terengganu (Terengga
|
||||
nu)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181120
|
||||
DTEND;VALUE=DATE:20181121
|
||||
UID:20181120_60o30db1c8o30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:The Prophet Muhammad's Birthday
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180722
|
||||
DTEND;VALUE=DATE:20180723
|
||||
UID:20180722_60o32e1i74o30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Sarawak Independence Day (Sarawak)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180917
|
||||
DTEND;VALUE=DATE:20180918
|
||||
UID:20180917_60o30db274o34c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Malaysia Day (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180916
|
||||
DTEND;VALUE=DATE:20180917
|
||||
UID:20180916_60o30db274o32c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Malaysia Day (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190813
|
||||
DTEND;VALUE=DATE:20190814
|
||||
UID:20190813_60o32e1hcko30c1g60o30db160@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Hari Raya Haji (Day 2) (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180601
|
||||
DTEND;VALUE=DATE:20180602
|
||||
UID:20180601_60o32e1i60o30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Gawai Dayak (Sarawak)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180602
|
||||
DTEND;VALUE=DATE:20180603
|
||||
UID:20180602_60o32e1i64o30c1g60o30dr568@google.com
|
||||
CREATED:20180731T230440Z
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Gawai Dayak Holiday (Sarawak)
|
||||
TRANSP:TRANSPARENT
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190603
|
||||
DTEND;VALUE=DATE:20190604
|
||||
UID:20190603_60o32e1i64o30e1g60o30dr56c@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Gawai Dayak Holiday observed (Sarawak)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181106
|
||||
DTEND;VALUE=DATE:20181107
|
||||
UID:20181106_60o30db268o30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Diwali/Deepavali (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181112
|
||||
DTEND;VALUE=DATE:20181113
|
||||
UID:20181112_60o32e1j64o30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Birthday of the Sultan of Kelantan (Day 2) (Kelantan)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180909
|
||||
DTEND;VALUE=DATE:20180910
|
||||
UID:20180909_60o30db1cko32c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:The Yang di-Pertuan Agong's Birthday (regional holiday)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190427
|
||||
DTEND;VALUE=DATE:20190428
|
||||
UID:20190427_60o32e1i70o30c1g60o30dr56c@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Birthday of the Sultan of Terengganu (Terengganu)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181102
|
||||
DTEND;VALUE=DATE:20181103
|
||||
UID:20181102_60o32e1icoo30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Birthday of the Sultan of Perak (Perak)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20191014
|
||||
DTEND;VALUE=DATE:20191015
|
||||
UID:20191014_60o32e1icco30e1g60o30dr56c@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Birthday of the Governor of Sarawak observed (Sarawak)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181006
|
||||
DTEND;VALUE=DATE:20181007
|
||||
UID:20181006_60o32e1ic4o30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Birthday of the Governor of Sabah (Sabah)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180214
|
||||
DTEND;VALUE=DATE:20180215
|
||||
UID:20180214_60o32dpo68o30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Valentine's Day
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190901
|
||||
DTEND;VALUE=DATE:20190902
|
||||
UID:20190901_60o30or46oo30c1g60o30db164@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Muharram/New Year
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190206
|
||||
DTEND;VALUE=DATE:20190207
|
||||
UID:20190206_60o30db170o30c1g60o32chmcc@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Second day of Chinese Lunar New Year
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180831
|
||||
DTEND;VALUE=DATE:20180901
|
||||
UID:20180831_60o30db1coo30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Malaysia's National Day
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180501
|
||||
DTEND;VALUE=DATE:20180502
|
||||
UID:20180501_60o30db1cco30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Labour Day
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181224
|
||||
DTEND;VALUE=DATE:20181225
|
||||
UID:20181224_60o30db26oo30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Christmas Eve
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181225
|
||||
DTEND;VALUE=DATE:20181226
|
||||
UID:20181225_60o30db26ko30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Christmas Day
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190205
|
||||
DTEND;VALUE=DATE:20190206
|
||||
UID:20190205_60o30db16so30c1g60o32chmcc@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Chinese Lunar New Year's Day
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20191110
|
||||
DTEND;VALUE=DATE:20191111
|
||||
UID:20191110_60o30db1c8o30c1g60o30db164@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:The Prophet Muhammad's Birthday
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180201
|
||||
DTEND;VALUE=DATE:20180202
|
||||
UID:20180201_60o30db174o30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Federal Territory Day
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190812
|
||||
DTEND;VALUE=DATE:20190813
|
||||
UID:20190812_60o30db26co30c1g60o30db160@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Hari Raya Haji
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190606
|
||||
DTEND;VALUE=DATE:20190607
|
||||
UID:20190606_60o30db264o30c1g60o30db160@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Hari Raya Puasa Day 2
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181231
|
||||
DTEND;VALUE=DATE:20190101
|
||||
UID:20181231_60o30db16ko30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:New Year's Eve
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190421
|
||||
DTEND;VALUE=DATE:20190422
|
||||
UID:20190421_60o30db270o30c1g60o30dr56c@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Easter Sunday
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190519
|
||||
DTEND;VALUE=DATE:20190520
|
||||
UID:20190519_60o30db1cgo30c1g60o30dr568@google.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Wesak Day
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
156
app/src/main/assets/mexico.ics
Normal file
156
app/src/main/assets/mexico.ics
Normal file
|
@ -0,0 +1,156 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20180101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
SUMMARY:Año Nuevo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20180205@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180205
|
||||
DTEND;VALUE=DATE:20180206
|
||||
SUMMARY:Día de la Constitución Mexicana
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20180319@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180319
|
||||
DTEND;VALUE=DATE:20180320
|
||||
SUMMARY:Natalicio de Benito Juárez
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20180501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180501
|
||||
DTEND;VALUE=DATE:20180502
|
||||
SUMMARY:Día del Trabajo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20180916@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180916
|
||||
DTEND;VALUE=DATE:20180917
|
||||
SUMMARY:Día de la Independencia
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20181119@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181119
|
||||
DTEND;VALUE=DATE:20181120
|
||||
SUMMARY:Revolución Mexicana
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20181201@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181201
|
||||
DTEND;VALUE=DATE:20181202
|
||||
SUMMARY:Transmisión del Poder Ejecutivo Federal
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20181225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181225
|
||||
DTEND;VALUE=DATE:20181226
|
||||
SUMMARY:Día de Navidad
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20190101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190101
|
||||
DTEND;VALUE=DATE:20190102
|
||||
SUMMARY:Año Nuevo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20190204@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190204
|
||||
DTEND;VALUE=DATE:20190205
|
||||
SUMMARY:Día de la Constitución Mexicana
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20190318@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190318
|
||||
DTEND;VALUE=DATE:20190319
|
||||
SUMMARY:Natalicio de Benito Juárez
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20190501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190501
|
||||
DTEND;VALUE=DATE:20190502
|
||||
SUMMARY:Día del Trabajo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20190916@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190916
|
||||
DTEND;VALUE=DATE:20190917
|
||||
SUMMARY:Día de la Independencia
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20191118@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191118
|
||||
DTEND;VALUE=DATE:20191119
|
||||
SUMMARY:Revolución Mexicana
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20191225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191225
|
||||
DTEND;VALUE=DATE:20191226
|
||||
SUMMARY:Día de Navidad
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20200101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200101
|
||||
DTEND;VALUE=DATE:20200102
|
||||
SUMMARY:Año Nuevo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20200203@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200203
|
||||
DTEND;VALUE=DATE:20200204
|
||||
SUMMARY:Día de la Constitución Mexicana
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20200316@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200316
|
||||
DTEND;VALUE=DATE:20200317
|
||||
SUMMARY:Natalicio de Benito Juárez
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20200501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200501
|
||||
DTEND;VALUE=DATE:20200502
|
||||
SUMMARY:Día del Trabajo
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20200916@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200916
|
||||
DTEND;VALUE=DATE:20200917
|
||||
SUMMARY:Día de la Independencia
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20201116@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201116
|
||||
DTEND;VALUE=DATE:20201117
|
||||
SUMMARY:Revolución Mexicana
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-mex-20201225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201225
|
||||
DTEND;VALUE=DATE:20201226
|
||||
SUMMARY:Día de Navidad
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
File diff suppressed because it is too large
Load diff
70
app/src/main/assets/nigeria.ics
Normal file
70
app/src/main/assets/nigeria.ics
Normal file
|
@ -0,0 +1,70 @@
|
|||
BEGIN:VCALENDER
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:New Year's Day
|
||||
UID:nig-20200101
|
||||
DTSTART;VALUE=DATE:20200101
|
||||
DTEND;VALUE=DATE:20200102
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTEND;VALUE=DATE:20200414
|
||||
DTSTART;VALUE=DATE:20200413
|
||||
SUMMARY:Easter Monday
|
||||
UID:nig-20200413
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTEND;VALUE=DATE:20200411
|
||||
DTSTART;VALUE=DATE:20200410
|
||||
SUMMARY:Good Friday
|
||||
UID:nig-20200410
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Christmas Day
|
||||
UID:nig-20201225
|
||||
DTSTART;VALUE=DATE:20201225
|
||||
DTEND;VALUE=DATE:20201226
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Democracy Day
|
||||
UID:nig-20200612
|
||||
DTEND;VALUE=DATE:20200613
|
||||
DTSTART;VALUE=DATE:20200612
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Sallah
|
||||
UID:nig-20200525
|
||||
DTEND;VALUE=DATE:20200526
|
||||
DTSTART;VALUE=DATE:20200525
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY: Worker's Day
|
||||
UID:nig-20200501
|
||||
DTEND;VALUE=DATE:20200502
|
||||
DTSTART;VALUE=DATE:20200501
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Independence Day
|
||||
UID:nig-20201001
|
||||
DTEND;VALUE=DATE:20201002
|
||||
DTSTART;VALUE=DATE:20201001
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Boxing Day
|
||||
UID:nig-20201226
|
||||
DTSTART;VALUE=DATE:20201226
|
||||
DTEND;VALUE=DATE:20201227
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
END:VCALENDER
|
File diff suppressed because it is too large
Load diff
296
app/src/main/assets/romania.ics
Normal file
296
app/src/main/assets/romania.ics
Normal file
|
@ -0,0 +1,296 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20180101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
SUMMARY:Anul nou
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20180102@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180102
|
||||
DTEND;VALUE=DATE:20180103
|
||||
SUMMARY:Anul nou
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20180124@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180124
|
||||
DTEND;VALUE=DATE:20180125
|
||||
SUMMARY:Unirea Principatelor Române/Mica Unire
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20180408@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180408
|
||||
DTEND;VALUE=DATE:20180409
|
||||
SUMMARY:Paştele
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20180409@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180409
|
||||
DTEND;VALUE=DATE:20180410
|
||||
SUMMARY:Doua zi de Pasti
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20180501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180501
|
||||
DTEND;VALUE=DATE:20180502
|
||||
SUMMARY:Ziua muncii
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20180527@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180527
|
||||
DTEND;VALUE=DATE:20180528
|
||||
SUMMARY:Rusaliile
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20180528@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180528
|
||||
DTEND;VALUE=DATE:20180529
|
||||
SUMMARY:Doua zi de Rusaliile
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20180601@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180601
|
||||
DTEND;VALUE=DATE:20180602
|
||||
SUMMARY:Ziua Copilului
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20180815@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180815
|
||||
DTEND;VALUE=DATE:20180816
|
||||
SUMMARY:Adormirea Maicii Domnului/Sfânta Maria Mare
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20181130@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181130
|
||||
DTEND;VALUE=DATE:20181201
|
||||
SUMMARY:Sfântul Andrei
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20181201@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181201
|
||||
DTEND;VALUE=DATE:20181202
|
||||
SUMMARY:Ziua Națională/Marea Unire
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20181225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181225
|
||||
DTEND;VALUE=DATE:20181226
|
||||
SUMMARY:Crăciunul
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20181226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181226
|
||||
DTEND;VALUE=DATE:20181227
|
||||
SUMMARY:Crăciunul
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20190101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190101
|
||||
DTEND;VALUE=DATE:20190102
|
||||
SUMMARY:Anul nou
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20190102@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190102
|
||||
DTEND;VALUE=DATE:20190103
|
||||
SUMMARY:Anul nou
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20190124@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190124
|
||||
DTEND;VALUE=DATE:20190125
|
||||
SUMMARY:Unirea Principatelor Române/Mica Unire
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20190428@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190428
|
||||
DTEND;VALUE=DATE:20190429
|
||||
SUMMARY:Paştele
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20190429@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190429
|
||||
DTEND;VALUE=DATE:20190430
|
||||
SUMMARY:Doua zi de Pasti
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20190501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190501
|
||||
DTEND;VALUE=DATE:20190502
|
||||
SUMMARY:Ziua muncii
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20190601@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190601
|
||||
DTEND;VALUE=DATE:20190602
|
||||
SUMMARY:Ziua Copilului
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20190616@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190616
|
||||
DTEND;VALUE=DATE:20190617
|
||||
SUMMARY:Rusaliile
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20190617@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190617
|
||||
DTEND;VALUE=DATE:20190618
|
||||
SUMMARY:Doua zi de Rusaliile
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20190815@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190815
|
||||
DTEND;VALUE=DATE:20190816
|
||||
SUMMARY:Adormirea Maicii Domnului/Sfânta Maria Mare
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20191130@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191130
|
||||
DTEND;VALUE=DATE:20191201
|
||||
SUMMARY:Sfântul Andrei
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20191201@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191201
|
||||
DTEND;VALUE=DATE:20191202
|
||||
SUMMARY:Ziua Națională/Marea Unire
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20191225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191225
|
||||
DTEND;VALUE=DATE:20191226
|
||||
SUMMARY:Crăciunul
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20191226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191226
|
||||
DTEND;VALUE=DATE:20191227
|
||||
SUMMARY:Crăciunul
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20200101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200101
|
||||
DTEND;VALUE=DATE:20200102
|
||||
SUMMARY:Anul nou
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20200102@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200102
|
||||
DTEND;VALUE=DATE:20200103
|
||||
SUMMARY:Anul nou
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20200124@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200124
|
||||
DTEND;VALUE=DATE:20200125
|
||||
SUMMARY:Unirea Principatelor Române/Mica Unire
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20200419@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200419
|
||||
DTEND;VALUE=DATE:20200420
|
||||
SUMMARY:Paştele
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20200420@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200420
|
||||
DTEND;VALUE=DATE:20200421
|
||||
SUMMARY:Doua zi de Pasti
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20200501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200501
|
||||
DTEND;VALUE=DATE:20200502
|
||||
SUMMARY:Ziua muncii
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20200601@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200601
|
||||
DTEND;VALUE=DATE:20200602
|
||||
SUMMARY:Ziua Copilului
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20200607@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200607
|
||||
DTEND;VALUE=DATE:20200608
|
||||
SUMMARY:Rusaliile
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20200608@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200608
|
||||
DTEND;VALUE=DATE:20200609
|
||||
SUMMARY:Doua zi de Rusaliile
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20200815@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200815
|
||||
DTEND;VALUE=DATE:20200816
|
||||
SUMMARY:Adormirea Maicii Domnului/Sfânta Maria Mare
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20201130@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201130
|
||||
DTEND;VALUE=DATE:20201201
|
||||
SUMMARY:Sfântul Andrei
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20201201@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201201
|
||||
DTEND;VALUE=DATE:20201202
|
||||
SUMMARY:Ziua Națională/Marea Unire
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20201225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201225
|
||||
DTEND;VALUE=DATE:20201226
|
||||
SUMMARY:Crăciunul
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-rou-20201226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201226
|
||||
DTEND;VALUE=DATE:20201227
|
||||
SUMMARY:Crăciunul
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
247
app/src/main/assets/serbia.ics
Normal file
247
app/src/main/assets/serbia.ics
Normal file
|
@ -0,0 +1,247 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20180101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
SUMMARY:Nova Godina
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20180102@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180102
|
||||
DTEND;VALUE=DATE:20180103
|
||||
SUMMARY:Nova Godina
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20180107@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180107
|
||||
DTEND;VALUE=DATE:20180108
|
||||
SUMMARY:Božić
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20180215@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180215
|
||||
DTEND;VALUE=DATE:20180216
|
||||
SUMMARY:Dan državnosti Srbije
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20180216@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180216
|
||||
DTEND;VALUE=DATE:20180217
|
||||
SUMMARY:Dan državnosti Srbije
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20180406@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180406
|
||||
DTEND;VALUE=DATE:20180407
|
||||
SUMMARY:Veliki petak
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20180408@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180408
|
||||
DTEND;VALUE=DATE:20180409
|
||||
SUMMARY:Vaskrs
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20180409@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180409
|
||||
DTEND;VALUE=DATE:20180410
|
||||
SUMMARY:Vaskrsni ponedeljak
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20180501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180501
|
||||
DTEND;VALUE=DATE:20180502
|
||||
SUMMARY:Praznik rada
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20180502@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180502
|
||||
DTEND;VALUE=DATE:20180503
|
||||
SUMMARY:Praznik rada
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20181111@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181111
|
||||
DTEND;VALUE=DATE:20181112
|
||||
SUMMARY:Dan primirja
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20181112@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181112
|
||||
DTEND;VALUE=DATE:20181113
|
||||
SUMMARY:Dan primirja
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20190101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190101
|
||||
DTEND;VALUE=DATE:20190102
|
||||
SUMMARY:Nova Godina
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20190102@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190102
|
||||
DTEND;VALUE=DATE:20190103
|
||||
SUMMARY:Nova Godina
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20190107@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190107
|
||||
DTEND;VALUE=DATE:20190108
|
||||
SUMMARY:Božić
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20190215@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190215
|
||||
DTEND;VALUE=DATE:20190216
|
||||
SUMMARY:Dan državnosti Srbije
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20190216@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190216
|
||||
DTEND;VALUE=DATE:20190217
|
||||
SUMMARY:Dan državnosti Srbije
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20190426@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190426
|
||||
DTEND;VALUE=DATE:20190427
|
||||
SUMMARY:Veliki petak
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20190428@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190428
|
||||
DTEND;VALUE=DATE:20190429
|
||||
SUMMARY:Vaskrs
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20190429@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190429
|
||||
DTEND;VALUE=DATE:20190430
|
||||
SUMMARY:Vaskrsni ponedeljak
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20190501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190501
|
||||
DTEND;VALUE=DATE:20190502
|
||||
SUMMARY:Praznik rada
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20190502@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190502
|
||||
DTEND;VALUE=DATE:20190503
|
||||
SUMMARY:Praznik rada
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20191111@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191111
|
||||
DTEND;VALUE=DATE:20191112
|
||||
SUMMARY:Dan primirja
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20200101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200101
|
||||
DTEND;VALUE=DATE:20200102
|
||||
SUMMARY:Nova Godina
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20200102@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200102
|
||||
DTEND;VALUE=DATE:20200103
|
||||
SUMMARY:Nova Godina
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20200107@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200107
|
||||
DTEND;VALUE=DATE:20200108
|
||||
SUMMARY:Božić
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20200215@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200215
|
||||
DTEND;VALUE=DATE:20200216
|
||||
SUMMARY:Dan državnosti Srbije
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20200216@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200216
|
||||
DTEND;VALUE=DATE:20200217
|
||||
SUMMARY:Dan državnosti Srbije
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20200217@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200217
|
||||
DTEND;VALUE=DATE:20200218
|
||||
SUMMARY:Dan državnosti Srbije
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20200417@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200417
|
||||
DTEND;VALUE=DATE:20200418
|
||||
SUMMARY:Veliki petak
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20200419@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200419
|
||||
DTEND;VALUE=DATE:20200420
|
||||
SUMMARY:Vaskrs
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20200420@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200420
|
||||
DTEND;VALUE=DATE:20200421
|
||||
SUMMARY:Vaskrsni ponedeljak
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20200501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200501
|
||||
DTEND;VALUE=DATE:20200502
|
||||
SUMMARY:Praznik rada
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20200502@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200502
|
||||
DTEND;VALUE=DATE:20200503
|
||||
SUMMARY:Praznik rada
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-srb-20201111@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201111
|
||||
DTEND;VALUE=DATE:20201112
|
||||
SUMMARY:Dan primirja
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
125
app/src/main/assets/singapore.ics
Executable file
125
app/src/main/assets/singapore.ics
Executable file
|
@ -0,0 +1,125 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181225
|
||||
DTEND;VALUE=DATE:20181226
|
||||
UID:20181225-christmas-day@www.mom.gov.sg
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Christmas Day
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181106
|
||||
DTEND;VALUE=DATE:20181107
|
||||
UID:20181106-deepavali@www.mom.gov.sg
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Deepavali
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20191027
|
||||
DTEND;VALUE=DATE:20191028
|
||||
UID:20191027-deepavali@www.mom.gov.sg
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Deepavali
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180822
|
||||
DTEND;VALUE=DATE:20180823
|
||||
UID:20180822-hari-raya-haji@www.mom.gov.sg
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Hari Raya Haji
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190811
|
||||
DTEND;VALUE=DATE:20190812
|
||||
UID:20190811-hari-raya-haji@www.mom.gov.sg
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Hari Raya Haji
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180809
|
||||
DTEND;VALUE=DATE:20180810
|
||||
UID:20180809-national-day@www.mom.gov.sg
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:National Day
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180615
|
||||
DTEND;VALUE=DATE:20180616
|
||||
UID:20180615-hari-raya-puasa@www.mom.gov.sg
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Hari Raya Puasa
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190605
|
||||
DTEND;VALUE=DATE:20190606
|
||||
UID:20190605-hari-raya-puasa@www.mom.gov.sg
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Hari Raya Puasa
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180529
|
||||
DTEND;VALUE=DATE:20180530
|
||||
UID:20180529-vesak-day@www.mom.gov.sg
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Vesak Day
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190519
|
||||
DTEND;VALUE=DATE:20190520
|
||||
UID:20190519-vesak-day@www.mom.gov.sg
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Vesak Day
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180501
|
||||
DTEND;VALUE=DATE:20180502
|
||||
UID:20180501-labour-day@www.mom.gov.sg
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Labour Day
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180330
|
||||
DTEND;VALUE=DATE:20180331
|
||||
UID:20180330-good-friday@www.mom.gov.sg
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Good Friday
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190419
|
||||
DTEND;VALUE=DATE:20190420
|
||||
UID:20190419-good-friday@www.mom.gov.sg
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Good Friday
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180217
|
||||
DTEND;VALUE=DATE:20180218
|
||||
UID:20180217-chinese-new-year@www.mom.gov.sg
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Chinese New Year
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180216
|
||||
DTEND;VALUE=DATE:20180217
|
||||
UID:20180216-chinese-new-year@www.mom.gov.sg
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Chinese New Year
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
UID:20180101-new-years-day@www.mom.gov.sg
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:New Year's Day
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190205
|
||||
DTEND;VALUE=DATE:20190206
|
||||
UID:20190205-chinese-new-year@www.mom.gov.sg
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Chinese New Year
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
275
app/src/main/assets/southafrica.ics
Normal file
275
app/src/main/assets/southafrica.ics
Normal file
|
@ -0,0 +1,275 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20180101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
SUMMARY:New Year's Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20180321@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180321
|
||||
DTEND;VALUE=DATE:20180322
|
||||
SUMMARY:Human Rights Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20180330@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180330
|
||||
DTEND;VALUE=DATE:20180331
|
||||
SUMMARY:Good Friday
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20180402@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180402
|
||||
DTEND;VALUE=DATE:20180403
|
||||
SUMMARY:Family Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20180427@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180427
|
||||
DTEND;VALUE=DATE:20180428
|
||||
SUMMARY:Freedom Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20180501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180501
|
||||
DTEND;VALUE=DATE:20180502
|
||||
SUMMARY:Workers' Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20180616@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180616
|
||||
DTEND;VALUE=DATE:20180617
|
||||
SUMMARY:Youth Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20180809@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180809
|
||||
DTEND;VALUE=DATE:20180810
|
||||
SUMMARY:National Women's Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20180924@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180924
|
||||
DTEND;VALUE=DATE:20180925
|
||||
SUMMARY:Heritage Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20181216@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181216
|
||||
DTEND;VALUE=DATE:20181217
|
||||
SUMMARY:Day of Reconciliation
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20181217@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181217
|
||||
DTEND;VALUE=DATE:20181218
|
||||
SUMMARY:Day of Reconciliation
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20181225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181225
|
||||
DTEND;VALUE=DATE:20181226
|
||||
SUMMARY:Christmas Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20181226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181226
|
||||
DTEND;VALUE=DATE:20181227
|
||||
SUMMARY:Day of Goodwill
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20190101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190101
|
||||
DTEND;VALUE=DATE:20190102
|
||||
SUMMARY:New Year's Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20190321@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190321
|
||||
DTEND;VALUE=DATE:20190322
|
||||
SUMMARY:Human Rights Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20190419@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190419
|
||||
DTEND;VALUE=DATE:20190420
|
||||
SUMMARY:Good Friday
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20190422@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190422
|
||||
DTEND;VALUE=DATE:20190423
|
||||
SUMMARY:Family Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20190427@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190427
|
||||
DTEND;VALUE=DATE:20190428
|
||||
SUMMARY:Freedom Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20190501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190501
|
||||
DTEND;VALUE=DATE:20190502
|
||||
SUMMARY:Workers' Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20190616@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190616
|
||||
DTEND;VALUE=DATE:20190617
|
||||
SUMMARY:Youth Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20190617@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190617
|
||||
DTEND;VALUE=DATE:20190618
|
||||
SUMMARY:Youth Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20190809@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190809
|
||||
DTEND;VALUE=DATE:20190810
|
||||
SUMMARY:National Women's Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20190924@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190924
|
||||
DTEND;VALUE=DATE:20190925
|
||||
SUMMARY:Heritage Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20191216@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191216
|
||||
DTEND;VALUE=DATE:20191217
|
||||
SUMMARY:Day of Reconciliation
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20191225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191225
|
||||
DTEND;VALUE=DATE:20191226
|
||||
SUMMARY:Christmas Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20191226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191226
|
||||
DTEND;VALUE=DATE:20191227
|
||||
SUMMARY:Day of Goodwill
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20200101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200101
|
||||
DTEND;VALUE=DATE:20200102
|
||||
SUMMARY:New Year's Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20200321@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200321
|
||||
DTEND;VALUE=DATE:20200322
|
||||
SUMMARY:Human Rights Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20200410@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200410
|
||||
DTEND;VALUE=DATE:20200411
|
||||
SUMMARY:Good Friday
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20200413@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200413
|
||||
DTEND;VALUE=DATE:20200414
|
||||
SUMMARY:Family Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20200427@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200427
|
||||
DTEND;VALUE=DATE:20200428
|
||||
SUMMARY:Freedom Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20200501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200501
|
||||
DTEND;VALUE=DATE:20200502
|
||||
SUMMARY:Workers' Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20200616@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200616
|
||||
DTEND;VALUE=DATE:20200617
|
||||
SUMMARY:Youth Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20200809@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200809
|
||||
DTEND;VALUE=DATE:20200810
|
||||
SUMMARY:National Women's Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20200810@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200810
|
||||
DTEND;VALUE=DATE:20200811
|
||||
SUMMARY:National Women's Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20200924@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200924
|
||||
DTEND;VALUE=DATE:20200925
|
||||
SUMMARY:Heritage Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20201216@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201216
|
||||
DTEND;VALUE=DATE:20201217
|
||||
SUMMARY:Day of Reconciliation
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20201225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201225
|
||||
DTEND;VALUE=DATE:20201226
|
||||
SUMMARY:Christmas Day
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-zaf-20201226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201226
|
||||
DTEND;VALUE=DATE:20201227
|
||||
SUMMARY:Day of Goodwill
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
|
@ -23,8 +23,8 @@ END:VEVENT
|
|||
BEGIN:VEVENT
|
||||
SUMMARY:설날 Lunar New Year's Day
|
||||
UID:3d064a26-70f2-431a-985a-ffd27be9e210
|
||||
DTSTART;VALUE=DATE:20190205
|
||||
DTEND;VALUE=DATE:20190206
|
||||
DTSTART;VALUE=DATE:20190204
|
||||
DTEND;VALUE=DATE:20190207
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
|
@ -44,8 +44,15 @@ END:VEVENT
|
|||
BEGIN:VEVENT
|
||||
SUMMARY:추석(한가위) Harvest Festival
|
||||
UID:14bd697c-a319-47fd-9abc-fdff74be58e5
|
||||
DTSTART;VALUE=DATE:20201001
|
||||
DTEND;VALUE=DATE:20201002
|
||||
DTSTART;VALUE=DATE:20200930
|
||||
DTEND;VALUE=DATE:20201003
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:추석(한가위) Harvest Festival
|
||||
UID:14bd697c-a319-47fd-9abc-fdffse58aa
|
||||
DTSTART;VALUE=DATE:20210920
|
||||
DTEND;VALUE=DATE:20210923
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
|
@ -65,14 +72,6 @@ STATUS:CONFIRMED
|
|||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:식목일 Arbor Day
|
||||
UID:5ae39a0f-5ef9-44d9-9dd5-e90049578e07
|
||||
DTSTART;VALUE=DATE:20000405
|
||||
DTEND;VALUE=DATE:20000406
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:어린이 날 Children's Day
|
||||
UID:5a0c39c0-da3b-407d-824b-890c6b82bd95
|
||||
DTSTART;VALUE=DATE:20000505
|
||||
|
@ -81,22 +80,6 @@ STATUS:CONFIRMED
|
|||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:어버이 날 Paren't Day
|
||||
UID:741d7127-995f-43e0-a014-04280dcbb661
|
||||
DTSTART;VALUE=DATE:20000510
|
||||
DTEND;VALUE=DATE:20000511
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:스승의 날 Teacher's Day
|
||||
UID:5309e45c-acca-4b4f-b7c4-fe7b3ddd545f
|
||||
DTSTART;VALUE=DATE:20000515
|
||||
DTEND;VALUE=DATE:20000516
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:현충일 Memorial Day
|
||||
UID:c67d164c-c91c-4b46-a0fa-bff756119cde
|
||||
DTSTART;VALUE=DATE:20000606
|
||||
|
@ -105,22 +88,6 @@ STATUS:CONFIRMED
|
|||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:6-25 사변일 6/25 War Memorial
|
||||
UID:c5907e9d-4314-423f-9441-d7309d39db45
|
||||
DTSTART;VALUE=DATE:20000625
|
||||
DTEND;VALUE=DATE:20000626
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:제헌절 Constitution Day
|
||||
UID:4f97c701-816b-4c23-a71e-13d2d2419c8f
|
||||
DTSTART;VALUE=DATE:20000717
|
||||
DTEND;VALUE=DATE:20000718
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:광복절 Liberation Day
|
||||
UID:1aba5d05-a8a7-4253-a6d2-66665bd2490d
|
||||
DTSTART;VALUE=DATE:20000815
|
||||
|
@ -129,14 +96,6 @@ STATUS:CONFIRMED
|
|||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:국군의 날 Armed Forces Day
|
||||
UID:99c12465-6366-4c9e-99c8-8635969cc7ee
|
||||
DTSTART;VALUE=DATE:20001001
|
||||
DTEND;VALUE=DATE:20001002
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:개천절 Foundation Day
|
||||
UID:220f5ee6-10a6-4227-87ca-197628adb976
|
||||
DTSTART;VALUE=DATE:20001003
|
||||
|
|
385
app/src/main/assets/sweden.ics
Executable file → Normal file
385
app/src/main/assets/sweden.ics
Executable file → Normal file
|
@ -1,380 +1,275 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Kristi himmelfärdsdag
|
||||
UID:uuid1211149223742
|
||||
DTSTART;VALUE=DATE:20170525
|
||||
DTEND;VALUE=DATE:20170526
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pingstafton
|
||||
UID:uuid1211149223743
|
||||
DTSTART;VALUE=DATE:20170603
|
||||
DTEND;VALUE=DATE:20170604
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pingstdagen
|
||||
UID:uuid1211149223744
|
||||
DTSTART;VALUE=DATE:20170604
|
||||
DTEND;VALUE=DATE:20170605
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Nationaldagen
|
||||
UID:uuid1211149223745
|
||||
DTSTART;VALUE=DATE:20170606
|
||||
DTEND;VALUE=DATE:20170607
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Midsommarafton
|
||||
UID:a076d1a7-69bb-4af5-9a60-89a3c533e6bf
|
||||
DTSTART;VALUE=DATE:20170623
|
||||
DTEND;VALUE=DATE:20170624
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Midsommardagen
|
||||
UID:uuid1211149223746
|
||||
DTSTART;VALUE=DATE:20170624
|
||||
DTEND;VALUE=DATE:20170625
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Övergång till vintertid
|
||||
UID:uuid1211149223747
|
||||
DTSTART;VALUE=DATE:20171029
|
||||
DTEND;VALUE=DATE:20171030
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Alla helgons dag
|
||||
UID:uuid1211149223748
|
||||
DTSTART;VALUE=DATE:20171104
|
||||
DTEND;VALUE=DATE:20171105
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Julafton
|
||||
UID:uuid1211149223749
|
||||
DTSTART;VALUE=DATE:20171224
|
||||
DTEND;VALUE=DATE:20171225
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Juldagen
|
||||
UID:uuid1211149223750
|
||||
DTSTART;VALUE=DATE:20171225
|
||||
DTEND;VALUE=DATE:20171226
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Annandag jul
|
||||
UID:uuid1211149223751
|
||||
DTSTART;VALUE=DATE:20171226
|
||||
DTEND;VALUE=DATE:20171227
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Nyårsafton
|
||||
UID:uuid1211149223752
|
||||
DTSTART;VALUE=DATE:20171231
|
||||
DTEND;VALUE=DATE:20180101
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Nyårsdagen
|
||||
UID:uuid1211149223753
|
||||
UID:enrico-swe-20180101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
SUMMARY:Nyårsdagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Trettondagsafton
|
||||
UID:uuid1211149223754
|
||||
DTSTART;VALUE=DATE:20180105
|
||||
DTEND;VALUE=DATE:20180106
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Trettondag jul
|
||||
UID:uuid1211149223755
|
||||
UID:enrico-swe-20180106@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180106
|
||||
DTEND;VALUE=DATE:20180107
|
||||
SUMMARY:Trettondagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Skärtorsdag
|
||||
UID:uuid1211149223757
|
||||
DTSTART;VALUE=DATE:20180329
|
||||
DTEND;VALUE=DATE:20180330
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Långfredag
|
||||
UID:uuid1211149223758
|
||||
UID:enrico-swe-20180330@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180330
|
||||
DTEND;VALUE=DATE:20180331
|
||||
SUMMARY:Långfredagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Påskdagen
|
||||
UID:uuid1211149223759
|
||||
UID:enrico-swe-20180401@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180401
|
||||
DTEND;VALUE=DATE:20180402
|
||||
SUMMARY:Påskdagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Annandag påsk
|
||||
UID:uuid1211149223760
|
||||
UID:enrico-swe-20180402@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180402
|
||||
DTEND;VALUE=DATE:20180403
|
||||
SUMMARY:Annandag påsk
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Valborgsmässoafton
|
||||
UID:uuid1211149223761
|
||||
DTSTART;VALUE=DATE:20180430
|
||||
DTEND;VALUE=DATE:20180501
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Första maj
|
||||
UID:uuid1211149223762
|
||||
UID:enrico-swe-20180501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180501
|
||||
DTEND;VALUE=DATE:20180502
|
||||
SUMMARY:Första maj
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Kristi himmelfärdsdag
|
||||
UID:uuid1211149223763
|
||||
UID:enrico-swe-20180510@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180510
|
||||
DTEND;VALUE=DATE:20180511
|
||||
SUMMARY:Kristi himmelfärds dag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pingstafton
|
||||
UID:uuid1211149223764
|
||||
DTSTART;VALUE=DATE:20180519
|
||||
DTEND;VALUE=DATE:20180520
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pingstdagen
|
||||
UID:uuid1211149223765
|
||||
UID:enrico-swe-20180520@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180520
|
||||
DTEND;VALUE=DATE:20180521
|
||||
SUMMARY:Pingstdagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Nationaldagen
|
||||
UID:uuid1211149223766
|
||||
UID:enrico-swe-20180606@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180606
|
||||
DTEND;VALUE=DATE:20180607
|
||||
SUMMARY:Sveriges nationaldag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Midsommarafton
|
||||
UID:ed74665e-e6b5-4dc8-8788-48eaab5640eb
|
||||
DTSTART;VALUE=DATE:20180622
|
||||
DTEND;VALUE=DATE:20180623
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Midsommardagen
|
||||
UID:uuid1211149223767
|
||||
UID:enrico-swe-20180623@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180623
|
||||
DTEND;VALUE=DATE:20180624
|
||||
SUMMARY:Midsommardagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Övergång till vintertid
|
||||
UID:uuid1211149223768
|
||||
DTSTART;VALUE=DATE:20181028
|
||||
DTEND;VALUE=DATE:20181029
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Alla helgons dag
|
||||
UID:uuid1211149223769
|
||||
UID:enrico-swe-20181103@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181103
|
||||
DTEND;VALUE=DATE:20181104
|
||||
SUMMARY:Alla helgons dag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Julafton
|
||||
UID:uuid1211149223770
|
||||
DTSTART;VALUE=DATE:20181224
|
||||
DTEND;VALUE=DATE:20181225
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Juldagen
|
||||
UID:uuid1211149223771
|
||||
UID:enrico-swe-20181225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181225
|
||||
DTEND;VALUE=DATE:20181226
|
||||
SUMMARY:Juldagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Annandag jul
|
||||
UID:uuid1211149223772
|
||||
UID:enrico-swe-20181226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181226
|
||||
DTEND;VALUE=DATE:20181227
|
||||
SUMMARY:Annandag jul
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Nyårsafton
|
||||
UID:uuid1211149223773
|
||||
DTSTART;VALUE=DATE:20181231
|
||||
DTEND;VALUE=DATE:20190101
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Nyårsdagen
|
||||
UID:uuid1211149223774
|
||||
UID:enrico-swe-20190101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190101
|
||||
DTEND;VALUE=DATE:20190102
|
||||
SUMMARY:Nyårsdagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Trettondagsafton
|
||||
UID:uuid1211149223775
|
||||
DTSTART;VALUE=DATE:20190105
|
||||
DTEND;VALUE=DATE:20190106
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Trettondag jul
|
||||
UID:uuid1211149223776
|
||||
UID:enrico-swe-20190106@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190106
|
||||
DTEND;VALUE=DATE:20190107
|
||||
SUMMARY:Trettondagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Skärtorsdag
|
||||
UID:uuid1211149223778
|
||||
DTSTART;VALUE=DATE:20190418
|
||||
DTEND;VALUE=DATE:20190419
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Långfredag
|
||||
UID:uuid1211149223779
|
||||
UID:enrico-swe-20190419@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190419
|
||||
DTEND;VALUE=DATE:20190420
|
||||
SUMMARY:Långfredagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Påskdagen
|
||||
UID:uuid1211149223780
|
||||
UID:enrico-swe-20190421@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190421
|
||||
DTEND;VALUE=DATE:20190422
|
||||
SUMMARY:Påskdagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Annandag påsk
|
||||
UID:uuid1211149223781
|
||||
UID:enrico-swe-20190422@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190422
|
||||
DTEND;VALUE=DATE:20190423
|
||||
SUMMARY:Annandag påsk
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Valborgsmässoafton
|
||||
UID:uuid1211149223782
|
||||
DTSTART;VALUE=DATE:20190430
|
||||
DTEND;VALUE=DATE:20190501
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Första maj
|
||||
UID:uuid1211149223783
|
||||
UID:enrico-swe-20190501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190501
|
||||
DTEND;VALUE=DATE:20190502
|
||||
SUMMARY:Första maj
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Kristi himmelfärdsdag
|
||||
UID:uuid1211149223784
|
||||
UID:enrico-swe-20190530@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190530
|
||||
DTEND;VALUE=DATE:20190531
|
||||
SUMMARY:Kristi himmelfärds dag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Nationaldagen
|
||||
UID:uuid1211149223785
|
||||
UID:enrico-swe-20190606@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190606
|
||||
DTEND;VALUE=DATE:20190607
|
||||
SUMMARY:Sveriges nationaldag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pingstafton
|
||||
UID:uuid1211149223786
|
||||
DTSTART;VALUE=DATE:20190608
|
||||
DTEND;VALUE=DATE:20190609
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pingstdagen
|
||||
UID:uuid1211149223787
|
||||
UID:enrico-swe-20190609@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190609
|
||||
DTEND;VALUE=DATE:20190610
|
||||
SUMMARY:Pingstdagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Midsommarafton
|
||||
UID:eeea5d95-9cd0-46ff-84a9-e6c575b3fca1
|
||||
DTSTART;VALUE=DATE:20190621
|
||||
DTEND;VALUE=DATE:20190622
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Midsommardagen
|
||||
UID:uuid1211149223788
|
||||
UID:enrico-swe-20190622@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190622
|
||||
DTEND;VALUE=DATE:20190623
|
||||
SUMMARY:Midsommardagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Övergång till vintertid
|
||||
UID:uuid1211149223789
|
||||
DTSTART;VALUE=DATE:20191027
|
||||
DTEND;VALUE=DATE:20191028
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Alla helgons dag
|
||||
UID:uuid1211149223790
|
||||
UID:enrico-swe-20191102@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191102
|
||||
DTEND;VALUE=DATE:20191103
|
||||
SUMMARY:Alla helgons dag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Julafton
|
||||
UID:uuid1211149223791
|
||||
DTSTART;VALUE=DATE:20191224
|
||||
DTEND;VALUE=DATE:20191225
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Juldagen
|
||||
UID:uuid1211149223792
|
||||
UID:enrico-swe-20191225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191225
|
||||
DTEND;VALUE=DATE:20191226
|
||||
SUMMARY:Juldagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Annandag jul
|
||||
UID:uuid1211149223793
|
||||
UID:enrico-swe-20191226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191226
|
||||
DTEND;VALUE=DATE:20191227
|
||||
SUMMARY:Annandag jul
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Nyårsafton
|
||||
UID:uuid1211149223794
|
||||
DTSTART;VALUE=DATE:20191231
|
||||
DTEND;VALUE=DATE:20200101
|
||||
UID:enrico-swe-20200101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200101
|
||||
DTEND;VALUE=DATE:20200102
|
||||
SUMMARY:Nyårsdagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-swe-20200106@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200106
|
||||
DTEND;VALUE=DATE:20200107
|
||||
SUMMARY:Trettondagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-swe-20200410@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200410
|
||||
DTEND;VALUE=DATE:20200411
|
||||
SUMMARY:Långfredagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-swe-20200412@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200412
|
||||
DTEND;VALUE=DATE:20200413
|
||||
SUMMARY:Påskdagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-swe-20200413@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200413
|
||||
DTEND;VALUE=DATE:20200414
|
||||
SUMMARY:Annandag påsk
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-swe-20200501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200501
|
||||
DTEND;VALUE=DATE:20200502
|
||||
SUMMARY:Första maj
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-swe-20200521@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200521
|
||||
DTEND;VALUE=DATE:20200522
|
||||
SUMMARY:Kristi himmelfärds dag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-swe-20200531@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200531
|
||||
DTEND;VALUE=DATE:20200601
|
||||
SUMMARY:Pingstdagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-swe-20200606@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200606
|
||||
DTEND;VALUE=DATE:20200607
|
||||
SUMMARY:Sveriges nationaldag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-swe-20200620@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200620
|
||||
DTEND;VALUE=DATE:20200621
|
||||
SUMMARY:Midsommardagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-swe-20201031@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201031
|
||||
DTEND;VALUE=DATE:20201101
|
||||
SUMMARY:Alla helgons dag
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-swe-20201225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201225
|
||||
DTEND;VALUE=DATE:20201226
|
||||
SUMMARY:Juldagen
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-swe-20201226@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201226
|
||||
DTEND;VALUE=DATE:20201227
|
||||
SUMMARY:Annandag jul
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
|
|
File diff suppressed because it is too large
Load diff
668
app/src/main/assets/taiwan.ics
Normal file
668
app/src/main/assets/taiwan.ics
Normal file
|
@ -0,0 +1,668 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200329
|
||||
DTEND;VALUE=DATE:20200330
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200329_60o30or4cgo30c1g60o30dr56g@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:青年節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190329
|
||||
DTEND;VALUE=DATE:20190330
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190329_60o30or4cgo30c1g60o30dr56c@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:青年節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180329
|
||||
DTEND;VALUE=DATE:20180330
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180329_60o30or4cgo30c1g60o30dr568@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:青年節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20201025
|
||||
DTEND;VALUE=DATE:20201026
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20201025_60o30dppc8o30c1g60o32chmcg@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:重陽節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20191007
|
||||
DTEND;VALUE=DATE:20191008
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20191007_60o30dppc8o30c1g60o32chmcc@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:重陽節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181017
|
||||
DTEND;VALUE=DATE:20181018
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20181017_60o30dppc8o30c1g60o32chmc8@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:重陽節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200204
|
||||
DTEND;VALUE=DATE:20200205
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200204_60o30dppcoo30c1g60o30dr56g@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:農民節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190204
|
||||
DTEND;VALUE=DATE:20190205
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190204_60o30dppcoo30c1g60o30dr56c@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:農民節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180204
|
||||
DTEND;VALUE=DATE:20180205
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180204_60o30dppcoo30c1g60o30dr568@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:農民節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200124
|
||||
DTEND;VALUE=DATE:20200125
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200124_60o30dpo70o30e1g60o32chmcc@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:農曆除夕
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190204
|
||||
DTEND;VALUE=DATE:20190205
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190204_60o30dpo70o30e1g60o32chmc8@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:農曆除夕
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180215
|
||||
DTEND;VALUE=DATE:20180216
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180215_60o30dpo70o30e1g60o32chmc4@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:農曆除夕
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200128
|
||||
DTEND;VALUE=DATE:20200129
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200128_60o30dpocco30c1g60o32chmcg@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:農曆初四
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190208
|
||||
DTEND;VALUE=DATE:20190209
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190208_60o30dpocco30c1g60o32chmcc@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:農曆初四
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180219
|
||||
DTEND;VALUE=DATE:20180220
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180219_60o30dpocco30c1g60o32chmc8@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:農曆初四
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200129
|
||||
DTEND;VALUE=DATE:20200130
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200129_60o30ob368o30c1g60o32chmcg@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:農曆初五
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190209
|
||||
DTEND;VALUE=DATE:20190210
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190209_60o30ob368o30c1g60o32chmcc@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:農曆初五
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180220
|
||||
DTEND;VALUE=DATE:20180221
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180220_60o30ob368o30c1g60o32chmc8@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:農曆初五
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200126
|
||||
DTEND;VALUE=DATE:20200127
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200126_60o30dpoc4o30c1g60o32chmcg@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:農曆初二
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190206
|
||||
DTEND;VALUE=DATE:20190207
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190206_60o30dpoc4o30c1g60o32chmcc@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:農曆初二
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180217
|
||||
DTEND;VALUE=DATE:20180218
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180217_60o30dpoc4o30c1g60o32chmc8@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:農曆初二
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200127
|
||||
DTEND;VALUE=DATE:20200128
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200127_60o30dpoc8o30c1g60o32chmcg@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:農曆初三
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190207
|
||||
DTEND;VALUE=DATE:20190208
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190207_60o30dpoc8o30c1g60o32chmcc@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:農曆初三
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180218
|
||||
DTEND;VALUE=DATE:20180219
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180218_60o30dpoc8o30c1g60o32chmc8@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:農曆初三
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200903
|
||||
DTEND;VALUE=DATE:20200904
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200903_60o30dpp64o32c1g60o30dr56g@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:軍人節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190903
|
||||
DTEND;VALUE=DATE:20190904
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190903_60o30dpp64o32c1g60o30dr56c@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:軍人節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180903
|
||||
DTEND;VALUE=DATE:20180904
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180903_60o30dpp64o32c1g60o30dr568@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:軍人節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20201225
|
||||
DTEND;VALUE=DATE:20201226
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20201225_60o30dppcco30c1g60o30dr56g@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:行憲紀念日
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20191225
|
||||
DTEND;VALUE=DATE:20191226
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20191225_60o30dppcco30c1g60o30dr56c@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:行憲紀念日
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181225
|
||||
DTEND;VALUE=DATE:20181226
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20181225_60o30dppcco30c1g60o30dr568@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:行憲紀念日
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200625
|
||||
DTEND;VALUE=DATE:20200626
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200625_60o30dpp60o30c1g60o32chmcg@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:端午節彈性放假
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190607
|
||||
DTEND;VALUE=DATE:20190608
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190607_60o30dpp60o30c1g60o32chmcc@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:端午節彈性放假
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180618
|
||||
DTEND;VALUE=DATE:20180619
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180618_60o30dpp60o30c1g60o32chmc8@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:端午節彈性放假
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200404
|
||||
DTEND;VALUE=DATE:20200405
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200404_60o30dpocko30c1g60o30dr56g@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:清明節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190405
|
||||
DTEND;VALUE=DATE:20190406
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190405_60o30dpocko30c1g60o30dr56c@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:清明節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180405
|
||||
DTEND;VALUE=DATE:20180406
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180405_60o30dpocko30c1g60o30dr568@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:清明節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200125
|
||||
DTEND;VALUE=DATE:20200126
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200125_60o30dpo74o30c1g60o32chmcg@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:春節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190205
|
||||
DTEND;VALUE=DATE:20190206
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190205_60o30dpo74o30c1g60o32chmcc@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:春節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180216
|
||||
DTEND;VALUE=DATE:20180217
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180216_60o30dpo74o30c1g60o32chmc8@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:春節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200928
|
||||
DTEND;VALUE=DATE:20200929
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200928_60o30dppc4o30c1g60o30dr56g@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:教師節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190928
|
||||
DTEND;VALUE=DATE:20190929
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190928_60o30dppc4o30c1g60o30dr56c@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:教師節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180928
|
||||
DTEND;VALUE=DATE:20180929
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180928_60o30dppc4o30c1g60o30dr568@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:教師節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200308
|
||||
DTEND;VALUE=DATE:20200309
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200308_60o30dpp6oo30c1g60o30dr56g@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:婦女節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190308
|
||||
DTEND;VALUE=DATE:20190309
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190308_60o30dpp6oo30c1g60o30dr56c@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:婦女節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180308
|
||||
DTEND;VALUE=DATE:20180309
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180308_60o30dpp6oo30c1g60o30dr568@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:婦女節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20201009
|
||||
DTEND;VALUE=DATE:20201010
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20201009_60o30dpp6co30e1g60o30dr56g@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:國慶日/雙十節彈性放假 補假
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20201010
|
||||
DTEND;VALUE=DATE:20201011
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20201010_60o30dpp6co30c1g60o30dr56g@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:國慶日/雙十節彈性放假
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20191010
|
||||
DTEND;VALUE=DATE:20191011
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20191010_60o30dpp6co30c1g60o30dr56c@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:國慶日/雙十節彈性放假
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181010
|
||||
DTEND;VALUE=DATE:20181011
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20181010_60o30dpp6co30c1g60o30dr568@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:國慶日/雙十節彈性放假
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20201025
|
||||
DTEND;VALUE=DATE:20201026
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20201025_60o30dpp74o30c1g60o30dr56g@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:台灣光復節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20191025
|
||||
DTEND;VALUE=DATE:20191026
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20191025_60o30dpp74o30c1g60o30dr56c@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:台灣光復節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20181025
|
||||
DTEND;VALUE=DATE:20181026
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20181025_60o30dpp74o30c1g60o30dr568@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:台灣光復節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200501
|
||||
DTEND;VALUE=DATE:20200502
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200501_60o30dpocoo30c1g60o30dr56g@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:勞動節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190501
|
||||
DTEND;VALUE=DATE:20190502
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190501_60o30dpocoo30c1g60o30dr56c@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:勞動節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180501
|
||||
DTEND;VALUE=DATE:20180502
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180501_60o30dpocoo30c1g60o30dr568@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:勞動節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200403
|
||||
DTEND;VALUE=DATE:20200404
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200403_60o30dpp70o34e1g60o30dr56g@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:兒童節 補假
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200404
|
||||
DTEND;VALUE=DATE:20200405
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200404_60o30dpp70o34c1g60o30dr56g@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:兒童節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190404
|
||||
DTEND;VALUE=DATE:20190405
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190404_60o30dpp70o34c1g60o30dr56c@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:兒童節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180404
|
||||
DTEND;VALUE=DATE:20180405
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180404_60o30dpp70o34c1g60o30dr568@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:兒童節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200208
|
||||
DTEND;VALUE=DATE:20200209
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200208_60o30dpp6go30c1g60o32chmcg@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:元宵節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190219
|
||||
DTEND;VALUE=DATE:20190220
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190219_60o30dpp6go30c1g60o32chmcc@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:元宵節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180302
|
||||
DTEND;VALUE=DATE:20180303
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180302_60o30dpp6go30c1g60o32chmc8@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:元宵節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200101
|
||||
DTEND;VALUE=DATE:20200102
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200101_60o30dpo6oo30c1g60o30dr56g@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:中華民國開國紀念日/元旦
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190101
|
||||
DTEND;VALUE=DATE:20190102
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190101_60o30dpo6oo30c1g60o30dr56c@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:中華民國開國紀念日/元旦
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180101_60o30dpo6oo30c1g60o30dr568@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:中華民國開國紀念日/元旦
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20201001
|
||||
DTEND;VALUE=DATE:20201002
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20201001_60o30dpp68o30c1g60o32chmcg@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:中秋節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190913
|
||||
DTEND;VALUE=DATE:20190914
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190913_60o30dpp68o30c1g60o32chmcc@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:中秋節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180924
|
||||
DTEND;VALUE=DATE:20180925
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180924_60o30dpp68o30c1g60o32chmc8@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:中秋節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200902
|
||||
DTEND;VALUE=DATE:20200903
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200902_60o30dr160o30c1g60o32chmcg@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:中元節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190815
|
||||
DTEND;VALUE=DATE:20190816
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190815_60o30dr160o30c1g60o32chmcc@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:中元節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180825
|
||||
DTEND;VALUE=DATE:20180826
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180825_60o30dr160o30c1g60o32chmc8@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:中元節
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200228
|
||||
DTEND;VALUE=DATE:20200229
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20200228_60o30dpocgo30c1g60o30dr56g@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:228連假
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190228
|
||||
DTEND;VALUE=DATE:20190301
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20190228_60o30dpocgo30c1g60o30dr56c@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:228連假
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20180228
|
||||
DTEND;VALUE=DATE:20180301
|
||||
DTSTAMP:20190328T061054Z
|
||||
UID:20180228_60o30dpocgo30c1g60o30dr568@google.com
|
||||
CREATED:20190221T131351Z
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:228連假
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
316
app/src/main/assets/ukraine.ics
Normal file
316
app/src/main/assets/ukraine.ics
Normal file
|
@ -0,0 +1,316 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20180101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180101
|
||||
DTEND;VALUE=DATE:20180102
|
||||
SUMMARY:Новий Рік
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20180108@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180108
|
||||
DTEND;VALUE=DATE:20180109
|
||||
SUMMARY:Різдво
|
||||
DESCRIPTION:Holiday in lieu of 7 Jan 2018
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20180308@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180308
|
||||
DTEND;VALUE=DATE:20180309
|
||||
SUMMARY:Міжнародний жіночий день
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20180309@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180309
|
||||
DTEND;VALUE=DATE:20180310
|
||||
SUMMARY:Свято
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20180408@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180408
|
||||
DTEND;VALUE=DATE:20180409
|
||||
SUMMARY:Пасха
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20180409@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180409
|
||||
DTEND;VALUE=DATE:20180410
|
||||
SUMMARY:Пасха
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20180430@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180430
|
||||
DTEND;VALUE=DATE:20180501
|
||||
SUMMARY:Свято
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20180501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180501
|
||||
DTEND;VALUE=DATE:20180502
|
||||
SUMMARY:День праці (День міжнародної солідарності трудящих)
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20180509@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180509
|
||||
DTEND;VALUE=DATE:20180510
|
||||
SUMMARY:День перемоги над нацизмом у Другій світовій війні
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20180527@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180527
|
||||
DTEND;VALUE=DATE:20180528
|
||||
SUMMARY:Трійця
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20180528@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180528
|
||||
DTEND;VALUE=DATE:20180529
|
||||
SUMMARY:Трійця
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20180628@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180628
|
||||
DTEND;VALUE=DATE:20180629
|
||||
SUMMARY:День Конституції
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20180629@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180629
|
||||
DTEND;VALUE=DATE:20180630
|
||||
SUMMARY:Свято
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20180824@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20180824
|
||||
DTEND;VALUE=DATE:20180825
|
||||
SUMMARY:День Незалежності
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20181015@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181015
|
||||
DTEND;VALUE=DATE:20181016
|
||||
SUMMARY:День захисника України
|
||||
DESCRIPTION:Holiday in lieu of 14 Oct 2018
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20181224@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181224
|
||||
DTEND;VALUE=DATE:20181225
|
||||
SUMMARY:Свято
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20181225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181225
|
||||
DTEND;VALUE=DATE:20181226
|
||||
SUMMARY:Різдво
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20181231@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20181231
|
||||
DTEND;VALUE=DATE:20190101
|
||||
SUMMARY:Свято
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20190101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190101
|
||||
DTEND;VALUE=DATE:20190102
|
||||
SUMMARY:Новий Рік
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20190107@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190107
|
||||
DTEND;VALUE=DATE:20190108
|
||||
SUMMARY:Різдво
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20190308@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190308
|
||||
DTEND;VALUE=DATE:20190309
|
||||
SUMMARY:Міжнародний жіночий день
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20190428@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190428
|
||||
DTEND;VALUE=DATE:20190429
|
||||
SUMMARY:Пасха
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20190429@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190429
|
||||
DTEND;VALUE=DATE:20190430
|
||||
SUMMARY:Пасха
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20190501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190501
|
||||
DTEND;VALUE=DATE:20190502
|
||||
SUMMARY:День праці (День міжнародної солідарності трудящих)
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20190509@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190509
|
||||
DTEND;VALUE=DATE:20190510
|
||||
SUMMARY:День перемоги над нацизмом у Другій світовій війні
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20190616@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190616
|
||||
DTEND;VALUE=DATE:20190617
|
||||
SUMMARY:Трійця
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20190617@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190617
|
||||
DTEND;VALUE=DATE:20190618
|
||||
SUMMARY:Трійця
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20190628@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190628
|
||||
DTEND;VALUE=DATE:20190629
|
||||
SUMMARY:День Конституції
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20190826@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20190826
|
||||
DTEND;VALUE=DATE:20190827
|
||||
SUMMARY:День Незалежності
|
||||
DESCRIPTION:Holiday in lieu of 24 Aug 2019
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20191014@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191014
|
||||
DTEND;VALUE=DATE:20191015
|
||||
SUMMARY:День захисника України
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20191225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20191225
|
||||
DTEND;VALUE=DATE:20191226
|
||||
SUMMARY:Різдво
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20200101@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200101
|
||||
DTEND;VALUE=DATE:20200102
|
||||
SUMMARY:Новий Рік
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20200107@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200107
|
||||
DTEND;VALUE=DATE:20200108
|
||||
SUMMARY:Різдво
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20200309@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200309
|
||||
DTEND;VALUE=DATE:20200310
|
||||
SUMMARY:Міжнародний жіночий день
|
||||
DESCRIPTION:Holiday in lieu of 8 Mar 2020
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20200419@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200419
|
||||
DTEND;VALUE=DATE:20200420
|
||||
SUMMARY:Пасха
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20200420@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200420
|
||||
DTEND;VALUE=DATE:20200421
|
||||
SUMMARY:Пасха
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20200501@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200501
|
||||
DTEND;VALUE=DATE:20200502
|
||||
SUMMARY:День праці (День міжнародної солідарності трудящих)
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20200511@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200511
|
||||
DTEND;VALUE=DATE:20200512
|
||||
SUMMARY:День перемоги над нацизмом у Другій світовій війні
|
||||
DESCRIPTION:Holiday in lieu of 9 May 2020
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20200607@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200607
|
||||
DTEND;VALUE=DATE:20200608
|
||||
SUMMARY:Трійця
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20200608@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200608
|
||||
DTEND;VALUE=DATE:20200609
|
||||
SUMMARY:Трійця
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20200629@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200629
|
||||
DTEND;VALUE=DATE:20200630
|
||||
SUMMARY:День Конституції
|
||||
DESCRIPTION:Holiday in lieu of 28 Jun 2020
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20200824@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20200824
|
||||
DTEND;VALUE=DATE:20200825
|
||||
SUMMARY:День Незалежності
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20201014@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201014
|
||||
DTEND;VALUE=DATE:20201015
|
||||
SUMMARY:День захисника України
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:enrico-ukr-20201225@kayaposoft.com
|
||||
DTSTART;VALUE=DATE:20201225
|
||||
DTEND;VALUE=DATE:20201226
|
||||
SUMMARY:Різдво
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
|
@ -2,58 +2,33 @@ BEGIN:VCALENDAR
|
|||
BEGIN:VEVENT
|
||||
SUMMARY:New Year's Day
|
||||
UID:4694f46a-aef0-49a0-a8eb-44ab6531e0d9
|
||||
DTSTART;VALUE=DATE:20170102
|
||||
DTEND;VALUE=DATE:20170103
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:St. David's Day
|
||||
UID:a08053d8-530b-4025-8edf-81c88d05fe84
|
||||
DTSTART;VALUE=DATE:20100301
|
||||
DTEND;VALUE=DATE:20100302
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:St. George's Day
|
||||
UID:b58227e2-7f9d-4571-afa5-0ae93192d10e
|
||||
DTSTART;VALUE=DATE:20100423
|
||||
DTEND;VALUE=DATE:20100424
|
||||
DTSTART;VALUE=DATE:20170101
|
||||
DTEND;VALUE=DATE:20170102
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Early May Bank Holiday
|
||||
UID:21626542-636f-43d7-8fa9-bad05bb82dca
|
||||
DTSTART;VALUE=DATE:20100503
|
||||
DTEND;VALUE=DATE:20100504
|
||||
DTSTART;VALUE=DATE:20210503
|
||||
DTEND;VALUE=DATE:20210504
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=5;BYDAY=1MO
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Early May Bank Holiday
|
||||
UID:21626542-636f-43d7-8fa9-bad05bbsds
|
||||
DTSTART;VALUE=DATE:20200508
|
||||
DTEND;VALUE=DATE:20200509
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Summer Bank Holiday
|
||||
UID:5dac6a63-e519-4ad1-a687-2fd5fccb4656
|
||||
DTSTART;VALUE=DATE:20100802
|
||||
DTEND;VALUE=DATE:20100803
|
||||
DTSTART;VALUE=DATE:20130826
|
||||
DTEND;VALUE=DATE:20130827
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=8;BYDAY=-1MO
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Summer Bank Holiday
|
||||
UID:3d37b115-f0fa-4456-98c9-3b18cfffb47d
|
||||
DTSTART;VALUE=DATE:20170828
|
||||
DTEND;VALUE=DATE:20170829
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:BST ends
|
||||
UID:8eb163f3-6d42-494e-9e7c-747619cf965f
|
||||
DTSTART:20101031T000000Z
|
||||
DTEND:20101031T020000Z
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Christmas Day
|
||||
|
@ -71,4 +46,53 @@ DTEND;VALUE=DATE:20101227
|
|||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTEND;VALUE=DATE:20190423
|
||||
DTSTART;VALUE=DATE:20190422
|
||||
SUMMARY:Easter Monday
|
||||
UID:ca6af7456b0088abad9a69f9f620f5ac-59@gov.uk
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20190419
|
||||
DTEND;VALUE=DATE:20190420
|
||||
SUMMARY:Good Friday
|
||||
UID:ca6af7456b0088abad9a69f9f620f5ac-58@gov.uk
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200410
|
||||
DTEND;VALUE=DATE:20200411
|
||||
SUMMARY:Good Friday
|
||||
UID:ca6af7456b0088abad9a69f9f620f5ac-2020-04-10-GoodFriday@gov.uk
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200413
|
||||
DTEND;VALUE=DATE:20200414
|
||||
SUMMARY:Easter Monday
|
||||
UID:ca6af7456b0088abad9a69f9f620f5ac-2020-04-13-EasterMonday@gov.uk
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20210402
|
||||
DTEND;VALUE=DATE:20210403
|
||||
SUMMARY:Good Friday
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20210405
|
||||
DTEND;VALUE=DATE:20210406
|
||||
SUMMARY:Easter Monday
|
||||
UID:ca6af7456b0088abad9a69f9f620f5ac-2021-04-05-EasterMonday@gov.uk
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Spring Bank Holiday
|
||||
UID:5dac6a63-e519-4ad1-a687-2fd5fccb4
|
||||
DTSTART;VALUE=DATE:20130527
|
||||
DTEND;VALUE=DATE:20130528
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=5;BYDAY=-1MO
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
|
|
|
@ -1,403 +1,83 @@
|
|||
BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ascension Day
|
||||
UID:7c8351e3-e3fd-4c0b-a60c-f558aa31df55
|
||||
DTSTART;VALUE=DATE:20170525
|
||||
DTEND;VALUE=DATE:20170526
|
||||
DTSTART;VALUE=DATE:20170101
|
||||
DTEND;VALUE=DATE:20170102
|
||||
UID:5a4b1ab2e4a3b@calendarlabs.com
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pentecost
|
||||
UID:452c678d-0b42-4a89-a347-a0b8e12c4fd6
|
||||
DTSTART;VALUE=DATE:20170604
|
||||
DTEND;VALUE=DATE:20170605
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Trinity Sunday
|
||||
UID:83608056-f721-4564-88ed-3cc5d12b01fb
|
||||
DTSTART;VALUE=DATE:20170611
|
||||
DTEND;VALUE=DATE:20170612
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ash Wednesday
|
||||
UID:6eff84ea-6763-46d3-9c64-b847376f3e34
|
||||
DTSTART;VALUE=DATE:20180214
|
||||
DTEND;VALUE=DATE:20180215
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Good Friday
|
||||
UID:19fb2499-97ae-457f-8d41-6ec76292c77f
|
||||
DTSTART;VALUE=DATE:20180330
|
||||
DTEND;VALUE=DATE:20180331
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Easter Sunday
|
||||
UID:d869e442-0b4d-40c4-b34c-6780afce8c46
|
||||
DTSTART;VALUE=DATE:20180401
|
||||
DTEND;VALUE=DATE:20180402
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ascension Day
|
||||
UID:db037aff-17bf-430b-b094-52e99879ba4e
|
||||
DTSTART;VALUE=DATE:20180510
|
||||
DTEND;VALUE=DATE:20180511
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pentecost
|
||||
UID:01fec43b-b371-4f56-97cb-ef454132a74a
|
||||
DTSTART;VALUE=DATE:20180520
|
||||
DTEND;VALUE=DATE:20180521
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Trinity Sunday
|
||||
UID:cc92b242-3a24-471c-b1be-b8918fb8b6de
|
||||
DTSTART;VALUE=DATE:20180527
|
||||
DTEND;VALUE=DATE:20180528
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ash Wednesday
|
||||
UID:e5d798cf-474f-42c3-83b8-0d1186c2c3ad
|
||||
DTSTART;VALUE=DATE:20190306
|
||||
DTEND;VALUE=DATE:20190307
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Palm Sunday
|
||||
UID:334646f6-5fef-43a9-83bc-d2dd88c9ebe6
|
||||
DTSTART;VALUE=DATE:20190414
|
||||
DTEND;VALUE=DATE:20190415
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Good Friday
|
||||
UID:0a125549-300d-4bd9-af20-3fc28935946e
|
||||
DTSTART;VALUE=DATE:20190419
|
||||
DTEND;VALUE=DATE:20190420
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Easter Sunday
|
||||
UID:135738b2-b8d5-4e65-bf7c-736e22c6b8b1
|
||||
DTSTART;VALUE=DATE:20190421
|
||||
DTEND;VALUE=DATE:20190422
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ascension Day
|
||||
UID:dddeea06-c165-474c-96aa-6c1b705c6b0a
|
||||
DTSTART;VALUE=DATE:20190530
|
||||
DTEND;VALUE=DATE:20190531
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pentecost
|
||||
UID:697b8004-261c-4c0b-a15e-06c1af95ab9b
|
||||
DTSTART;VALUE=DATE:20190609
|
||||
DTEND;VALUE=DATE:20190610
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Trinity Sunday
|
||||
UID:006195b6-8021-4814-9635-f9f5bffa7a36
|
||||
DTSTART;VALUE=DATE:20190616
|
||||
DTEND;VALUE=DATE:20190617
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ash Wednesday
|
||||
UID:9d17488f-12b8-474b-8790-d22e6786735e
|
||||
DTSTART;VALUE=DATE:20200226
|
||||
DTEND;VALUE=DATE:20200227
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Palm Sunday
|
||||
UID:7f9c6e82-610a-4485-b5fd-dde7f0dba4b8
|
||||
DTSTART;VALUE=DATE:20200405
|
||||
DTEND;VALUE=DATE:20200406
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Good Friday
|
||||
UID:50de218e-013d-4739-b8d4-f30f74a57168
|
||||
DTSTART;VALUE=DATE:20200410
|
||||
DTEND;VALUE=DATE:20200411
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Easter Sunday
|
||||
UID:7606494f-0019-46e6-9d47-ab9498569e5a
|
||||
DTSTART;VALUE=DATE:20200412
|
||||
DTEND;VALUE=DATE:20200413
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Ascension Day
|
||||
UID:09a3f71c-83df-4649-b7d1-4792ae2fb523
|
||||
DTSTART;VALUE=DATE:20200521
|
||||
DTEND;VALUE=DATE:20200522
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Pentecost
|
||||
UID:ac723797-16b2-4fd9-9d5e-2f55cc90dc22
|
||||
DTSTART;VALUE=DATE:20200531
|
||||
DTEND;VALUE=DATE:20200601
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Trinity Sunday
|
||||
UID:b60896ca-b1eb-4ec1-a9cd-67c7403c6335
|
||||
DTSTART;VALUE=DATE:20200607
|
||||
DTEND;VALUE=DATE:20200608
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:New Year's Day
|
||||
UID:b1f194fc-1dd1-11b2-a973-d219c68b95c4
|
||||
DTSTART;VALUE=DATE:20000101
|
||||
DTEND;VALUE=DATE:20000102
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Groundhog's Day
|
||||
UID:0c771532-1dd2-11b2-8dd9-8638db3aef63
|
||||
DTSTART;VALUE=DATE:20000202
|
||||
DTEND;VALUE=DATE:20000203
|
||||
DTSTART;VALUE=DATE:20170116
|
||||
DTEND;VALUE=DATE:20170117
|
||||
UID:5a4b1ab2e4b97@calendarlabs.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:M L King Day
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=1;BYDAY=3MO
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Abraham Lincoln's Birthday
|
||||
UID:4d5b843e-1dd2-11b2-a6c9-8ea942124d1b
|
||||
DTSTART;VALUE=DATE:20000212
|
||||
DTEND;VALUE=DATE:20000213
|
||||
DTSTART;VALUE=DATE:20170220
|
||||
DTEND;VALUE=DATE:20170221
|
||||
UID:5a4b1ab2e4c77@calendarlabs.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
SUMMARY:Presidents' Day
|
||||
RRULE:FREQ=YEARLY;BYMONTH=2;BYDAY=3MO
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Valentine's Day
|
||||
UID:790b86e2-1dd2-11b2-9cb9-c905fa35c6f9
|
||||
DTSTART;VALUE=DATE:20000214
|
||||
DTEND;VALUE=DATE:20000215
|
||||
DTSTART;VALUE=DATE:20170529
|
||||
DTEND;VALUE=DATE:20170530
|
||||
UID:5a4b1ab2e4e43@calendarlabs.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:President's Day
|
||||
UID:9f3df592-1dd1-11b2-8b51-a8c49a575f97
|
||||
DTSTART;VALUE=DATE:20000221
|
||||
DTEND;VALUE=DATE:20000222
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:George Washington's Birthday (actual)
|
||||
UID:aff9f3c8-1dd1-11b2-8593-c63469762eb1
|
||||
DTSTART;VALUE=DATE:20000222
|
||||
DTEND;VALUE=DATE:20000223
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:St. Patrick's Day
|
||||
UID:bd6cfe4c-1dd1-11b2-b3dc-ebaab9302c26
|
||||
DTSTART;VALUE=DATE:20000317
|
||||
DTEND;VALUE=DATE:20000318
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:April Fool's Day
|
||||
UID:c981b858-1dd1-11b2-b69b-94d05f8bda66
|
||||
DTSTART;VALUE=DATE:20000401
|
||||
DTEND;VALUE=DATE:20000402
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Tax Day
|
||||
UID:e46086c2-1dd1-11b2-8a16-a2c99f1c525a
|
||||
DTSTART;VALUE=DATE:20000415
|
||||
DTEND;VALUE=DATE:20000416
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Earth Day
|
||||
UID:f1561106-1dd1-11b2-955f-ba14e5210f45
|
||||
DTSTART;VALUE=DATE:20000422
|
||||
DTEND;VALUE=DATE:20000423
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Arbor Day
|
||||
UID:e20f1b5c-8ac4-4bea-acf4-b4f2bfe95329
|
||||
DTSTART;VALUE=DATE:20000428
|
||||
DTEND;VALUE=DATE:20000429
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:National Day of Prayer
|
||||
UID:a44b8b6e-7ae4-4120-b7ad-14e91691be2a
|
||||
DTSTART;VALUE=DATE:20000504
|
||||
DTEND;VALUE=DATE:20000505
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Mother's Day
|
||||
UID:e0d4c156-1dd1-11b2-b6a4-dac750e0163e
|
||||
DTSTART;VALUE=DATE:20000514
|
||||
DTEND;VALUE=DATE:20000515
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Armed Forces Day
|
||||
UID:c2783248-1dd1-11b2-affa-ee50c39d8083
|
||||
DTSTART;VALUE=DATE:20000520
|
||||
DTEND;VALUE=DATE:20000521
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Memorial Day
|
||||
UID:d9706fa6-1dd1-11b2-a349-e97241bd4740
|
||||
DTSTART;VALUE=DATE:20000529
|
||||
DTEND;VALUE=DATE:20000530
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
RRULE:FREQ=YEARLY;BYMONTH=5;BYDAY=-1MO
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Flag Day
|
||||
UID:e8022726-1dd1-11b2-aae6-9f73f16c0f01
|
||||
DTSTART;VALUE=DATE:20000614
|
||||
DTEND;VALUE=DATE:20000615
|
||||
DTSTART;VALUE=DATE:20170704
|
||||
DTEND;VALUE=DATE:20170705
|
||||
UID:5a4b1ab2e4f3d@calendarlabs.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Father's Day
|
||||
UID:cb90487e-1dd1-11b2-9e06-d1a12cc963dc
|
||||
DTSTART;VALUE=DATE:20000618
|
||||
DTEND;VALUE=DATE:20000619
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Independence Day
|
||||
UID:f669a974-1dd1-11b2-9fac-f44d91c657af
|
||||
DTSTART;VALUE=DATE:20000704
|
||||
DTEND;VALUE=DATE:20000705
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Parents' Day
|
||||
UID:46e6845c-1dd2-11b2-bd3d-d8755a1a171f
|
||||
DTSTART;VALUE=DATE:20000723
|
||||
DTEND;VALUE=DATE:20000724
|
||||
DTSTART;VALUE=DATE:20170904
|
||||
DTEND;VALUE=DATE:20170905
|
||||
UID:5a4b1ab2e4fd4@calendarlabs.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Labor Day
|
||||
UID:0726ea42-1dd2-11b2-9fe6-dda3d063fb50
|
||||
DTSTART;VALUE=DATE:20000904
|
||||
DTEND;VALUE=DATE:20000905
|
||||
RRULE:FREQ=YEARLY;BYMONTH=9;BYDAY=1MO
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20171009
|
||||
DTEND;VALUE=DATE:20171010
|
||||
UID:5a4b1ab2e502a@calendarlabs.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Columbus Day
|
||||
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=2MO
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20171111
|
||||
DTEND;VALUE=DATE:20171112
|
||||
UID:5a4b1ab2e515a@calendarlabs.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Veterans Day
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Constitution Day\, Citizenship Day
|
||||
UID:d3c521e1-ffab-414c-8cfa-99e76758d8c8
|
||||
DTSTART;VALUE=DATE:20000917
|
||||
DTEND;VALUE=DATE:20000918
|
||||
DTSTART;VALUE=DATE:20171123
|
||||
DTEND;VALUE=DATE:20171124
|
||||
UID:5a4b1ab2e51ca@calendarlabs.com
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:United Nations Day
|
||||
UID:8a05b5d3-6b97-4fe1-b26e-b258a073c5e0
|
||||
DTSTART;VALUE=DATE:20001024
|
||||
DTEND;VALUE=DATE:20001025
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Halloween
|
||||
UID:7d4402f4-1dd2-11b2-9790-b6193cfa4349
|
||||
DTSTART;VALUE=DATE:20001031
|
||||
DTEND;VALUE=DATE:20001101
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Veteran's Day
|
||||
UID:2c7ba10c-1dd2-11b2-b0b7-96f89f288199
|
||||
DTSTART;VALUE=DATE:20001111
|
||||
DTEND;VALUE=DATE:20001112
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Thanksgiving Day
|
||||
UID:4299a358-1dd2-11b2-a228-d062222b6f88
|
||||
DTSTART;VALUE=DATE:20001123
|
||||
DTEND;VALUE=DATE:20001124
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=4TH
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Christmas Day
|
||||
UID:54f392fa-1dd2-11b2-8ecb-9ae0a7fcebd1
|
||||
DTSTART;VALUE=DATE:20001225
|
||||
DTEND;VALUE=DATE:20001226
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:New Year's Eve
|
||||
UID:a2cbca9c-1dd1-11b2-83e2-abab36f0506d
|
||||
DTSTART;VALUE=DATE:20001231
|
||||
DTEND;VALUE=DATE:20010101
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Inauguration Day
|
||||
UID:088031d1-abea-47ed-978d-39c6319e8bf2
|
||||
DTSTART;VALUE=DATE:20010120
|
||||
DTEND;VALUE=DATE:20010121
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=4
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Daylight Saving Time begins
|
||||
UID:e462881a-20b8-4b70-ab3c-cf38016d3398
|
||||
DTSTART;VALUE=DATE:20070311
|
||||
DTEND;VALUE=DATE:20070312
|
||||
STATUS:CONFIRMED
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Daylight Saving Time ends
|
||||
UID:13f83ed2-1dd2-11b2-a0de-ee8645423959
|
||||
DTSTART;VALUE=DATE:20071104
|
||||
DTEND;VALUE=DATE:20071105
|
||||
DTSTART;VALUE=DATE:20171225
|
||||
DTEND;VALUE=DATE:20171226
|
||||
UID:5a4b1ab2e5265@calendarlabs.com
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Christmas
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
package com.simplemobiletools.calendar
|
||||
|
||||
import android.support.multidex.MultiDexApplication
|
||||
import com.facebook.stetho.Stetho
|
||||
import com.simplemobiletools.commons.extensions.checkUseEnglish
|
||||
import com.squareup.leakcanary.LeakCanary
|
||||
|
||||
class App : MultiDexApplication() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
if (BuildConfig.DEBUG) {
|
||||
if (LeakCanary.isInAnalyzerProcess(this)) {
|
||||
return
|
||||
}
|
||||
LeakCanary.install(this)
|
||||
Stetho.initializeWithDefaults(this)
|
||||
}
|
||||
|
||||
checkUseEnglish()
|
||||
}
|
||||
}
|
|
@ -1,129 +0,0 @@
|
|||
package com.simplemobiletools.calendar.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.view.ViewPager
|
||||
import android.util.SparseIntArray
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.adapters.MyDayPagerAdapter
|
||||
import com.simplemobiletools.calendar.dialogs.FilterEventTypesDialog
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.calendar.extensions.dbHelper
|
||||
import com.simplemobiletools.calendar.extensions.getNewEventTimestampFromCode
|
||||
import com.simplemobiletools.calendar.helpers.DAY_CODE
|
||||
import com.simplemobiletools.calendar.helpers.Formatter
|
||||
import com.simplemobiletools.calendar.helpers.NEW_EVENT_START_TS
|
||||
import com.simplemobiletools.calendar.interfaces.NavigationListener
|
||||
import com.simplemobiletools.commons.extensions.isActivityDestroyed
|
||||
import com.simplemobiletools.commons.extensions.updateTextColors
|
||||
import kotlinx.android.synthetic.main.activity_day.*
|
||||
import org.joda.time.DateTime
|
||||
import java.util.*
|
||||
|
||||
class DayActivity : SimpleActivity(), NavigationListener, ViewPager.OnPageChangeListener {
|
||||
private val PREFILLED_DAYS = 121
|
||||
private var mDayCode = ""
|
||||
private var mPagerDays: MutableList<String>? = null
|
||||
private var mPagerPos = 0
|
||||
private var eventTypeColors = SparseIntArray()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_day)
|
||||
|
||||
val intent = intent ?: return
|
||||
mDayCode = intent.getStringExtra(DAY_CODE)
|
||||
if (mDayCode.isEmpty())
|
||||
return
|
||||
|
||||
fillViewPager(mDayCode)
|
||||
|
||||
day_fab.setOnClickListener { addNewEvent() }
|
||||
updateTextColors(day_coordinator)
|
||||
|
||||
dbHelper.getEventTypes {
|
||||
if (!isActivityDestroyed()) {
|
||||
eventTypeColors.clear()
|
||||
it.map { eventTypeColors.put(it.id, it.color) }
|
||||
invalidateOptionsMenu()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_day, menu)
|
||||
menu.findItem(R.id.filter).isVisible = eventTypeColors.size() > 1 || config.displayEventTypes.isEmpty()
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.filter -> showFilterDialog()
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun fillViewPager(targetDay: String) {
|
||||
getDays(targetDay)
|
||||
val daysAdapter = MyDayPagerAdapter(supportFragmentManager, mPagerDays!!, this)
|
||||
mPagerPos = mPagerDays!!.size / 2
|
||||
view_pager.apply {
|
||||
adapter = daysAdapter
|
||||
currentItem = mPagerPos
|
||||
addOnPageChangeListener(this@DayActivity)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showFilterDialog() {
|
||||
FilterEventTypesDialog(this) {
|
||||
recheckEvents()
|
||||
}
|
||||
}
|
||||
|
||||
private fun addNewEvent() {
|
||||
Intent(applicationContext, EventActivity::class.java).apply {
|
||||
putExtra(NEW_EVENT_START_TS, getNewEventTimestampFromCode(mPagerDays?.get(view_pager.currentItem).toString()))
|
||||
startActivity(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDays(code: String) {
|
||||
mPagerDays = ArrayList(PREFILLED_DAYS)
|
||||
val today = Formatter.getDateTimeFromCode(code)
|
||||
for (i in -PREFILLED_DAYS / 2..PREFILLED_DAYS / 2) {
|
||||
mPagerDays!!.add(Formatter.getDayCodeFromDateTime(today.plusDays(i)))
|
||||
}
|
||||
}
|
||||
|
||||
fun recheckEvents() {
|
||||
(view_pager.adapter as MyDayPagerAdapter).checkDayEvents(mPagerPos)
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
mPagerPos = position
|
||||
(view_pager.adapter as MyDayPagerAdapter).destroyMultiselector(position)
|
||||
}
|
||||
|
||||
override fun goLeft() {
|
||||
view_pager.currentItem = view_pager.currentItem - 1
|
||||
}
|
||||
|
||||
override fun goRight() {
|
||||
view_pager.currentItem = view_pager.currentItem + 1
|
||||
}
|
||||
|
||||
override fun goToDateTime(dateTime: DateTime) {
|
||||
fillViewPager(Formatter.getDayCodeFromDateTime(dateTime))
|
||||
}
|
||||
}
|
|
@ -1,754 +0,0 @@
|
|||
package com.simplemobiletools.calendar.activities
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.DatePickerDialog
|
||||
import android.app.TimePickerDialog
|
||||
import android.os.Bundle
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.WindowManager
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.dialogs.*
|
||||
import com.simplemobiletools.calendar.extensions.*
|
||||
import com.simplemobiletools.calendar.helpers.*
|
||||
import com.simplemobiletools.calendar.helpers.Formatter
|
||||
import com.simplemobiletools.calendar.models.CalDAVCalendar
|
||||
import com.simplemobiletools.calendar.models.Event
|
||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import kotlinx.android.synthetic.main.activity_event.*
|
||||
import org.joda.time.DateTime
|
||||
import java.util.*
|
||||
|
||||
class EventActivity : SimpleActivity() {
|
||||
private var mReminder1Minutes = 0
|
||||
private var mReminder2Minutes = 0
|
||||
private var mReminder3Minutes = 0
|
||||
private var mRepeatInterval = 0
|
||||
private var mRepeatLimit = 0
|
||||
private var mRepeatRule = 0
|
||||
private var mEventTypeId = DBHelper.REGULAR_EVENT_TYPE_ID
|
||||
private var mDialogTheme = 0
|
||||
private var mEventOccurrenceTS = 0
|
||||
private var mEventCalendarId = STORED_LOCALLY_ONLY
|
||||
private var wasActivityInitialized = false
|
||||
|
||||
lateinit var mEventStartDateTime: DateTime
|
||||
lateinit var mEventEndDateTime: DateTime
|
||||
lateinit var mEvent: Event
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_event)
|
||||
|
||||
supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_cross)
|
||||
val intent = intent ?: return
|
||||
mDialogTheme = getDialogTheme()
|
||||
|
||||
val eventId = intent.getIntExtra(EVENT_ID, 0)
|
||||
val event = dbHelper.getEventWithId(eventId)
|
||||
|
||||
if (eventId != 0 && event == null) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
|
||||
if (event != null) {
|
||||
mEvent = event
|
||||
mEventOccurrenceTS = intent.getIntExtra(EVENT_OCCURRENCE_TS, 0)
|
||||
setupEditEvent()
|
||||
} else {
|
||||
mEvent = Event()
|
||||
mReminder1Minutes = config.defaultReminderMinutes
|
||||
mReminder2Minutes = -1
|
||||
mReminder3Minutes = -1
|
||||
val startTS = intent.getIntExtra(NEW_EVENT_START_TS, 0)
|
||||
if (startTS == 0) {
|
||||
return
|
||||
}
|
||||
|
||||
setupNewEvent(Formatter.getDateTimeFromTS(startTS))
|
||||
}
|
||||
|
||||
checkReminderTexts()
|
||||
updateRepetitionText()
|
||||
updateStartTexts()
|
||||
updateEndTexts()
|
||||
updateEventType()
|
||||
updateCalDAVCalendar()
|
||||
updateLocation()
|
||||
|
||||
event_start_date.setOnClickListener { setupStartDate() }
|
||||
event_start_time.setOnClickListener { setupStartTime() }
|
||||
event_end_date.setOnClickListener { setupEndDate() }
|
||||
event_end_time.setOnClickListener { setupEndTime() }
|
||||
|
||||
event_all_day.setOnCheckedChangeListener { compoundButton, isChecked -> toggleAllDay(isChecked) }
|
||||
event_repetition.setOnClickListener { showRepeatIntervalDialog() }
|
||||
event_repetition_rule_holder.setOnClickListener { showRepetitionRuleDialog() }
|
||||
event_repetition_limit_holder.setOnClickListener { showRepetitionTypePicker() }
|
||||
|
||||
event_reminder_1.setOnClickListener { showReminder1Dialog() }
|
||||
event_reminder_2.setOnClickListener { showReminder2Dialog() }
|
||||
event_reminder_3.setOnClickListener { showReminder3Dialog() }
|
||||
|
||||
event_type_holder.setOnClickListener { showEventTypeDialog() }
|
||||
|
||||
if (mEvent.flags and FLAG_ALL_DAY != 0)
|
||||
event_all_day.toggle()
|
||||
|
||||
updateTextColors(event_scrollview)
|
||||
updateIconColors()
|
||||
wasActivityInitialized = true
|
||||
}
|
||||
|
||||
private fun setupEditEvent() {
|
||||
val realStart = if (mEventOccurrenceTS == 0) mEvent.startTS else mEventOccurrenceTS
|
||||
val duration = mEvent.endTS - mEvent.startTS
|
||||
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
|
||||
supportActionBar?.title = resources.getString(R.string.edit_event)
|
||||
mEventStartDateTime = Formatter.getDateTimeFromTS(realStart)
|
||||
mEventEndDateTime = Formatter.getDateTimeFromTS(realStart + duration)
|
||||
event_title.setText(mEvent.title)
|
||||
event_location.setText(mEvent.location)
|
||||
event_description.setText(mEvent.description)
|
||||
event_description.movementMethod = LinkMovementMethod.getInstance()
|
||||
|
||||
mReminder1Minutes = mEvent.reminder1Minutes
|
||||
mReminder2Minutes = mEvent.reminder2Minutes
|
||||
mReminder3Minutes = mEvent.reminder3Minutes
|
||||
mRepeatInterval = mEvent.repeatInterval
|
||||
mRepeatLimit = mEvent.repeatLimit
|
||||
mRepeatRule = mEvent.repeatRule
|
||||
mEventTypeId = mEvent.eventType
|
||||
mEventCalendarId = mEvent.getCalDAVCalendarId()
|
||||
checkRepeatTexts(mRepeatInterval)
|
||||
}
|
||||
|
||||
private fun setupNewEvent(dateTime: DateTime) {
|
||||
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
|
||||
supportActionBar?.title = resources.getString(R.string.new_event)
|
||||
mEventStartDateTime = dateTime
|
||||
|
||||
val addHours = if (intent.getBooleanExtra(NEW_EVENT_SET_HOUR_DURATION, false)) 1 else 0
|
||||
mEventEndDateTime = mEventStartDateTime.plusHours(addHours)
|
||||
|
||||
val isLastCaldavCalendarOK = config.caldavSync && config.getSyncedCalendarIdsAsList().contains(config.lastUsedCaldavCalendar.toString())
|
||||
mEventCalendarId = if (isLastCaldavCalendarOK) config.lastUsedCaldavCalendar else STORED_LOCALLY_ONLY
|
||||
}
|
||||
|
||||
private fun showReminder1Dialog() {
|
||||
showEventReminderDialog(mReminder1Minutes) {
|
||||
mReminder1Minutes = it
|
||||
checkReminderTexts()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showReminder2Dialog() {
|
||||
showEventReminderDialog(mReminder2Minutes) {
|
||||
mReminder2Minutes = it
|
||||
checkReminderTexts()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showReminder3Dialog() {
|
||||
showEventReminderDialog(mReminder3Minutes) {
|
||||
mReminder3Minutes = it
|
||||
checkReminderTexts()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showRepeatIntervalDialog() {
|
||||
showEventRepeatIntervalDialog(mRepeatInterval) {
|
||||
setRepeatInterval(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setRepeatInterval(interval: Int) {
|
||||
mRepeatInterval = interval
|
||||
updateRepetitionText()
|
||||
checkRepeatTexts(interval)
|
||||
|
||||
if (mRepeatInterval.isXWeeklyRepetition()) {
|
||||
setRepeatRule(Math.pow(2.0, (mEventStartDateTime.dayOfWeek - 1).toDouble()).toInt())
|
||||
} else if (mRepeatInterval.isXMonthlyRepetition()) {
|
||||
setRepeatRule(REPEAT_MONTH_SAME_DAY)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkRepeatTexts(limit: Int) {
|
||||
event_repetition_limit_holder.beGoneIf(limit == 0)
|
||||
checkRepetitionLimitText()
|
||||
|
||||
event_repetition_rule_holder.beVisibleIf(mRepeatInterval.isXWeeklyRepetition() || mRepeatInterval.isXMonthlyRepetition())
|
||||
checkRepetitionRuleText()
|
||||
}
|
||||
|
||||
private fun showRepetitionTypePicker() {
|
||||
hideKeyboard()
|
||||
RepeatLimitTypePickerDialog(this, mRepeatLimit, mEventStartDateTime.seconds()) {
|
||||
setRepeatLimit(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setRepeatLimit(limit: Int) {
|
||||
mRepeatLimit = limit
|
||||
checkRepetitionLimitText()
|
||||
}
|
||||
|
||||
private fun checkRepetitionLimitText() {
|
||||
event_repetition_limit.text = when {
|
||||
mRepeatLimit == 0 -> {
|
||||
event_repetition_limit_label.text = getString(R.string.repeat)
|
||||
resources.getString(R.string.forever)
|
||||
}
|
||||
mRepeatLimit > 0 -> {
|
||||
event_repetition_limit_label.text = getString(R.string.repeat_till)
|
||||
val repeatLimitDateTime = Formatter.getDateTimeFromTS(mRepeatLimit)
|
||||
Formatter.getFullDate(applicationContext, repeatLimitDateTime)
|
||||
}
|
||||
else -> {
|
||||
event_repetition_limit_label.text = getString(R.string.repeat)
|
||||
"${-mRepeatLimit} ${getString(R.string.times)}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showRepetitionRuleDialog() {
|
||||
hideKeyboard()
|
||||
if (mRepeatInterval.isXWeeklyRepetition()) {
|
||||
RepeatRuleWeeklyDialog(this, mRepeatRule) {
|
||||
setRepeatRule(it)
|
||||
}
|
||||
} else if (mRepeatInterval.isXMonthlyRepetition()) {
|
||||
val items = arrayListOf(RadioItem(REPEAT_MONTH_SAME_DAY, getString(R.string.repeat_on_the_same_day)))
|
||||
|
||||
// split Every Last Sunday and Every Fourth Sunday of the month, if the month has 4 sundays
|
||||
if (isLastWeekDayOfMonth()) {
|
||||
val order = (mEventStartDateTime.dayOfMonth - 1) / 7 + 1
|
||||
if (order == 4) {
|
||||
items.add(RadioItem(REPEAT_MONTH_ORDER_WEEKDAY, getRepeatXthDayString(true, REPEAT_MONTH_ORDER_WEEKDAY)))
|
||||
items.add(RadioItem(REPEAT_MONTH_ORDER_WEEKDAY_USE_LAST, getRepeatXthDayString(true, REPEAT_MONTH_ORDER_WEEKDAY_USE_LAST)))
|
||||
} else if (order == 5) {
|
||||
items.add(RadioItem(REPEAT_MONTH_ORDER_WEEKDAY_USE_LAST, getRepeatXthDayString(true, REPEAT_MONTH_ORDER_WEEKDAY_USE_LAST)))
|
||||
}
|
||||
} else {
|
||||
items.add(RadioItem(REPEAT_MONTH_ORDER_WEEKDAY, getRepeatXthDayString(true, REPEAT_MONTH_ORDER_WEEKDAY)))
|
||||
}
|
||||
|
||||
if (isLastDayOfTheMonth()) {
|
||||
items.add(RadioItem(REPEAT_MONTH_LAST_DAY, getString(R.string.repeat_on_the_last_day)))
|
||||
}
|
||||
|
||||
RadioGroupDialog(this, items, mRepeatRule) {
|
||||
setRepeatRule(it as Int)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isLastDayOfTheMonth() = mEventStartDateTime.dayOfMonth == mEventStartDateTime.dayOfMonth().withMaximumValue().dayOfMonth
|
||||
|
||||
private fun isLastWeekDayOfMonth() = mEventStartDateTime.monthOfYear != mEventStartDateTime.plusDays(7).monthOfYear
|
||||
|
||||
private fun getRepeatXthDayString(includeBase: Boolean, repeatRule: Int): String {
|
||||
val dayOfWeek = mEventStartDateTime.dayOfWeek
|
||||
val base = getBaseString(dayOfWeek)
|
||||
val order = getOrderString(repeatRule)
|
||||
val dayString = getDayString(dayOfWeek)
|
||||
return if (includeBase) {
|
||||
"$base $order $dayString"
|
||||
} else {
|
||||
val everyString = getString(if (isMaleGender(mEventStartDateTime.dayOfWeek)) R.string.every_m else R.string.every_f)
|
||||
"$everyString $order $dayString"
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBaseString(day: Int): String {
|
||||
return getString(if (isMaleGender(day)) {
|
||||
R.string.repeat_every_m
|
||||
} else {
|
||||
R.string.repeat_every_f
|
||||
})
|
||||
}
|
||||
|
||||
private fun isMaleGender(day: Int) = day == 1 || day == 2 || day == 4 || day == 5
|
||||
|
||||
private fun getOrderString(repeatRule: Int): String {
|
||||
val dayOfMonth = mEventStartDateTime.dayOfMonth
|
||||
var order = (dayOfMonth - 1) / 7 + 1
|
||||
if (order == 4 && isLastWeekDayOfMonth() && repeatRule == REPEAT_MONTH_ORDER_WEEKDAY_USE_LAST) {
|
||||
order = -1
|
||||
}
|
||||
|
||||
val isMale = isMaleGender(mEventStartDateTime.dayOfWeek)
|
||||
return getString(when (order) {
|
||||
1 -> if (isMale) R.string.first_m else R.string.first_f
|
||||
2 -> if (isMale) R.string.second_m else R.string.second_f
|
||||
3 -> if (isMale) R.string.third_m else R.string.third_f
|
||||
4 -> if (isMale) R.string.fourth_m else R.string.fourth_f
|
||||
else -> if (isMale) R.string.last_m else R.string.last_f
|
||||
})
|
||||
}
|
||||
|
||||
private fun getDayString(day: Int): String {
|
||||
return getString(when (day) {
|
||||
1 -> R.string.monday_alt
|
||||
2 -> R.string.tuesday_alt
|
||||
3 -> R.string.wednesday_alt
|
||||
4 -> R.string.thursday_alt
|
||||
5 -> R.string.friday_alt
|
||||
6 -> R.string.saturday_alt
|
||||
else -> R.string.sunday_alt
|
||||
})
|
||||
}
|
||||
|
||||
private fun setRepeatRule(rule: Int) {
|
||||
mRepeatRule = rule
|
||||
checkRepetitionRuleText()
|
||||
if (rule == 0) {
|
||||
setRepeatInterval(0)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkRepetitionRuleText() {
|
||||
if (mRepeatInterval.isXWeeklyRepetition()) {
|
||||
event_repetition_rule.text = if (mRepeatRule == EVERY_DAY) getString(R.string.every_day) else getSelectedDaysString()
|
||||
} else if (mRepeatInterval.isXMonthlyRepetition()) {
|
||||
val repeatString = if (mRepeatRule == REPEAT_MONTH_ORDER_WEEKDAY_USE_LAST || mRepeatRule == REPEAT_MONTH_ORDER_WEEKDAY)
|
||||
R.string.repeat else R.string.repeat_on
|
||||
|
||||
event_repetition_rule_label.text = getString(repeatString)
|
||||
event_repetition_rule.text = getMonthlyRepetitionRuleText()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSelectedDaysString(): String {
|
||||
var days = ""
|
||||
if (mRepeatRule and MONDAY != 0)
|
||||
days += "${getString(R.string.monday).substringTo(3)}, "
|
||||
if (mRepeatRule and TUESDAY != 0)
|
||||
days += "${getString(R.string.tuesday).substringTo(3)}, "
|
||||
if (mRepeatRule and WEDNESDAY != 0)
|
||||
days += "${getString(R.string.wednesday).substringTo(3)}, "
|
||||
if (mRepeatRule and THURSDAY != 0)
|
||||
days += "${getString(R.string.thursday).substringTo(3)}, "
|
||||
if (mRepeatRule and FRIDAY != 0)
|
||||
days += "${getString(R.string.friday).substringTo(3)}, "
|
||||
if (mRepeatRule and SATURDAY != 0)
|
||||
days += "${getString(R.string.saturday).substringTo(3)}, "
|
||||
if (mRepeatRule and SUNDAY != 0)
|
||||
days += "${getString(R.string.sunday).substringTo(3)}, "
|
||||
|
||||
return days.trim().trimEnd(',')
|
||||
}
|
||||
|
||||
private fun getMonthlyRepetitionRuleText() = when (mRepeatRule) {
|
||||
REPEAT_MONTH_SAME_DAY -> getString(R.string.the_same_day)
|
||||
REPEAT_MONTH_LAST_DAY -> getString(R.string.the_last_day)
|
||||
else -> getRepeatXthDayString(false, mRepeatRule)
|
||||
}
|
||||
|
||||
private fun showEventTypeDialog() {
|
||||
hideKeyboard()
|
||||
SelectEventTypeDialog(this, mEventTypeId) {
|
||||
mEventTypeId = it
|
||||
updateEventType()
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkReminderTexts() {
|
||||
updateReminder1Text()
|
||||
updateReminder2Text()
|
||||
updateReminder3Text()
|
||||
}
|
||||
|
||||
private fun updateReminder1Text() {
|
||||
event_reminder_1.text = getFormattedMinutes(mReminder1Minutes)
|
||||
if (mReminder1Minutes == REMINDER_OFF) {
|
||||
mReminder2Minutes = REMINDER_OFF
|
||||
mReminder3Minutes = REMINDER_OFF
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateReminder2Text() {
|
||||
event_reminder_2.apply {
|
||||
beGoneIf(mReminder1Minutes == REMINDER_OFF)
|
||||
if (mReminder2Minutes == REMINDER_OFF) {
|
||||
text = resources.getString(R.string.add_another_reminder)
|
||||
alpha = 0.4f
|
||||
mReminder3Minutes = REMINDER_OFF
|
||||
} else {
|
||||
text = getFormattedMinutes(mReminder2Minutes)
|
||||
alpha = 1f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateReminder3Text() {
|
||||
event_reminder_3.apply {
|
||||
beGoneIf(mReminder2Minutes == REMINDER_OFF || mReminder1Minutes == REMINDER_OFF)
|
||||
if (mReminder3Minutes == REMINDER_OFF) {
|
||||
text = resources.getString(R.string.add_another_reminder)
|
||||
alpha = 0.4f
|
||||
} else {
|
||||
text = getFormattedMinutes(mReminder3Minutes)
|
||||
alpha = 1f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateRepetitionText() {
|
||||
event_repetition.text = getRepetitionText(mRepeatInterval)
|
||||
}
|
||||
|
||||
private fun updateEventType() {
|
||||
val eventType = dbHelper.getEventType(mEventTypeId)
|
||||
if (eventType != null) {
|
||||
event_type.text = eventType.title
|
||||
event_type_color.setBackgroundWithStroke(eventType.color, config.backgroundColor)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateCalDAVCalendar() {
|
||||
if (config.caldavSync) {
|
||||
event_caldav_calendar_image.beVisible()
|
||||
event_caldav_calendar_holder.beVisible()
|
||||
event_caldav_calendar_divider.beVisible()
|
||||
|
||||
val calendars = CalDAVHandler(applicationContext).getCalDAVCalendars().filter {
|
||||
it.canWrite() && config.getSyncedCalendarIdsAsList().contains(it.id.toString())
|
||||
}
|
||||
updateCurrentCalendarInfo(if (mEventCalendarId == STORED_LOCALLY_ONLY) null else getCalendarWithId(calendars, getCalendarId()))
|
||||
|
||||
event_caldav_calendar_holder.setOnClickListener {
|
||||
hideKeyboard()
|
||||
SelectEventCalendarDialog(this, calendars, mEventCalendarId) {
|
||||
if (mEventCalendarId != STORED_LOCALLY_ONLY && it == STORED_LOCALLY_ONLY) {
|
||||
mEventTypeId = DBHelper.REGULAR_EVENT_TYPE_ID
|
||||
updateEventType()
|
||||
}
|
||||
mEventCalendarId = it
|
||||
config.lastUsedCaldavCalendar = it
|
||||
updateCurrentCalendarInfo(getCalendarWithId(calendars, it))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
updateCurrentCalendarInfo(null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCalendarId() = if (mEvent.source == SOURCE_SIMPLE_CALENDAR) config.lastUsedCaldavCalendar else mEvent.getCalDAVCalendarId()
|
||||
|
||||
private fun getCalendarWithId(calendars: List<CalDAVCalendar>, calendarId: Int): CalDAVCalendar? =
|
||||
calendars.firstOrNull { it.id == calendarId }
|
||||
|
||||
private fun updateCurrentCalendarInfo(currentCalendar: CalDAVCalendar?) {
|
||||
event_type_image.beVisibleIf(currentCalendar == null)
|
||||
event_type_holder.beVisibleIf(currentCalendar == null)
|
||||
event_caldav_calendar_divider.beVisibleIf(currentCalendar == null)
|
||||
event_caldav_calendar_email.beGoneIf(currentCalendar == null)
|
||||
|
||||
if (currentCalendar == null) {
|
||||
event_caldav_calendar_name.apply {
|
||||
text = getString(R.string.store_locally_only)
|
||||
setPadding(paddingLeft, paddingTop, paddingRight, resources.getDimension(R.dimen.medium_margin).toInt())
|
||||
}
|
||||
} else {
|
||||
event_caldav_calendar_email.text = currentCalendar.accountName
|
||||
event_caldav_calendar_name.apply {
|
||||
text = currentCalendar.displayName
|
||||
setPadding(paddingLeft, paddingTop, paddingRight, resources.getDimension(R.dimen.tiny_margin).toInt())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateLocation() {
|
||||
event_location.setText(mEvent.location)
|
||||
}
|
||||
|
||||
private fun toggleAllDay(isChecked: Boolean) {
|
||||
hideKeyboard()
|
||||
event_start_time.beGoneIf(isChecked)
|
||||
event_end_time.beGoneIf(isChecked)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_event, menu)
|
||||
if (wasActivityInitialized) {
|
||||
menu.findItem(R.id.delete).isVisible = mEvent.id != 0
|
||||
menu.findItem(R.id.share).isVisible = mEvent.id != 0
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.save -> saveEvent()
|
||||
R.id.delete -> deleteEvent()
|
||||
R.id.share -> shareEvent()
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun shareEvent() {
|
||||
shareEvents(arrayListOf(mEvent.id))
|
||||
}
|
||||
|
||||
private fun deleteEvent() {
|
||||
DeleteEventDialog(this, arrayListOf(mEvent.id)) {
|
||||
if (it) {
|
||||
dbHelper.deleteEvents(arrayOf(mEvent.id.toString()), true)
|
||||
} else {
|
||||
dbHelper.addEventRepeatException(mEvent.id, mEventOccurrenceTS)
|
||||
}
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveEvent() {
|
||||
val newTitle = event_title.value
|
||||
if (newTitle.isEmpty()) {
|
||||
toast(R.string.title_empty)
|
||||
event_title.requestFocus()
|
||||
return
|
||||
}
|
||||
|
||||
val newStartTS = mEventStartDateTime.withSecondOfMinute(0).withMillisOfSecond(0).seconds()
|
||||
val newEndTS = mEventEndDateTime.withSecondOfMinute(0).withMillisOfSecond(0).seconds()
|
||||
|
||||
if (newStartTS > newEndTS) {
|
||||
toast(R.string.end_before_start)
|
||||
return
|
||||
}
|
||||
|
||||
val wasRepeatable = mEvent.repeatInterval > 0
|
||||
val oldSource = mEvent.source
|
||||
val newImportId = if (mEvent.id != 0) mEvent.importId else UUID.randomUUID().toString().replace("-", "") + System.currentTimeMillis().toString()
|
||||
|
||||
val newEventType = if (!config.caldavSync || config.lastUsedCaldavCalendar == 0 || mEventCalendarId == STORED_LOCALLY_ONLY) {
|
||||
mEventTypeId
|
||||
} else {
|
||||
dbHelper.getEventTypeWithCalDAVCalendarId(config.lastUsedCaldavCalendar)?.id ?: DBHelper.REGULAR_EVENT_TYPE_ID
|
||||
}
|
||||
|
||||
val newSource = if (!config.caldavSync || config.lastUsedCaldavCalendar == 0 || mEventCalendarId == STORED_LOCALLY_ONLY) {
|
||||
SOURCE_SIMPLE_CALENDAR
|
||||
} else {
|
||||
"$CALDAV-${config.lastUsedCaldavCalendar}"
|
||||
}
|
||||
|
||||
val reminders = sortedSetOf(mReminder1Minutes, mReminder2Minutes, mReminder3Minutes).filter { it != REMINDER_OFF }
|
||||
mEvent.apply {
|
||||
startTS = newStartTS
|
||||
endTS = newEndTS
|
||||
title = newTitle
|
||||
description = event_description.value
|
||||
reminder1Minutes = reminders.elementAtOrElse(0) { REMINDER_OFF }
|
||||
reminder2Minutes = reminders.elementAtOrElse(1) { REMINDER_OFF }
|
||||
reminder3Minutes = reminders.elementAtOrElse(2) { REMINDER_OFF }
|
||||
repeatInterval = mRepeatInterval
|
||||
importId = newImportId
|
||||
flags = if (event_all_day.isChecked) (mEvent.flags or FLAG_ALL_DAY) else (mEvent.flags.removeFlag(FLAG_ALL_DAY))
|
||||
repeatLimit = if (repeatInterval == 0) 0 else mRepeatLimit
|
||||
repeatRule = mRepeatRule
|
||||
eventType = newEventType
|
||||
offset = getCurrentOffset()
|
||||
isDstIncluded = TimeZone.getDefault().inDaylightTime(Date())
|
||||
lastUpdated = System.currentTimeMillis()
|
||||
source = newSource
|
||||
location = event_location.value
|
||||
}
|
||||
|
||||
// recreate the event if it was moved in a different CalDAV calendar
|
||||
if (mEvent.id != 0 && oldSource != newSource) {
|
||||
dbHelper.deleteEvents(arrayOf(mEvent.id.toString()), true)
|
||||
mEvent.id = 0
|
||||
}
|
||||
|
||||
storeEvent(wasRepeatable)
|
||||
}
|
||||
|
||||
private fun storeEvent(wasRepeatable: Boolean) {
|
||||
if (mEvent.id == 0) {
|
||||
dbHelper.insert(mEvent, true) {
|
||||
if (DateTime.now().isAfter(mEventStartDateTime.millis)) {
|
||||
if (mEvent.getReminders().isNotEmpty()) {
|
||||
notifyEvent(mEvent)
|
||||
}
|
||||
} else {
|
||||
toast(R.string.event_added)
|
||||
}
|
||||
|
||||
finish()
|
||||
}
|
||||
} else {
|
||||
if (mRepeatInterval > 0 && wasRepeatable) {
|
||||
EditRepeatingEventDialog(this) {
|
||||
if (it) {
|
||||
dbHelper.update(mEvent, true) {
|
||||
eventUpdated()
|
||||
}
|
||||
} else {
|
||||
dbHelper.addEventRepeatException(mEvent.id, mEventOccurrenceTS)
|
||||
mEvent.parentId = mEvent.id
|
||||
mEvent.id = 0
|
||||
dbHelper.insert(mEvent, true) {
|
||||
toast(R.string.event_updated)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dbHelper.update(mEvent, true) {
|
||||
eventUpdated()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun eventUpdated() {
|
||||
toast(R.string.event_updated)
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun updateStartTexts() {
|
||||
updateStartDateText()
|
||||
updateStartTimeText()
|
||||
}
|
||||
|
||||
private fun updateStartDateText() {
|
||||
event_start_date.text = Formatter.getDate(applicationContext, mEventStartDateTime)
|
||||
checkStartEndValidity()
|
||||
}
|
||||
|
||||
private fun updateStartTimeText() {
|
||||
event_start_time.text = Formatter.getTime(this, mEventStartDateTime)
|
||||
checkStartEndValidity()
|
||||
}
|
||||
|
||||
private fun updateEndTexts() {
|
||||
updateEndDateText()
|
||||
updateEndTimeText()
|
||||
}
|
||||
|
||||
private fun updateEndDateText() {
|
||||
event_end_date.text = Formatter.getDate(applicationContext, mEventEndDateTime)
|
||||
checkStartEndValidity()
|
||||
}
|
||||
|
||||
private fun updateEndTimeText() {
|
||||
event_end_time.text = Formatter.getTime(this, mEventEndDateTime)
|
||||
checkStartEndValidity()
|
||||
}
|
||||
|
||||
private fun checkStartEndValidity() {
|
||||
val textColor = if (mEventStartDateTime.isAfter(mEventEndDateTime)) resources.getColor(R.color.red_text) else config.textColor
|
||||
event_end_date.setTextColor(textColor)
|
||||
event_end_time.setTextColor(textColor)
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private fun setupStartDate() {
|
||||
hideKeyboard()
|
||||
config.backgroundColor.getContrastColor()
|
||||
val datepicker = DatePickerDialog(this, mDialogTheme, startDateSetListener, mEventStartDateTime.year, mEventStartDateTime.monthOfYear - 1,
|
||||
mEventStartDateTime.dayOfMonth)
|
||||
|
||||
if (isLollipopPlus()) {
|
||||
datepicker.datePicker.firstDayOfWeek = if (config.isSundayFirst) Calendar.SUNDAY else Calendar.MONDAY
|
||||
}
|
||||
|
||||
datepicker.show()
|
||||
}
|
||||
|
||||
private fun setupStartTime() {
|
||||
hideKeyboard()
|
||||
TimePickerDialog(this, mDialogTheme, startTimeSetListener, mEventStartDateTime.hourOfDay, mEventStartDateTime.minuteOfHour, config.use24hourFormat).show()
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private fun setupEndDate() {
|
||||
hideKeyboard()
|
||||
val datepicker = DatePickerDialog(this, mDialogTheme, endDateSetListener, mEventEndDateTime.year, mEventEndDateTime.monthOfYear - 1,
|
||||
mEventEndDateTime.dayOfMonth)
|
||||
|
||||
if (isLollipopPlus()) {
|
||||
datepicker.datePicker.firstDayOfWeek = if (config.isSundayFirst) Calendar.SUNDAY else Calendar.MONDAY
|
||||
}
|
||||
|
||||
datepicker.show()
|
||||
}
|
||||
|
||||
private fun setupEndTime() {
|
||||
hideKeyboard()
|
||||
TimePickerDialog(this, mDialogTheme, endTimeSetListener, mEventEndDateTime.hourOfDay, mEventEndDateTime.minuteOfHour, config.use24hourFormat).show()
|
||||
}
|
||||
|
||||
private val startDateSetListener = DatePickerDialog.OnDateSetListener { view, year, monthOfYear, dayOfMonth ->
|
||||
dateSet(year, monthOfYear, dayOfMonth, true)
|
||||
}
|
||||
|
||||
private val startTimeSetListener = TimePickerDialog.OnTimeSetListener { view, hourOfDay, minute ->
|
||||
timeSet(hourOfDay, minute, true)
|
||||
}
|
||||
|
||||
private val endDateSetListener = DatePickerDialog.OnDateSetListener { view, year, monthOfYear, dayOfMonth -> dateSet(year, monthOfYear, dayOfMonth, false) }
|
||||
|
||||
private val endTimeSetListener = TimePickerDialog.OnTimeSetListener { view, hourOfDay, minute -> timeSet(hourOfDay, minute, false) }
|
||||
|
||||
private fun dateSet(year: Int, month: Int, day: Int, isStart: Boolean) {
|
||||
if (isStart) {
|
||||
val diff = mEventEndDateTime.seconds() - mEventStartDateTime.seconds()
|
||||
|
||||
mEventStartDateTime = mEventStartDateTime.withDate(year, month + 1, day)
|
||||
updateStartDateText()
|
||||
checkRepeatRule()
|
||||
|
||||
mEventEndDateTime = mEventStartDateTime.plusSeconds(diff)
|
||||
updateEndTexts()
|
||||
} else {
|
||||
mEventEndDateTime = mEventEndDateTime.withDate(year, month + 1, day)
|
||||
updateEndDateText()
|
||||
}
|
||||
}
|
||||
|
||||
private fun timeSet(hours: Int, minutes: Int, isStart: Boolean) {
|
||||
if (isStart) {
|
||||
val diff = mEventEndDateTime.seconds() - mEventStartDateTime.seconds()
|
||||
|
||||
mEventStartDateTime = mEventStartDateTime.withHourOfDay(hours).withMinuteOfHour(minutes)
|
||||
updateStartTimeText()
|
||||
|
||||
mEventEndDateTime = mEventStartDateTime.plusSeconds(diff)
|
||||
updateEndTexts()
|
||||
} else {
|
||||
mEventEndDateTime = mEventEndDateTime.withHourOfDay(hours).withMinuteOfHour(minutes)
|
||||
updateEndTimeText()
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkRepeatRule() {
|
||||
if (mRepeatInterval.isXWeeklyRepetition()) {
|
||||
val day = mRepeatRule
|
||||
if (day == MONDAY || day == TUESDAY || day == WEDNESDAY || day == THURSDAY || day == FRIDAY || day == SATURDAY || day == SUNDAY) {
|
||||
setRepeatRule(Math.pow(2.0, (mEventStartDateTime.dayOfWeek - 1).toDouble()).toInt())
|
||||
}
|
||||
} else if (mRepeatInterval.isXMonthlyRepetition()) {
|
||||
if (mRepeatRule == REPEAT_MONTH_LAST_DAY && !isLastDayOfTheMonth())
|
||||
mRepeatRule = REPEAT_MONTH_SAME_DAY
|
||||
checkRepetitionRuleText()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateIconColors() {
|
||||
val textColor = config.textColor
|
||||
event_time_image.applyColorFilter(textColor)
|
||||
event_repetition_image.applyColorFilter(textColor)
|
||||
event_reminder_image.applyColorFilter(textColor)
|
||||
event_type_image.applyColorFilter(textColor)
|
||||
event_caldav_calendar_image.applyColorFilter(textColor)
|
||||
}
|
||||
}
|
|
@ -1,832 +0,0 @@
|
|||
package com.simplemobiletools.calendar.activities
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.content.Intent
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.database.ContentObserver
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.provider.CalendarContract
|
||||
import android.provider.ContactsContract
|
||||
import android.support.v4.view.ViewPager
|
||||
import android.util.SparseIntArray
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import com.simplemobiletools.calendar.BuildConfig
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.adapters.MyMonthPagerAdapter
|
||||
import com.simplemobiletools.calendar.adapters.MyWeekPagerAdapter
|
||||
import com.simplemobiletools.calendar.adapters.MyYearPagerAdapter
|
||||
import com.simplemobiletools.calendar.dialogs.ExportEventsDialog
|
||||
import com.simplemobiletools.calendar.dialogs.FilterEventTypesDialog
|
||||
import com.simplemobiletools.calendar.dialogs.ImportEventsDialog
|
||||
import com.simplemobiletools.calendar.extensions.*
|
||||
import com.simplemobiletools.calendar.fragments.EventListFragment
|
||||
import com.simplemobiletools.calendar.fragments.WeekFragment
|
||||
import com.simplemobiletools.calendar.helpers.*
|
||||
import com.simplemobiletools.calendar.helpers.Formatter
|
||||
import com.simplemobiletools.calendar.interfaces.NavigationListener
|
||||
import com.simplemobiletools.calendar.models.Event
|
||||
import com.simplemobiletools.calendar.models.EventType
|
||||
import com.simplemobiletools.calendar.views.MyScrollView
|
||||
import com.simplemobiletools.commons.dialogs.FilePickerDialog
|
||||
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.models.Release
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import org.joda.time.DateTime
|
||||
import java.io.FileOutputStream
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class MainActivity : SimpleActivity(), NavigationListener {
|
||||
private val CALDAV_SYNC_DELAY = 2000L
|
||||
private val PREFILLED_MONTHS = 97
|
||||
private val PREFILLED_YEARS = 31
|
||||
private val PREFILLED_WEEKS = 61
|
||||
|
||||
private var mIsMonthSelected = false
|
||||
private var mStoredUseEnglish = false
|
||||
private var mStoredTextColor = 0
|
||||
private var mStoredBackgroundColor = 0
|
||||
private var mStoredPrimaryColor = 0
|
||||
private var mStoredDayCode = ""
|
||||
private var mStoredIsSundayFirst = false
|
||||
private var mStoredUse24HourFormat = false
|
||||
private var mShouldFilterBeVisible = false
|
||||
private var mCalDAVSyncHandler = Handler()
|
||||
|
||||
private var mDefaultWeeklyPage = 0
|
||||
private var mDefaultMonthlyPage = 0
|
||||
private var mDefaultYearlyPage = 0
|
||||
|
||||
companion object {
|
||||
var mWeekScrollY = 0
|
||||
var eventTypeColors = SparseIntArray()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
appLaunched()
|
||||
calendar_fab.setOnClickListener { launchNewEventIntent() }
|
||||
checkWhatsNewDialog()
|
||||
|
||||
if (resources.getBoolean(R.bool.portrait_only))
|
||||
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||
|
||||
if (intent?.action == Intent.ACTION_VIEW && intent.data != null) {
|
||||
val uri = intent.data
|
||||
if (uri.authority == "com.android.calendar") {
|
||||
// clicking date on a third party widget: content://com.android.calendar/time/1507309245683
|
||||
if (intent?.extras?.getBoolean("DETAIL_VIEW", false) == true) {
|
||||
val timestamp = uri.pathSegments.last()
|
||||
if (timestamp.areDigitsOnly()) {
|
||||
openDayAt(timestamp.toLong())
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tryImportEventsFromFile(uri)
|
||||
}
|
||||
}
|
||||
|
||||
storeStateVariables()
|
||||
updateViewPager()
|
||||
|
||||
if (!hasPermission(PERMISSION_WRITE_CALENDAR) || !hasPermission(PERMISSION_READ_CALENDAR)) {
|
||||
config.caldavSync = false
|
||||
}
|
||||
|
||||
recheckCalDAVCalendars {}
|
||||
|
||||
if (config.googleSync) {
|
||||
val ids = dbHelper.getGoogleSyncEvents().map { it.id.toString() }.toTypedArray()
|
||||
dbHelper.deleteEvents(ids, false)
|
||||
config.googleSync = false
|
||||
}
|
||||
|
||||
checkOpenIntents()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (mStoredUseEnglish != config.useEnglish) {
|
||||
restartActivity()
|
||||
return
|
||||
}
|
||||
|
||||
if (mStoredTextColor != config.textColor || mStoredBackgroundColor != config.backgroundColor || mStoredPrimaryColor != config.primaryColor
|
||||
|| mStoredDayCode != Formatter.getTodayCode()) {
|
||||
updateViewPager()
|
||||
}
|
||||
|
||||
dbHelper.getEventTypes {
|
||||
eventTypeColors.clear()
|
||||
it.map { eventTypeColors.put(it.id, it.color) }
|
||||
mShouldFilterBeVisible = eventTypeColors.size() > 1 || config.displayEventTypes.isEmpty()
|
||||
invalidateOptionsMenu()
|
||||
}
|
||||
|
||||
storeStateVariables()
|
||||
if (config.storedView == WEEKLY_VIEW) {
|
||||
if (mStoredIsSundayFirst != config.isSundayFirst || mStoredUse24HourFormat != config.use24hourFormat) {
|
||||
fillWeeklyViewPager()
|
||||
}
|
||||
}
|
||||
|
||||
updateWidgets()
|
||||
updateTextColors(calendar_coordinator)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
storeStateVariables()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mCalDAVSyncHandler.removeCallbacksAndMessages(null)
|
||||
contentResolver.unregisterContentObserver(calDAVSyncObserver)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_main, menu)
|
||||
menu.apply {
|
||||
findItem(R.id.filter).isVisible = mShouldFilterBeVisible
|
||||
findItem(R.id.go_to_today).isVisible = shouldGoToTodayBeVisible()
|
||||
findItem(R.id.refresh_caldav_calendars).isVisible = config.caldavSync
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.change_view -> showViewDialog()
|
||||
R.id.go_to_today -> goToToday()
|
||||
R.id.filter -> showFilterDialog()
|
||||
R.id.refresh_caldav_calendars -> refreshCalDAVCalendars()
|
||||
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.settings -> launchSettings()
|
||||
R.id.about -> launchAbout()
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (mIsMonthSelected && config.storedView == YEARLY_VIEW) {
|
||||
updateView(YEARLY_VIEW)
|
||||
} else {
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
private fun storeStateVariables() {
|
||||
config.apply {
|
||||
mStoredUseEnglish = useEnglish
|
||||
mStoredIsSundayFirst = isSundayFirst
|
||||
mStoredTextColor = textColor
|
||||
mStoredPrimaryColor = primaryColor
|
||||
mStoredBackgroundColor = backgroundColor
|
||||
mStoredUse24HourFormat = use24hourFormat
|
||||
}
|
||||
mStoredDayCode = Formatter.getTodayCode()
|
||||
}
|
||||
|
||||
private fun checkOpenIntents() {
|
||||
val dayCodeToOpen = intent.getStringExtra(DAY_CODE) ?: ""
|
||||
if (dayCodeToOpen.isNotEmpty()) {
|
||||
openDayCode(dayCodeToOpen)
|
||||
}
|
||||
|
||||
val eventIdToOpen = intent.getIntExtra(EVENT_ID, 0)
|
||||
val eventOccurrenceToOpen = intent.getIntExtra(EVENT_OCCURRENCE_TS, 0)
|
||||
if (eventIdToOpen != 0 && eventOccurrenceToOpen != 0) {
|
||||
Intent(this, EventActivity::class.java).apply {
|
||||
putExtra(EVENT_ID, eventIdToOpen)
|
||||
putExtra(EVENT_OCCURRENCE_TS, eventOccurrenceToOpen)
|
||||
startActivity(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showViewDialog() {
|
||||
val res = resources
|
||||
val items = arrayListOf(
|
||||
RadioItem(WEEKLY_VIEW, res.getString(R.string.weekly_view)),
|
||||
RadioItem(MONTHLY_VIEW, res.getString(R.string.monthly_view)),
|
||||
RadioItem(YEARLY_VIEW, res.getString(R.string.yearly_view)),
|
||||
RadioItem(EVENTS_LIST_VIEW, res.getString(R.string.simple_event_list)))
|
||||
|
||||
RadioGroupDialog(this, items, config.storedView) {
|
||||
updateView(it as Int)
|
||||
invalidateOptionsMenu()
|
||||
}
|
||||
}
|
||||
|
||||
private fun goToToday() {
|
||||
if (config.storedView == WEEKLY_VIEW) {
|
||||
week_view_view_pager.currentItem = mDefaultWeeklyPage
|
||||
} else if (config.storedView == MONTHLY_VIEW) {
|
||||
main_view_pager.currentItem = mDefaultMonthlyPage
|
||||
} else if (config.storedView == YEARLY_VIEW) {
|
||||
if (mIsMonthSelected) {
|
||||
openMonthlyToday()
|
||||
} else {
|
||||
main_view_pager.currentItem = mDefaultYearlyPage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun shouldGoToTodayBeVisible() = when {
|
||||
config.storedView == WEEKLY_VIEW -> week_view_view_pager.currentItem != mDefaultWeeklyPage
|
||||
config.storedView == MONTHLY_VIEW -> main_view_pager.currentItem != mDefaultMonthlyPage
|
||||
config.storedView == YEARLY_VIEW -> main_view_pager.currentItem != mDefaultYearlyPage
|
||||
else -> false
|
||||
}
|
||||
|
||||
private fun showFilterDialog() {
|
||||
FilterEventTypesDialog(this) {
|
||||
refreshViewPager()
|
||||
}
|
||||
}
|
||||
|
||||
private fun refreshCalDAVCalendars() {
|
||||
toast(R.string.refreshing)
|
||||
val uri = CalendarContract.Calendars.CONTENT_URI
|
||||
contentResolver.registerContentObserver(uri, false, calDAVSyncObserver)
|
||||
Bundle().apply {
|
||||
putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true)
|
||||
putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true)
|
||||
ContentResolver.requestSync(null, uri.authority, this)
|
||||
}
|
||||
scheduleCalDAVSync(true)
|
||||
}
|
||||
|
||||
private val calDAVSyncObserver = object : ContentObserver(Handler()) {
|
||||
override fun onChange(selfChange: Boolean) {
|
||||
super.onChange(selfChange)
|
||||
if (!selfChange) {
|
||||
mCalDAVSyncHandler.removeCallbacksAndMessages(null)
|
||||
mCalDAVSyncHandler.postDelayed({
|
||||
recheckCalDAVCalendars {
|
||||
refreshViewPager()
|
||||
toast(R.string.refreshing_complete)
|
||||
}
|
||||
}, CALDAV_SYNC_DELAY)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addHolidays() {
|
||||
val items = getHolidayRadioItems()
|
||||
RadioGroupDialog(this, items) {
|
||||
toast(R.string.importing)
|
||||
Thread {
|
||||
val holidays = getString(R.string.holidays)
|
||||
var eventTypeId = dbHelper.getEventTypeIdWithTitle(holidays)
|
||||
if (eventTypeId == -1) {
|
||||
val eventType = EventType(0, holidays, resources.getColor(R.color.default_holidays_color))
|
||||
eventTypeId = dbHelper.insertEventType(eventType)
|
||||
}
|
||||
val result = IcsImporter(this).importEvents(it as String, eventTypeId)
|
||||
handleParseResult(result)
|
||||
if (result != IcsImporter.ImportResult.IMPORT_FAIL) {
|
||||
runOnUiThread {
|
||||
updateViewPager()
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryAddBirthdays() {
|
||||
handlePermission(PERMISSION_READ_CONTACTS) {
|
||||
if (it) {
|
||||
Thread {
|
||||
addContactEvents(true) {
|
||||
if (it > 0) {
|
||||
toast(R.string.birthdays_added)
|
||||
updateViewPager()
|
||||
} else {
|
||||
toast(R.string.no_birthdays)
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
} else {
|
||||
toast(R.string.no_contacts_permission)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryAddAnniversaries() {
|
||||
handlePermission(PERMISSION_READ_CONTACTS) {
|
||||
if (it) {
|
||||
Thread {
|
||||
addContactEvents(false) {
|
||||
if (it > 0) {
|
||||
toast(R.string.anniversaries_added)
|
||||
updateViewPager()
|
||||
} else {
|
||||
toast(R.string.no_anniversaries)
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
} else {
|
||||
toast(R.string.no_contacts_permission)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleParseResult(result: IcsImporter.ImportResult) {
|
||||
toast(when (result) {
|
||||
IcsImporter.ImportResult.IMPORT_OK -> R.string.holidays_imported_successfully
|
||||
IcsImporter.ImportResult.IMPORT_PARTIAL -> R.string.importing_some_holidays_failed
|
||||
else -> R.string.importing_holidays_failed
|
||||
}, Toast.LENGTH_LONG)
|
||||
}
|
||||
|
||||
private fun addContactEvents(birthdays: Boolean, callback: (Int) -> Unit) {
|
||||
var eventsAdded = 0
|
||||
val uri = ContactsContract.Data.CONTENT_URI
|
||||
val projection = arrayOf(ContactsContract.Contacts.DISPLAY_NAME,
|
||||
ContactsContract.CommonDataKinds.Event.CONTACT_ID,
|
||||
ContactsContract.CommonDataKinds.Event.CONTACT_LAST_UPDATED_TIMESTAMP,
|
||||
ContactsContract.CommonDataKinds.Event.START_DATE)
|
||||
|
||||
val selection = "${ContactsContract.Data.MIMETYPE} = ? AND ${ContactsContract.CommonDataKinds.Event.TYPE} = ?"
|
||||
val type = if (birthdays) ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY else ContactsContract.CommonDataKinds.Event.TYPE_ANNIVERSARY
|
||||
val selectionArgs = arrayOf(ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE, type.toString())
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = contentResolver.query(uri, projection, selection, selectionArgs, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
val dateFormats = getDateFormats()
|
||||
val existingEvents = if (birthdays) dbHelper.getBirthdays() else dbHelper.getAnniversaries()
|
||||
val importIDs = existingEvents.map { it.importId }
|
||||
val eventTypeId = if (birthdays) getBirthdaysEventTypeId() else getAnniversariesEventTypeId()
|
||||
|
||||
do {
|
||||
val contactId = cursor.getIntValue(ContactsContract.CommonDataKinds.Event.CONTACT_ID).toString()
|
||||
val name = cursor.getStringValue(ContactsContract.Contacts.DISPLAY_NAME)
|
||||
val startDate = cursor.getStringValue(ContactsContract.CommonDataKinds.Event.START_DATE)
|
||||
|
||||
for (format in dateFormats) {
|
||||
try {
|
||||
val formatter = SimpleDateFormat(format, Locale.getDefault())
|
||||
val date = formatter.parse(startDate)
|
||||
if (date.year < 70)
|
||||
date.year = 70
|
||||
|
||||
val timestamp = (date.time / 1000).toInt()
|
||||
val source = if (birthdays) SOURCE_CONTACT_BIRTHDAY else SOURCE_CONTACT_ANNIVERSARY
|
||||
val lastUpdated = cursor.getLongValue(ContactsContract.CommonDataKinds.Event.CONTACT_LAST_UPDATED_TIMESTAMP)
|
||||
val event = Event(0, timestamp, timestamp, name, importId = contactId, flags = FLAG_ALL_DAY, repeatInterval = YEAR,
|
||||
eventType = eventTypeId, source = source, lastUpdated = lastUpdated)
|
||||
|
||||
if (!importIDs.contains(contactId)) {
|
||||
dbHelper.insert(event, false) {
|
||||
eventsAdded++
|
||||
}
|
||||
}
|
||||
break
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
}
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
|
||||
runOnUiThread {
|
||||
callback(eventsAdded)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBirthdaysEventTypeId(): Int {
|
||||
val birthdays = getString(R.string.birthdays)
|
||||
var eventTypeId = dbHelper.getEventTypeIdWithTitle(birthdays)
|
||||
if (eventTypeId == -1) {
|
||||
val eventType = EventType(0, birthdays, resources.getColor(R.color.default_birthdays_color))
|
||||
eventTypeId = dbHelper.insertEventType(eventType)
|
||||
}
|
||||
return eventTypeId
|
||||
}
|
||||
|
||||
private fun getAnniversariesEventTypeId(): Int {
|
||||
val anniversaries = getString(R.string.anniversaries)
|
||||
var eventTypeId = dbHelper.getEventTypeIdWithTitle(anniversaries)
|
||||
if (eventTypeId == -1) {
|
||||
val eventType = EventType(0, anniversaries, resources.getColor(R.color.default_anniversaries_color))
|
||||
eventTypeId = dbHelper.insertEventType(eventType)
|
||||
}
|
||||
return eventTypeId
|
||||
}
|
||||
|
||||
private fun updateView(view: Int) {
|
||||
calendar_fab.beGoneIf(view == YEARLY_VIEW)
|
||||
mIsMonthSelected = view == MONTHLY_VIEW
|
||||
config.storedView = view
|
||||
updateViewPager()
|
||||
}
|
||||
|
||||
private fun updateViewPager() {
|
||||
resetTitle()
|
||||
when {
|
||||
config.storedView == YEARLY_VIEW -> fillYearlyViewPager()
|
||||
config.storedView == EVENTS_LIST_VIEW -> fillEventsList()
|
||||
config.storedView == WEEKLY_VIEW -> fillWeeklyViewPager()
|
||||
else -> openMonthlyToday()
|
||||
}
|
||||
|
||||
mWeekScrollY = 0
|
||||
}
|
||||
|
||||
private fun openMonthlyToday() {
|
||||
val targetDay = DateTime().toString(Formatter.DAYCODE_PATTERN)
|
||||
fillMonthlyViewPager(targetDay)
|
||||
}
|
||||
|
||||
private fun refreshViewPager() {
|
||||
when {
|
||||
config.storedView == YEARLY_VIEW && !mIsMonthSelected -> (main_view_pager.adapter as? MyYearPagerAdapter)?.refreshEvents(main_view_pager.currentItem)
|
||||
config.storedView == EVENTS_LIST_VIEW -> fillEventsList()
|
||||
config.storedView == WEEKLY_VIEW -> (week_view_view_pager.adapter as? MyWeekPagerAdapter)?.refreshEvents(week_view_view_pager.currentItem)
|
||||
else -> (main_view_pager.adapter as? MyMonthPagerAdapter)?.refreshEvents(main_view_pager.currentItem)
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryImportEvents() {
|
||||
handlePermission(PERMISSION_READ_STORAGE) {
|
||||
if (it) {
|
||||
importEvents()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun importEvents() {
|
||||
FilePickerDialog(this) {
|
||||
importEventsDialog(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryImportEventsFromFile(uri: Uri) {
|
||||
when {
|
||||
uri.scheme == "file" -> importEventsDialog(uri.path)
|
||||
uri.scheme == "content" -> {
|
||||
val tempFile = getTempFile()
|
||||
if (tempFile == null) {
|
||||
toast(R.string.unknown_error_occurred)
|
||||
return
|
||||
}
|
||||
|
||||
val inputStream = contentResolver.openInputStream(uri)
|
||||
val out = FileOutputStream(tempFile)
|
||||
inputStream.copyTo(out)
|
||||
importEventsDialog(tempFile.absolutePath)
|
||||
}
|
||||
else -> toast(R.string.invalid_file_format)
|
||||
}
|
||||
}
|
||||
|
||||
private fun importEventsDialog(path: String) {
|
||||
ImportEventsDialog(this, path) {
|
||||
if (it) {
|
||||
runOnUiThread {
|
||||
updateViewPager()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryExportEvents() {
|
||||
handlePermission(PERMISSION_WRITE_STORAGE) {
|
||||
if (it) {
|
||||
exportEvents()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun exportEvents() {
|
||||
FilePickerDialog(this, pickFile = false, showFAB = true) {
|
||||
val path = it
|
||||
ExportEventsDialog(this, path) { exportPastEvents, file, eventTypes ->
|
||||
Thread {
|
||||
val events = dbHelper.getEventsToExport(exportPastEvents).filter { eventTypes.contains(it.eventType.toString()) }
|
||||
if (events.isEmpty()) {
|
||||
toast(R.string.no_events_for_exporting)
|
||||
} else {
|
||||
toast(R.string.exporting)
|
||||
IcsExporter().exportEvents(this, file, events as ArrayList<Event>) {
|
||||
toast(when (it) {
|
||||
IcsExporter.ExportResult.EXPORT_OK -> R.string.events_exported_successfully
|
||||
IcsExporter.ExportResult.EXPORT_PARTIAL -> R.string.exporting_some_events_failed
|
||||
else -> R.string.exporting_events_failed
|
||||
})
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun launchSettings() {
|
||||
startActivity(Intent(applicationContext, SettingsActivity::class.java))
|
||||
}
|
||||
|
||||
private fun launchAbout() {
|
||||
startAboutActivity(R.string.app_name, LICENSE_KOTLIN or LICENSE_JODA or LICENSE_STETHO or LICENSE_MULTISELECT or LICENSE_GSON or
|
||||
LICENSE_LEAK_CANARY, BuildConfig.VERSION_NAME)
|
||||
}
|
||||
|
||||
private fun resetTitle() {
|
||||
supportActionBar?.title = getString(R.string.app_launcher_name)
|
||||
supportActionBar?.subtitle = ""
|
||||
}
|
||||
|
||||
private fun fillMonthlyViewPager(targetDay: String) {
|
||||
main_weekly_scrollview.beGone()
|
||||
calendar_fab.beVisible()
|
||||
val codes = getMonths(targetDay)
|
||||
val monthlyAdapter = MyMonthPagerAdapter(supportFragmentManager, codes, this)
|
||||
mDefaultMonthlyPage = codes.size / 2
|
||||
|
||||
main_view_pager.apply {
|
||||
adapter = monthlyAdapter
|
||||
beVisible()
|
||||
addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
invalidateOptionsMenu()
|
||||
if (config.storedView == YEARLY_VIEW) {
|
||||
val dateTime = Formatter.getDateTimeFromCode(codes[position])
|
||||
supportActionBar?.title = "${getString(R.string.app_launcher_name)} - ${Formatter.getYear(dateTime)}"
|
||||
}
|
||||
}
|
||||
})
|
||||
currentItem = mDefaultMonthlyPage
|
||||
}
|
||||
calendar_event_list_holder.beGone()
|
||||
}
|
||||
|
||||
private fun getMonths(code: String): List<String> {
|
||||
val months = ArrayList<String>(PREFILLED_MONTHS)
|
||||
val today = Formatter.getDateTimeFromCode(code)
|
||||
for (i in -PREFILLED_MONTHS / 2..PREFILLED_MONTHS / 2) {
|
||||
months.add(Formatter.getDayCodeFromDateTime(today.plusMonths(i)))
|
||||
}
|
||||
|
||||
return months
|
||||
}
|
||||
|
||||
private fun fillWeeklyViewPager() {
|
||||
var thisweek = DateTime().withDayOfWeek(1).withTimeAtStartOfDay().minusDays(if (config.isSundayFirst) 1 else 0)
|
||||
if (DateTime().minusDays(7).seconds() > thisweek.seconds()) {
|
||||
thisweek = thisweek.plusDays(7)
|
||||
}
|
||||
val weekTSs = getWeekTimestamps(thisweek.seconds())
|
||||
val weeklyAdapter = MyWeekPagerAdapter(supportFragmentManager, weekTSs, object : WeekFragment.WeekScrollListener {
|
||||
override fun scrollTo(y: Int) {
|
||||
week_view_hours_scrollview.scrollY = y
|
||||
mWeekScrollY = y
|
||||
}
|
||||
})
|
||||
main_view_pager.beGone()
|
||||
calendar_event_list_holder.beGone()
|
||||
main_weekly_scrollview.beVisible()
|
||||
|
||||
week_view_hours_holder.removeAllViews()
|
||||
val hourDateTime = DateTime().withDate(2000, 1, 1).withTime(0, 0, 0, 0)
|
||||
for (i in 1..23) {
|
||||
val formattedHours = Formatter.getHours(applicationContext, hourDateTime.withHourOfDay(i))
|
||||
(layoutInflater.inflate(R.layout.weekly_view_hour_textview, null, false) as TextView).apply {
|
||||
text = formattedHours
|
||||
setTextColor(mStoredTextColor)
|
||||
week_view_hours_holder.addView(this)
|
||||
}
|
||||
}
|
||||
|
||||
mDefaultWeeklyPage = weekTSs.size / 2
|
||||
week_view_view_pager.apply {
|
||||
adapter = weeklyAdapter
|
||||
addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
invalidateOptionsMenu()
|
||||
setupWeeklyActionbarTitle(weekTSs[position])
|
||||
}
|
||||
})
|
||||
currentItem = mDefaultWeeklyPage
|
||||
}
|
||||
|
||||
week_view_hours_scrollview.setOnScrollviewListener(object : MyScrollView.ScrollViewListener {
|
||||
override fun onScrollChanged(scrollView: MyScrollView, x: Int, y: Int, oldx: Int, oldy: Int) {
|
||||
mWeekScrollY = y
|
||||
weeklyAdapter.updateScrollY(week_view_view_pager.currentItem, y)
|
||||
}
|
||||
})
|
||||
week_view_hours_scrollview.setOnTouchListener { view, motionEvent -> true }
|
||||
}
|
||||
|
||||
fun updateHoursTopMargin(margin: Int) {
|
||||
week_view_hours_divider.layoutParams.height = margin
|
||||
week_view_hours_scrollview.requestLayout()
|
||||
}
|
||||
|
||||
private fun getWeekTimestamps(targetWeekTS: Int): List<Int> {
|
||||
val weekTSs = ArrayList<Int>(PREFILLED_WEEKS)
|
||||
for (i in -PREFILLED_WEEKS / 2..PREFILLED_WEEKS / 2) {
|
||||
weekTSs.add(Formatter.getDateTimeFromTS(targetWeekTS).plusWeeks(i).seconds())
|
||||
}
|
||||
return weekTSs
|
||||
}
|
||||
|
||||
private fun setupWeeklyActionbarTitle(timestamp: Int) {
|
||||
val startDateTime = Formatter.getDateTimeFromTS(timestamp)
|
||||
val endDateTime = Formatter.getDateTimeFromTS(timestamp + WEEK_SECONDS)
|
||||
val startMonthName = Formatter.getMonthName(applicationContext, startDateTime.monthOfYear)
|
||||
if (startDateTime.monthOfYear == endDateTime.monthOfYear) {
|
||||
var newTitle = startMonthName
|
||||
if (startDateTime.year != DateTime().year)
|
||||
newTitle += " - ${startDateTime.year}"
|
||||
supportActionBar?.title = newTitle
|
||||
} else {
|
||||
val endMonthName = Formatter.getMonthName(applicationContext, endDateTime.monthOfYear)
|
||||
supportActionBar?.title = "$startMonthName - $endMonthName"
|
||||
}
|
||||
supportActionBar?.subtitle = "${getString(R.string.week)} ${startDateTime.plusDays(3).weekOfWeekyear}"
|
||||
}
|
||||
|
||||
private fun fillYearlyViewPager() {
|
||||
main_weekly_scrollview.beGone()
|
||||
calendar_fab.beGone()
|
||||
val targetYear = DateTime().toString(Formatter.YEAR_PATTERN).toInt()
|
||||
val years = getYears(targetYear)
|
||||
val yearlyAdapter = MyYearPagerAdapter(supportFragmentManager, years, this)
|
||||
|
||||
mDefaultYearlyPage = years.size / 2
|
||||
main_view_pager.apply {
|
||||
adapter = yearlyAdapter
|
||||
addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
invalidateOptionsMenu()
|
||||
if (position < years.size) {
|
||||
supportActionBar?.title = "${getString(R.string.app_launcher_name)} - ${years[position]}"
|
||||
}
|
||||
}
|
||||
})
|
||||
currentItem = mDefaultYearlyPage
|
||||
beVisible()
|
||||
}
|
||||
supportActionBar?.title = "${getString(R.string.app_launcher_name)} - ${years[years.size / 2]}"
|
||||
calendar_event_list_holder.beGone()
|
||||
}
|
||||
|
||||
private fun getYears(targetYear: Int): List<Int> {
|
||||
val years = ArrayList<Int>(PREFILLED_YEARS)
|
||||
years += targetYear - PREFILLED_YEARS / 2..targetYear + PREFILLED_YEARS / 2
|
||||
return years
|
||||
}
|
||||
|
||||
private fun fillEventsList() {
|
||||
main_view_pager.adapter = null
|
||||
main_view_pager.beGone()
|
||||
main_weekly_scrollview.beGone()
|
||||
calendar_event_list_holder.beVisible()
|
||||
supportFragmentManager.beginTransaction().replace(R.id.calendar_event_list_holder, EventListFragment(), "").commit()
|
||||
}
|
||||
|
||||
override fun goLeft() {
|
||||
main_view_pager.currentItem = main_view_pager.currentItem - 1
|
||||
}
|
||||
|
||||
override fun goRight() {
|
||||
main_view_pager.currentItem = main_view_pager.currentItem + 1
|
||||
}
|
||||
|
||||
override fun goToDateTime(dateTime: DateTime) {
|
||||
fillMonthlyViewPager(Formatter.getDayCodeFromDateTime(dateTime))
|
||||
mIsMonthSelected = true
|
||||
}
|
||||
|
||||
private fun openDayAt(timestamp: Long) {
|
||||
val dayCode = Formatter.getDayCodeFromTS((timestamp / 1000).toInt())
|
||||
openDayCode(dayCode)
|
||||
}
|
||||
|
||||
private fun openDayCode(dayCode: String) {
|
||||
Intent(this, DayActivity::class.java).apply {
|
||||
putExtra(DAY_CODE, dayCode)
|
||||
startActivity(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getHolidayRadioItems(): ArrayList<RadioItem> {
|
||||
val items = ArrayList<RadioItem>()
|
||||
|
||||
LinkedHashMap<String, String>().apply {
|
||||
put("Algeria", "algeria.ics")
|
||||
put("Argentina", "argentina.ics")
|
||||
put("België", "belgium.ics")
|
||||
put("Bolivia", "bolivia.ics")
|
||||
put("Brasil", "brazil.ics")
|
||||
put("Canada", "canada.ics")
|
||||
put("Česká republika", "czech.ics")
|
||||
put("Deutschland", "germany.ics")
|
||||
put("Eesti", "estonia.ics")
|
||||
put("España", "spain.ics")
|
||||
put("Éire", "ireland.ics")
|
||||
put("France", "france.ics")
|
||||
put("Hanguk", "southkorea.ics")
|
||||
put("Hellas", "greece.ics")
|
||||
put("India", "india.ics")
|
||||
put("Ísland", "iceland.ics")
|
||||
put("Italia", "italy.ics")
|
||||
put("Magyarország", "hungary.ics")
|
||||
put("Nederland", "netherlands.ics")
|
||||
put("日本", "japan.ics")
|
||||
put("Norge", "norway.ics")
|
||||
put("Österreich", "austria.ics")
|
||||
put("Pākistān", "pakistan.ics")
|
||||
put("Polska", "poland.ics")
|
||||
put("Portugal", "portugal.ics")
|
||||
put("Россия", "russia.ics")
|
||||
put("Schweiz", "switzerland.ics")
|
||||
put("Slovenija", "slovenia.ics")
|
||||
put("Slovensko", "slovakia.ics")
|
||||
put("Suomi", "finland.ics")
|
||||
put("Sverige", "sweden.ics")
|
||||
put("United Kingdom", "unitedkingdom.ics")
|
||||
put("United States", "unitedstates.ics")
|
||||
|
||||
var i = 0
|
||||
for ((country, file) in this) {
|
||||
items.add(RadioItem(i++, country, file))
|
||||
}
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
private fun checkWhatsNewDialog() {
|
||||
arrayListOf<Release>().apply {
|
||||
add(Release(39, R.string.release_39))
|
||||
add(Release(40, R.string.release_40))
|
||||
add(Release(42, R.string.release_42))
|
||||
add(Release(44, R.string.release_44))
|
||||
add(Release(46, R.string.release_46))
|
||||
add(Release(48, R.string.release_48))
|
||||
add(Release(49, R.string.release_49))
|
||||
add(Release(51, R.string.release_51))
|
||||
add(Release(52, R.string.release_52))
|
||||
add(Release(54, R.string.release_54))
|
||||
add(Release(57, R.string.release_57))
|
||||
add(Release(59, R.string.release_59))
|
||||
add(Release(60, R.string.release_60))
|
||||
add(Release(62, R.string.release_62))
|
||||
add(Release(67, R.string.release_67))
|
||||
add(Release(69, R.string.release_69))
|
||||
add(Release(71, R.string.release_71))
|
||||
add(Release(73, R.string.release_73))
|
||||
add(Release(76, R.string.release_76))
|
||||
add(Release(77, R.string.release_77))
|
||||
add(Release(80, R.string.release_80))
|
||||
add(Release(84, R.string.release_84))
|
||||
add(Release(86, R.string.release_86))
|
||||
add(Release(88, R.string.release_88))
|
||||
add(Release(98, R.string.release_98))
|
||||
checkWhatsNew(this, BuildConfig.VERSION_CODE)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,367 +0,0 @@
|
|||
package com.simplemobiletools.calendar.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.res.Resources
|
||||
import android.media.RingtoneManager
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.text.TextUtils
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.dialogs.CustomEventReminderDialog
|
||||
import com.simplemobiletools.calendar.dialogs.SelectCalendarsDialog
|
||||
import com.simplemobiletools.calendar.dialogs.SnoozePickerDialog
|
||||
import com.simplemobiletools.calendar.extensions.*
|
||||
import com.simplemobiletools.calendar.helpers.CalDAVHandler
|
||||
import com.simplemobiletools.calendar.helpers.FONT_SIZE_LARGE
|
||||
import com.simplemobiletools.calendar.helpers.FONT_SIZE_MEDIUM
|
||||
import com.simplemobiletools.calendar.helpers.FONT_SIZE_SMALL
|
||||
import com.simplemobiletools.calendar.models.EventType
|
||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.PERMISSION_READ_CALENDAR
|
||||
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_CALENDAR
|
||||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import kotlinx.android.synthetic.main.activity_settings.*
|
||||
import java.util.*
|
||||
|
||||
class SettingsActivity : SimpleActivity() {
|
||||
private val GET_RINGTONE_URI = 1
|
||||
|
||||
lateinit var res: Resources
|
||||
private var mStoredPrimaryColor = 0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_settings)
|
||||
res = resources
|
||||
mStoredPrimaryColor = config.primaryColor
|
||||
setupCaldavSync()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
setupCustomizeColors()
|
||||
setupUseEnglish()
|
||||
setupManageEventTypes()
|
||||
setupHourFormat()
|
||||
setupSundayFirst()
|
||||
setupReplaceDescription()
|
||||
setupWeekNumbers()
|
||||
setupWeeklyStart()
|
||||
setupWeeklyEnd()
|
||||
setupVibrate()
|
||||
setupReminderSound()
|
||||
setupSnoozeDelay()
|
||||
setupEventReminder()
|
||||
setupDisplayPastEvents()
|
||||
setupFontSize()
|
||||
updateTextColors(settings_holder)
|
||||
checkPrimaryColor()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mStoredPrimaryColor = config.primaryColor
|
||||
}
|
||||
|
||||
private fun checkPrimaryColor() {
|
||||
if (config.primaryColor != mStoredPrimaryColor) {
|
||||
dbHelper.getEventTypes {
|
||||
if (it.filter { it.caldavCalendarId == 0 }.size == 1) {
|
||||
val eventType = it.first { it.caldavCalendarId == 0 }
|
||||
eventType.color = config.primaryColor
|
||||
dbHelper.updateEventType(eventType)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupCustomizeColors() {
|
||||
settings_customize_colors_holder.setOnClickListener {
|
||||
startCustomizationActivity()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupUseEnglish() {
|
||||
settings_use_english_holder.beVisibleIf(config.wasUseEnglishToggled || Locale.getDefault().language != "en")
|
||||
settings_use_english.isChecked = config.useEnglish
|
||||
settings_use_english_holder.setOnClickListener {
|
||||
settings_use_english.toggle()
|
||||
config.useEnglish = settings_use_english.isChecked
|
||||
useEnglishToggled()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupManageEventTypes() {
|
||||
settings_manage_event_types_holder.setOnClickListener {
|
||||
startActivity(Intent(this, ManageEventTypesActivity::class.java))
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupHourFormat() {
|
||||
settings_hour_format.isChecked = config.use24hourFormat
|
||||
settings_hour_format_holder.setOnClickListener {
|
||||
settings_hour_format.toggle()
|
||||
config.use24hourFormat = settings_hour_format.isChecked
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupCaldavSync() {
|
||||
settings_caldav_sync.isChecked = config.caldavSync
|
||||
settings_caldav_sync_holder.setOnClickListener {
|
||||
if (config.caldavSync) {
|
||||
toggleCaldavSync(false)
|
||||
} else {
|
||||
handlePermission(PERMISSION_WRITE_CALENDAR) {
|
||||
if (it) {
|
||||
handlePermission(PERMISSION_READ_CALENDAR) {
|
||||
if (it) {
|
||||
toggleCaldavSync(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
settings_manage_synced_calendars_holder.beVisibleIf(config.caldavSync)
|
||||
settings_manage_synced_calendars_holder.setOnClickListener {
|
||||
showCalendarPicker()
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleCaldavSync(enable: Boolean) {
|
||||
if (enable) {
|
||||
showCalendarPicker()
|
||||
} else {
|
||||
settings_caldav_sync.isChecked = false
|
||||
config.caldavSync = false
|
||||
settings_manage_synced_calendars_holder.beGone()
|
||||
config.getSyncedCalendarIdsAsList().forEach {
|
||||
CalDAVHandler(applicationContext).deleteCalDAVCalendarEvents(it.toLong())
|
||||
}
|
||||
dbHelper.deleteEventTypesWithCalendarId(config.caldavSyncedCalendarIDs)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showCalendarPicker() {
|
||||
val oldCalendarIds = config.getSyncedCalendarIdsAsList()
|
||||
|
||||
SelectCalendarsDialog(this) {
|
||||
val newCalendarIds = config.getSyncedCalendarIdsAsList()
|
||||
settings_manage_synced_calendars_holder.beVisibleIf(newCalendarIds.isNotEmpty())
|
||||
settings_caldav_sync.isChecked = newCalendarIds.isNotEmpty()
|
||||
config.caldavSync = newCalendarIds.isNotEmpty()
|
||||
toast(R.string.syncing)
|
||||
|
||||
Thread {
|
||||
if (newCalendarIds.isNotEmpty()) {
|
||||
val existingEventTypeNames = dbHelper.fetchEventTypes().map { it.getDisplayTitle().toLowerCase() } as ArrayList<String>
|
||||
getSyncedCalDAVCalendars().forEach {
|
||||
val calendarTitle = it.getFullTitle()
|
||||
if (!existingEventTypeNames.contains(calendarTitle.toLowerCase())) {
|
||||
val eventType = EventType(0, it.displayName, it.color, it.id, it.displayName, it.accountName)
|
||||
existingEventTypeNames.add(calendarTitle.toLowerCase())
|
||||
dbHelper.insertEventType(eventType)
|
||||
}
|
||||
}
|
||||
CalDAVHandler(applicationContext).refreshCalendars(this) {}
|
||||
}
|
||||
|
||||
val removedCalendarIds = oldCalendarIds.filter { !newCalendarIds.contains(it) }
|
||||
removedCalendarIds.forEach {
|
||||
CalDAVHandler(applicationContext).deleteCalDAVCalendarEvents(it.toLong())
|
||||
dbHelper.getEventTypeWithCalDAVCalendarId(it.toInt())?.apply {
|
||||
dbHelper.deleteEventTypes(arrayListOf(this), true) {}
|
||||
}
|
||||
}
|
||||
dbHelper.deleteEventTypesWithCalendarId(TextUtils.join(",", removedCalendarIds))
|
||||
toast(R.string.synchronization_completed)
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupSundayFirst() {
|
||||
settings_sunday_first.isChecked = config.isSundayFirst
|
||||
settings_sunday_first_holder.setOnClickListener {
|
||||
settings_sunday_first.toggle()
|
||||
config.isSundayFirst = settings_sunday_first.isChecked
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupReplaceDescription() {
|
||||
settings_replace_description.isChecked = config.replaceDescription
|
||||
settings_replace_description_holder.setOnClickListener {
|
||||
settings_replace_description.toggle()
|
||||
config.replaceDescription = settings_replace_description.isChecked
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupWeeklyStart() {
|
||||
settings_start_weekly_at.text = getHoursString(config.startWeeklyAt)
|
||||
settings_start_weekly_at_holder.setOnClickListener {
|
||||
val items = ArrayList<RadioItem>()
|
||||
(0..24).mapTo(items) { RadioItem(it, getHoursString(it)) }
|
||||
|
||||
RadioGroupDialog(this@SettingsActivity, items, config.startWeeklyAt) {
|
||||
if (it as Int >= config.endWeeklyAt) {
|
||||
toast(R.string.day_end_before_start)
|
||||
} else {
|
||||
config.startWeeklyAt = it
|
||||
settings_start_weekly_at.text = getHoursString(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupWeeklyEnd() {
|
||||
settings_end_weekly_at.text = getHoursString(config.endWeeklyAt)
|
||||
settings_end_weekly_at_holder.setOnClickListener {
|
||||
val items = ArrayList<RadioItem>()
|
||||
(0..24).mapTo(items) { RadioItem(it, getHoursString(it)) }
|
||||
|
||||
RadioGroupDialog(this@SettingsActivity, items, config.endWeeklyAt) {
|
||||
if (it as Int <= config.startWeeklyAt) {
|
||||
toast(R.string.day_end_before_start)
|
||||
} else {
|
||||
config.endWeeklyAt = it
|
||||
settings_end_weekly_at.text = getHoursString(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupWeekNumbers() {
|
||||
settings_week_numbers.isChecked = config.displayWeekNumbers
|
||||
settings_week_numbers_holder.setOnClickListener {
|
||||
settings_week_numbers.toggle()
|
||||
config.displayWeekNumbers = settings_week_numbers.isChecked
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupReminderSound() {
|
||||
val noRingtone = res.getString(R.string.no_ringtone_selected)
|
||||
if (config.reminderSound.isEmpty()) {
|
||||
settings_reminder_sound.text = noRingtone
|
||||
} else {
|
||||
settings_reminder_sound.text = RingtoneManager.getRingtone(this, Uri.parse(config.reminderSound))?.getTitle(this) ?: noRingtone
|
||||
}
|
||||
settings_reminder_sound_holder.setOnClickListener {
|
||||
Intent(RingtoneManager.ACTION_RINGTONE_PICKER).apply {
|
||||
putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION)
|
||||
putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, res.getString(R.string.reminder_sound))
|
||||
putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, Uri.parse(config.reminderSound))
|
||||
|
||||
if (resolveActivity(packageManager) != null)
|
||||
startActivityForResult(this, GET_RINGTONE_URI)
|
||||
else {
|
||||
toast(R.string.no_ringtone_picker)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupVibrate() {
|
||||
settings_vibrate.isChecked = config.vibrateOnReminder
|
||||
settings_vibrate_holder.setOnClickListener {
|
||||
settings_vibrate.toggle()
|
||||
config.vibrateOnReminder = settings_vibrate.isChecked
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupSnoozeDelay() {
|
||||
updateSnoozeText()
|
||||
settings_snooze_delay_holder.setOnClickListener {
|
||||
SnoozePickerDialog(this, config.snoozeDelay) {
|
||||
config.snoozeDelay = it
|
||||
updateSnoozeText()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSnoozeText() {
|
||||
settings_snooze_delay.text = res.getQuantityString(R.plurals.by_minutes, config.snoozeDelay, config.snoozeDelay)
|
||||
}
|
||||
|
||||
private fun setupEventReminder() {
|
||||
var reminderMinutes = config.defaultReminderMinutes
|
||||
settings_default_reminder.text = getFormattedMinutes(reminderMinutes)
|
||||
settings_default_reminder_holder.setOnClickListener {
|
||||
showEventReminderDialog(reminderMinutes) {
|
||||
config.defaultReminderMinutes = it
|
||||
reminderMinutes = it
|
||||
settings_default_reminder.text = getFormattedMinutes(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getHoursString(hours: Int): String {
|
||||
return if (hours < 10) {
|
||||
"0$hours:00"
|
||||
} else {
|
||||
"$hours:00"
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupDisplayPastEvents() {
|
||||
var displayPastEvents = config.displayPastEvents
|
||||
updatePastEventsText(displayPastEvents)
|
||||
settings_display_past_events_holder.setOnClickListener {
|
||||
CustomEventReminderDialog(this, displayPastEvents) {
|
||||
displayPastEvents = it
|
||||
config.displayPastEvents = it
|
||||
updatePastEventsText(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePastEventsText(displayPastEvents: Int) {
|
||||
settings_display_past_events.text = getDisplayPastEventsText(displayPastEvents)
|
||||
}
|
||||
|
||||
private fun getDisplayPastEventsText(displayPastEvents: Int): String {
|
||||
return if (displayPastEvents == 0)
|
||||
getString(R.string.never)
|
||||
else
|
||||
getFormattedMinutes(displayPastEvents, false)
|
||||
}
|
||||
|
||||
private fun setupFontSize() {
|
||||
settings_font_size.text = getFontSizeText()
|
||||
settings_font_size_holder.setOnClickListener {
|
||||
val items = arrayListOf(
|
||||
RadioItem(FONT_SIZE_SMALL, res.getString(R.string.small)),
|
||||
RadioItem(FONT_SIZE_MEDIUM, res.getString(R.string.medium)),
|
||||
RadioItem(FONT_SIZE_LARGE, res.getString(R.string.large)))
|
||||
|
||||
RadioGroupDialog(this@SettingsActivity, items, config.fontSize) {
|
||||
config.fontSize = it as Int
|
||||
settings_font_size.text = getFontSizeText()
|
||||
updateWidgets()
|
||||
updateListWidget()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFontSizeText() = getString(when (config.fontSize) {
|
||||
FONT_SIZE_SMALL -> R.string.small
|
||||
FONT_SIZE_MEDIUM -> R.string.medium
|
||||
else -> R.string.large
|
||||
})
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
if (requestCode == GET_RINGTONE_URI) {
|
||||
val uri = data?.getParcelableExtra<Parcelable>(RingtoneManager.EXTRA_RINGTONE_PICKED_URI)
|
||||
if (uri == null) {
|
||||
config.reminderSound = ""
|
||||
} else {
|
||||
settings_reminder_sound.text = RingtoneManager.getRingtone(this, uri as Uri)?.getTitle(this)
|
||||
config.reminderSound = uri.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
package com.simplemobiletools.calendar.activities
|
||||
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.dialogs.CustomEventReminderDialog
|
||||
import com.simplemobiletools.calendar.dialogs.CustomEventRepeatIntervalDialog
|
||||
import com.simplemobiletools.calendar.extensions.getFormattedMinutes
|
||||
import com.simplemobiletools.calendar.extensions.getRepetitionText
|
||||
import com.simplemobiletools.calendar.helpers.DAY
|
||||
import com.simplemobiletools.calendar.helpers.MONTH
|
||||
import com.simplemobiletools.calendar.helpers.WEEK
|
||||
import com.simplemobiletools.calendar.helpers.YEAR
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||
import com.simplemobiletools.commons.extensions.hideKeyboard
|
||||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import java.util.TreeSet
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
open class SimpleActivity : BaseSimpleActivity() {
|
||||
protected fun showEventReminderDialog(curMinutes: Int, callback: (minutes: Int) -> Unit) {
|
||||
hideKeyboard()
|
||||
val minutes = TreeSet<Int>()
|
||||
minutes.apply {
|
||||
add(-1)
|
||||
add(0)
|
||||
add(10)
|
||||
add(30)
|
||||
add(curMinutes)
|
||||
}
|
||||
|
||||
val items = ArrayList<RadioItem>(minutes.size + 1)
|
||||
minutes.mapIndexedTo(items, { index, value ->
|
||||
RadioItem(index, getFormattedMinutes(value), value)
|
||||
})
|
||||
|
||||
var selectedIndex = 0
|
||||
minutes.forEachIndexed { index, value ->
|
||||
if (value == curMinutes)
|
||||
selectedIndex = index
|
||||
}
|
||||
|
||||
items.add(RadioItem(-2, getString(R.string.custom)))
|
||||
|
||||
RadioGroupDialog(this, items, selectedIndex) {
|
||||
if (it == -2) {
|
||||
CustomEventReminderDialog(this) {
|
||||
callback(it)
|
||||
}
|
||||
} else {
|
||||
callback(it as Int)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun showEventRepeatIntervalDialog(curSeconds: Int, callback: (minutes: Int) -> Unit) {
|
||||
hideKeyboard()
|
||||
val seconds = TreeSet<Int>()
|
||||
seconds.apply {
|
||||
add(0)
|
||||
add(DAY)
|
||||
add(WEEK)
|
||||
add(MONTH)
|
||||
add(YEAR)
|
||||
add(curSeconds)
|
||||
}
|
||||
|
||||
val items = ArrayList<RadioItem>(seconds.size + 1)
|
||||
seconds.mapIndexedTo(items, { index, value ->
|
||||
RadioItem(index, getRepetitionText(value), value)
|
||||
})
|
||||
|
||||
var selectedIndex = 0
|
||||
seconds.forEachIndexed { index, value ->
|
||||
if (value == curSeconds)
|
||||
selectedIndex = index
|
||||
}
|
||||
|
||||
items.add(RadioItem(-1, getString(R.string.custom)))
|
||||
|
||||
RadioGroupDialog(this, items, selectedIndex) {
|
||||
if (it == -1) {
|
||||
CustomEventRepeatIntervalDialog(this) {
|
||||
callback(it)
|
||||
}
|
||||
} else {
|
||||
callback(it as Int)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package com.simplemobiletools.calendar.activities
|
||||
|
||||
import android.content.Intent
|
||||
import com.simplemobiletools.calendar.helpers.DAY_CODE
|
||||
import com.simplemobiletools.calendar.helpers.EVENT_ID
|
||||
import com.simplemobiletools.calendar.helpers.EVENT_OCCURRENCE_TS
|
||||
import com.simplemobiletools.commons.activities.BaseSplashActivity
|
||||
|
||||
class SplashActivity : BaseSplashActivity() {
|
||||
override fun initActivity() {
|
||||
when {
|
||||
intent.extras?.containsKey(DAY_CODE) == true -> Intent(this, MainActivity::class.java).apply {
|
||||
putExtra(DAY_CODE, intent.getStringExtra(DAY_CODE))
|
||||
startActivity(this)
|
||||
}
|
||||
intent.extras?.containsKey(EVENT_ID) == true -> Intent(this, MainActivity::class.java).apply {
|
||||
putExtra(EVENT_ID, intent.getIntExtra(EVENT_ID, 0))
|
||||
putExtra(EVENT_OCCURRENCE_TS, intent.getIntExtra(EVENT_OCCURRENCE_TS, 0))
|
||||
startActivity(this)
|
||||
}
|
||||
else -> startActivity(Intent(this, MainActivity::class.java))
|
||||
}
|
||||
finish()
|
||||
}
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
package com.simplemobiletools.calendar.adapters
|
||||
|
||||
import android.view.Menu
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.activities.SimpleActivity
|
||||
import com.simplemobiletools.calendar.dialogs.DeleteEventDialog
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.calendar.extensions.shareEvents
|
||||
import com.simplemobiletools.calendar.helpers.Formatter
|
||||
import com.simplemobiletools.calendar.interfaces.DeleteEventsListener
|
||||
import com.simplemobiletools.calendar.models.Event
|
||||
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
|
||||
import com.simplemobiletools.commons.extensions.applyColorFilter
|
||||
import com.simplemobiletools.commons.extensions.beInvisible
|
||||
import com.simplemobiletools.commons.extensions.beInvisibleIf
|
||||
import com.simplemobiletools.commons.views.MyRecyclerView
|
||||
import kotlinx.android.synthetic.main.event_item_day_view.view.*
|
||||
|
||||
class DayEventsAdapter(activity: SimpleActivity, val events: ArrayList<Event>, val listener: DeleteEventsListener?, recyclerView: MyRecyclerView,
|
||||
itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, itemClick) {
|
||||
|
||||
private var allDayString = resources.getString(R.string.all_day)
|
||||
private var replaceDescriptionWithLocation = activity.config.replaceDescription
|
||||
|
||||
override fun getActionMenuId() = R.menu.cab_day
|
||||
|
||||
override fun prepareActionMode(menu: Menu) {}
|
||||
|
||||
override fun prepareItemSelection(view: View) {}
|
||||
|
||||
override fun markItemSelection(select: Boolean, view: View?) {
|
||||
view?.event_item_frame?.isSelected = select
|
||||
}
|
||||
|
||||
override fun actionItemPressed(id: Int) {
|
||||
when (id) {
|
||||
R.id.cab_share -> shareEvents()
|
||||
R.id.cab_delete -> askConfirmDelete()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSelectableItemCount() = events.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int) = createViewHolder(R.layout.event_item_day_view, parent)
|
||||
|
||||
override fun onBindViewHolder(holder: MyRecyclerViewAdapter.ViewHolder, position: Int) {
|
||||
val event = events[position]
|
||||
val view = holder.bindView(event) { itemView, layoutPosition ->
|
||||
setupView(itemView, event)
|
||||
}
|
||||
bindViewHolder(holder, position, view)
|
||||
}
|
||||
|
||||
override fun getItemCount() = events.size
|
||||
|
||||
private fun setupView(view: View, event: Event) {
|
||||
view.apply {
|
||||
event_section_title.text = event.title
|
||||
event_item_description.text = if (replaceDescriptionWithLocation) event.location else event.description
|
||||
event_item_start.text = if (event.getIsAllDay()) allDayString else Formatter.getTimeFromTS(context, event.startTS)
|
||||
event_item_end.beInvisibleIf(event.startTS == event.endTS)
|
||||
event_item_color.applyColorFilter(event.color)
|
||||
|
||||
if (event.startTS != event.endTS) {
|
||||
val startCode = Formatter.getDayCodeFromTS(event.startTS)
|
||||
val endCode = Formatter.getDayCodeFromTS(event.endTS)
|
||||
|
||||
event_item_end.apply {
|
||||
text = Formatter.getTimeFromTS(context, event.endTS)
|
||||
if (startCode != endCode) {
|
||||
if (event.getIsAllDay()) {
|
||||
text = Formatter.getDateFromCode(context, endCode, true)
|
||||
} else {
|
||||
append(" (${Formatter.getDateFromCode(context, endCode, true)})")
|
||||
}
|
||||
} else if (event.getIsAllDay()) {
|
||||
beInvisible()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event_item_start.setTextColor(textColor)
|
||||
event_item_end.setTextColor(textColor)
|
||||
event_section_title.setTextColor(textColor)
|
||||
event_item_description.setTextColor(textColor)
|
||||
}
|
||||
}
|
||||
|
||||
private fun shareEvents() {
|
||||
val eventIds = ArrayList<Int>(selectedPositions.size)
|
||||
selectedPositions.forEach {
|
||||
eventIds.add(events[it].id)
|
||||
}
|
||||
activity.shareEvents(eventIds.distinct())
|
||||
}
|
||||
|
||||
private fun askConfirmDelete() {
|
||||
val eventIds = ArrayList<Int>(selectedPositions.size)
|
||||
val timestamps = ArrayList<Int>(selectedPositions.size)
|
||||
selectedPositions.forEach {
|
||||
eventIds.add(events[it].id)
|
||||
timestamps.add(events[it].startTS)
|
||||
}
|
||||
|
||||
DeleteEventDialog(activity, eventIds) {
|
||||
val eventsToDelete = ArrayList<Event>(selectedPositions.size)
|
||||
selectedPositions.sortedDescending().forEach {
|
||||
val event = events[it]
|
||||
eventsToDelete.add(event)
|
||||
}
|
||||
events.removeAll(eventsToDelete)
|
||||
|
||||
if (it) {
|
||||
listener?.deleteItems(eventIds)
|
||||
} else {
|
||||
listener?.addEventRepeatException(eventIds, timestamps)
|
||||
}
|
||||
removeSelectedItems()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,166 +0,0 @@
|
|||
package com.simplemobiletools.calendar.adapters
|
||||
|
||||
import android.view.Menu
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.activities.SimpleActivity
|
||||
import com.simplemobiletools.calendar.dialogs.DeleteEventDialog
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.calendar.extensions.shareEvents
|
||||
import com.simplemobiletools.calendar.helpers.Formatter
|
||||
import com.simplemobiletools.calendar.interfaces.DeleteEventsListener
|
||||
import com.simplemobiletools.calendar.models.ListEvent
|
||||
import com.simplemobiletools.calendar.models.ListItem
|
||||
import com.simplemobiletools.calendar.models.ListSection
|
||||
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
|
||||
import com.simplemobiletools.commons.extensions.applyColorFilter
|
||||
import com.simplemobiletools.commons.extensions.beInvisible
|
||||
import com.simplemobiletools.commons.extensions.beInvisibleIf
|
||||
import com.simplemobiletools.commons.views.MyRecyclerView
|
||||
import kotlinx.android.synthetic.main.event_list_item.view.*
|
||||
import java.util.*
|
||||
|
||||
class EventListAdapter(activity: SimpleActivity, val listItems: ArrayList<ListItem>, val allowLongClick: Boolean, val listener: DeleteEventsListener?,
|
||||
recyclerView: MyRecyclerView, itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, itemClick) {
|
||||
|
||||
private val ITEM_EVENT = 0
|
||||
private val ITEM_HEADER = 1
|
||||
|
||||
private val topDivider = resources.getDrawable(R.drawable.divider_width)
|
||||
private val allDayString = resources.getString(R.string.all_day)
|
||||
private val replaceDescriptionWithLocation = activity.config.replaceDescription
|
||||
private val redTextColor = resources.getColor(R.color.red_text)
|
||||
private val now = (System.currentTimeMillis() / 1000).toInt()
|
||||
private val todayDate = Formatter.getDayTitle(activity, Formatter.getDayCodeFromTS(now))
|
||||
|
||||
override fun getActionMenuId() = R.menu.cab_event_list
|
||||
|
||||
override fun prepareActionMode(menu: Menu) {}
|
||||
|
||||
override fun prepareItemSelection(view: View) {}
|
||||
|
||||
override fun markItemSelection(select: Boolean, view: View?) {
|
||||
view?.event_item_frame?.isSelected = select
|
||||
}
|
||||
|
||||
override fun actionItemPressed(id: Int) {
|
||||
when (id) {
|
||||
R.id.cab_share -> shareEvents()
|
||||
R.id.cab_delete -> askConfirmDelete()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSelectableItemCount() = listItems.filter { it is ListEvent }.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): MyRecyclerViewAdapter.ViewHolder {
|
||||
val layoutId = if (viewType == ITEM_EVENT) R.layout.event_list_item else R.layout.event_list_section
|
||||
return createViewHolder(layoutId, parent)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: MyRecyclerViewAdapter.ViewHolder, position: Int) {
|
||||
val listItem = listItems[position]
|
||||
val view = holder.bindView(listItem, allowLongClick) { itemView, layoutPosition ->
|
||||
if (listItem is ListSection) {
|
||||
setupListSection(itemView, listItem, position)
|
||||
} else if (listItem is ListEvent) {
|
||||
setupListEvent(itemView, listItem)
|
||||
}
|
||||
}
|
||||
bindViewHolder(holder, position, view)
|
||||
}
|
||||
|
||||
override fun getItemCount() = listItems.size
|
||||
|
||||
override fun getItemViewType(position: Int) = if (listItems[position] is ListEvent) ITEM_EVENT else ITEM_HEADER
|
||||
|
||||
private fun setupListEvent(view: View, listEvent: ListEvent) {
|
||||
view.apply {
|
||||
event_section_title.text = listEvent.title
|
||||
event_item_description.text = if (replaceDescriptionWithLocation) listEvent.location else listEvent.description
|
||||
event_item_start.text = if (listEvent.isAllDay) allDayString else Formatter.getTimeFromTS(context, listEvent.startTS)
|
||||
event_item_end.beInvisibleIf(listEvent.startTS == listEvent.endTS)
|
||||
event_item_color.applyColorFilter(listEvent.color)
|
||||
|
||||
if (listEvent.startTS != listEvent.endTS) {
|
||||
val startCode = Formatter.getDayCodeFromTS(listEvent.startTS)
|
||||
val endCode = Formatter.getDayCodeFromTS(listEvent.endTS)
|
||||
|
||||
event_item_end.apply {
|
||||
text = Formatter.getTimeFromTS(context, listEvent.endTS)
|
||||
if (startCode != endCode) {
|
||||
if (listEvent.isAllDay) {
|
||||
text = Formatter.getDateFromCode(context, endCode, true)
|
||||
} else {
|
||||
append(" (${Formatter.getDateFromCode(context, endCode, true)})")
|
||||
}
|
||||
} else if (listEvent.isAllDay) {
|
||||
beInvisible()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var startTextColor = textColor
|
||||
var endTextColor = textColor
|
||||
if (listEvent.startTS <= now && listEvent.endTS <= now) {
|
||||
if (listEvent.isAllDay) {
|
||||
if (Formatter.getDayCodeFromTS(listEvent.startTS) == Formatter.getDayCodeFromTS(now))
|
||||
startTextColor = primaryColor
|
||||
} else {
|
||||
startTextColor = redTextColor
|
||||
}
|
||||
endTextColor = redTextColor
|
||||
} else if (listEvent.startTS <= now && listEvent.endTS >= now) {
|
||||
startTextColor = primaryColor
|
||||
}
|
||||
|
||||
event_item_start.setTextColor(startTextColor)
|
||||
event_item_end.setTextColor(endTextColor)
|
||||
event_section_title.setTextColor(startTextColor)
|
||||
event_item_description.setTextColor(startTextColor)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupListSection(view: View, listSection: ListSection, position: Int) {
|
||||
view.event_section_title.apply {
|
||||
text = listSection.title
|
||||
setCompoundDrawablesWithIntrinsicBounds(null, if (position == 0) null else topDivider, null, null)
|
||||
setTextColor(if (listSection.title == todayDate) primaryColor else textColor)
|
||||
}
|
||||
}
|
||||
|
||||
private fun shareEvents() {
|
||||
val eventIds = ArrayList<Int>(selectedPositions.size)
|
||||
selectedPositions.forEach {
|
||||
eventIds.add((listItems[it] as ListEvent).id)
|
||||
}
|
||||
activity.shareEvents(eventIds.distinct())
|
||||
finishActMode()
|
||||
}
|
||||
|
||||
private fun askConfirmDelete() {
|
||||
val eventIds = ArrayList<Int>(selectedPositions.size)
|
||||
val timestamps = ArrayList<Int>(selectedPositions.size)
|
||||
|
||||
selectedPositions.forEach {
|
||||
eventIds.add((listItems[it] as ListEvent).id)
|
||||
timestamps.add((listItems[it] as ListEvent).startTS)
|
||||
}
|
||||
|
||||
DeleteEventDialog(activity, eventIds) {
|
||||
val listItemsToDelete = ArrayList<ListItem>(selectedPositions.size)
|
||||
selectedPositions.sortedDescending().forEach {
|
||||
val listItem = listItems[it]
|
||||
listItemsToDelete.add(listItem)
|
||||
}
|
||||
listItems.removeAll(listItemsToDelete)
|
||||
|
||||
if (it) {
|
||||
listener?.deleteItems(eventIds)
|
||||
} else {
|
||||
listener?.addEventRepeatException(eventIds, timestamps)
|
||||
}
|
||||
finishActMode()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
package com.simplemobiletools.calendar.adapters
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.view.View
|
||||
import android.widget.RemoteViews
|
||||
import android.widget.RemoteViewsService
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.R.id.event_item_holder
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.calendar.extensions.dbHelper
|
||||
import com.simplemobiletools.calendar.extensions.seconds
|
||||
import com.simplemobiletools.calendar.helpers.EVENT_ID
|
||||
import com.simplemobiletools.calendar.helpers.EVENT_OCCURRENCE_TS
|
||||
import com.simplemobiletools.calendar.helpers.Formatter
|
||||
import com.simplemobiletools.calendar.models.ListEvent
|
||||
import com.simplemobiletools.calendar.models.ListItem
|
||||
import com.simplemobiletools.calendar.models.ListSection
|
||||
import com.simplemobiletools.commons.extensions.getColoredBitmap
|
||||
import com.simplemobiletools.commons.extensions.setText
|
||||
import com.simplemobiletools.commons.extensions.setTextSize
|
||||
import org.joda.time.DateTime
|
||||
import java.util.*
|
||||
|
||||
class EventListWidgetAdapter(val context: Context) : RemoteViewsService.RemoteViewsFactory {
|
||||
private val ITEM_EVENT = 0
|
||||
private val ITEM_HEADER = 1
|
||||
|
||||
private val allDayString = context.resources.getString(R.string.all_day)
|
||||
private var events = ArrayList<ListItem>()
|
||||
private val textColor = context.config.widgetTextColor
|
||||
private val replaceDescription = context.config.replaceDescription
|
||||
private var mediumFontSize = context.config.getFontSize()
|
||||
private var todayDate = ""
|
||||
|
||||
override fun getViewAt(position: Int): RemoteViews? {
|
||||
val type = getItemViewType(position)
|
||||
val remoteView: RemoteViews
|
||||
|
||||
if (type == ITEM_EVENT) {
|
||||
val item = events[position] as ListEvent
|
||||
remoteView = RemoteViews(context.packageName, R.layout.event_list_item_widget).apply {
|
||||
setText(R.id.event_section_title, item.title)
|
||||
setText(R.id.event_item_description, if (replaceDescription) item.location else item.description)
|
||||
setText(R.id.event_item_start, if (item.isAllDay) allDayString else Formatter.getTimeFromTS(context, item.startTS))
|
||||
setImageViewBitmap(R.id.event_item_color, context.resources.getColoredBitmap(R.drawable.monthly_event_dot, item.color))
|
||||
|
||||
if (item.startTS == item.endTS) {
|
||||
setViewVisibility(R.id.event_item_end, View.INVISIBLE)
|
||||
} else {
|
||||
setViewVisibility(R.id.event_item_end, View.VISIBLE)
|
||||
var endString = Formatter.getTimeFromTS(context, item.endTS)
|
||||
val startCode = Formatter.getDayCodeFromTS(item.startTS)
|
||||
val endCode = Formatter.getDayCodeFromTS(item.endTS)
|
||||
|
||||
if (startCode != endCode) {
|
||||
if (item.isAllDay) {
|
||||
endString = Formatter.getDateFromCode(context, endCode, true)
|
||||
} else {
|
||||
endString += " (${Formatter.getDateFromCode(context, endCode, true)})"
|
||||
}
|
||||
} else if (item.isAllDay) {
|
||||
setViewVisibility(R.id.event_item_end, View.INVISIBLE)
|
||||
}
|
||||
setText(R.id.event_item_end, endString)
|
||||
}
|
||||
|
||||
setTextColor(R.id.event_section_title, textColor)
|
||||
setTextColor(R.id.event_item_description, textColor)
|
||||
setTextColor(R.id.event_item_start, textColor)
|
||||
setTextColor(R.id.event_item_end, textColor)
|
||||
|
||||
setTextSize(R.id.event_section_title, mediumFontSize)
|
||||
setTextSize(R.id.event_item_description, mediumFontSize)
|
||||
setTextSize(R.id.event_item_start, mediumFontSize)
|
||||
setTextSize(R.id.event_item_end, mediumFontSize)
|
||||
|
||||
Intent().apply {
|
||||
putExtra(EVENT_ID, item.id)
|
||||
putExtra(EVENT_OCCURRENCE_TS, item.startTS)
|
||||
setOnClickFillInIntent(event_item_holder, this)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val item = events[position] as ListSection
|
||||
remoteView = RemoteViews(context.packageName, R.layout.event_list_section_widget).apply {
|
||||
setTextColor(R.id.event_section_title, textColor)
|
||||
setTextSize(R.id.event_section_title, mediumFontSize)
|
||||
setText(R.id.event_section_title, item.title)
|
||||
}
|
||||
}
|
||||
|
||||
return remoteView
|
||||
}
|
||||
|
||||
private fun getItemViewType(position: Int) = if (events[position] is ListEvent) ITEM_EVENT else ITEM_HEADER
|
||||
|
||||
override fun getLoadingView() = null
|
||||
|
||||
override fun getViewTypeCount() = 2
|
||||
|
||||
override fun onCreate() {
|
||||
val now = (System.currentTimeMillis() / 1000).toInt()
|
||||
val todayCode = Formatter.getDayCodeFromTS(now)
|
||||
todayDate = Formatter.getDayTitle(context, todayCode)
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int) = position.toLong()
|
||||
|
||||
override fun onDataSetChanged() {
|
||||
mediumFontSize = context.config.getFontSize()
|
||||
val fromTS = DateTime().seconds() - context.config.displayPastEvents * 60
|
||||
val toTS = DateTime().plusYears(1).seconds()
|
||||
context.dbHelper.getEventsInBackground(fromTS, toTS) {
|
||||
val listItems = ArrayList<ListItem>(it.size)
|
||||
val replaceDescription = context.config.replaceDescription
|
||||
val sorted = it.sortedWith(compareBy({ it.startTS }, { it.endTS }, { it.title }, { if (replaceDescription) it.location else it.description }))
|
||||
val sublist = sorted.subList(0, Math.min(sorted.size, 100))
|
||||
var prevCode = ""
|
||||
sublist.forEach {
|
||||
val code = Formatter.getDayCodeFromTS(it.startTS)
|
||||
if (code != prevCode) {
|
||||
val day = Formatter.getDayTitle(context, code)
|
||||
if (day != todayDate)
|
||||
listItems.add(ListSection(day))
|
||||
prevCode = code
|
||||
}
|
||||
listItems.add(ListEvent(it.id, it.startTS, it.endTS, it.title, it.description, it.getIsAllDay(), it.color, it.location))
|
||||
}
|
||||
|
||||
this@EventListWidgetAdapter.events = listItems
|
||||
}
|
||||
}
|
||||
|
||||
override fun hasStableIds() = true
|
||||
|
||||
override fun getCount() = events.size
|
||||
|
||||
override fun onDestroy() {}
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
package com.simplemobiletools.calendar.adapters
|
||||
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.util.SparseArray
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.activities.SimpleActivity
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.calendar.models.EventType
|
||||
import com.simplemobiletools.commons.extensions.setBackgroundWithStroke
|
||||
import com.simplemobiletools.commons.interfaces.MyAdapterListener
|
||||
import kotlinx.android.synthetic.main.filter_event_type_view.view.*
|
||||
import java.util.*
|
||||
|
||||
class FilterEventTypeAdapter(val activity: SimpleActivity, val eventTypes: List<EventType>, val displayEventTypes: Set<String>) :
|
||||
RecyclerView.Adapter<FilterEventTypeAdapter.ViewHolder>() {
|
||||
private val itemViews = SparseArray<View>()
|
||||
private val selectedPositions = HashSet<Int>()
|
||||
|
||||
init {
|
||||
eventTypes.forEachIndexed { index, eventType ->
|
||||
if (displayEventTypes.contains(eventType.id.toString())) {
|
||||
selectedPositions.add(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleItemSelection(select: Boolean, pos: Int) {
|
||||
if (select) {
|
||||
if (itemViews[pos] != null) {
|
||||
selectedPositions.add(pos)
|
||||
}
|
||||
} else {
|
||||
selectedPositions.remove(pos)
|
||||
}
|
||||
|
||||
itemViews[pos]?.filter_event_type_checkbox?.isChecked = select
|
||||
}
|
||||
|
||||
private val adapterListener = object : MyAdapterListener {
|
||||
override fun toggleItemSelectionAdapter(select: Boolean, position: Int) {
|
||||
toggleItemSelection(select, position)
|
||||
}
|
||||
|
||||
override fun getSelectedPositions() = selectedPositions
|
||||
|
||||
override fun itemLongClicked(position: Int) {}
|
||||
}
|
||||
|
||||
fun getSelectedItemsSet(): HashSet<String> {
|
||||
val selectedItemsSet = HashSet<String>(selectedPositions.size)
|
||||
selectedPositions.forEach { selectedItemsSet.add(eventTypes[it].id.toString()) }
|
||||
return selectedItemsSet
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
|
||||
val view = activity.layoutInflater.inflate(R.layout.filter_event_type_view, parent, false)
|
||||
return ViewHolder(view, adapterListener, activity)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val eventType = eventTypes[position]
|
||||
itemViews.put(position, holder.bindView(eventType))
|
||||
toggleItemSelection(selectedPositions.contains(position), position)
|
||||
}
|
||||
|
||||
override fun getItemCount() = eventTypes.size
|
||||
|
||||
class ViewHolder(view: View, val adapterListener: MyAdapterListener, val activity: SimpleActivity) : RecyclerView.ViewHolder(view) {
|
||||
fun bindView(eventType: EventType): View {
|
||||
itemView.apply {
|
||||
filter_event_type_checkbox.setColors(activity.config.textColor, activity.config.primaryColor, activity.config.backgroundColor)
|
||||
filter_event_type_checkbox.text = eventType.getDisplayTitle()
|
||||
filter_event_type_color.setBackgroundWithStroke(eventType.color, activity.config.backgroundColor)
|
||||
filter_event_type_holder.setOnClickListener { viewClicked(!filter_event_type_checkbox.isChecked) }
|
||||
}
|
||||
|
||||
return itemView
|
||||
}
|
||||
|
||||
private fun viewClicked(select: Boolean) {
|
||||
adapterListener.toggleItemSelectionAdapter(select, adapterPosition)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
package com.simplemobiletools.calendar.adapters
|
||||
|
||||
import android.view.Menu
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.activities.SimpleActivity
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.calendar.extensions.dbHelper
|
||||
import com.simplemobiletools.calendar.helpers.DBHelper
|
||||
import com.simplemobiletools.calendar.interfaces.DeleteEventTypesListener
|
||||
import com.simplemobiletools.calendar.models.EventType
|
||||
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
|
||||
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||
import com.simplemobiletools.commons.extensions.setBackgroundWithStroke
|
||||
import com.simplemobiletools.commons.extensions.toast
|
||||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import com.simplemobiletools.commons.views.MyRecyclerView
|
||||
import kotlinx.android.synthetic.main.item_event_type.view.*
|
||||
import java.util.*
|
||||
|
||||
class ManageEventTypesAdapter(activity: SimpleActivity, val eventTypes: ArrayList<EventType>, val listener: DeleteEventTypesListener?, recyclerView: MyRecyclerView,
|
||||
itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, itemClick) {
|
||||
|
||||
override fun getActionMenuId() = R.menu.cab_event_type
|
||||
|
||||
override fun prepareActionMode(menu: Menu) {}
|
||||
|
||||
override fun prepareItemSelection(view: View) {}
|
||||
|
||||
override fun markItemSelection(select: Boolean, view: View?) {
|
||||
view?.event_item_frame?.isSelected = select
|
||||
}
|
||||
|
||||
override fun actionItemPressed(id: Int) {
|
||||
when (id) {
|
||||
R.id.cab_delete -> askConfirmDelete()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSelectableItemCount() = eventTypes.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int) = createViewHolder(R.layout.item_event_type, parent)
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val eventType = eventTypes[position]
|
||||
val view = holder.bindView(eventType) { itemView, layoutPosition ->
|
||||
setupView(itemView, eventType)
|
||||
}
|
||||
bindViewHolder(holder, position, view)
|
||||
}
|
||||
|
||||
override fun getItemCount() = eventTypes.size
|
||||
|
||||
private fun setupView(view: View, eventType: EventType) {
|
||||
view.apply {
|
||||
event_type_title.text = eventType.getDisplayTitle()
|
||||
event_type_color.setBackgroundWithStroke(eventType.color, activity.config.backgroundColor)
|
||||
event_type_title.setTextColor(textColor)
|
||||
}
|
||||
}
|
||||
|
||||
private fun askConfirmDelete() {
|
||||
val eventTypes = ArrayList<EventType>(selectedPositions.size)
|
||||
selectedPositions.forEach { eventTypes.add(this.eventTypes[it]) }
|
||||
|
||||
if (activity.dbHelper.doEventTypesContainEvent(eventTypes)) {
|
||||
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)))
|
||||
add(RadioItem(DELETE_EVENTS, res.getString(R.string.remove_affected_events)))
|
||||
}
|
||||
RadioGroupDialog(activity, items) {
|
||||
deleteEventTypes(it == DELETE_EVENTS)
|
||||
}
|
||||
} else {
|
||||
ConfirmationDialog(activity) {
|
||||
deleteEventTypes(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteEventTypes(deleteEvents: Boolean) {
|
||||
val eventTypesToDelete = ArrayList<EventType>(selectedPositions.size)
|
||||
|
||||
for (pos in selectedPositions) {
|
||||
if (eventTypes[pos].id == DBHelper.REGULAR_EVENT_TYPE_ID) {
|
||||
activity.toast(R.string.cannot_delete_default_type)
|
||||
selectedPositions.remove(pos)
|
||||
toggleItemSelection(false, pos)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
selectedPositions.sortedDescending().forEach {
|
||||
val eventType = eventTypes[it]
|
||||
eventTypesToDelete.add(eventType)
|
||||
}
|
||||
|
||||
eventTypes.removeAll(eventTypesToDelete)
|
||||
listener?.deleteEventTypes(eventTypesToDelete, deleteEvents)
|
||||
removeSelectedItems()
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
package com.simplemobiletools.calendar.adapters
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentManager
|
||||
import android.support.v4.app.FragmentStatePagerAdapter
|
||||
import android.util.SparseArray
|
||||
import com.simplemobiletools.calendar.fragments.WeekFragment
|
||||
import com.simplemobiletools.calendar.helpers.WEEK_START_TIMESTAMP
|
||||
|
||||
class MyWeekPagerAdapter(fm: FragmentManager, val mWeekTimestamps: List<Int>, val mListener: WeekFragment.WeekScrollListener) : FragmentStatePagerAdapter(fm) {
|
||||
private val mFragments = SparseArray<WeekFragment>()
|
||||
|
||||
override fun getCount() = mWeekTimestamps.size
|
||||
|
||||
override fun getItem(position: Int): Fragment {
|
||||
val bundle = Bundle()
|
||||
val weekTimestamp = mWeekTimestamps[position]
|
||||
bundle.putInt(WEEK_START_TIMESTAMP, weekTimestamp)
|
||||
|
||||
val fragment = WeekFragment()
|
||||
fragment.arguments = bundle
|
||||
fragment.mListener = mListener
|
||||
|
||||
mFragments.put(position, fragment)
|
||||
return fragment
|
||||
}
|
||||
|
||||
fun updateScrollY(pos: Int, y: Int) {
|
||||
mFragments[pos - 1]?.updateScrollY(y)
|
||||
mFragments[pos + 1]?.updateScrollY(y)
|
||||
}
|
||||
|
||||
fun refreshEvents(pos: Int) {
|
||||
for (i in -1..1) {
|
||||
mFragments[pos + i]?.updateEvents()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
package com.simplemobiletools.calendar.dialogs
|
||||
|
||||
import android.app.Activity
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.commons.extensions.hideKeyboard
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import com.simplemobiletools.commons.extensions.value
|
||||
import kotlinx.android.synthetic.main.dialog_custom_event_reminder.view.*
|
||||
|
||||
class CustomEventReminderDialog(val activity: Activity, val selectedMinutes: Int = 0, val callback: (minutes: Int) -> Unit) {
|
||||
var dialog: AlertDialog
|
||||
var view = (activity.layoutInflater.inflate(R.layout.dialog_custom_event_reminder, null) as ViewGroup).apply {
|
||||
when {
|
||||
selectedMinutes == 0 -> dialog_radio_view.check(R.id.dialog_radio_minutes)
|
||||
selectedMinutes % 1440 == 0 -> {
|
||||
dialog_radio_view.check(R.id.dialog_radio_days)
|
||||
dialog_custom_reminder_value.setText((selectedMinutes / 1440).toString())
|
||||
}
|
||||
selectedMinutes % 60 == 0 -> {
|
||||
dialog_radio_view.check(R.id.dialog_radio_hours)
|
||||
dialog_custom_reminder_value.setText((selectedMinutes / 60).toString())
|
||||
}
|
||||
else -> {
|
||||
dialog_radio_view.check(R.id.dialog_radio_minutes)
|
||||
dialog_custom_reminder_value.setText(selectedMinutes.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
dialog = AlertDialog.Builder(activity)
|
||||
.setPositiveButton(R.string.ok, { dialogInterface, i -> confirmReminder() })
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create().apply {
|
||||
window!!.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
||||
activity.setupDialogStuff(view, this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun confirmReminder() {
|
||||
val value = view.dialog_custom_reminder_value.value
|
||||
val multiplier = getMultiplier(view.dialog_radio_view.checkedRadioButtonId)
|
||||
val minutes = Integer.valueOf(if (value.isEmpty()) "0" else value)
|
||||
callback(minutes * multiplier)
|
||||
activity.hideKeyboard()
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
private fun getMultiplier(id: Int) = when (id) {
|
||||
R.id.dialog_radio_hours -> 60
|
||||
R.id.dialog_radio_days -> 1440
|
||||
else -> 1
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
package com.simplemobiletools.calendar.dialogs
|
||||
|
||||
import android.app.Activity
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.ViewGroup
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.extensions.dbHelper
|
||||
import com.simplemobiletools.commons.extensions.beVisibleIf
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import kotlinx.android.synthetic.main.dialog_delete_event.view.*
|
||||
|
||||
class DeleteEventDialog(val activity: Activity, eventIds: List<Int>, val callback: (allOccurrences: Boolean) -> Unit) {
|
||||
val dialog: AlertDialog?
|
||||
|
||||
init {
|
||||
val events = activity.dbHelper.getEventsWithIds(eventIds)
|
||||
val hasRepeatableEvent = events.any { it.repeatInterval > 0 }
|
||||
|
||||
val view = activity.layoutInflater.inflate(R.layout.dialog_delete_event, null).apply {
|
||||
delete_event_repeat_description.beVisibleIf(hasRepeatableEvent)
|
||||
delete_event_radio_view.beVisibleIf(hasRepeatableEvent)
|
||||
|
||||
if (eventIds.size > 1) {
|
||||
delete_event_repeat_description.text = resources.getString(R.string.selection_contains_repetition)
|
||||
}
|
||||
}
|
||||
|
||||
dialog = AlertDialog.Builder(activity)
|
||||
.setPositiveButton(R.string.yes, { dialog, which -> dialogConfirmed(view as ViewGroup, hasRepeatableEvent) })
|
||||
.setNegativeButton(R.string.no, null)
|
||||
.create().apply {
|
||||
activity.setupDialogStuff(view, this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun dialogConfirmed(view: ViewGroup, hasRepeatableEvent: Boolean) {
|
||||
val deleteAllOccurrences = !hasRepeatableEvent || view.delete_event_radio_view.checkedRadioButtonId == R.id.delete_event_all
|
||||
dialog?.dismiss()
|
||||
callback(deleteAllOccurrences)
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
package com.simplemobiletools.calendar.dialogs
|
||||
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.activities.SimpleActivity
|
||||
import com.simplemobiletools.calendar.adapters.FilterEventTypeAdapter
|
||||
import com.simplemobiletools.calendar.extensions.dbHelper
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import kotlinx.android.synthetic.main.dialog_export_events.view.*
|
||||
import java.io.File
|
||||
|
||||
class ExportEventsDialog(val activity: SimpleActivity, val path: String, val callback: (exportPastEvents: Boolean, file: File, eventTypes: HashSet<String>) -> Unit) {
|
||||
|
||||
init {
|
||||
val view = (activity.layoutInflater.inflate(R.layout.dialog_export_events, null) as ViewGroup).apply {
|
||||
export_events_folder.text = activity.humanizePath(path)
|
||||
export_events_filename.setText("events_${System.currentTimeMillis() / 1000}")
|
||||
|
||||
activity.dbHelper.getEventTypes {
|
||||
val eventTypes = HashSet<String>()
|
||||
it.mapTo(eventTypes, { it.id.toString() })
|
||||
|
||||
activity.runOnUiThread {
|
||||
export_events_types_list.adapter = FilterEventTypeAdapter(activity, it, eventTypes)
|
||||
if (it.size > 1) {
|
||||
export_events_pick_types.beVisible()
|
||||
|
||||
val margin = activity.resources.getDimension(R.dimen.normal_margin).toInt()
|
||||
(export_events_checkbox.layoutParams as LinearLayout.LayoutParams).leftMargin = margin
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AlertDialog.Builder(activity)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create().apply {
|
||||
activity.setupDialogStuff(view, this, R.string.export_events) {
|
||||
getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
||||
val filename = view.export_events_filename.value
|
||||
when {
|
||||
filename.isEmpty() -> activity.toast(R.string.empty_name)
|
||||
filename.isAValidFilename() -> {
|
||||
val file = File(path, "$filename.ics")
|
||||
if (file.exists()) {
|
||||
activity.toast(R.string.name_taken)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
val eventTypes = (view.export_events_types_list.adapter as FilterEventTypeAdapter).getSelectedItemsSet()
|
||||
callback(view.export_events_checkbox.isChecked, file, eventTypes)
|
||||
dismiss()
|
||||
}
|
||||
else -> activity.toast(R.string.invalid_name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package com.simplemobiletools.calendar.dialogs
|
||||
|
||||
import android.support.v7.app.AlertDialog
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.activities.SimpleActivity
|
||||
import com.simplemobiletools.calendar.adapters.FilterEventTypeAdapter
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.calendar.extensions.dbHelper
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import kotlinx.android.synthetic.main.dialog_filter_event_types.view.*
|
||||
|
||||
class FilterEventTypesDialog(val activity: SimpleActivity, val callback: () -> Unit) {
|
||||
var dialog: AlertDialog
|
||||
val view = activity.layoutInflater.inflate(R.layout.dialog_filter_event_types, null)
|
||||
|
||||
init {
|
||||
val eventTypes = activity.dbHelper.fetchEventTypes()
|
||||
val displayEventTypes = activity.config.displayEventTypes
|
||||
view.filter_event_types_list.adapter = FilterEventTypeAdapter(activity, eventTypes, displayEventTypes)
|
||||
|
||||
dialog = AlertDialog.Builder(activity)
|
||||
.setPositiveButton(R.string.ok, { dialogInterface, i -> confirmEventTypes() })
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create().apply {
|
||||
activity.setupDialogStuff(view, this, R.string.filter_events_by_type)
|
||||
}
|
||||
}
|
||||
|
||||
private fun confirmEventTypes() {
|
||||
val selectedItems = (view.filter_event_types_list.adapter as FilterEventTypeAdapter).getSelectedItemsSet()
|
||||
if (activity.config.displayEventTypes != selectedItems) {
|
||||
activity.config.displayEventTypes = selectedItems
|
||||
callback()
|
||||
}
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
package com.simplemobiletools.calendar.dialogs
|
||||
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.ViewGroup
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.activities.SimpleActivity
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.calendar.extensions.dbHelper
|
||||
import com.simplemobiletools.calendar.helpers.DBHelper
|
||||
import com.simplemobiletools.calendar.helpers.IcsImporter
|
||||
import com.simplemobiletools.calendar.helpers.IcsImporter.ImportResult.*
|
||||
import com.simplemobiletools.commons.extensions.setBackgroundWithStroke
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import com.simplemobiletools.commons.extensions.toast
|
||||
import kotlinx.android.synthetic.main.dialog_import_events.view.*
|
||||
|
||||
class ImportEventsDialog(val activity: SimpleActivity, val path: String, val callback: (refreshView: Boolean) -> Unit) {
|
||||
var currEventTypeId = DBHelper.REGULAR_EVENT_TYPE_ID
|
||||
|
||||
init {
|
||||
val view = (activity.layoutInflater.inflate(R.layout.dialog_import_events, null) as ViewGroup).apply {
|
||||
updateEventType(this)
|
||||
import_event_type_holder.setOnClickListener {
|
||||
SelectEventTypeDialog(activity, currEventTypeId) {
|
||||
currEventTypeId = it
|
||||
updateEventType(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AlertDialog.Builder(activity)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create().apply {
|
||||
activity.setupDialogStuff(view, this, R.string.import_events) {
|
||||
getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
||||
activity.toast(R.string.importing)
|
||||
Thread {
|
||||
val result = IcsImporter(activity).importEvents(path, currEventTypeId)
|
||||
handleParseResult(result)
|
||||
dismiss()
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateEventType(view: ViewGroup) {
|
||||
val eventType = activity.dbHelper.getEventType(currEventTypeId)
|
||||
view.import_event_type_title.text = eventType!!.getDisplayTitle()
|
||||
view.import_event_type_color.setBackgroundWithStroke(eventType.color, activity.config.backgroundColor)
|
||||
}
|
||||
|
||||
private fun handleParseResult(result: IcsImporter.ImportResult) {
|
||||
activity.toast(when (result) {
|
||||
IMPORT_OK -> R.string.events_imported_successfully
|
||||
IMPORT_PARTIAL -> R.string.importing_some_events_failed
|
||||
else -> R.string.importing_events_failed
|
||||
})
|
||||
callback(result != IMPORT_FAIL)
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
package com.simplemobiletools.calendar.dialogs
|
||||
|
||||
import android.app.Activity
|
||||
import android.graphics.Color
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.ViewGroup
|
||||
import android.widget.RadioButton
|
||||
import android.widget.RadioGroup
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.calendar.helpers.CalDAVHandler
|
||||
import com.simplemobiletools.calendar.models.EventType
|
||||
import com.simplemobiletools.commons.extensions.setBackgroundWithStroke
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import kotlinx.android.synthetic.main.dialog_select_radio_group.view.*
|
||||
import kotlinx.android.synthetic.main.radio_button_with_color.view.*
|
||||
|
||||
class SelectEventTypeColorDialog(val activity: Activity, val eventType: EventType, val callback: (color: Int) -> Unit) {
|
||||
private val dialog: AlertDialog?
|
||||
private val radioGroup: RadioGroup
|
||||
private var wasInit = false
|
||||
private val colors = CalDAVHandler(activity).getAvailableCalDAVCalendarColors(eventType)
|
||||
|
||||
init {
|
||||
val view = activity.layoutInflater.inflate(R.layout.dialog_select_radio_group, null) as ViewGroup
|
||||
radioGroup = view.dialog_radio_group
|
||||
|
||||
colors.forEachIndexed { index, value ->
|
||||
addRadioButton(index, value)
|
||||
}
|
||||
|
||||
wasInit = true
|
||||
dialog = AlertDialog.Builder(activity)
|
||||
.create().apply {
|
||||
activity.setupDialogStuff(view, this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addRadioButton(colorKey: Int, color: Int) {
|
||||
val view = activity.layoutInflater.inflate(R.layout.radio_button_with_color, null)
|
||||
(view.dialog_radio_button as RadioButton).apply {
|
||||
text = String.format("#%06X", 0xFFFFFF and color)
|
||||
isChecked = color == eventType.color
|
||||
id = colorKey
|
||||
}
|
||||
|
||||
if (color != Color.TRANSPARENT)
|
||||
view.dialog_radio_color.setBackgroundWithStroke(color, activity.config.backgroundColor)
|
||||
|
||||
view.setOnClickListener { viewClicked(colorKey) }
|
||||
radioGroup.addView(view, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
|
||||
}
|
||||
|
||||
private fun viewClicked(colorKey: Int) {
|
||||
if (!wasInit)
|
||||
return
|
||||
|
||||
callback(colors[colorKey])
|
||||
dialog?.dismiss()
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
package com.simplemobiletools.calendar.dialogs
|
||||
|
||||
import android.app.Activity
|
||||
import android.graphics.Color
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.ViewGroup
|
||||
import android.widget.RadioButton
|
||||
import android.widget.RadioGroup
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.calendar.extensions.dbHelper
|
||||
import com.simplemobiletools.calendar.models.EventType
|
||||
import com.simplemobiletools.commons.extensions.hideKeyboard
|
||||
import com.simplemobiletools.commons.extensions.setBackgroundWithStroke
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import com.simplemobiletools.commons.extensions.updateTextColors
|
||||
import kotlinx.android.synthetic.main.dialog_select_radio_group.view.*
|
||||
import kotlinx.android.synthetic.main.radio_button_with_color.view.*
|
||||
import java.util.*
|
||||
|
||||
class SelectEventTypeDialog(val activity: Activity, val currEventType: Int, val callback: (checkedId: Int) -> Unit) {
|
||||
private val NEW_TYPE_ID = -2
|
||||
|
||||
private val dialog: AlertDialog?
|
||||
private val radioGroup: RadioGroup
|
||||
private var wasInit = false
|
||||
private var eventTypes = ArrayList<EventType>()
|
||||
|
||||
init {
|
||||
val view = activity.layoutInflater.inflate(R.layout.dialog_select_radio_group, null) as ViewGroup
|
||||
radioGroup = view.dialog_radio_group
|
||||
|
||||
activity.dbHelper.getEventTypes {
|
||||
eventTypes = it
|
||||
activity.runOnUiThread {
|
||||
eventTypes.filter { it.caldavCalendarId == 0 }.forEach {
|
||||
addRadioButton(it.getDisplayTitle(), it.id, it.color)
|
||||
}
|
||||
addRadioButton(activity.getString(R.string.add_new_type), NEW_TYPE_ID, Color.TRANSPARENT)
|
||||
wasInit = true
|
||||
activity.updateTextColors(view.dialog_radio_holder)
|
||||
}
|
||||
}
|
||||
|
||||
dialog = AlertDialog.Builder(activity)
|
||||
.create().apply {
|
||||
activity.setupDialogStuff(view, this)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
text = title
|
||||
isChecked = typeId == currEventType
|
||||
id = typeId
|
||||
}
|
||||
|
||||
if (color != Color.TRANSPARENT)
|
||||
view.dialog_radio_color.setBackgroundWithStroke(color, activity.config.backgroundColor)
|
||||
|
||||
view.setOnClickListener { viewClicked(typeId) }
|
||||
radioGroup.addView(view, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
|
||||
}
|
||||
|
||||
private fun viewClicked(typeId: Int) {
|
||||
if (!wasInit)
|
||||
return
|
||||
|
||||
if (typeId == NEW_TYPE_ID) {
|
||||
UpdateEventTypeDialog(activity) {
|
||||
callback(it)
|
||||
activity.hideKeyboard()
|
||||
dialog?.dismiss()
|
||||
}
|
||||
} else {
|
||||
callback(typeId)
|
||||
dialog?.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package com.simplemobiletools.calendar.dialogs
|
||||
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.activities.SimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import com.simplemobiletools.commons.extensions.value
|
||||
import kotlinx.android.synthetic.main.dialog_snooze_picker.view.*
|
||||
|
||||
class SnoozePickerDialog(val activity: SimpleActivity, val minutes: Int, val callback: (newMinutes: Int) -> Unit) {
|
||||
init {
|
||||
val view = (activity.layoutInflater.inflate(R.layout.dialog_snooze_picker, null) as ViewGroup).apply {
|
||||
snooze_picker_label.text = snooze_picker_label.text.toString().capitalize()
|
||||
snooze_picker.setText(minutes.toString())
|
||||
}
|
||||
|
||||
AlertDialog.Builder(activity)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create().apply {
|
||||
activity.setupDialogStuff(view, this) {
|
||||
window!!.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
||||
getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
||||
val value = view.snooze_picker.value
|
||||
val minutes = Integer.valueOf(if (value.isEmpty() || value == "0") "1" else value)
|
||||
callback(minutes)
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
package com.simplemobiletools.calendar.dialogs
|
||||
|
||||
import android.app.Activity
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.WindowManager
|
||||
import android.widget.ImageView
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.calendar.extensions.dbHelper
|
||||
import com.simplemobiletools.calendar.models.EventType
|
||||
import com.simplemobiletools.commons.dialogs.ColorPickerDialog
|
||||
import com.simplemobiletools.commons.extensions.setBackgroundWithStroke
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import com.simplemobiletools.commons.extensions.toast
|
||||
import com.simplemobiletools.commons.extensions.value
|
||||
import kotlinx.android.synthetic.main.dialog_event_type.view.*
|
||||
|
||||
class UpdateEventTypeDialog(val activity: Activity, var eventType: EventType? = null, val callback: (eventTypeId: Int) -> Unit) {
|
||||
var isNewEvent = eventType == null
|
||||
|
||||
init {
|
||||
if (eventType == null)
|
||||
eventType = EventType(0, "", activity.config.primaryColor)
|
||||
|
||||
val view = activity.layoutInflater.inflate(R.layout.dialog_event_type, null).apply {
|
||||
setupColor(type_color)
|
||||
type_title.setText(eventType!!.title)
|
||||
type_color.setOnClickListener {
|
||||
if (eventType?.caldavCalendarId == 0) {
|
||||
ColorPickerDialog(activity, eventType!!.color) {
|
||||
eventType!!.color = it
|
||||
setupColor(type_color)
|
||||
}
|
||||
} else {
|
||||
SelectEventTypeColorDialog(activity, eventType!!) {
|
||||
eventType!!.color = it
|
||||
setupColor(type_color)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AlertDialog.Builder(activity)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create().apply {
|
||||
window!!.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
||||
activity.setupDialogStuff(view, this, if (isNewEvent) R.string.add_new_type else R.string.edit_type) {
|
||||
getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
||||
val title = view.type_title.value
|
||||
val eventIdWithTitle = activity.dbHelper.getEventTypeIdWithTitle(title)
|
||||
var isEventTypeTitleTaken = isNewEvent && eventIdWithTitle != -1
|
||||
if (!isEventTypeTitleTaken)
|
||||
isEventTypeTitleTaken = !isNewEvent && eventType!!.id != eventIdWithTitle && eventIdWithTitle != -1
|
||||
|
||||
if (title.isEmpty()) {
|
||||
activity.toast(R.string.title_empty)
|
||||
return@setOnClickListener
|
||||
} else if (isEventTypeTitleTaken) {
|
||||
activity.toast(R.string.type_already_exists)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
eventType!!.title = title
|
||||
if (eventType!!.caldavCalendarId != 0)
|
||||
eventType!!.caldavDisplayName = title
|
||||
|
||||
val eventTypeId = if (isNewEvent) {
|
||||
activity.dbHelper.insertEventType(eventType!!)
|
||||
} else {
|
||||
activity.dbHelper.updateEventType(eventType!!)
|
||||
}
|
||||
|
||||
if (eventTypeId != -1) {
|
||||
dismiss()
|
||||
callback(eventTypeId)
|
||||
} else {
|
||||
activity.toast(R.string.editing_calendar_failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupColor(view: ImageView) {
|
||||
view.setBackgroundWithStroke(eventType!!.color, activity.config.backgroundColor)
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package com.simplemobiletools.calendar.extensions
|
||||
|
||||
import com.simplemobiletools.calendar.BuildConfig
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.helpers.IcsExporter
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.getFilePublicUri
|
||||
import com.simplemobiletools.commons.extensions.shareUri
|
||||
import com.simplemobiletools.commons.extensions.toast
|
||||
import java.io.File
|
||||
|
||||
fun BaseSimpleActivity.shareEvents(ids: List<Int>) {
|
||||
val file = getTempFile()
|
||||
if (file == null) {
|
||||
toast(R.string.unknown_error_occurred)
|
||||
return
|
||||
}
|
||||
|
||||
val events = dbHelper.getEventsWithIds(ids)
|
||||
IcsExporter().exportEvents(this, file, events) {
|
||||
if (it == IcsExporter.ExportResult.EXPORT_OK) {
|
||||
val uri = getFilePublicUri(file, BuildConfig.APPLICATION_ID)
|
||||
shareUri(uri, BuildConfig.APPLICATION_ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun BaseSimpleActivity.getTempFile(): File? {
|
||||
val folder = File(cacheDir, "events")
|
||||
if (!folder.exists()) {
|
||||
if (!folder.mkdir()) {
|
||||
toast(R.string.unknown_error_occurred)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return File(folder, "events.ics")
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package com.simplemobiletools.calendar.extensions
|
||||
|
||||
import java.io.BufferedWriter
|
||||
|
||||
fun BufferedWriter.writeLn(line: String) {
|
||||
write(line)
|
||||
newLine()
|
||||
}
|
|
@ -1,325 +0,0 @@
|
|||
package com.simplemobiletools.calendar.extensions
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.*
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.Resources
|
||||
import android.net.Uri
|
||||
import android.support.v4.app.NotificationCompat
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.activities.EventActivity
|
||||
import com.simplemobiletools.calendar.helpers.*
|
||||
import com.simplemobiletools.calendar.helpers.Formatter
|
||||
import com.simplemobiletools.calendar.models.DayMonthly
|
||||
import com.simplemobiletools.calendar.models.Event
|
||||
import com.simplemobiletools.calendar.receivers.CalDAVSyncReceiver
|
||||
import com.simplemobiletools.calendar.receivers.NotificationReceiver
|
||||
import com.simplemobiletools.calendar.services.SnoozeService
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import org.joda.time.DateTime
|
||||
import org.joda.time.DateTimeZone
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
val Context.config: Config get() = Config.newInstance(applicationContext)
|
||||
|
||||
val Context.dbHelper: DBHelper get() = DBHelper.newInstance(applicationContext)
|
||||
|
||||
fun Context.updateWidgets() {
|
||||
val widgetsCnt = AppWidgetManager.getInstance(applicationContext).getAppWidgetIds(ComponentName(applicationContext, MyWidgetMonthlyProvider::class.java))
|
||||
if (widgetsCnt.isNotEmpty()) {
|
||||
val ids = intArrayOf(R.xml.widget_monthly_info)
|
||||
Intent(applicationContext, MyWidgetMonthlyProvider::class.java).apply {
|
||||
action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
|
||||
putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
|
||||
sendBroadcast(this)
|
||||
}
|
||||
}
|
||||
|
||||
updateListWidget()
|
||||
}
|
||||
|
||||
fun Context.updateListWidget() {
|
||||
val widgetsCnt = AppWidgetManager.getInstance(applicationContext).getAppWidgetIds(ComponentName(applicationContext, MyWidgetListProvider::class.java))
|
||||
if (widgetsCnt.isNotEmpty()) {
|
||||
val ids = intArrayOf(R.xml.widget_list_info)
|
||||
Intent(applicationContext, MyWidgetListProvider::class.java).apply {
|
||||
action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
|
||||
putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
|
||||
sendBroadcast(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.scheduleAllEvents() {
|
||||
val events = dbHelper.getEventsAtReboot()
|
||||
events.forEach {
|
||||
scheduleNextEventReminder(it, dbHelper)
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.scheduleNextEventReminder(event: Event, dbHelper: DBHelper) {
|
||||
if (event.getReminders().isEmpty())
|
||||
return
|
||||
|
||||
val now = (System.currentTimeMillis() / 1000).toInt()
|
||||
val reminderSeconds = event.getReminders().reversed().map { it * 60 }
|
||||
dbHelper.getEvents(now, now + YEAR, event.id) {
|
||||
if (it.isNotEmpty()) {
|
||||
for (curEvent in it) {
|
||||
for (curReminder in reminderSeconds) {
|
||||
if (curEvent.getEventStartTS() - curReminder > now) {
|
||||
scheduleEventIn((curEvent.getEventStartTS() - curReminder) * 1000L, curEvent)
|
||||
return@getEvents
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.scheduleEventIn(notifTS: Long, event: Event) {
|
||||
if (notifTS < System.currentTimeMillis())
|
||||
return
|
||||
|
||||
val pendingIntent = getNotificationIntent(applicationContext, event)
|
||||
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
|
||||
when {
|
||||
isMarshmallowPlus() -> alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, notifTS, pendingIntent)
|
||||
isKitkatPlus() -> alarmManager.setExact(AlarmManager.RTC_WAKEUP, notifTS, pendingIntent)
|
||||
else -> alarmManager.set(AlarmManager.RTC_WAKEUP, notifTS, pendingIntent)
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.cancelNotification(id: Int) {
|
||||
val intent = Intent(applicationContext, NotificationReceiver::class.java)
|
||||
PendingIntent.getBroadcast(applicationContext, id, intent, PendingIntent.FLAG_UPDATE_CURRENT).cancel()
|
||||
}
|
||||
|
||||
private fun getNotificationIntent(context: Context, event: Event): PendingIntent {
|
||||
val intent = Intent(context, NotificationReceiver::class.java)
|
||||
intent.putExtra(EVENT_ID, event.id)
|
||||
intent.putExtra(EVENT_OCCURRENCE_TS, event.startTS)
|
||||
return PendingIntent.getBroadcast(context, event.id, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
}
|
||||
|
||||
fun Context.getFormattedMinutes(minutes: Int, showBefore: Boolean = true) = when (minutes) {
|
||||
-1 -> getString(R.string.no_reminder)
|
||||
0 -> getString(R.string.at_start)
|
||||
else -> {
|
||||
if (minutes % 525600 == 0)
|
||||
resources.getQuantityString(R.plurals.years, minutes / 525600, minutes / 525600)
|
||||
|
||||
when {
|
||||
minutes % 43200 == 0 -> resources.getQuantityString(R.plurals.months, minutes / 43200, minutes / 43200)
|
||||
minutes % 10080 == 0 -> resources.getQuantityString(R.plurals.weeks, minutes / 10080, minutes / 10080)
|
||||
minutes % 1440 == 0 -> resources.getQuantityString(R.plurals.days, minutes / 1440, minutes / 1440)
|
||||
minutes % 60 == 0 -> {
|
||||
val base = if (showBefore) R.plurals.hours_before else R.plurals.by_hours
|
||||
resources.getQuantityString(base, minutes / 60, minutes / 60)
|
||||
}
|
||||
else -> {
|
||||
val base = if (showBefore) R.plurals.minutes_before else R.plurals.by_minutes
|
||||
resources.getQuantityString(base, minutes, minutes)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.getRepetitionText(seconds: Int) = when (seconds) {
|
||||
0 -> getString(R.string.no_repetition)
|
||||
DAY -> getString(R.string.daily)
|
||||
WEEK -> getString(R.string.weekly)
|
||||
MONTH -> getString(R.string.monthly)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.getFilteredEvents(events: List<Event>): List<Event> {
|
||||
val displayEventTypes = config.displayEventTypes
|
||||
return events.filter { displayEventTypes.contains(it.eventType.toString()) }
|
||||
}
|
||||
|
||||
fun Context.notifyRunningEvents() {
|
||||
dbHelper.getRunningEvents().forEach { notifyEvent(it) }
|
||||
}
|
||||
|
||||
fun Context.notifyEvent(event: Event) {
|
||||
val pendingIntent = getPendingIntent(applicationContext, event)
|
||||
val startTime = Formatter.getTimeFromTS(applicationContext, event.startTS)
|
||||
val endTime = Formatter.getTimeFromTS(applicationContext, event.endTS)
|
||||
val timeRange = if (event.getIsAllDay()) getString(R.string.all_day) else getFormattedEventTime(startTime, endTime)
|
||||
val descriptionOrLocation = if (config.replaceDescription) event.location else event.description
|
||||
val notification = getNotification(applicationContext, pendingIntent, event, "$timeRange $descriptionOrLocation")
|
||||
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
notificationManager.notify(event.id, notification)
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private fun getNotification(context: Context, pendingIntent: PendingIntent, event: Event, content: String): Notification {
|
||||
val channelId = "reminder_channel"
|
||||
if (context.isOreoPlus()) {
|
||||
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
val name = context.resources.getString(R.string.event_reminders)
|
||||
val importance = NotificationManager.IMPORTANCE_HIGH
|
||||
NotificationChannel(channelId, name, importance).apply {
|
||||
enableLights(true)
|
||||
lightColor = event.color
|
||||
enableVibration(false)
|
||||
notificationManager.createNotificationChannel(this)
|
||||
}
|
||||
}
|
||||
|
||||
val soundUri = Uri.parse(context.config.reminderSound)
|
||||
val builder = NotificationCompat.Builder(context)
|
||||
.setContentTitle(event.title)
|
||||
.setContentText(content)
|
||||
.setSmallIcon(R.drawable.ic_calendar)
|
||||
.setContentIntent(pendingIntent)
|
||||
.setPriority(Notification.PRIORITY_HIGH)
|
||||
.setDefaults(Notification.DEFAULT_LIGHTS)
|
||||
.setAutoCancel(true)
|
||||
.setSound(soundUri)
|
||||
.setChannelId(channelId)
|
||||
.addAction(R.drawable.ic_snooze, context.getString(R.string.snooze), getSnoozePendingIntent(context, event))
|
||||
|
||||
if (context.isLollipopPlus())
|
||||
builder.setVisibility(Notification.VISIBILITY_PUBLIC)
|
||||
|
||||
if (context.config.vibrateOnReminder)
|
||||
builder.setVibrate(longArrayOf(0, 300, 300, 300))
|
||||
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
private fun getFormattedEventTime(startTime: String, endTime: String) = if (startTime == endTime) startTime else "$startTime - $endTime"
|
||||
|
||||
private fun getPendingIntent(context: Context, event: Event): PendingIntent {
|
||||
val intent = Intent(context, EventActivity::class.java)
|
||||
intent.putExtra(EVENT_ID, event.id)
|
||||
intent.putExtra(EVENT_OCCURRENCE_TS, event.startTS)
|
||||
return PendingIntent.getActivity(context, event.id, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
}
|
||||
|
||||
private fun getSnoozePendingIntent(context: Context, event: Event): PendingIntent {
|
||||
val intent = Intent(context, SnoozeService::class.java).setAction("snooze")
|
||||
intent.putExtra(EVENT_ID, event.id)
|
||||
intent.putExtra(EVENT_OCCURRENCE_TS, event.startTS)
|
||||
return PendingIntent.getService(context, event.id, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
}
|
||||
|
||||
fun Context.launchNewEventIntent() {
|
||||
val code = Formatter.getDayCodeFromDateTime(DateTime(DateTimeZone.getDefault()))
|
||||
Intent(applicationContext, EventActivity::class.java).apply {
|
||||
putExtra(NEW_EVENT_START_TS, getNewEventTimestampFromCode(code))
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
startActivity(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.getNewEventTimestampFromCode(dayCode: String): Int {
|
||||
val currHour = DateTime(System.currentTimeMillis(), DateTimeZone.getDefault()).hourOfDay
|
||||
val dateTime = Formatter.getLocalDateTimeFromCode(dayCode).withHourOfDay(currHour)
|
||||
val newDateTime = dateTime.plusHours(1).withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0)
|
||||
// make sure the date doesn't change
|
||||
return newDateTime.withDate(dateTime.year, dateTime.monthOfYear, dateTime.dayOfMonth).seconds()
|
||||
}
|
||||
|
||||
fun Context.getCurrentOffset() = SimpleDateFormat("Z", Locale.getDefault()).format(Date())
|
||||
|
||||
fun Context.getSyncedCalDAVCalendars() = CalDAVHandler(applicationContext).getCalDAVCalendars(null, config.caldavSyncedCalendarIDs)
|
||||
|
||||
fun Context.recheckCalDAVCalendars(callback: () -> Unit) {
|
||||
if (config.caldavSync) {
|
||||
Thread {
|
||||
CalDAVHandler(applicationContext).refreshCalendars(null, callback)
|
||||
updateWidgets()
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.scheduleCalDAVSync(activate: Boolean) {
|
||||
val syncIntent = Intent(applicationContext, CalDAVSyncReceiver::class.java)
|
||||
val pendingIntent = PendingIntent.getBroadcast(applicationContext, 0, syncIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
val alarm = getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
|
||||
if (activate) {
|
||||
val syncCheckInterval = 4 * AlarmManager.INTERVAL_HOUR
|
||||
alarm.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + syncCheckInterval, syncCheckInterval, pendingIntent)
|
||||
} else {
|
||||
alarm.cancel(pendingIntent)
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.addDayNumber(rawTextColor: Int, day: DayMonthly, linearLayout: LinearLayout, dayLabelHeight: Int, callback: (Int) -> Unit) {
|
||||
var textColor = rawTextColor
|
||||
if (!day.isThisMonth)
|
||||
textColor = textColor.adjustAlpha(LOW_ALPHA)
|
||||
|
||||
(View.inflate(applicationContext, R.layout.day_monthly_number_view, null) as TextView).apply {
|
||||
setTextColor(textColor)
|
||||
text = day.value.toString()
|
||||
gravity = Gravity.TOP or Gravity.CENTER_HORIZONTAL
|
||||
layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
linearLayout.addView(this)
|
||||
|
||||
if (day.isToday) {
|
||||
val primaryColor = config.primaryColor
|
||||
setTextColor(config.primaryColor.getContrastColor())
|
||||
if (dayLabelHeight == 0) {
|
||||
onGlobalLayout {
|
||||
val height = this@apply.height
|
||||
if (height > 0) {
|
||||
callback(height)
|
||||
addTodaysBackground(this, resources, height, primaryColor)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
addTodaysBackground(this, resources, dayLabelHeight, primaryColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addTodaysBackground(textView: TextView, res: Resources, dayLabelHeight: Int, mPrimaryColor: Int) =
|
||||
textView.addResizedBackgroundDrawable(res, dayLabelHeight, mPrimaryColor, R.drawable.monthly_today_circle)
|
||||
|
||||
fun Context.addDayEvents(day: DayMonthly, linearLayout: LinearLayout, res: Resources, dividerMargin: Int) {
|
||||
val eventLayoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
|
||||
day.dayEvents.sortedWith(compareBy({ it.startTS }, { it.endTS }, { it.title })).forEach {
|
||||
val backgroundDrawable = res.getDrawable(R.drawable.day_monthly_event_background)
|
||||
backgroundDrawable.applyColorFilter(it.color)
|
||||
eventLayoutParams.setMargins(dividerMargin, 0, dividerMargin, dividerMargin)
|
||||
|
||||
var textColor = it.color.getContrastColor()
|
||||
if (!day.isThisMonth) {
|
||||
backgroundDrawable.alpha = 64
|
||||
textColor = textColor.adjustAlpha(0.25f)
|
||||
}
|
||||
|
||||
(View.inflate(applicationContext, R.layout.day_monthly_event_view, null) as TextView).apply {
|
||||
setTextColor(textColor)
|
||||
text = it.title.replace(" ", "\u00A0") // allow word break by char
|
||||
background = backgroundDrawable
|
||||
layoutParams = eventLayoutParams
|
||||
linearLayout.addView(this)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
package com.simplemobiletools.calendar.extensions
|
||||
|
||||
import org.joda.time.DateTime
|
||||
|
||||
fun DateTime.seconds() = (millis / 1000).toInt()
|
|
@ -1,16 +0,0 @@
|
|||
package com.simplemobiletools.calendar.extensions
|
||||
|
||||
import com.simplemobiletools.calendar.helpers.Formatter
|
||||
import com.simplemobiletools.calendar.helpers.MONTH
|
||||
import com.simplemobiletools.calendar.helpers.WEEK
|
||||
import com.simplemobiletools.calendar.models.Event
|
||||
|
||||
fun Int.isTsOnProperDay(event: Event): Boolean {
|
||||
val dateTime = Formatter.getDateTimeFromTS(this)
|
||||
val power = Math.pow(2.0, (dateTime.dayOfWeek - 1).toDouble()).toInt()
|
||||
return event.repeatRule and power != 0
|
||||
}
|
||||
|
||||
fun Int.isXWeeklyRepetition() = this != 0 && this % WEEK == 0
|
||||
|
||||
fun Int.isXMonthlyRepetition() = this != 0 && this % MONTH == 0
|
|
@ -1,8 +0,0 @@
|
|||
package com.simplemobiletools.calendar.extensions
|
||||
|
||||
fun String.substringTo(cnt: Int): String {
|
||||
return if (isEmpty()) {
|
||||
""
|
||||
} else
|
||||
substring(0, Math.min(length, cnt))
|
||||
}
|
|
@ -1,170 +0,0 @@
|
|||
package com.simplemobiletools.calendar.fragments
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.res.Resources
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.DatePicker
|
||||
import android.widget.RelativeLayout
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.activities.DayActivity
|
||||
import com.simplemobiletools.calendar.activities.EventActivity
|
||||
import com.simplemobiletools.calendar.activities.SimpleActivity
|
||||
import com.simplemobiletools.calendar.adapters.DayEventsAdapter
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.calendar.extensions.dbHelper
|
||||
import com.simplemobiletools.calendar.extensions.getFilteredEvents
|
||||
import com.simplemobiletools.calendar.helpers.DAY_CODE
|
||||
import com.simplemobiletools.calendar.helpers.EVENT_ID
|
||||
import com.simplemobiletools.calendar.helpers.EVENT_OCCURRENCE_TS
|
||||
import com.simplemobiletools.calendar.helpers.Formatter
|
||||
import com.simplemobiletools.calendar.interfaces.DeleteEventsListener
|
||||
import com.simplemobiletools.calendar.interfaces.NavigationListener
|
||||
import com.simplemobiletools.calendar.models.Event
|
||||
import com.simplemobiletools.commons.extensions.applyColorFilter
|
||||
import com.simplemobiletools.commons.extensions.getDialogTheme
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import kotlinx.android.synthetic.main.fragment_day.view.*
|
||||
import kotlinx.android.synthetic.main.top_navigation.view.*
|
||||
import org.joda.time.DateTime
|
||||
import java.util.*
|
||||
|
||||
class DayFragment : Fragment(), DeleteEventsListener {
|
||||
var mListener: NavigationListener? = null
|
||||
private var mTextColor = 0
|
||||
private var mDayCode = ""
|
||||
private var lastHash = 0
|
||||
|
||||
lateinit var mRes: Resources
|
||||
lateinit var mHolder: RelativeLayout
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
val view = inflater.inflate(R.layout.fragment_day, container, false)
|
||||
mRes = resources
|
||||
mHolder = view.day_holder
|
||||
|
||||
mDayCode = arguments!!.getString(DAY_CODE)
|
||||
val day = Formatter.getDayTitle(context!!, mDayCode)
|
||||
mHolder.top_value.apply {
|
||||
text = day
|
||||
setOnClickListener { pickDay() }
|
||||
setTextColor(context.config.textColor)
|
||||
}
|
||||
|
||||
setupButtons()
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
checkEvents()
|
||||
}
|
||||
|
||||
private fun setupButtons() {
|
||||
mTextColor = context!!.config.textColor
|
||||
|
||||
mHolder.apply {
|
||||
top_left_arrow.applyColorFilter(mTextColor)
|
||||
top_right_arrow.applyColorFilter(mTextColor)
|
||||
top_left_arrow.background = null
|
||||
top_right_arrow.background = null
|
||||
|
||||
top_left_arrow.setOnClickListener {
|
||||
mListener?.goLeft()
|
||||
}
|
||||
|
||||
top_right_arrow.setOnClickListener {
|
||||
mListener?.goRight()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getDayEventsAdapter() = mHolder.day_events?.adapter as? DayEventsAdapter
|
||||
|
||||
private fun pickDay() {
|
||||
activity!!.setTheme(context!!.getDialogTheme())
|
||||
val view = layoutInflater.inflate(R.layout.date_picker, null)
|
||||
val datePicker = view.findViewById<DatePicker>(R.id.date_picker)
|
||||
|
||||
val dateTime = Formatter.getDateTimeFromCode(mDayCode)
|
||||
datePicker.init(dateTime.year, dateTime.monthOfYear - 1, dateTime.dayOfMonth, null)
|
||||
|
||||
AlertDialog.Builder(context!!)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setPositiveButton(R.string.ok) { dialog, which -> positivePressed(dateTime, datePicker) }
|
||||
.create().apply {
|
||||
activity?.setupDialogStuff(view, this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun positivePressed(dateTime: DateTime, datePicker: DatePicker) {
|
||||
val month = datePicker.month + 1
|
||||
val year = datePicker.year
|
||||
val day = datePicker.dayOfMonth
|
||||
val newDateTime = dateTime.withDate(year, month, day)
|
||||
mListener?.goToDateTime(newDateTime)
|
||||
}
|
||||
|
||||
fun checkEvents() {
|
||||
val startTS = Formatter.getDayStartTS(mDayCode)
|
||||
val endTS = Formatter.getDayEndTS(mDayCode)
|
||||
context!!.dbHelper.getEvents(startTS, endTS) {
|
||||
receivedEvents(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun receivedEvents(events: List<Event>) {
|
||||
val filtered = context?.getFilteredEvents(events) ?: ArrayList()
|
||||
val newHash = filtered.hashCode()
|
||||
if (newHash == lastHash || !isAdded) {
|
||||
return
|
||||
}
|
||||
lastHash = newHash
|
||||
|
||||
val replaceDescription = context!!.config.replaceDescription
|
||||
val sorted = ArrayList<Event>(filtered.sortedWith(compareBy({ it.startTS }, { it.endTS }, { it.title }, {
|
||||
if (replaceDescription) it.location else it.description
|
||||
})))
|
||||
|
||||
activity?.runOnUiThread {
|
||||
updateEvents(sorted)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateEvents(events: ArrayList<Event>) {
|
||||
if (activity == null)
|
||||
return
|
||||
|
||||
DayEventsAdapter(activity as SimpleActivity, events, this, mHolder.day_events) {
|
||||
editEvent(it as Event)
|
||||
}.apply {
|
||||
setupDragListener(true)
|
||||
addVerticalDividers(true)
|
||||
mHolder.day_events.adapter = this
|
||||
}
|
||||
}
|
||||
|
||||
private fun editEvent(event: Event) {
|
||||
Intent(context, EventActivity::class.java).apply {
|
||||
putExtra(EVENT_ID, event.id)
|
||||
putExtra(EVENT_OCCURRENCE_TS, event.startTS)
|
||||
startActivity(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun deleteItems(ids: ArrayList<Int>) {
|
||||
val eventIDs = Array(ids.size, { i -> (ids[i].toString()) })
|
||||
context!!.dbHelper.deleteEvents(eventIDs, true)
|
||||
}
|
||||
|
||||
override fun addEventRepeatException(parentIds: ArrayList<Int>, timestamps: ArrayList<Int>) {
|
||||
parentIds.forEachIndexed { index, value ->
|
||||
context!!.dbHelper.addEventRepeatException(parentIds[index], timestamps[index])
|
||||
}
|
||||
(activity as DayActivity).recheckEvents()
|
||||
}
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
package com.simplemobiletools.calendar.fragments
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.activities.EventActivity
|
||||
import com.simplemobiletools.calendar.activities.SimpleActivity
|
||||
import com.simplemobiletools.calendar.adapters.EventListAdapter
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.calendar.extensions.dbHelper
|
||||
import com.simplemobiletools.calendar.extensions.getFilteredEvents
|
||||
import com.simplemobiletools.calendar.extensions.seconds
|
||||
import com.simplemobiletools.calendar.helpers.EVENT_ID
|
||||
import com.simplemobiletools.calendar.helpers.EVENT_OCCURRENCE_TS
|
||||
import com.simplemobiletools.calendar.helpers.Formatter
|
||||
import com.simplemobiletools.calendar.interfaces.DeleteEventsListener
|
||||
import com.simplemobiletools.calendar.models.Event
|
||||
import com.simplemobiletools.calendar.models.ListEvent
|
||||
import com.simplemobiletools.calendar.models.ListItem
|
||||
import com.simplemobiletools.calendar.models.ListSection
|
||||
import com.simplemobiletools.commons.extensions.beGoneIf
|
||||
import com.simplemobiletools.commons.extensions.beVisibleIf
|
||||
import kotlinx.android.synthetic.main.fragment_event_list.view.*
|
||||
import org.joda.time.DateTime
|
||||
import java.util.*
|
||||
|
||||
class EventListFragment : Fragment(), DeleteEventsListener {
|
||||
private var mEvents: List<Event> = ArrayList()
|
||||
private var prevEventsHash = 0
|
||||
private var lastHash = 0
|
||||
lateinit var mView: View
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
mView = inflater.inflate(R.layout.fragment_event_list, container, false)
|
||||
val placeholderText = String.format(getString(R.string.two_string_placeholder), "${getString(R.string.no_upcoming_events)}\n", getString(R.string.add_some_events))
|
||||
mView.calendar_empty_list_placeholder.text = placeholderText
|
||||
return mView
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
checkEvents()
|
||||
}
|
||||
|
||||
private fun checkEvents() {
|
||||
val fromTS = DateTime().seconds() - context!!.config.displayPastEvents * 60
|
||||
val toTS = DateTime().plusYears(1).seconds()
|
||||
context!!.dbHelper.getEvents(fromTS, toTS) {
|
||||
receivedEvents(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun receivedEvents(events: MutableList<Event>) {
|
||||
if (context == null || activity == null)
|
||||
return
|
||||
|
||||
val newHash = events.hashCode()
|
||||
if (newHash == lastHash) {
|
||||
return
|
||||
}
|
||||
lastHash = newHash
|
||||
|
||||
val filtered = context!!.getFilteredEvents(events)
|
||||
val hash = filtered.hashCode()
|
||||
if (prevEventsHash == hash)
|
||||
return
|
||||
|
||||
prevEventsHash = hash
|
||||
mEvents = filtered
|
||||
val listItems = ArrayList<ListItem>(mEvents.size)
|
||||
val replaceDescription = context!!.config.replaceDescription
|
||||
val sorted = mEvents.sortedWith(compareBy({ it.startTS }, { it.endTS }, { it.title }, { if (replaceDescription) it.location else it.description }))
|
||||
val sublist = sorted.subList(0, Math.min(sorted.size, 100))
|
||||
var prevCode = ""
|
||||
sublist.forEach {
|
||||
val code = Formatter.getDayCodeFromTS(it.startTS)
|
||||
if (code != prevCode) {
|
||||
val day = Formatter.getDayTitle(context!!, code)
|
||||
listItems.add(ListSection(day))
|
||||
prevCode = code
|
||||
}
|
||||
listItems.add(ListEvent(it.id, it.startTS, it.endTS, it.title, it.description, it.getIsAllDay(), it.color, it.location))
|
||||
}
|
||||
|
||||
val eventsAdapter = EventListAdapter(activity as SimpleActivity, listItems, true, this, mView.calendar_events_list) {
|
||||
if (it is ListEvent) {
|
||||
editEvent(it)
|
||||
}
|
||||
}
|
||||
|
||||
activity?.runOnUiThread {
|
||||
mView.calendar_events_list.apply {
|
||||
this@apply.adapter = eventsAdapter
|
||||
}
|
||||
checkPlaceholderVisibility()
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPlaceholderVisibility() {
|
||||
mView.calendar_empty_list_placeholder.beVisibleIf(mEvents.isEmpty())
|
||||
mView.calendar_events_list.beGoneIf(mEvents.isEmpty())
|
||||
if (activity != null)
|
||||
mView.calendar_empty_list_placeholder.setTextColor(activity!!.config.textColor)
|
||||
}
|
||||
|
||||
private fun editEvent(event: ListEvent) {
|
||||
Intent(context, EventActivity::class.java).apply {
|
||||
putExtra(EVENT_ID, event.id)
|
||||
putExtra(EVENT_OCCURRENCE_TS, event.startTS)
|
||||
startActivity(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun deleteItems(ids: ArrayList<Int>) {
|
||||
val eventIDs = Array(ids.size, { i -> (ids[i].toString()) })
|
||||
context!!.dbHelper.deleteEvents(eventIDs, true)
|
||||
checkEvents()
|
||||
}
|
||||
|
||||
override fun addEventRepeatException(parentIds: ArrayList<Int>, timestamps: ArrayList<Int>) {
|
||||
parentIds.forEachIndexed { index, value ->
|
||||
context!!.dbHelper.addEventRepeatException(value, timestamps[index])
|
||||
}
|
||||
checkEvents()
|
||||
}
|
||||
}
|
|
@ -1,201 +0,0 @@
|
|||
package com.simplemobiletools.calendar.fragments
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.Resources
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.DatePicker
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.TextView
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.activities.DayActivity
|
||||
import com.simplemobiletools.calendar.extensions.addDayEvents
|
||||
import com.simplemobiletools.calendar.extensions.addDayNumber
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.calendar.helpers.*
|
||||
import com.simplemobiletools.calendar.interfaces.MonthlyCalendar
|
||||
import com.simplemobiletools.calendar.interfaces.NavigationListener
|
||||
import com.simplemobiletools.calendar.models.DayMonthly
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import kotlinx.android.synthetic.main.first_row.*
|
||||
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 mPrimaryColor = 0
|
||||
private var mSundayFirst = false
|
||||
private var mDayCode = ""
|
||||
private var mPackageName = ""
|
||||
private var dayLabelHeight = 0
|
||||
private var lastHash = 0L
|
||||
|
||||
var listener: NavigationListener? = null
|
||||
|
||||
lateinit var mRes: Resources
|
||||
lateinit var mHolder: RelativeLayout
|
||||
lateinit var mConfig: Config
|
||||
lateinit var mCalendar: MonthlyCalendarImpl
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
val view = inflater.inflate(R.layout.fragment_month, container, false)
|
||||
mRes = resources
|
||||
mPackageName = activity!!.packageName
|
||||
|
||||
mHolder = view.calendar_holder
|
||||
mDayCode = arguments!!.getString(DAY_CODE)
|
||||
mConfig = context!!.config
|
||||
mSundayFirst = mConfig.isSundayFirst
|
||||
|
||||
setupButtons()
|
||||
|
||||
setupLabels()
|
||||
mCalendar = MonthlyCalendarImpl(this, context!!)
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (mConfig.isSundayFirst != mSundayFirst) {
|
||||
mSundayFirst = mConfig.isSundayFirst
|
||||
setupLabels()
|
||||
}
|
||||
|
||||
mCalendar.apply {
|
||||
mTargetDate = Formatter.getDateTimeFromCode(mDayCode)
|
||||
getDays(false) // prefill the screen asap, even if without events
|
||||
}
|
||||
updateCalendar()
|
||||
}
|
||||
|
||||
fun updateCalendar() {
|
||||
mCalendar.updateMonthlyCalendar(Formatter.getDateTimeFromCode(mDayCode))
|
||||
}
|
||||
|
||||
override fun updateMonthlyCalendar(context: Context, month: String, days: List<DayMonthly>, checkedEvents: Boolean) {
|
||||
val newHash = month.hashCode() + days.hashCode().toLong()
|
||||
if ((lastHash != 0L && !checkedEvents) || lastHash == newHash) {
|
||||
return
|
||||
}
|
||||
lastHash = newHash
|
||||
|
||||
activity?.runOnUiThread {
|
||||
mHolder.top_value.apply {
|
||||
text = month
|
||||
setTextColor(mConfig.textColor)
|
||||
}
|
||||
updateDays(days)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupButtons() {
|
||||
val baseColor = mConfig.textColor
|
||||
mTextColor = baseColor
|
||||
mPrimaryColor = mConfig.primaryColor
|
||||
|
||||
mHolder.top_left_arrow.apply {
|
||||
applyColorFilter(mTextColor)
|
||||
background = null
|
||||
setOnClickListener {
|
||||
listener?.goLeft()
|
||||
}
|
||||
}
|
||||
|
||||
mHolder.top_right_arrow.apply {
|
||||
applyColorFilter(mTextColor)
|
||||
background = null
|
||||
setOnClickListener {
|
||||
listener?.goRight()
|
||||
}
|
||||
}
|
||||
|
||||
mHolder.top_value.setOnClickListener { showMonthDialog() }
|
||||
}
|
||||
|
||||
private fun showMonthDialog() {
|
||||
activity!!.setTheme(context!!.getDialogTheme())
|
||||
val view = layoutInflater.inflate(R.layout.date_picker, null)
|
||||
val datePicker = view.findViewById<DatePicker>(R.id.date_picker)
|
||||
datePicker.findViewById<View>(Resources.getSystem().getIdentifier("day", "id", "android")).beGone()
|
||||
|
||||
val dateTime = DateTime(mCalendar.mTargetDate.toString())
|
||||
datePicker.init(dateTime.year, dateTime.monthOfYear - 1, 1, null)
|
||||
|
||||
AlertDialog.Builder(context!!)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setPositiveButton(R.string.ok) { dialog, which -> positivePressed(dateTime, datePicker) }
|
||||
.create().apply {
|
||||
activity?.setupDialogStuff(view, this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun positivePressed(dateTime: DateTime, datePicker: DatePicker) {
|
||||
val month = datePicker.month + 1
|
||||
val year = datePicker.year
|
||||
val newDateTime = dateTime.withDate(year, month, 1)
|
||||
listener?.goToDateTime(newDateTime)
|
||||
}
|
||||
|
||||
private fun setupLabels() {
|
||||
val letters = letterIDs
|
||||
|
||||
for (i in 0..6) {
|
||||
var index = i
|
||||
if (!mSundayFirst)
|
||||
index = (index + 1) % letters.size
|
||||
|
||||
mHolder.findViewById<TextView>(mRes.getIdentifier("label_$i", "id", mPackageName)).apply {
|
||||
setTextColor(mTextColor)
|
||||
text = getString(letters[index])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateDays(days: List<DayMonthly>) {
|
||||
val displayWeekNumbers = mConfig.displayWeekNumbers
|
||||
val len = days.size
|
||||
|
||||
if (week_num == null)
|
||||
return
|
||||
|
||||
week_num.setTextColor(mTextColor)
|
||||
week_num.beVisibleIf(displayWeekNumbers)
|
||||
|
||||
for (i in 0..5) {
|
||||
mHolder.findViewById<TextView>(mRes.getIdentifier("week_num_$i", "id", mPackageName)).apply {
|
||||
text = "${days[i * 7 + 3].weekOfYear}:" // fourth day of the week matters
|
||||
setTextColor(mTextColor)
|
||||
beVisibleIf(displayWeekNumbers)
|
||||
}
|
||||
}
|
||||
|
||||
val dividerMargin = mRes.displayMetrics.density.toInt()
|
||||
for (i in 0 until len) {
|
||||
mHolder.findViewById<LinearLayout>(mRes.getIdentifier("day_$i", "id", mPackageName)).apply {
|
||||
val day = days[i]
|
||||
setOnClickListener { openDay(day.code) }
|
||||
|
||||
removeAllViews()
|
||||
context.addDayNumber(mTextColor, day, this, dayLabelHeight) { dayLabelHeight = it }
|
||||
context.addDayEvents(day, this, mRes, dividerMargin)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun openDay(code: String) {
|
||||
if (code.isNotEmpty()) {
|
||||
Intent(context, DayActivity::class.java).apply {
|
||||
putExtra(DAY_CODE, code)
|
||||
startActivity(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,440 +0,0 @@
|
|||
package com.simplemobiletools.calendar.fragments
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Rect
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.view.*
|
||||
import android.widget.ImageView
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.TextView
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.activities.EventActivity
|
||||
import com.simplemobiletools.calendar.activities.MainActivity
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.calendar.extensions.getFilteredEvents
|
||||
import com.simplemobiletools.calendar.extensions.seconds
|
||||
import com.simplemobiletools.calendar.helpers.*
|
||||
import com.simplemobiletools.calendar.helpers.Formatter
|
||||
import com.simplemobiletools.calendar.interfaces.WeeklyCalendar
|
||||
import com.simplemobiletools.calendar.models.Event
|
||||
import com.simplemobiletools.calendar.views.MyScrollView
|
||||
import com.simplemobiletools.commons.extensions.applyColorFilter
|
||||
import com.simplemobiletools.commons.extensions.beGone
|
||||
import com.simplemobiletools.commons.extensions.getContrastColor
|
||||
import kotlinx.android.synthetic.main.fragment_week.*
|
||||
import kotlinx.android.synthetic.main.fragment_week.view.*
|
||||
import org.joda.time.DateTime
|
||||
import org.joda.time.Days
|
||||
import java.util.*
|
||||
|
||||
class WeekFragment : Fragment(), WeeklyCalendar {
|
||||
private val CLICK_DURATION_THRESHOLD = 150
|
||||
private val PLUS_FADEOUT_DELAY = 5000L
|
||||
|
||||
var mListener: WeekScrollListener? = null
|
||||
private var mWeekTimestamp = 0
|
||||
private var mRowHeight = 0
|
||||
private var minScrollY = -1
|
||||
private var maxScrollY = -1
|
||||
private var mWasDestroyed = false
|
||||
private var primaryColor = 0
|
||||
private var lastHash = 0
|
||||
private var isFragmentVisible = false
|
||||
private var wasFragmentInit = false
|
||||
private var wasExtraHeightAdded = false
|
||||
private var clickStartTime = 0L
|
||||
private var selectedGrid: View? = null
|
||||
private var todayColumnIndex = -1
|
||||
private var events = ArrayList<Event>()
|
||||
private var allDayHolders = ArrayList<RelativeLayout>()
|
||||
private var allDayRows = ArrayList<HashSet<Int>>()
|
||||
|
||||
lateinit var inflater: LayoutInflater
|
||||
lateinit var mView: View
|
||||
lateinit var mCalendar: WeeklyCalendarImpl
|
||||
lateinit var mRes: Resources
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
this.inflater = inflater
|
||||
mRowHeight = (context!!.resources.getDimension(R.dimen.weekly_view_row_height)).toInt()
|
||||
minScrollY = mRowHeight * context!!.config.startWeeklyAt
|
||||
mWeekTimestamp = arguments!!.getInt(WEEK_START_TIMESTAMP)
|
||||
primaryColor = context!!.config.primaryColor
|
||||
mRes = resources
|
||||
allDayRows.add(HashSet())
|
||||
|
||||
mView = inflater.inflate(R.layout.fragment_week, container, false).apply {
|
||||
week_events_scrollview.setOnScrollviewListener(object : MyScrollView.ScrollViewListener {
|
||||
override fun onScrollChanged(scrollView: MyScrollView, x: Int, y: Int, oldx: Int, oldy: Int) {
|
||||
checkScrollLimits(y)
|
||||
}
|
||||
})
|
||||
|
||||
week_events_scrollview.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
|
||||
override fun onGlobalLayout() {
|
||||
week_events_scrollview.viewTreeObserver.removeOnGlobalLayoutListener(this)
|
||||
updateScrollY(Math.max(MainActivity.mWeekScrollY, minScrollY))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
(0..6).map { inflater.inflate(R.layout.stroke_vertical_divider, mView.week_vertical_grid_holder) }
|
||||
(0..23).map { inflater.inflate(R.layout.stroke_horizontal_divider, mView.week_horizontal_grid_holder) }
|
||||
|
||||
mCalendar = WeeklyCalendarImpl(this, context!!)
|
||||
wasFragmentInit = true
|
||||
return mView
|
||||
}
|
||||
|
||||
override fun setMenuVisibility(menuVisible: Boolean) {
|
||||
super.setMenuVisibility(menuVisible)
|
||||
isFragmentVisible = menuVisible
|
||||
if (isFragmentVisible && wasFragmentInit) {
|
||||
(activity as MainActivity).updateHoursTopMargin(mView.week_top_holder.height)
|
||||
checkScrollLimits(mView.week_events_scrollview.scrollY)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
wasExtraHeightAdded = true
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
setupDayLabels()
|
||||
mCalendar.updateWeeklyCalendar(mWeekTimestamp)
|
||||
|
||||
mView.week_events_scrollview.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
|
||||
override fun onGlobalLayout() {
|
||||
if (context == null)
|
||||
return
|
||||
|
||||
mView.week_events_scrollview.viewTreeObserver.removeOnGlobalLayoutListener(this)
|
||||
minScrollY = mRowHeight * context!!.config.startWeeklyAt
|
||||
maxScrollY = mRowHeight * context!!.config.endWeeklyAt
|
||||
|
||||
val bounds = Rect()
|
||||
week_events_holder.getGlobalVisibleRect(bounds)
|
||||
maxScrollY -= bounds.bottom - bounds.top
|
||||
if (minScrollY > maxScrollY)
|
||||
maxScrollY = -1
|
||||
|
||||
checkScrollLimits(mView.week_events_scrollview.scrollY)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun setupDayLabels() {
|
||||
var curDay = Formatter.getDateTimeFromTS(mWeekTimestamp)
|
||||
val textColor = context!!.config.textColor
|
||||
val todayCode = Formatter.getDayCodeFromDateTime(DateTime())
|
||||
for (i in 0..6) {
|
||||
val dayCode = Formatter.getDayCodeFromDateTime(curDay)
|
||||
val dayLetter = getDayLetter(curDay.dayOfWeek)
|
||||
mView.findViewById<TextView>(mRes.getIdentifier("week_day_label_$i", "id", context!!.packageName)).apply {
|
||||
text = "$dayLetter\n${curDay.dayOfMonth}"
|
||||
setTextColor(if (todayCode == dayCode) primaryColor else textColor)
|
||||
if (todayCode == dayCode)
|
||||
todayColumnIndex = i
|
||||
}
|
||||
curDay = curDay.plusDays(1)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDayLetter(pos: Int): String {
|
||||
return mRes.getString(when (pos) {
|
||||
1 -> R.string.monday_letter
|
||||
2 -> R.string.tuesday_letter
|
||||
3 -> R.string.wednesday_letter
|
||||
4 -> R.string.thursday_letter
|
||||
5 -> R.string.friday_letter
|
||||
6 -> R.string.saturday_letter
|
||||
else -> R.string.sunday_letter
|
||||
})
|
||||
}
|
||||
|
||||
private fun checkScrollLimits(y: Int) {
|
||||
if (minScrollY != -1 && y < minScrollY) {
|
||||
mView.week_events_scrollview.scrollY = minScrollY
|
||||
} else if (maxScrollY != -1 && y > maxScrollY) {
|
||||
mView.week_events_scrollview.scrollY = maxScrollY
|
||||
} else {
|
||||
if (isFragmentVisible)
|
||||
mListener?.scrollTo(y)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initGrid() {
|
||||
(0..6).map { getColumnWithId(it) }
|
||||
.forEachIndexed { index, layout ->
|
||||
layout.removeAllViews()
|
||||
layout.setOnTouchListener { view, motionEvent ->
|
||||
checkGridClick(motionEvent, index, layout)
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkGridClick(event: MotionEvent, index: Int, view: ViewGroup) {
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> clickStartTime = System.currentTimeMillis()
|
||||
MotionEvent.ACTION_UP -> {
|
||||
if (System.currentTimeMillis() - clickStartTime < CLICK_DURATION_THRESHOLD) {
|
||||
selectedGrid?.animation?.cancel()
|
||||
selectedGrid?.beGone()
|
||||
|
||||
val rowHeight = resources.getDimension(R.dimen.weekly_view_row_height)
|
||||
val hour = (event.y / rowHeight).toInt()
|
||||
selectedGrid = (inflater.inflate(R.layout.week_grid_item, null, false) as View).apply {
|
||||
view.addView(this)
|
||||
background = ColorDrawable(primaryColor)
|
||||
layoutParams.width = view.width
|
||||
layoutParams.height = rowHeight.toInt()
|
||||
y = hour * rowHeight
|
||||
|
||||
setOnClickListener {
|
||||
val timestamp = mWeekTimestamp + index * DAY_SECONDS + hour * 60 * 60
|
||||
Intent(context, EventActivity::class.java).apply {
|
||||
putExtra(NEW_EVENT_START_TS, timestamp)
|
||||
putExtra(NEW_EVENT_SET_HOUR_DURATION, true)
|
||||
startActivity(this)
|
||||
}
|
||||
}
|
||||
animate().alpha(0f).setStartDelay(PLUS_FADEOUT_DELAY).withEndAction {
|
||||
beGone()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateWeeklyCalendar(events: ArrayList<Event>) {
|
||||
val newHash = events.hashCode()
|
||||
if (newHash == lastHash) {
|
||||
return
|
||||
}
|
||||
lastHash = newHash
|
||||
this.events = events
|
||||
updateEvents()
|
||||
}
|
||||
|
||||
fun updateEvents() {
|
||||
if (mWasDestroyed)
|
||||
return
|
||||
|
||||
activity!!.runOnUiThread {
|
||||
if (context != null && isAdded)
|
||||
addEvents()
|
||||
}
|
||||
}
|
||||
|
||||
private fun addEvents() {
|
||||
val filtered = context!!.getFilteredEvents(events)
|
||||
|
||||
initGrid()
|
||||
allDayHolders.clear()
|
||||
allDayRows.clear()
|
||||
allDayRows.add(HashSet())
|
||||
week_all_day_holder?.removeAllViews()
|
||||
|
||||
addNewLine()
|
||||
|
||||
val fullHeight = mRes.getDimension(R.dimen.weekly_view_events_height)
|
||||
val minuteHeight = fullHeight / (24 * 60)
|
||||
val minimalHeight = mRes.getDimension(R.dimen.weekly_view_minimal_event_height).toInt()
|
||||
|
||||
var hadAllDayEvent = false
|
||||
val replaceDescription = context!!.config.replaceDescription
|
||||
val sorted = filtered.sortedWith(compareBy({ it.startTS }, { it.endTS }, { it.title }, { if (replaceDescription) it.location else it.description }))
|
||||
for (event in sorted) {
|
||||
if (event.getIsAllDay() || Formatter.getDayCodeFromTS(event.startTS) != Formatter.getDayCodeFromTS(event.endTS)) {
|
||||
hadAllDayEvent = true
|
||||
addAllDayEvent(event)
|
||||
} else {
|
||||
val startDateTime = Formatter.getDateTimeFromTS(event.startTS)
|
||||
val endDateTime = Formatter.getDateTimeFromTS(event.endTS)
|
||||
val dayOfWeek = startDateTime.plusDays(if (context!!.config.isSundayFirst) 1 else 0).dayOfWeek - 1
|
||||
val layout = getColumnWithId(dayOfWeek)
|
||||
|
||||
val startMinutes = startDateTime.minuteOfDay
|
||||
val duration = endDateTime.minuteOfDay - startMinutes
|
||||
|
||||
(inflater.inflate(R.layout.week_event_marker, null, false) as TextView).apply {
|
||||
val backgroundColor = MainActivity.eventTypeColors.get(event.eventType, primaryColor)
|
||||
background = ColorDrawable(backgroundColor)
|
||||
setTextColor(backgroundColor.getContrastColor())
|
||||
text = event.title
|
||||
layout.addView(this)
|
||||
y = startMinutes * minuteHeight
|
||||
(layoutParams as RelativeLayout.LayoutParams).apply {
|
||||
width = layout.width - 1
|
||||
minHeight = if (event.startTS == event.endTS) minimalHeight else (duration * minuteHeight).toInt() - 1
|
||||
}
|
||||
setOnClickListener {
|
||||
Intent(context, EventActivity::class.java).apply {
|
||||
putExtra(EVENT_ID, event.id)
|
||||
putExtra(EVENT_OCCURRENCE_TS, event.startTS)
|
||||
startActivity(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hadAllDayEvent) {
|
||||
checkTopHolderHeight()
|
||||
}
|
||||
|
||||
addCurrentTimeIndicator(minuteHeight)
|
||||
}
|
||||
|
||||
private fun addNewLine() {
|
||||
val allDaysLine = inflater.inflate(R.layout.all_day_events_holder_line, null, false) as RelativeLayout
|
||||
week_all_day_holder.addView(allDaysLine)
|
||||
allDayHolders.add(allDaysLine)
|
||||
}
|
||||
|
||||
private fun addCurrentTimeIndicator(minuteHeight: Float) {
|
||||
if (todayColumnIndex != -1) {
|
||||
val minutes = DateTime().minuteOfDay
|
||||
val todayColumn = getColumnWithId(todayColumnIndex)
|
||||
(inflater.inflate(R.layout.week_now_marker, null, false) as ImageView).apply {
|
||||
applyColorFilter(primaryColor)
|
||||
mView.week_events_holder.addView(this, 0)
|
||||
val extraWidth = (todayColumn.width * 0.3).toInt()
|
||||
val markerHeight = resources.getDimension(R.dimen.weekly_view_now_height).toInt()
|
||||
(layoutParams as RelativeLayout.LayoutParams).apply {
|
||||
width = todayColumn.width + extraWidth
|
||||
height = markerHeight
|
||||
}
|
||||
x = todayColumn.x - extraWidth / 2
|
||||
y = minutes * minuteHeight - markerHeight / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkTopHolderHeight() {
|
||||
mView.week_top_holder.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
|
||||
override fun onGlobalLayout() {
|
||||
mView.week_top_holder.viewTreeObserver.removeOnGlobalLayoutListener(this)
|
||||
if (isFragmentVisible && activity != null) {
|
||||
(activity as MainActivity).updateHoursTopMargin(mView.week_top_holder.height)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun addAllDayEvent(event: Event) {
|
||||
(inflater.inflate(R.layout.week_all_day_event_marker, null, false) as TextView).apply {
|
||||
if (activity == null)
|
||||
return
|
||||
|
||||
val backgroundColor = MainActivity.eventTypeColors.get(event.eventType, primaryColor)
|
||||
background = ColorDrawable(backgroundColor)
|
||||
setTextColor(backgroundColor.getContrastColor())
|
||||
text = event.title
|
||||
|
||||
val startDateTime = Formatter.getDateTimeFromTS(event.startTS)
|
||||
val endDateTime = Formatter.getDateTimeFromTS(event.endTS)
|
||||
|
||||
val minTS = Math.max(startDateTime.seconds(), mWeekTimestamp)
|
||||
val maxTS = Math.min(endDateTime.seconds(), mWeekTimestamp + WEEK_SECONDS)
|
||||
val startDateTimeInWeek = Formatter.getDateTimeFromTS(minTS)
|
||||
val firstDayIndex = (startDateTimeInWeek.dayOfWeek - if (context.config.isSundayFirst) 0 else 1) % 7
|
||||
val daysCnt = Days.daysBetween(Formatter.getDateTimeFromTS(minTS).toLocalDate(), Formatter.getDateTimeFromTS(maxTS).toLocalDate()).days
|
||||
|
||||
var doesEventFit: Boolean
|
||||
val cnt = allDayRows.size - 1
|
||||
var wasEventHandled = false
|
||||
var drawAtLine = 0
|
||||
for (index in 0..cnt) {
|
||||
doesEventFit = true
|
||||
drawAtLine = index
|
||||
val row = allDayRows[index]
|
||||
for (i in firstDayIndex..firstDayIndex + daysCnt) {
|
||||
if (row.contains(i)) {
|
||||
doesEventFit = false
|
||||
}
|
||||
}
|
||||
|
||||
for (dayIndex in firstDayIndex..firstDayIndex + daysCnt) {
|
||||
if (doesEventFit) {
|
||||
row.add(dayIndex)
|
||||
wasEventHandled = true
|
||||
} else if (index == cnt) {
|
||||
if (allDayRows.size == index + 1) {
|
||||
allDayRows.add(HashSet<Int>())
|
||||
addNewLine()
|
||||
drawAtLine++
|
||||
wasEventHandled = true
|
||||
}
|
||||
allDayRows.last().add(dayIndex)
|
||||
}
|
||||
}
|
||||
if (wasEventHandled) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
allDayHolders[drawAtLine].addView(this)
|
||||
(layoutParams as RelativeLayout.LayoutParams).apply {
|
||||
topMargin = mRes.getDimension(R.dimen.tiny_margin).toInt()
|
||||
leftMargin = getColumnWithId(firstDayIndex).x.toInt()
|
||||
bottomMargin = 1
|
||||
width = getColumnWithId(Math.min(firstDayIndex + daysCnt, 6)).right - leftMargin - 1
|
||||
}
|
||||
|
||||
calculateExtraHeight()
|
||||
|
||||
setOnClickListener {
|
||||
Intent(context, EventActivity::class.java).apply {
|
||||
putExtra(EVENT_ID, event.id)
|
||||
putExtra(EVENT_OCCURRENCE_TS, event.startTS)
|
||||
startActivity(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateExtraHeight() {
|
||||
mView.week_top_holder.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
|
||||
override fun onGlobalLayout() {
|
||||
if (activity == null)
|
||||
return
|
||||
|
||||
mView.week_top_holder.viewTreeObserver.removeOnGlobalLayoutListener(this)
|
||||
if (isFragmentVisible) {
|
||||
(activity as MainActivity).updateHoursTopMargin(mView.week_top_holder.height)
|
||||
}
|
||||
|
||||
if (!wasExtraHeightAdded) {
|
||||
maxScrollY += mView.week_all_day_holder.height
|
||||
wasExtraHeightAdded = true
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
mWasDestroyed = true
|
||||
}
|
||||
|
||||
private fun getColumnWithId(id: Int) = mView.findViewById<ViewGroup>(mRes.getIdentifier("week_column_$id", "id", context!!.packageName))
|
||||
|
||||
fun updateScrollY(y: Int) {
|
||||
if (wasFragmentInit)
|
||||
mView.week_events_scrollview.scrollY = y
|
||||
}
|
||||
|
||||
interface WeekScrollListener {
|
||||
fun scrollTo(y: Int)
|
||||
}
|
||||
}
|
|
@ -1,406 +0,0 @@
|
|||
package com.simplemobiletools.calendar.helpers
|
||||
|
||||
import android.content.ContentUris
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.provider.CalendarContract
|
||||
import android.provider.CalendarContract.Reminders
|
||||
import android.util.SparseIntArray
|
||||
import com.simplemobiletools.calendar.activities.SimpleActivity
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.calendar.extensions.dbHelper
|
||||
import com.simplemobiletools.calendar.extensions.scheduleCalDAVSync
|
||||
import com.simplemobiletools.calendar.models.CalDAVCalendar
|
||||
import com.simplemobiletools.calendar.models.Event
|
||||
import com.simplemobiletools.calendar.models.EventType
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.PERMISSION_READ_CALENDAR
|
||||
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_CALENDAR
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class CalDAVHandler(val context: Context) {
|
||||
fun refreshCalendars(activity: SimpleActivity? = null, callback: () -> Unit) {
|
||||
val dbHelper = context.dbHelper
|
||||
for (calendar in getCalDAVCalendars(activity, context.config.caldavSyncedCalendarIDs)) {
|
||||
val localEventType = dbHelper.getEventTypeWithCalDAVCalendarId(calendar.id) ?: continue
|
||||
localEventType.apply {
|
||||
title = calendar.displayName
|
||||
caldavDisplayName = calendar.displayName
|
||||
caldavEmail = calendar.accountName
|
||||
color = calendar.color
|
||||
dbHelper.updateLocalEventType(this)
|
||||
}
|
||||
|
||||
CalDAVHandler(context).fetchCalDAVCalendarEvents(calendar.id, localEventType.id, activity)
|
||||
}
|
||||
context.scheduleCalDAVSync(true)
|
||||
callback()
|
||||
}
|
||||
|
||||
fun getCalDAVCalendars(activity: SimpleActivity? = null, ids: String = ""): List<CalDAVCalendar> {
|
||||
val calendars = ArrayList<CalDAVCalendar>()
|
||||
if (!context.hasPermission(PERMISSION_WRITE_CALENDAR) || !context.hasPermission(PERMISSION_READ_CALENDAR)) {
|
||||
return calendars
|
||||
}
|
||||
|
||||
val uri = CalendarContract.Calendars.CONTENT_URI
|
||||
val projection = arrayOf(
|
||||
CalendarContract.Calendars._ID,
|
||||
CalendarContract.Calendars.CALENDAR_DISPLAY_NAME,
|
||||
CalendarContract.Calendars.ACCOUNT_NAME,
|
||||
CalendarContract.Calendars.OWNER_ACCOUNT,
|
||||
CalendarContract.Calendars.CALENDAR_COLOR,
|
||||
CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL)
|
||||
|
||||
val selection = if (ids.trim().isNotEmpty()) "${CalendarContract.Calendars._ID} IN ($ids)" else null
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = context.contentResolver.query(uri, projection, selection, null, null)
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
val id = cursor.getIntValue(CalendarContract.Calendars._ID)
|
||||
val displayName = cursor.getStringValue(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME)
|
||||
val accountName = cursor.getStringValue(CalendarContract.Calendars.ACCOUNT_NAME)
|
||||
val ownerName = cursor.getStringValue(CalendarContract.Calendars.OWNER_ACCOUNT)
|
||||
val color = cursor.getIntValue(CalendarContract.Calendars.CALENDAR_COLOR)
|
||||
val accessLevel = cursor.getIntValue(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL)
|
||||
val calendar = CalDAVCalendar(id, displayName, accountName, ownerName, color, accessLevel)
|
||||
calendars.add(calendar)
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
activity?.showErrorToast(e)
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
return calendars
|
||||
}
|
||||
|
||||
fun updateCalDAVCalendar(eventType: EventType): Boolean {
|
||||
val uri = CalendarContract.Calendars.CONTENT_URI
|
||||
val values = fillCalendarContentValues(eventType)
|
||||
val newUri = ContentUris.withAppendedId(uri, eventType.caldavCalendarId.toLong())
|
||||
return try {
|
||||
context.contentResolver.update(newUri, values, null, null) == 1
|
||||
} catch (e: IllegalArgumentException) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun fillCalendarContentValues(eventType: EventType): ContentValues {
|
||||
val colorKey = getEventTypeColorKey(eventType)
|
||||
return ContentValues().apply {
|
||||
put(CalendarContract.Calendars.CALENDAR_COLOR_KEY, colorKey)
|
||||
put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, eventType.title)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getEventTypeColorKey(eventType: EventType): Int {
|
||||
val uri = CalendarContract.Colors.CONTENT_URI
|
||||
val projection = arrayOf(CalendarContract.Colors.COLOR_KEY)
|
||||
val selection = "${CalendarContract.Colors.COLOR_TYPE} = ? AND ${CalendarContract.Colors.COLOR} = ? AND ${CalendarContract.Colors.ACCOUNT_NAME} = ?"
|
||||
val selectionArgs = arrayOf(CalendarContract.Colors.TYPE_CALENDAR.toString(), eventType.color.toString(), eventType.caldavEmail)
|
||||
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
return cursor.getStringValue(CalendarContract.Colors.COLOR_KEY).toInt()
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
// it doesnt work properly, needs better SyncAdapter handling
|
||||
private fun insertNewColor(eventType: EventType): Int {
|
||||
val maxId = getMaxColorId(eventType) + 1
|
||||
|
||||
val values = ContentValues().apply {
|
||||
put(CalendarContract.Colors.COLOR_KEY, maxId)
|
||||
put(CalendarContract.Colors.COLOR, eventType.color)
|
||||
put(CalendarContract.Colors.ACCOUNT_NAME, eventType.caldavEmail)
|
||||
put(CalendarContract.Colors.ACCOUNT_TYPE, "com.google")
|
||||
put(CalendarContract.Colors.COLOR_TYPE, CalendarContract.Colors.TYPE_CALENDAR)
|
||||
}
|
||||
|
||||
val uri = CalendarContract.Colors.CONTENT_URI.buildUpon()
|
||||
.appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
|
||||
.appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, eventType.caldavEmail)
|
||||
.appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, "com.google")
|
||||
.build()
|
||||
|
||||
return if (context.contentResolver.insert(uri, values) != null) {
|
||||
maxId
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
private fun getMaxColorId(eventType: EventType): Int {
|
||||
val uri = CalendarContract.Colors.CONTENT_URI
|
||||
val projection = arrayOf(CalendarContract.Colors.COLOR_KEY, CalendarContract.Colors.COLOR)
|
||||
val selection = "${CalendarContract.Colors.COLOR_TYPE} = ? AND ${CalendarContract.Colors.ACCOUNT_NAME} = ?"
|
||||
val selectionArgs = arrayOf(CalendarContract.Colors.TYPE_CALENDAR.toString(), eventType.caldavEmail)
|
||||
var maxId = 1
|
||||
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null)
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
maxId = Math.max(maxId, cursor.getIntValue(CalendarContract.Colors.COLOR_KEY))
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
|
||||
return maxId
|
||||
}
|
||||
|
||||
fun getAvailableCalDAVCalendarColors(eventType: EventType): ArrayList<Int> {
|
||||
val colors = SparseIntArray()
|
||||
val uri = CalendarContract.Colors.CONTENT_URI
|
||||
val projection = arrayOf(CalendarContract.Colors.COLOR, CalendarContract.Colors.COLOR_KEY)
|
||||
val selection = "${CalendarContract.Colors.COLOR_TYPE} = ? AND ${CalendarContract.Colors.ACCOUNT_NAME} = ?"
|
||||
val selectionArgs = arrayOf(CalendarContract.Colors.TYPE_CALENDAR.toString(), eventType.caldavEmail)
|
||||
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null)
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
val colorKey = cursor.getIntValue(CalendarContract.Colors.COLOR_KEY)
|
||||
val color = cursor.getIntValue(CalendarContract.Colors.COLOR)
|
||||
colors.put(colorKey, color)
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
|
||||
val sortedColors = ArrayList<Int>(colors.size())
|
||||
(0 until colors.size()).mapTo(sortedColors) { colors[it] }
|
||||
|
||||
return sortedColors
|
||||
}
|
||||
|
||||
private fun fetchCalDAVCalendarEvents(calendarId: Int, eventTypeId: Int, activity: SimpleActivity?) {
|
||||
val importIdsMap = HashMap<String, Event>()
|
||||
val fetchedEventIds = ArrayList<String>()
|
||||
val existingEvents = context.dbHelper.getEventsFromCalDAVCalendar(calendarId)
|
||||
existingEvents.forEach {
|
||||
importIdsMap.put(it.importId, it)
|
||||
}
|
||||
|
||||
val uri = CalendarContract.Events.CONTENT_URI
|
||||
val projection = arrayOf(
|
||||
CalendarContract.Events._ID,
|
||||
CalendarContract.Events.TITLE,
|
||||
CalendarContract.Events.DESCRIPTION,
|
||||
CalendarContract.Events.DTSTART,
|
||||
CalendarContract.Events.DTEND,
|
||||
CalendarContract.Events.DURATION,
|
||||
CalendarContract.Events.ALL_DAY,
|
||||
CalendarContract.Events.RRULE,
|
||||
CalendarContract.Events.EVENT_LOCATION)
|
||||
|
||||
val selection = "${CalendarContract.Events.CALENDAR_ID} = $calendarId"
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = context.contentResolver.query(uri, projection, selection, null, null)
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
val id = cursor.getLongValue(CalendarContract.Events._ID)
|
||||
val title = cursor.getStringValue(CalendarContract.Events.TITLE) ?: continue
|
||||
val description = cursor.getStringValue(CalendarContract.Events.DESCRIPTION) ?: ""
|
||||
val startTS = (cursor.getLongValue(CalendarContract.Events.DTSTART) / 1000).toInt()
|
||||
var endTS = (cursor.getLongValue(CalendarContract.Events.DTEND) / 1000).toInt()
|
||||
val allDay = cursor.getIntValue(CalendarContract.Events.ALL_DAY)
|
||||
val rrule = cursor.getStringValue(CalendarContract.Events.RRULE) ?: ""
|
||||
val location = cursor.getStringValue(CalendarContract.Events.EVENT_LOCATION) ?: ""
|
||||
val reminders = getCalDAVEventReminders(id)
|
||||
|
||||
if (endTS == 0) {
|
||||
val duration = cursor.getStringValue(CalendarContract.Events.DURATION) ?: ""
|
||||
endTS = startTS + Parser().parseDurationSeconds(duration)
|
||||
}
|
||||
|
||||
val importId = getCalDAVEventImportId(calendarId, id)
|
||||
val repeatRule = Parser().parseRepeatInterval(rrule, startTS)
|
||||
val event = Event(0, startTS, endTS, title, description, reminders.getOrElse(0, { -1 }),
|
||||
reminders.getOrElse(1, { -1 }), reminders.getOrElse(2, { -1 }), repeatRule.repeatInterval,
|
||||
importId, allDay, repeatRule.repeatLimit, repeatRule.repeatRule, eventTypeId, source = "$CALDAV-$calendarId",
|
||||
location = location)
|
||||
|
||||
if (event.getIsAllDay() && endTS > startTS) {
|
||||
event.endTS -= DAY
|
||||
}
|
||||
|
||||
fetchedEventIds.add(importId)
|
||||
if (importIdsMap.containsKey(event.importId)) {
|
||||
val existingEvent = importIdsMap[importId]
|
||||
val originalEventId = existingEvent!!.id
|
||||
existingEvent.id = 0
|
||||
if (existingEvent.hashCode() != event.hashCode()) {
|
||||
event.id = originalEventId
|
||||
context.dbHelper.update(event, false) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
context.dbHelper.insert(event, false) {
|
||||
importIdsMap.put(event.importId, event)
|
||||
}
|
||||
}
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
activity?.showErrorToast(e)
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
|
||||
val eventIdsToDelete = ArrayList<String>()
|
||||
importIdsMap.keys.filter { !fetchedEventIds.contains(it) }.forEach {
|
||||
val caldavEventId = it
|
||||
existingEvents.forEach {
|
||||
if (it.importId == caldavEventId) {
|
||||
eventIdsToDelete.add(it.id.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eventIdsToDelete.forEach {
|
||||
context.dbHelper.deleteEvents(eventIdsToDelete.toTypedArray(), false)
|
||||
}
|
||||
}
|
||||
|
||||
fun insertCalDAVEvent(event: Event) {
|
||||
val uri = CalendarContract.Events.CONTENT_URI
|
||||
val values = fillEventContentValues(event)
|
||||
val newUri = context.contentResolver.insert(uri, values)
|
||||
|
||||
val calendarId = event.getCalDAVCalendarId()
|
||||
val eventRemoteID = java.lang.Long.parseLong(newUri.lastPathSegment)
|
||||
event.importId = getCalDAVEventImportId(calendarId, eventRemoteID)
|
||||
|
||||
setupCalDAVEventReminders(event)
|
||||
setupCalDAVEventImportId(event)
|
||||
}
|
||||
|
||||
fun updateCalDAVEvent(event: Event) {
|
||||
val uri = CalendarContract.Events.CONTENT_URI
|
||||
val values = fillEventContentValues(event)
|
||||
val eventRemoteID = event.getCalDAVEventId()
|
||||
event.importId = getCalDAVEventImportId(event.getCalDAVCalendarId(), eventRemoteID)
|
||||
|
||||
val newUri = ContentUris.withAppendedId(uri, eventRemoteID)
|
||||
context.contentResolver.update(newUri, values, null, null)
|
||||
|
||||
setupCalDAVEventReminders(event)
|
||||
setupCalDAVEventImportId(event)
|
||||
}
|
||||
|
||||
private fun setupCalDAVEventReminders(event: Event) {
|
||||
clearEventReminders(event)
|
||||
event.getReminders().forEach {
|
||||
ContentValues().apply {
|
||||
put(Reminders.MINUTES, it)
|
||||
put(Reminders.EVENT_ID, event.getCalDAVEventId())
|
||||
put(Reminders.METHOD, Reminders.METHOD_ALERT)
|
||||
context.contentResolver.insert(Reminders.CONTENT_URI, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupCalDAVEventImportId(event: Event) {
|
||||
context.dbHelper.updateEventImportIdAndSource(event.id, event.importId, "$CALDAV-${event.getCalDAVCalendarId()}")
|
||||
}
|
||||
|
||||
private fun fillEventContentValues(event: Event): ContentValues {
|
||||
return ContentValues().apply {
|
||||
put(CalendarContract.Events.CALENDAR_ID, event.getCalDAVCalendarId())
|
||||
put(CalendarContract.Events.TITLE, event.title)
|
||||
put(CalendarContract.Events.DESCRIPTION, event.description)
|
||||
put(CalendarContract.Events.DTSTART, event.startTS * 1000L)
|
||||
put(CalendarContract.Events.ALL_DAY, if (event.getIsAllDay()) 1 else 0)
|
||||
put(CalendarContract.Events.RRULE, Parser().getRepeatCode(event))
|
||||
put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().toString())
|
||||
put(CalendarContract.Events.EVENT_LOCATION, event.location)
|
||||
|
||||
if (event.getIsAllDay() && event.endTS > event.startTS)
|
||||
event.endTS += DAY
|
||||
|
||||
if (event.repeatInterval > 0) {
|
||||
put(CalendarContract.Events.DURATION, getDurationCode(event))
|
||||
putNull(CalendarContract.Events.DTEND)
|
||||
} else {
|
||||
put(CalendarContract.Events.DTEND, event.endTS * 1000L)
|
||||
putNull(CalendarContract.Events.DURATION)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearEventReminders(event: Event) {
|
||||
val selection = "${Reminders.EVENT_ID} = ?"
|
||||
val selectionArgs = arrayOf(event.getCalDAVEventId().toString())
|
||||
context.contentResolver.delete(Reminders.CONTENT_URI, selection, selectionArgs)
|
||||
}
|
||||
|
||||
private fun getDurationCode(event: Event): String {
|
||||
return if (event.getIsAllDay()) {
|
||||
val dur = Math.max(1, (event.endTS - event.startTS) / DAY)
|
||||
"P${dur}D"
|
||||
} else {
|
||||
Parser().getDurationCode((event.endTS - event.startTS) / 60)
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteCalDAVCalendarEvents(calendarId: Long) {
|
||||
val events = context.dbHelper.getCalDAVCalendarEvents(calendarId)
|
||||
val eventIds = events.map { it.id.toString() }.toTypedArray()
|
||||
context.dbHelper.deleteEvents(eventIds, false)
|
||||
}
|
||||
|
||||
fun deleteCalDAVEvent(event: Event) {
|
||||
val uri = CalendarContract.Events.CONTENT_URI
|
||||
val contentUri = ContentUris.withAppendedId(uri, event.getCalDAVEventId())
|
||||
try {
|
||||
context.contentResolver.delete(contentUri, null, null)
|
||||
} catch (ignored: Exception) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCalDAVEventReminders(eventId: Long): List<Int> {
|
||||
val reminders = ArrayList<Int>()
|
||||
val uri = CalendarContract.Reminders.CONTENT_URI
|
||||
val projection = arrayOf(
|
||||
CalendarContract.Reminders.MINUTES,
|
||||
CalendarContract.Reminders.METHOD)
|
||||
val selection = "${CalendarContract.Reminders.EVENT_ID} = $eventId"
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = context.contentResolver.query(uri, projection, selection, null, null)
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
val minutes = cursor.getIntValue(CalendarContract.Reminders.MINUTES)
|
||||
val method = cursor.getIntValue(CalendarContract.Reminders.METHOD)
|
||||
if (method == CalendarContract.Reminders.METHOD_ALERT) {
|
||||
reminders.add(minutes)
|
||||
}
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
return reminders
|
||||
}
|
||||
|
||||
private fun getCalDAVEventImportId(calendarId: Int, eventId: Long) = "$CALDAV-$calendarId-$eventId"
|
||||
}
|
|
@ -1,132 +0,0 @@
|
|||
package com.simplemobiletools.calendar.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.media.RingtoneManager
|
||||
import android.text.format.DateFormat
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.extensions.scheduleCalDAVSync
|
||||
import com.simplemobiletools.commons.helpers.BaseConfig
|
||||
import java.util.*
|
||||
|
||||
class Config(context: Context) : BaseConfig(context) {
|
||||
companion object {
|
||||
fun newInstance(context: Context) = Config(context)
|
||||
}
|
||||
|
||||
var isSundayFirst: Boolean
|
||||
get() {
|
||||
val isSundayFirst = Calendar.getInstance(Locale.getDefault()).firstDayOfWeek == Calendar.SUNDAY
|
||||
return prefs.getBoolean(SUNDAY_FIRST, isSundayFirst)
|
||||
}
|
||||
set(sundayFirst) = prefs.edit().putBoolean(SUNDAY_FIRST, sundayFirst).apply()
|
||||
|
||||
var use24hourFormat: Boolean
|
||||
get() {
|
||||
val use24hourFormat = DateFormat.is24HourFormat(context)
|
||||
return prefs.getBoolean(USE_24_HOUR_FORMAT, use24hourFormat)
|
||||
}
|
||||
set(use24hourFormat) = prefs.edit().putBoolean(USE_24_HOUR_FORMAT, use24hourFormat).apply()
|
||||
|
||||
var displayWeekNumbers: Boolean
|
||||
get() = prefs.getBoolean(WEEK_NUMBERS, false)
|
||||
set(displayWeekNumbers) = prefs.edit().putBoolean(WEEK_NUMBERS, displayWeekNumbers).apply()
|
||||
|
||||
var startWeeklyAt: Int
|
||||
get() = prefs.getInt(START_WEEKLY_AT, 7)
|
||||
set(startWeeklyAt) = prefs.edit().putInt(START_WEEKLY_AT, startWeeklyAt).apply()
|
||||
|
||||
var endWeeklyAt: Int
|
||||
get() = prefs.getInt(END_WEEKLY_AT, 23)
|
||||
set(endWeeklyAt) = prefs.edit().putInt(END_WEEKLY_AT, endWeeklyAt).apply()
|
||||
|
||||
var vibrateOnReminder: Boolean
|
||||
get() = prefs.getBoolean(VIBRATE, false)
|
||||
set(vibrate) = prefs.edit().putBoolean(VIBRATE, vibrate).apply()
|
||||
|
||||
var reminderSound: String
|
||||
get() = prefs.getString(REMINDER_SOUND, getDefaultNotificationSound())
|
||||
set(path) = prefs.edit().putString(REMINDER_SOUND, path).apply()
|
||||
|
||||
var storedView: Int
|
||||
get() = prefs.getInt(VIEW, MONTHLY_VIEW)
|
||||
set(view) = prefs.edit().putInt(VIEW, view).apply()
|
||||
|
||||
var defaultReminderMinutes: Int
|
||||
get() = prefs.getInt(REMINDER_MINUTES, 10)
|
||||
set(mins) = prefs.edit().putInt(REMINDER_MINUTES, mins).apply()
|
||||
|
||||
var snoozeDelay: Int
|
||||
get() = prefs.getInt(SNOOZE_DELAY, 10)
|
||||
set(snoozeDelay) = prefs.edit().putInt(SNOOZE_DELAY, snoozeDelay).apply()
|
||||
|
||||
var displayPastEvents: Int
|
||||
get() = prefs.getInt(DISPLAY_PAST_EVENTS, 0)
|
||||
set(displayPastEvents) = prefs.edit().putInt(DISPLAY_PAST_EVENTS, displayPastEvents).apply()
|
||||
|
||||
var displayEventTypes: Set<String>
|
||||
get() = prefs.getStringSet(DISPLAY_EVENT_TYPES, HashSet<String>())
|
||||
set(displayEventTypes) = prefs.edit().remove(DISPLAY_EVENT_TYPES).putStringSet(DISPLAY_EVENT_TYPES, displayEventTypes).apply()
|
||||
|
||||
var fontSize: Int
|
||||
get() = prefs.getInt(FONT_SIZE, FONT_SIZE_MEDIUM)
|
||||
set(size) = prefs.edit().putInt(FONT_SIZE, size).apply()
|
||||
|
||||
var googleSync: Boolean
|
||||
get() = prefs.getBoolean(GOOGLE_SYNC, false)
|
||||
set(googleSync) = prefs.edit().putBoolean(GOOGLE_SYNC, googleSync).apply()
|
||||
|
||||
var caldavSync: Boolean
|
||||
get() = prefs.getBoolean(CALDAV_SYNC, false)
|
||||
set(caldavSync) {
|
||||
context.scheduleCalDAVSync(caldavSync)
|
||||
prefs.edit().putBoolean(CALDAV_SYNC, caldavSync).apply()
|
||||
}
|
||||
|
||||
var caldavSyncedCalendarIDs: String
|
||||
get() = prefs.getString(CALDAV_SYNCED_CALENDAR_IDS, "")
|
||||
set(calendarIDs) = prefs.edit().putString(CALDAV_SYNCED_CALENDAR_IDS, calendarIDs).apply()
|
||||
|
||||
var lastUsedCaldavCalendar: Int
|
||||
get() = prefs.getInt(LAST_USED_CALDAV_CALENDAR, getSyncedCalendarIdsAsList().first().toInt())
|
||||
set(calendarId) = prefs.edit().putInt(LAST_USED_CALDAV_CALENDAR, calendarId).apply()
|
||||
|
||||
var replaceDescription: Boolean
|
||||
get() = prefs.getBoolean(REPLACE_DESCRIPTION, false)
|
||||
set(replaceDescription) = prefs.edit().putBoolean(REPLACE_DESCRIPTION, replaceDescription).apply()
|
||||
|
||||
fun getSyncedCalendarIdsAsList() = caldavSyncedCalendarIDs.split(",").filter { it.trim().isNotEmpty() } as ArrayList<String>
|
||||
|
||||
fun addDisplayEventType(type: String) {
|
||||
addDisplayEventTypes(HashSet<String>(Arrays.asList(type)))
|
||||
}
|
||||
|
||||
private fun addDisplayEventTypes(types: Set<String>) {
|
||||
val currDisplayEventTypes = HashSet<String>(displayEventTypes)
|
||||
currDisplayEventTypes.addAll(types)
|
||||
displayEventTypes = currDisplayEventTypes
|
||||
}
|
||||
|
||||
fun removeDisplayEventTypes(types: Set<String>) {
|
||||
val currDisplayEventTypes = HashSet<String>(displayEventTypes)
|
||||
currDisplayEventTypes.removeAll(types)
|
||||
displayEventTypes = currDisplayEventTypes
|
||||
}
|
||||
|
||||
private fun getDefaultNotificationSound(): String {
|
||||
return try {
|
||||
RingtoneManager.getActualDefaultRingtoneUri(context, RingtoneManager.TYPE_NOTIFICATION)?.toString() ?: ""
|
||||
} catch (e: Exception) {
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
fun getFontSize() = when (fontSize) {
|
||||
FONT_SIZE_SMALL -> getSmallFontSize()
|
||||
FONT_SIZE_MEDIUM -> getMediumFontSize()
|
||||
else -> getLargeFontSize()
|
||||
}
|
||||
|
||||
private fun getSmallFontSize() = getMediumFontSize() - 3f
|
||||
private fun getMediumFontSize() = context.resources.getDimension(R.dimen.day_text_size) / context.resources.displayMetrics.density
|
||||
private fun getLargeFontSize() = getMediumFontSize() + 3f
|
||||
}
|
|
@ -1,138 +0,0 @@
|
|||
package com.simplemobiletools.calendar.helpers
|
||||
|
||||
import com.simplemobiletools.calendar.R
|
||||
|
||||
val LOW_ALPHA = .3f
|
||||
val MEDIUM_ALPHA = .6f
|
||||
val STORED_LOCALLY_ONLY = 0
|
||||
|
||||
val DAY_CODE = "day_code"
|
||||
val YEAR_LABEL = "year"
|
||||
val EVENT_ID = "event_id"
|
||||
val EVENT_OCCURRENCE_TS = "event_occurrence_ts"
|
||||
val NEW_EVENT_START_TS = "new_event_start_ts"
|
||||
val WEEK_START_TIMESTAMP = "week_start_timestamp"
|
||||
val NEW_EVENT_SET_HOUR_DURATION = "new_event_set_hour_duration"
|
||||
val CALDAV = "Caldav"
|
||||
|
||||
val MONTHLY_VIEW = 1
|
||||
val YEARLY_VIEW = 2
|
||||
val EVENTS_LIST_VIEW = 3
|
||||
val WEEKLY_VIEW = 4
|
||||
|
||||
val REMINDER_OFF = -1
|
||||
|
||||
val DAY = 86400
|
||||
val WEEK = 604800
|
||||
val MONTH = 2592001 // exact value not taken into account, Joda is used for adding months and years
|
||||
val YEAR = 31536000
|
||||
|
||||
val DAY_MINUTES = 24 * 60
|
||||
val DAY_SECONDS = 24 * 60 * 60
|
||||
val WEEK_SECONDS = 7 * DAY_SECONDS
|
||||
|
||||
// Shared Preferences
|
||||
val USE_24_HOUR_FORMAT = "use_24_hour_format"
|
||||
val SUNDAY_FIRST = "sunday_first"
|
||||
val WEEK_NUMBERS = "week_numbers"
|
||||
val START_WEEKLY_AT = "start_weekly_at"
|
||||
val END_WEEKLY_AT = "end_weekly_at"
|
||||
val VIBRATE = "vibrate"
|
||||
val REMINDER_SOUND = "reminder_sound"
|
||||
val VIEW = "view"
|
||||
val REMINDER_MINUTES = "reminder_minutes"
|
||||
val DISPLAY_EVENT_TYPES = "display_event_types"
|
||||
val FONT_SIZE = "font_size"
|
||||
val CALDAV_SYNC = "caldav_sync"
|
||||
val CALDAV_SYNCED_CALENDAR_IDS = "caldav_synced_calendar_ids"
|
||||
val LAST_USED_CALDAV_CALENDAR = "last_used_caldav_calendar"
|
||||
val SNOOZE_DELAY = "snooze_delay"
|
||||
val DISPLAY_PAST_EVENTS = "display_past_events"
|
||||
val REPLACE_DESCRIPTION = "replace_description"
|
||||
val GOOGLE_SYNC = "google_sync" // deprecated
|
||||
|
||||
val letterIDs = intArrayOf(R.string.sunday_letter, R.string.monday_letter, R.string.tuesday_letter, R.string.wednesday_letter,
|
||||
R.string.thursday_letter, R.string.friday_letter, R.string.saturday_letter)
|
||||
|
||||
// repeat_rule for weekly repetition
|
||||
val MONDAY = 1
|
||||
val TUESDAY = 2
|
||||
val WEDNESDAY = 4
|
||||
val THURSDAY = 8
|
||||
val FRIDAY = 16
|
||||
val SATURDAY = 32
|
||||
val SUNDAY = 64
|
||||
val EVERY_DAY = 127
|
||||
|
||||
// repeat_rule for monthly repetition
|
||||
val REPEAT_MONTH_SAME_DAY = 1 // ie 25th every month
|
||||
val REPEAT_MONTH_ORDER_WEEKDAY_USE_LAST = 2 // ie every xth sunday. 4th if a month has 4 sundays, 5th if 5
|
||||
val REPEAT_MONTH_LAST_DAY = 3 // ie every last day of the month
|
||||
val REPEAT_MONTH_ORDER_WEEKDAY = 4 // ie every 4th sunday, even if a month has 4 sundays only (will stay 4th even at months with 5)
|
||||
|
||||
// special event flags
|
||||
val FLAG_ALL_DAY = 1
|
||||
|
||||
// constants related to ICS file exporting / importing
|
||||
val BEGIN_CALENDAR = "BEGIN:VCALENDAR"
|
||||
val END_CALENDAR = "END:VCALENDAR"
|
||||
val CALENDAR_PRODID = "PRODID:-//Simple Mobile Tools//NONSGML Event Calendar//EN"
|
||||
val CALENDAR_VERSION = "VERSION:2.0"
|
||||
val BEGIN_EVENT = "BEGIN:VEVENT"
|
||||
val END_EVENT = "END:VEVENT"
|
||||
val BEGIN_ALARM = "BEGIN:VALARM"
|
||||
val END_ALARM = "END:VALARM"
|
||||
val DTSTART = "DTSTART"
|
||||
val DTEND = "DTEND"
|
||||
val LAST_MODIFIED = "LAST-MODIFIED"
|
||||
val DURATION = "DURATION:"
|
||||
val SUMMARY = "SUMMARY"
|
||||
val DESCRIPTION = "DESCRIPTION:"
|
||||
val UID = "UID:"
|
||||
val ACTION = "ACTION:"
|
||||
val TRIGGER = "TRIGGER:"
|
||||
val RRULE = "RRULE:"
|
||||
val CATEGORIES = "CATEGORIES:"
|
||||
val STATUS = "STATUS:"
|
||||
val EXDATE = "EXDATE"
|
||||
val BYDAY = "BYDAY"
|
||||
val BYMONTHDAY = "BYMONTHDAY"
|
||||
val LOCATION = "LOCATION:"
|
||||
|
||||
// this tag isn't a standard ICS tag, but there's no official way of adding a category color in an ics file
|
||||
val CATEGORY_COLOR = "CATEGORY_COLOR:"
|
||||
|
||||
val DISPLAY = "DISPLAY"
|
||||
val FREQ = "FREQ"
|
||||
val UNTIL = "UNTIL"
|
||||
val COUNT = "COUNT"
|
||||
val INTERVAL = "INTERVAL"
|
||||
val CONFIRMED = "CONFIRMED"
|
||||
val VALUE = "VALUE"
|
||||
val DATE = "DATE"
|
||||
|
||||
val DAILY = "DAILY"
|
||||
val WEEKLY = "WEEKLY"
|
||||
val MONTHLY = "MONTHLY"
|
||||
val YEARLY = "YEARLY"
|
||||
|
||||
val MO = "MO"
|
||||
val TU = "TU"
|
||||
val WE = "WE"
|
||||
val TH = "TH"
|
||||
val FR = "FR"
|
||||
val SA = "SA"
|
||||
val SU = "SU"
|
||||
|
||||
// font sizes
|
||||
val FONT_SIZE_SMALL = 0
|
||||
val FONT_SIZE_MEDIUM = 1
|
||||
val FONT_SIZE_LARGE = 2
|
||||
|
||||
val SOURCE_SIMPLE_CALENDAR = "simple-calendar"
|
||||
val SOURCE_IMPORTED_ICS = "imported-ics"
|
||||
val SOURCE_CONTACT_BIRTHDAY = "contact-birthday"
|
||||
val SOURCE_CONTACT_ANNIVERSARY = "contact-anniversary"
|
||||
|
||||
// deprecated
|
||||
val SOURCE_GOOGLE_CALENDAR = 1
|
|
@ -1,960 +0,0 @@
|
|||
package com.simplemobiletools.calendar.helpers
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.database.sqlite.SQLiteException
|
||||
import android.database.sqlite.SQLiteOpenHelper
|
||||
import android.database.sqlite.SQLiteQueryBuilder
|
||||
import android.text.TextUtils
|
||||
import android.util.SparseIntArray
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.extensions.*
|
||||
import com.simplemobiletools.calendar.models.Event
|
||||
import com.simplemobiletools.calendar.models.EventType
|
||||
import com.simplemobiletools.commons.extensions.getIntValue
|
||||
import com.simplemobiletools.commons.extensions.getLongValue
|
||||
import com.simplemobiletools.commons.extensions.getStringValue
|
||||
import org.joda.time.DateTime
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(context, DB_NAME, null, DB_VERSION) {
|
||||
private val MAIN_TABLE_NAME = "events"
|
||||
private val COL_ID = "id"
|
||||
private val COL_START_TS = "start_ts"
|
||||
private val COL_END_TS = "end_ts"
|
||||
private val COL_TITLE = "title"
|
||||
private val COL_DESCRIPTION = "description"
|
||||
private val COL_REMINDER_MINUTES = "reminder_minutes"
|
||||
private val COL_REMINDER_MINUTES_2 = "reminder_minutes_2"
|
||||
private val COL_REMINDER_MINUTES_3 = "reminder_minutes_3"
|
||||
private val COL_IMPORT_ID = "import_id"
|
||||
private val COL_FLAGS = "flags"
|
||||
private val COL_EVENT_TYPE = "event_type"
|
||||
private val COL_OFFSET = "offset"
|
||||
private val COL_IS_DST_INCLUDED = "is_dst_included"
|
||||
private val COL_LAST_UPDATED = "last_updated"
|
||||
private val COL_EVENT_SOURCE = "event_source"
|
||||
private val COL_LOCATION = "location"
|
||||
private val COL_SOURCE = "source" // deprecated
|
||||
|
||||
private val META_TABLE_NAME = "events_meta"
|
||||
private val COL_EVENT_ID = "event_id"
|
||||
private val COL_REPEAT_START = "repeat_start"
|
||||
private val COL_REPEAT_INTERVAL = "repeat_interval"
|
||||
private val COL_REPEAT_RULE = "repeat_rule"
|
||||
private val COL_REPEAT_LIMIT = "repeat_limit"
|
||||
|
||||
private val TYPES_TABLE_NAME = "event_types"
|
||||
private val COL_TYPE_ID = "event_type_id"
|
||||
private val COL_TYPE_TITLE = "event_type_title"
|
||||
private val COL_TYPE_COLOR = "event_type_color"
|
||||
private val COL_TYPE_CALDAV_CALENDAR_ID = "event_caldav_calendar_id"
|
||||
private val COL_TYPE_CALDAV_DISPLAY_NAME = "event_caldav_display_name"
|
||||
private val COL_TYPE_CALDAV_EMAIL = "event_caldav_email"
|
||||
|
||||
private val EXCEPTIONS_TABLE_NAME = "event_repeat_exceptions"
|
||||
private val COL_EXCEPTION_ID = "event_exception_id"
|
||||
private val COL_OCCURRENCE_TIMESTAMP = "event_occurrence_timestamp"
|
||||
private val COL_OCCURRENCE_DAYCODE = "event_occurrence_daycode"
|
||||
private val COL_PARENT_EVENT_ID = "event_parent_id"
|
||||
private val COL_CHILD_EVENT_ID = "event_child_id"
|
||||
|
||||
private val mDb: SQLiteDatabase = writableDatabase
|
||||
|
||||
companion object {
|
||||
private val DB_VERSION = 19
|
||||
val DB_NAME = "events.db"
|
||||
val REGULAR_EVENT_TYPE_ID = 1
|
||||
var dbInstance: DBHelper? = null
|
||||
|
||||
fun newInstance(context: Context): DBHelper {
|
||||
if (dbInstance == null)
|
||||
dbInstance = DBHelper(context)
|
||||
|
||||
return dbInstance!!
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(db: SQLiteDatabase) {
|
||||
db.execSQL("CREATE TABLE $MAIN_TABLE_NAME ($COL_ID INTEGER PRIMARY KEY AUTOINCREMENT, $COL_START_TS INTEGER, $COL_END_TS INTEGER, " +
|
||||
"$COL_TITLE TEXT, $COL_DESCRIPTION TEXT, $COL_REMINDER_MINUTES INTEGER, $COL_REMINDER_MINUTES_2 INTEGER, $COL_REMINDER_MINUTES_3 INTEGER, " +
|
||||
"$COL_IMPORT_ID TEXT, $COL_FLAGS INTEGER, $COL_EVENT_TYPE INTEGER NOT NULL DEFAULT $REGULAR_EVENT_TYPE_ID, " +
|
||||
"$COL_PARENT_EVENT_ID INTEGER, $COL_OFFSET TEXT, $COL_IS_DST_INCLUDED INTEGER, $COL_LAST_UPDATED INTEGER, $COL_EVENT_SOURCE TEXT, " +
|
||||
"$COL_LOCATION TEXT)")
|
||||
|
||||
createMetaTable(db)
|
||||
createTypesTable(db)
|
||||
createExceptionsTable(db)
|
||||
}
|
||||
|
||||
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
if (oldVersion == 1) {
|
||||
db.execSQL("ALTER TABLE $MAIN_TABLE_NAME ADD COLUMN $COL_REMINDER_MINUTES INTEGER DEFAULT -1")
|
||||
}
|
||||
|
||||
if (oldVersion < 3) {
|
||||
createMetaTable(db)
|
||||
}
|
||||
|
||||
if (oldVersion < 4) {
|
||||
db.execSQL("ALTER TABLE $MAIN_TABLE_NAME ADD COLUMN $COL_IMPORT_ID TEXT DEFAULT ''")
|
||||
}
|
||||
|
||||
if (oldVersion < 5) {
|
||||
db.execSQL("ALTER TABLE $MAIN_TABLE_NAME ADD COLUMN $COL_FLAGS INTEGER NOT NULL DEFAULT 0")
|
||||
db.execSQL("ALTER TABLE $META_TABLE_NAME ADD COLUMN $COL_REPEAT_LIMIT INTEGER NOT NULL DEFAULT 0")
|
||||
}
|
||||
|
||||
if (oldVersion < 6) {
|
||||
db.execSQL("ALTER TABLE $MAIN_TABLE_NAME ADD COLUMN $COL_REMINDER_MINUTES_2 INTEGER NOT NULL DEFAULT -1")
|
||||
db.execSQL("ALTER TABLE $MAIN_TABLE_NAME ADD COLUMN $COL_REMINDER_MINUTES_3 INTEGER NOT NULL DEFAULT -1")
|
||||
}
|
||||
|
||||
if (oldVersion < 7) {
|
||||
createTypesTable(db)
|
||||
db.execSQL("ALTER TABLE $MAIN_TABLE_NAME ADD COLUMN $COL_EVENT_TYPE INTEGER NOT NULL DEFAULT $REGULAR_EVENT_TYPE_ID")
|
||||
}
|
||||
|
||||
if (oldVersion < 8) {
|
||||
db.execSQL("ALTER TABLE $MAIN_TABLE_NAME ADD COLUMN $COL_PARENT_EVENT_ID INTEGER NOT NULL DEFAULT 0")
|
||||
createExceptionsTable(db)
|
||||
}
|
||||
|
||||
if (oldVersion < 9) {
|
||||
try {
|
||||
db.execSQL("ALTER TABLE $EXCEPTIONS_TABLE_NAME ADD COLUMN $COL_OCCURRENCE_DAYCODE INTEGER NOT NULL DEFAULT 0")
|
||||
} catch (ignored: SQLiteException) {
|
||||
}
|
||||
convertExceptionTimestampToDaycode(db)
|
||||
}
|
||||
|
||||
if (oldVersion < 11) {
|
||||
db.execSQL("ALTER TABLE $META_TABLE_NAME ADD COLUMN $COL_REPEAT_RULE INTEGER NOT NULL DEFAULT 0")
|
||||
setupRepeatRules(db)
|
||||
}
|
||||
|
||||
if (oldVersion < 12) {
|
||||
db.execSQL("ALTER TABLE $MAIN_TABLE_NAME ADD COLUMN $COL_OFFSET TEXT DEFAULT ''")
|
||||
db.execSQL("ALTER TABLE $MAIN_TABLE_NAME ADD COLUMN $COL_IS_DST_INCLUDED INTEGER NOT NULL DEFAULT 0")
|
||||
}
|
||||
|
||||
if (oldVersion < 13) {
|
||||
try {
|
||||
createExceptionsTable(db)
|
||||
} catch (e: Exception) {
|
||||
try {
|
||||
db.execSQL("ALTER TABLE $EXCEPTIONS_TABLE_NAME ADD COLUMN $COL_CHILD_EVENT_ID INTEGER NOT NULL DEFAULT 0")
|
||||
} catch (e: Exception) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (oldVersion < 14) {
|
||||
db.execSQL("ALTER TABLE $MAIN_TABLE_NAME ADD COLUMN $COL_LAST_UPDATED INTEGER NOT NULL DEFAULT 0")
|
||||
}
|
||||
|
||||
if (oldVersion < 15) {
|
||||
db.execSQL("ALTER TABLE $MAIN_TABLE_NAME ADD COLUMN $COL_EVENT_SOURCE TEXT DEFAULT ''")
|
||||
}
|
||||
|
||||
if (oldVersion < 16) {
|
||||
db.execSQL("ALTER TABLE $TYPES_TABLE_NAME ADD COLUMN $COL_TYPE_CALDAV_CALENDAR_ID INTEGER NOT NULL DEFAULT 0")
|
||||
}
|
||||
|
||||
if (oldVersion < 17) {
|
||||
db.execSQL("ALTER TABLE $TYPES_TABLE_NAME ADD COLUMN $COL_TYPE_CALDAV_DISPLAY_NAME TEXT DEFAULT ''")
|
||||
db.execSQL("ALTER TABLE $TYPES_TABLE_NAME ADD COLUMN $COL_TYPE_CALDAV_EMAIL TEXT DEFAULT ''")
|
||||
}
|
||||
|
||||
if (oldVersion < 18) {
|
||||
updateOldMonthlyEvents(db)
|
||||
}
|
||||
|
||||
if (oldVersion < 19) {
|
||||
db.execSQL("ALTER TABLE $MAIN_TABLE_NAME ADD COLUMN $COL_LOCATION TEXT DEFAULT ''")
|
||||
}
|
||||
}
|
||||
|
||||
private fun createMetaTable(db: SQLiteDatabase) {
|
||||
db.execSQL("CREATE TABLE $META_TABLE_NAME ($COL_ID INTEGER PRIMARY KEY AUTOINCREMENT, $COL_EVENT_ID INTEGER UNIQUE, $COL_REPEAT_START INTEGER, " +
|
||||
"$COL_REPEAT_INTERVAL INTEGER, $COL_REPEAT_LIMIT INTEGER, $COL_REPEAT_RULE INTEGER)")
|
||||
}
|
||||
|
||||
private fun createTypesTable(db: SQLiteDatabase) {
|
||||
db.execSQL("CREATE TABLE $TYPES_TABLE_NAME ($COL_TYPE_ID INTEGER PRIMARY KEY AUTOINCREMENT, $COL_TYPE_TITLE TEXT, $COL_TYPE_COLOR INTEGER, " +
|
||||
"$COL_TYPE_CALDAV_CALENDAR_ID INTEGER, $COL_TYPE_CALDAV_DISPLAY_NAME TEXT, $COL_TYPE_CALDAV_EMAIL TEXT)")
|
||||
addRegularEventType(db)
|
||||
}
|
||||
|
||||
private fun createExceptionsTable(db: SQLiteDatabase) {
|
||||
db.execSQL("CREATE TABLE $EXCEPTIONS_TABLE_NAME ($COL_EXCEPTION_ID INTEGER PRIMARY KEY AUTOINCREMENT, $COL_PARENT_EVENT_ID INTEGER, " +
|
||||
"$COL_OCCURRENCE_TIMESTAMP INTEGER, $COL_OCCURRENCE_DAYCODE INTEGER, $COL_CHILD_EVENT_ID INTEGER)")
|
||||
}
|
||||
|
||||
private fun addRegularEventType(db: SQLiteDatabase) {
|
||||
val regularEvent = context.resources.getString(R.string.regular_event)
|
||||
val eventType = EventType(REGULAR_EVENT_TYPE_ID, regularEvent, context.config.primaryColor)
|
||||
addEventType(eventType, db)
|
||||
}
|
||||
|
||||
fun insert(event: Event, addToCalDAV: Boolean, callback: (id: Int) -> Unit) {
|
||||
if (event.startTS > event.endTS || event.title.trim().isEmpty()) {
|
||||
callback(0)
|
||||
return
|
||||
}
|
||||
|
||||
val eventValues = fillEventValues(event)
|
||||
val id = mDb.insert(MAIN_TABLE_NAME, null, eventValues)
|
||||
event.id = id.toInt()
|
||||
|
||||
if (event.repeatInterval != 0 && event.parentId == 0) {
|
||||
val metaValues = fillMetaValues(event)
|
||||
mDb.insert(META_TABLE_NAME, null, metaValues)
|
||||
}
|
||||
|
||||
context.updateWidgets()
|
||||
context.scheduleNextEventReminder(event, this)
|
||||
|
||||
if (addToCalDAV && event.source != SOURCE_SIMPLE_CALENDAR && context.config.caldavSync) {
|
||||
CalDAVHandler(context).insertCalDAVEvent(event)
|
||||
}
|
||||
|
||||
callback(event.id)
|
||||
}
|
||||
|
||||
fun update(event: Event, updateAtCalDAV: Boolean, callback: () -> Unit) {
|
||||
val selectionArgs = arrayOf(event.id.toString())
|
||||
val values = fillEventValues(event)
|
||||
val selection = "$COL_ID = ?"
|
||||
mDb.update(MAIN_TABLE_NAME, values, selection, selectionArgs)
|
||||
|
||||
if (event.repeatInterval == 0) {
|
||||
val metaSelection = "$COL_EVENT_ID = ?"
|
||||
mDb.delete(META_TABLE_NAME, metaSelection, selectionArgs)
|
||||
} else {
|
||||
val metaValues = fillMetaValues(event)
|
||||
mDb.insertWithOnConflict(META_TABLE_NAME, null, metaValues, SQLiteDatabase.CONFLICT_REPLACE)
|
||||
}
|
||||
|
||||
context.updateWidgets()
|
||||
context.scheduleNextEventReminder(event, this)
|
||||
if (updateAtCalDAV && event.source != SOURCE_SIMPLE_CALENDAR && context.config.caldavSync) {
|
||||
CalDAVHandler(context).updateCalDAVEvent(event)
|
||||
}
|
||||
callback()
|
||||
}
|
||||
|
||||
private fun fillEventValues(event: Event): ContentValues {
|
||||
return ContentValues().apply {
|
||||
put(COL_START_TS, event.startTS)
|
||||
put(COL_END_TS, event.endTS)
|
||||
put(COL_TITLE, event.title)
|
||||
put(COL_DESCRIPTION, event.description)
|
||||
put(COL_REMINDER_MINUTES, event.reminder1Minutes)
|
||||
put(COL_REMINDER_MINUTES_2, event.reminder2Minutes)
|
||||
put(COL_REMINDER_MINUTES_3, event.reminder3Minutes)
|
||||
put(COL_IMPORT_ID, event.importId)
|
||||
put(COL_FLAGS, event.flags)
|
||||
put(COL_EVENT_TYPE, event.eventType)
|
||||
put(COL_PARENT_EVENT_ID, event.parentId)
|
||||
put(COL_OFFSET, event.offset)
|
||||
put(COL_IS_DST_INCLUDED, if (event.isDstIncluded) 1 else 0)
|
||||
put(COL_LAST_UPDATED, event.lastUpdated)
|
||||
put(COL_EVENT_SOURCE, event.source)
|
||||
put(COL_LOCATION, event.location)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fillMetaValues(event: Event): ContentValues {
|
||||
return ContentValues().apply {
|
||||
put(COL_EVENT_ID, event.id)
|
||||
put(COL_REPEAT_START, event.startTS)
|
||||
put(COL_REPEAT_INTERVAL, event.repeatInterval)
|
||||
put(COL_REPEAT_LIMIT, event.repeatLimit)
|
||||
put(COL_REPEAT_RULE, event.repeatRule)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addEventType(eventType: EventType, db: SQLiteDatabase) {
|
||||
insertEventType(eventType, db)
|
||||
}
|
||||
|
||||
fun insertEventType(eventType: EventType, db: SQLiteDatabase = mDb): Int {
|
||||
val values = fillEventTypeValues(eventType)
|
||||
val insertedId = db.insert(TYPES_TABLE_NAME, null, values).toInt()
|
||||
context.config.addDisplayEventType(insertedId.toString())
|
||||
return insertedId
|
||||
}
|
||||
|
||||
fun updateEventType(eventType: EventType): Int {
|
||||
return if (eventType.caldavCalendarId != 0) {
|
||||
if (CalDAVHandler(context).updateCalDAVCalendar(eventType)) {
|
||||
updateLocalEventType(eventType)
|
||||
} else {
|
||||
-1
|
||||
}
|
||||
} else {
|
||||
updateLocalEventType(eventType)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateLocalEventType(eventType: EventType): Int {
|
||||
val selectionArgs = arrayOf(eventType.id.toString())
|
||||
val values = fillEventTypeValues(eventType)
|
||||
val selection = "$COL_TYPE_ID = ?"
|
||||
return mDb.update(TYPES_TABLE_NAME, values, selection, selectionArgs)
|
||||
}
|
||||
|
||||
private fun fillEventTypeValues(eventType: EventType): ContentValues {
|
||||
return ContentValues().apply {
|
||||
put(COL_TYPE_TITLE, eventType.title)
|
||||
put(COL_TYPE_COLOR, eventType.color)
|
||||
put(COL_TYPE_CALDAV_CALENDAR_ID, eventType.caldavCalendarId)
|
||||
put(COL_TYPE_CALDAV_DISPLAY_NAME, eventType.caldavDisplayName)
|
||||
put(COL_TYPE_CALDAV_EMAIL, eventType.caldavEmail)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fillExceptionValues(parentEventId: Int, occurrenceTS: Int, callback: (values: ContentValues) -> Unit) {
|
||||
val childEvent = getEventWithId(parentEventId)
|
||||
if (childEvent == null) {
|
||||
callback(ContentValues())
|
||||
return
|
||||
}
|
||||
|
||||
childEvent.apply {
|
||||
id = 0
|
||||
parentId = parentEventId
|
||||
startTS = 0
|
||||
endTS = 0
|
||||
}
|
||||
|
||||
insert(childEvent, false) {
|
||||
callback(ContentValues().apply {
|
||||
put(COL_PARENT_EVENT_ID, parentEventId)
|
||||
put(COL_OCCURRENCE_DAYCODE, Formatter.getDayCodeFromTS(occurrenceTS))
|
||||
put(COL_CHILD_EVENT_ID, it)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun getEventTypeIdWithTitle(title: String): Int {
|
||||
val cols = arrayOf(COL_TYPE_ID)
|
||||
val selection = "$COL_TYPE_TITLE = ? COLLATE NOCASE"
|
||||
val selectionArgs = arrayOf(title)
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = mDb.query(TYPES_TABLE_NAME, cols, selection, selectionArgs, null, null, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
return cursor.getIntValue(COL_TYPE_ID)
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
fun getEventTypeWithCalDAVCalendarId(calendarId: Int): EventType? {
|
||||
val cols = arrayOf(COL_TYPE_ID)
|
||||
val selection = "$COL_TYPE_CALDAV_CALENDAR_ID = ?"
|
||||
val selectionArgs = arrayOf(calendarId.toString())
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = mDb.query(TYPES_TABLE_NAME, cols, selection, selectionArgs, null, null, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
return getEventType(cursor.getIntValue(COL_TYPE_ID))
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun getEventType(id: Int): EventType? {
|
||||
val cols = arrayOf(COL_TYPE_TITLE, COL_TYPE_COLOR, COL_TYPE_CALDAV_CALENDAR_ID, COL_TYPE_CALDAV_DISPLAY_NAME, COL_TYPE_CALDAV_EMAIL)
|
||||
val selection = "$COL_TYPE_ID = ?"
|
||||
val selectionArgs = arrayOf(id.toString())
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = mDb.query(TYPES_TABLE_NAME, cols, selection, selectionArgs, null, null, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
val title = cursor.getStringValue(COL_TYPE_TITLE)
|
||||
val color = cursor.getIntValue(COL_TYPE_COLOR)
|
||||
val calendarId = cursor.getIntValue(COL_TYPE_CALDAV_CALENDAR_ID)
|
||||
val displayName = cursor.getStringValue(COL_TYPE_CALDAV_DISPLAY_NAME)
|
||||
val email = cursor.getStringValue(COL_TYPE_CALDAV_EMAIL)
|
||||
return EventType(id, title, color, calendarId, displayName, email)
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun getBirthdays(): List<Event> {
|
||||
val selection = "$MAIN_TABLE_NAME.$COL_EVENT_SOURCE = ?"
|
||||
val selectionArgs = arrayOf(SOURCE_CONTACT_BIRTHDAY)
|
||||
val cursor = getEventsCursor(selection, selectionArgs)
|
||||
return fillEvents(cursor)
|
||||
}
|
||||
|
||||
fun getAnniversaries(): List<Event> {
|
||||
val selection = "$MAIN_TABLE_NAME.$COL_EVENT_SOURCE = ?"
|
||||
val selectionArgs = arrayOf(SOURCE_CONTACT_ANNIVERSARY)
|
||||
val cursor = getEventsCursor(selection, selectionArgs)
|
||||
return fillEvents(cursor)
|
||||
}
|
||||
|
||||
fun deleteEvents(ids: Array<String>, deleteFromCalDAV: Boolean) {
|
||||
val args = TextUtils.join(", ", ids)
|
||||
val selection = "$MAIN_TABLE_NAME.$COL_ID IN ($args)"
|
||||
val cursor = getEventsCursor(selection)
|
||||
val events = fillEvents(cursor).filter { it.importId.isNotEmpty() }
|
||||
|
||||
mDb.delete(MAIN_TABLE_NAME, selection, null)
|
||||
|
||||
val metaSelection = "$COL_EVENT_ID IN ($args)"
|
||||
mDb.delete(META_TABLE_NAME, metaSelection, null)
|
||||
|
||||
val exceptionSelection = "$COL_PARENT_EVENT_ID IN ($args)"
|
||||
mDb.delete(EXCEPTIONS_TABLE_NAME, exceptionSelection, null)
|
||||
|
||||
context.updateWidgets()
|
||||
|
||||
ids.forEach {
|
||||
context.cancelNotification(it.toInt())
|
||||
}
|
||||
|
||||
if (deleteFromCalDAV && context.config.caldavSync) {
|
||||
events.forEach {
|
||||
CalDAVHandler(context).deleteCalDAVEvent(it)
|
||||
}
|
||||
}
|
||||
|
||||
deleteChildEvents(args, deleteFromCalDAV)
|
||||
}
|
||||
|
||||
private fun deleteChildEvents(ids: String, deleteFromCalDAV: Boolean) {
|
||||
val projection = arrayOf(COL_ID)
|
||||
val selection = "$COL_PARENT_EVENT_ID IN ($ids)"
|
||||
val childIds = ArrayList<String>()
|
||||
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = mDb.query(MAIN_TABLE_NAME, projection, selection, null, null, null, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
childIds.add(cursor.getStringValue(COL_ID))
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
|
||||
if (childIds.isNotEmpty())
|
||||
deleteEvents(childIds.toTypedArray(), deleteFromCalDAV)
|
||||
}
|
||||
|
||||
fun getCalDAVCalendarEvents(calendarId: Long): List<Event> {
|
||||
val selection = "$MAIN_TABLE_NAME.$COL_EVENT_SOURCE = (?)"
|
||||
val selectionArgs = arrayOf("$CALDAV-$calendarId")
|
||||
val cursor = getEventsCursor(selection, selectionArgs)
|
||||
return fillEvents(cursor).filter { it.importId.isNotEmpty() }
|
||||
}
|
||||
|
||||
private fun updateOldMonthlyEvents(db: SQLiteDatabase) {
|
||||
val OLD_MONTH = 2592000
|
||||
val projection = arrayOf(COL_ID, COL_REPEAT_INTERVAL)
|
||||
val selection = "$COL_REPEAT_INTERVAL != 0 AND $COL_REPEAT_INTERVAL % $OLD_MONTH == 0"
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = db.query(META_TABLE_NAME, projection, selection, null, null, null, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
val id = cursor.getIntValue(COL_ID)
|
||||
val repeatInterval = cursor.getIntValue(COL_REPEAT_INTERVAL)
|
||||
val multiplies = repeatInterval / OLD_MONTH
|
||||
|
||||
val values = ContentValues().apply {
|
||||
put(COL_REPEAT_INTERVAL, multiplies * MONTH)
|
||||
}
|
||||
|
||||
val updateSelection = "$COL_ID = $id"
|
||||
db.update(META_TABLE_NAME, values, updateSelection, null)
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
}
|
||||
|
||||
fun addEventRepeatException(parentEventId: Int, occurrenceTS: Int) {
|
||||
fillExceptionValues(parentEventId, occurrenceTS) {
|
||||
mDb.insert(EXCEPTIONS_TABLE_NAME, null, it)
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteEventTypes(eventTypes: ArrayList<EventType>, deleteEvents: Boolean, callback: (deletedCnt: Int) -> Unit) {
|
||||
var deleteIds = eventTypes.filter { it.caldavCalendarId == 0 }.map { it.id }
|
||||
deleteIds = deleteIds.filter { it != DBHelper.REGULAR_EVENT_TYPE_ID } as ArrayList<Int>
|
||||
|
||||
val deletedSet = HashSet<String>()
|
||||
deleteIds.map { deletedSet.add(it.toString()) }
|
||||
context.config.removeDisplayEventTypes(deletedSet)
|
||||
if (deleteIds.isEmpty())
|
||||
return
|
||||
|
||||
for (eventTypeId in deleteIds) {
|
||||
if (deleteEvents) {
|
||||
deleteEventsWithType(eventTypeId)
|
||||
} else {
|
||||
resetEventsWithType(eventTypeId)
|
||||
}
|
||||
}
|
||||
|
||||
val args = TextUtils.join(", ", deleteIds)
|
||||
val selection = "$COL_TYPE_ID IN ($args)"
|
||||
callback(mDb.delete(TYPES_TABLE_NAME, selection, null))
|
||||
}
|
||||
|
||||
fun deleteEventTypesWithCalendarId(calendarIds: String) {
|
||||
val selection = "$COL_TYPE_CALDAV_CALENDAR_ID IN ($calendarIds)"
|
||||
mDb.delete(TYPES_TABLE_NAME, selection, null)
|
||||
}
|
||||
|
||||
private fun deleteEventsWithType(eventTypeId: Int) {
|
||||
val selection = "$MAIN_TABLE_NAME.$COL_EVENT_TYPE = ?"
|
||||
val selectionArgs = arrayOf(eventTypeId.toString())
|
||||
val cursor = getEventsCursor(selection, selectionArgs)
|
||||
val events = fillEvents(cursor)
|
||||
val eventIDs = Array(events.size, { i -> (events[i].id.toString()) })
|
||||
deleteEvents(eventIDs, true)
|
||||
}
|
||||
|
||||
private fun resetEventsWithType(eventTypeId: Int) {
|
||||
val values = ContentValues()
|
||||
values.put(COL_EVENT_TYPE, REGULAR_EVENT_TYPE_ID)
|
||||
|
||||
val selection = "$COL_EVENT_TYPE = ?"
|
||||
val selectionArgs = arrayOf(eventTypeId.toString())
|
||||
mDb.update(MAIN_TABLE_NAME, values, selection, selectionArgs)
|
||||
}
|
||||
|
||||
fun updateEventImportIdAndSource(eventId: Int, importId: String, source: String) {
|
||||
val values = ContentValues()
|
||||
values.put(COL_IMPORT_ID, importId)
|
||||
values.put(COL_EVENT_SOURCE, source)
|
||||
|
||||
val selection = "$MAIN_TABLE_NAME.$COL_ID = ?"
|
||||
val selectionArgs = arrayOf(eventId.toString())
|
||||
mDb.update(MAIN_TABLE_NAME, values, selection, selectionArgs)
|
||||
}
|
||||
|
||||
fun getEventsWithImportIds() = getEvents("").filter { it.importId.trim().isNotEmpty() } as ArrayList<Event>
|
||||
|
||||
fun getEventWithId(id: Int): Event? {
|
||||
val selection = "$MAIN_TABLE_NAME.$COL_ID = ?"
|
||||
val selectionArgs = arrayOf(id.toString())
|
||||
val cursor = getEventsCursor(selection, selectionArgs)
|
||||
val events = fillEvents(cursor)
|
||||
return if (events.isNotEmpty()) {
|
||||
events[0]
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun getEvents(fromTS: Int, toTS: Int, eventId: Int = -1, callback: (events: MutableList<Event>) -> Unit) {
|
||||
Thread {
|
||||
getEventsInBackground(fromTS, toTS, eventId, callback)
|
||||
}.start()
|
||||
}
|
||||
|
||||
fun getEventsInBackground(fromTS: Int, toTS: Int, eventId: Int = -1, callback: (events: MutableList<Event>) -> Unit) {
|
||||
val events = ArrayList<Event>()
|
||||
|
||||
var selection = "$COL_START_TS <= ? AND $COL_END_TS >= ? AND $COL_REPEAT_INTERVAL IS NULL AND $COL_START_TS != 0"
|
||||
if (eventId != -1)
|
||||
selection += " AND $MAIN_TABLE_NAME.$COL_ID = $eventId"
|
||||
val selectionArgs = arrayOf(toTS.toString(), fromTS.toString())
|
||||
val cursor = getEventsCursor(selection, selectionArgs)
|
||||
events.addAll(fillEvents(cursor))
|
||||
|
||||
events.addAll(getRepeatableEventsFor(fromTS, toTS, eventId))
|
||||
|
||||
events.addAll(getAllDayEvents(fromTS, toTS, eventId))
|
||||
|
||||
val filtered = events.distinct().filterNot { it.ignoreEventOccurrences.contains(Formatter.getDayCodeFromTS(it.startTS).toInt()) } as MutableList<Event>
|
||||
callback(filtered)
|
||||
}
|
||||
|
||||
private fun getRepeatableEventsFor(fromTS: Int, toTS: Int, eventId: Int = -1): List<Event> {
|
||||
val newEvents = ArrayList<Event>()
|
||||
|
||||
// get repeatable events
|
||||
var selection = "$COL_REPEAT_INTERVAL != 0 AND $COL_START_TS <= $toTS AND $COL_START_TS != 0"
|
||||
if (eventId != -1)
|
||||
selection += " AND $MAIN_TABLE_NAME.$COL_ID = $eventId"
|
||||
val events = getEvents(selection)
|
||||
val startTimes = SparseIntArray(events.size)
|
||||
events.forEach {
|
||||
startTimes.put(it.id, it.startTS)
|
||||
if (it.repeatLimit >= 0) {
|
||||
newEvents.addAll(getEventsRepeatingTillDateOrForever(fromTS, toTS, startTimes, it))
|
||||
} else {
|
||||
newEvents.addAll(getEventsRepeatingXTimes(fromTS, toTS, startTimes, it))
|
||||
}
|
||||
}
|
||||
|
||||
return newEvents
|
||||
}
|
||||
|
||||
private fun getEventsRepeatingTillDateOrForever(fromTS: Int, toTS: Int, startTimes: SparseIntArray, event: Event): ArrayList<Event> {
|
||||
val original = event.copy()
|
||||
val events = ArrayList<Event>()
|
||||
while (event.startTS <= toTS && (event.repeatLimit == 0 || event.repeatLimit >= event.startTS)) {
|
||||
if (event.endTS >= fromTS) {
|
||||
if (event.repeatInterval.isXWeeklyRepetition()) {
|
||||
if (event.startTS.isTsOnProperDay(event)) {
|
||||
if (isOnProperWeek(event, startTimes)) {
|
||||
events.add(event.copy())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
events.add(event.copy())
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getIsAllDay()) {
|
||||
if (event.repeatInterval.isXWeeklyRepetition()) {
|
||||
if (event.endTS >= toTS && event.startTS.isTsOnProperDay(event)) {
|
||||
if (isOnProperWeek(event, startTimes)) {
|
||||
events.add(event.copy())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val dayCode = Formatter.getDayCodeFromTS(fromTS)
|
||||
val endDayCode = Formatter.getDayCodeFromTS(event.endTS)
|
||||
if (dayCode == endDayCode) {
|
||||
events.add(event.copy())
|
||||
}
|
||||
}
|
||||
}
|
||||
event.addIntervalTime(original)
|
||||
}
|
||||
return events
|
||||
}
|
||||
|
||||
private fun getEventsRepeatingXTimes(fromTS: Int, toTS: Int, startTimes: SparseIntArray, event: Event): ArrayList<Event> {
|
||||
val original = event.copy()
|
||||
val events = ArrayList<Event>()
|
||||
while (event.repeatLimit < 0 && event.startTS <= toTS) {
|
||||
if (event.repeatInterval.isXWeeklyRepetition()) {
|
||||
if (event.startTS.isTsOnProperDay(event)) {
|
||||
if (isOnProperWeek(event, startTimes)) {
|
||||
if (event.endTS >= fromTS) {
|
||||
events.add(event.copy())
|
||||
}
|
||||
event.repeatLimit++
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (event.endTS >= fromTS) {
|
||||
events.add(event.copy())
|
||||
} else if (event.getIsAllDay()) {
|
||||
val dayCode = Formatter.getDayCodeFromTS(fromTS)
|
||||
val endDayCode = Formatter.getDayCodeFromTS(event.endTS)
|
||||
if (dayCode == endDayCode) {
|
||||
events.add(event.copy())
|
||||
}
|
||||
}
|
||||
event.repeatLimit++
|
||||
}
|
||||
event.addIntervalTime(original)
|
||||
}
|
||||
return events
|
||||
}
|
||||
|
||||
private fun getAllDayEvents(fromTS: Int, toTS: Int, eventId: Int = -1): List<Event> {
|
||||
val events = ArrayList<Event>()
|
||||
var selection = "($COL_FLAGS & $FLAG_ALL_DAY) != 0"
|
||||
if (eventId != -1)
|
||||
selection += " AND $MAIN_TABLE_NAME.$COL_ID = $eventId"
|
||||
|
||||
val dayCode = Formatter.getDayCodeFromTS(fromTS)
|
||||
val cursor = getEventsCursor(selection)
|
||||
events.addAll(fillEvents(cursor).filter { dayCode == Formatter.getDayCodeFromTS(it.startTS) })
|
||||
return events
|
||||
}
|
||||
|
||||
// check if its the proper week, for events repeating by x weeks
|
||||
private fun isOnProperWeek(event: Event, startTimes: SparseIntArray): Boolean {
|
||||
val initialWeekOfYear = Formatter.getDateTimeFromTS(startTimes[event.id]).weekOfWeekyear
|
||||
val currentWeekOfYear = Formatter.getDateTimeFromTS(event.startTS).weekOfWeekyear
|
||||
return (currentWeekOfYear - initialWeekOfYear) % (event.repeatInterval / WEEK) == 0
|
||||
}
|
||||
|
||||
fun getRunningEvents(): List<Event> {
|
||||
val events = ArrayList<Event>()
|
||||
val ts = (System.currentTimeMillis() / 1000).toInt()
|
||||
|
||||
val selection = "$COL_START_TS <= ? AND $COL_END_TS >= ? AND $COL_REPEAT_INTERVAL IS 0 AND $COL_START_TS != 0"
|
||||
val selectionArgs = arrayOf(ts.toString(), ts.toString())
|
||||
val cursor = getEventsCursor(selection, selectionArgs)
|
||||
events.addAll(fillEvents(cursor))
|
||||
|
||||
events.addAll(getRepeatableEventsFor(ts, ts))
|
||||
return events
|
||||
}
|
||||
|
||||
private fun getEvents(selection: String): List<Event> {
|
||||
val events = ArrayList<Event>()
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = getEventsCursor(selection)
|
||||
if (cursor != null) {
|
||||
val currEvents = fillEvents(cursor)
|
||||
events.addAll(currEvents)
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
|
||||
return events
|
||||
}
|
||||
|
||||
fun getEventsWithIds(ids: List<Int>): ArrayList<Event> {
|
||||
val args = TextUtils.join(", ", ids)
|
||||
val selection = "$MAIN_TABLE_NAME.$COL_ID IN ($args)"
|
||||
return getEvents(selection) as ArrayList<Event>
|
||||
}
|
||||
|
||||
// get deprecated Google Sync events
|
||||
fun getGoogleSyncEvents(): ArrayList<Event> {
|
||||
val selection = "$MAIN_TABLE_NAME.$COL_SOURCE = $SOURCE_GOOGLE_CALENDAR"
|
||||
return getEvents(selection) as ArrayList<Event>
|
||||
}
|
||||
|
||||
fun getEventsAtReboot(): List<Event> {
|
||||
val selection = "$COL_REMINDER_MINUTES != -1 AND ($COL_START_TS > ? OR $COL_REPEAT_INTERVAL != 0) AND $COL_START_TS != 0"
|
||||
val selectionArgs = arrayOf(DateTime.now().seconds().toString())
|
||||
val cursor = getEventsCursor(selection, selectionArgs)
|
||||
return fillEvents(cursor)
|
||||
}
|
||||
|
||||
fun getEventsToExport(includePast: Boolean): ArrayList<Event> {
|
||||
val currTime = (System.currentTimeMillis() / 1000).toString()
|
||||
var events = ArrayList<Event>()
|
||||
|
||||
// non repeating events
|
||||
var cursor = if (includePast) {
|
||||
getEventsCursor()
|
||||
} else {
|
||||
val selection = "$COL_END_TS > ?"
|
||||
val selectionArgs = arrayOf(currTime)
|
||||
getEventsCursor(selection, selectionArgs)
|
||||
}
|
||||
events.addAll(fillEvents(cursor))
|
||||
|
||||
// repeating events
|
||||
if (!includePast) {
|
||||
val selection = "$COL_REPEAT_INTERVAL != 0 AND ($COL_REPEAT_LIMIT == 0 OR $COL_REPEAT_LIMIT > ?)"
|
||||
val selectionArgs = arrayOf(currTime)
|
||||
cursor = getEventsCursor(selection, selectionArgs)
|
||||
events.addAll(fillEvents(cursor))
|
||||
}
|
||||
|
||||
events = events.distinctBy { it.id } as ArrayList<Event>
|
||||
return events
|
||||
}
|
||||
|
||||
fun getEventsFromCalDAVCalendar(calendarId: Int): List<Event> {
|
||||
val selection = "$MAIN_TABLE_NAME.$COL_EVENT_SOURCE = ?"
|
||||
val selectionArgs = arrayOf("$CALDAV-$calendarId")
|
||||
val cursor = getEventsCursor(selection, selectionArgs)
|
||||
return fillEvents(cursor)
|
||||
}
|
||||
|
||||
private fun getEventsCursor(selection: String = "", selectionArgs: Array<String>? = null): Cursor? {
|
||||
val builder = SQLiteQueryBuilder()
|
||||
builder.tables = "$MAIN_TABLE_NAME LEFT OUTER JOIN $META_TABLE_NAME ON $COL_EVENT_ID = $MAIN_TABLE_NAME.$COL_ID"
|
||||
val projection = allColumns
|
||||
return builder.query(mDb, projection, selection, selectionArgs, "$MAIN_TABLE_NAME.$COL_ID", null, COL_START_TS)
|
||||
}
|
||||
|
||||
private val allColumns: Array<String>
|
||||
get() = arrayOf("$MAIN_TABLE_NAME.$COL_ID", COL_START_TS, COL_END_TS, COL_TITLE, COL_DESCRIPTION, COL_REMINDER_MINUTES, COL_REMINDER_MINUTES_2,
|
||||
COL_REMINDER_MINUTES_3, COL_REPEAT_INTERVAL, COL_REPEAT_RULE, COL_IMPORT_ID, COL_FLAGS, COL_REPEAT_LIMIT, COL_EVENT_TYPE, COL_OFFSET,
|
||||
COL_IS_DST_INCLUDED, COL_LAST_UPDATED, COL_EVENT_SOURCE, COL_LOCATION)
|
||||
|
||||
private fun fillEvents(cursor: Cursor?): List<Event> {
|
||||
val eventTypeColors = SparseIntArray()
|
||||
fetchEventTypes().forEach {
|
||||
eventTypeColors.put(it.id, it.color)
|
||||
}
|
||||
|
||||
val events = ArrayList<Event>()
|
||||
cursor?.use {
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
val id = cursor.getIntValue(COL_ID)
|
||||
val startTS = cursor.getIntValue(COL_START_TS)
|
||||
val endTS = cursor.getIntValue(COL_END_TS)
|
||||
val reminder1Minutes = cursor.getIntValue(COL_REMINDER_MINUTES)
|
||||
val reminder2Minutes = cursor.getIntValue(COL_REMINDER_MINUTES_2)
|
||||
val reminder3Minutes = cursor.getIntValue(COL_REMINDER_MINUTES_3)
|
||||
val repeatInterval = cursor.getIntValue(COL_REPEAT_INTERVAL)
|
||||
var repeatRule = cursor.getIntValue(COL_REPEAT_RULE)
|
||||
val title = cursor.getStringValue(COL_TITLE)
|
||||
val description = cursor.getStringValue(COL_DESCRIPTION)
|
||||
val importId = cursor.getStringValue(COL_IMPORT_ID) ?: ""
|
||||
val flags = cursor.getIntValue(COL_FLAGS)
|
||||
val repeatLimit = cursor.getIntValue(COL_REPEAT_LIMIT)
|
||||
val eventType = cursor.getIntValue(COL_EVENT_TYPE)
|
||||
val offset = cursor.getStringValue(COL_OFFSET)
|
||||
val isDstIncluded = cursor.getIntValue(COL_IS_DST_INCLUDED) == 1
|
||||
val lastUpdated = cursor.getLongValue(COL_LAST_UPDATED)
|
||||
val source = cursor.getStringValue(COL_EVENT_SOURCE)
|
||||
val location = cursor.getStringValue(COL_LOCATION)
|
||||
val color = eventTypeColors[eventType]
|
||||
|
||||
val ignoreEventOccurrences = if (repeatInterval != 0) {
|
||||
getIgnoredOccurrences(id)
|
||||
} else {
|
||||
ArrayList()
|
||||
}
|
||||
|
||||
if (repeatInterval > 0 && repeatInterval % MONTH == 0 && repeatRule == 0) {
|
||||
repeatRule = REPEAT_MONTH_SAME_DAY
|
||||
}
|
||||
|
||||
val event = Event(id, startTS, endTS, title, description, reminder1Minutes, reminder2Minutes, reminder3Minutes,
|
||||
repeatInterval, importId, flags, repeatLimit, repeatRule, eventType, ignoreEventOccurrences, offset, isDstIncluded,
|
||||
0, lastUpdated, source, color, location)
|
||||
events.add(event)
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
}
|
||||
return events
|
||||
}
|
||||
|
||||
fun getEventTypes(callback: (types: ArrayList<EventType>) -> Unit) {
|
||||
Thread {
|
||||
callback(fetchEventTypes())
|
||||
}.start()
|
||||
}
|
||||
|
||||
fun fetchEventTypes(): ArrayList<EventType> {
|
||||
val eventTypes = ArrayList<EventType>(4)
|
||||
val cols = arrayOf(COL_TYPE_ID, COL_TYPE_TITLE, COL_TYPE_COLOR, COL_TYPE_CALDAV_CALENDAR_ID, COL_TYPE_CALDAV_DISPLAY_NAME, COL_TYPE_CALDAV_EMAIL)
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = mDb.query(TYPES_TABLE_NAME, cols, null, null, null, null, "$COL_TYPE_TITLE ASC")
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
val id = cursor.getIntValue(COL_TYPE_ID)
|
||||
val title = cursor.getStringValue(COL_TYPE_TITLE)
|
||||
val color = cursor.getIntValue(COL_TYPE_COLOR)
|
||||
val calendarId = cursor.getIntValue(COL_TYPE_CALDAV_CALENDAR_ID)
|
||||
val displayName = cursor.getStringValue(COL_TYPE_CALDAV_DISPLAY_NAME)
|
||||
val email = cursor.getStringValue(COL_TYPE_CALDAV_EMAIL)
|
||||
val eventType = EventType(id, title, color, calendarId, displayName, email)
|
||||
eventTypes.add(eventType)
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
return eventTypes
|
||||
}
|
||||
|
||||
fun doEventTypesContainEvent(types: ArrayList<EventType>): Boolean {
|
||||
val args = TextUtils.join(", ", types.map { it.id })
|
||||
val columns = arrayOf(COL_ID)
|
||||
val selection = "$COL_EVENT_TYPE IN ($args)"
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = mDb.query(MAIN_TABLE_NAME, columns, selection, null, null, null, null)
|
||||
return cursor?.moveToFirst() == true
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getIgnoredOccurrences(eventId: Int): ArrayList<Int> {
|
||||
val projection = arrayOf(COL_OCCURRENCE_DAYCODE)
|
||||
val selection = "$COL_PARENT_EVENT_ID = ?"
|
||||
val selectionArgs = arrayOf(eventId.toString())
|
||||
val daycodes = ArrayList<Int>()
|
||||
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = mDb.query(EXCEPTIONS_TABLE_NAME, projection, selection, selectionArgs, null, null, COL_OCCURRENCE_DAYCODE)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
daycodes.add(cursor.getIntValue(COL_OCCURRENCE_DAYCODE))
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
return daycodes
|
||||
}
|
||||
|
||||
private fun convertExceptionTimestampToDaycode(db: SQLiteDatabase) {
|
||||
val projection = arrayOf(COL_EXCEPTION_ID, COL_OCCURRENCE_TIMESTAMP)
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = db.query(EXCEPTIONS_TABLE_NAME, projection, null, null, null, null, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
val id = cursor.getIntValue(COL_EXCEPTION_ID)
|
||||
val ts = cursor.getIntValue(COL_OCCURRENCE_TIMESTAMP)
|
||||
val values = ContentValues()
|
||||
values.put(COL_OCCURRENCE_DAYCODE, Formatter.getDayCodeFromTS(ts))
|
||||
|
||||
val selection = "$COL_EXCEPTION_ID = ?"
|
||||
val selectionArgs = arrayOf(id.toString())
|
||||
db.update(EXCEPTIONS_TABLE_NAME, values, selection, selectionArgs)
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupRepeatRules(db: SQLiteDatabase) {
|
||||
val projection = arrayOf(COL_EVENT_ID, COL_REPEAT_INTERVAL, COL_REPEAT_START)
|
||||
val selection = "$COL_REPEAT_INTERVAL != 0"
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = db.query(META_TABLE_NAME, projection, selection, null, null, null, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
val interval = cursor.getIntValue(COL_REPEAT_INTERVAL)
|
||||
if (interval != MONTH && interval % WEEK != 0)
|
||||
continue
|
||||
|
||||
val eventId = cursor.getIntValue(COL_EVENT_ID)
|
||||
val start = cursor.getIntValue(COL_REPEAT_START)
|
||||
var rule = Math.pow(2.0, (Formatter.getDateTimeFromTS(start).dayOfWeek - 1).toDouble()).toInt()
|
||||
if (interval == MONTH) {
|
||||
rule = REPEAT_MONTH_SAME_DAY
|
||||
}
|
||||
|
||||
val values = ContentValues()
|
||||
values.put(COL_REPEAT_RULE, rule)
|
||||
val curSelection = "$COL_EVENT_ID = ?"
|
||||
val curSelectionArgs = arrayOf(eventId.toString())
|
||||
db.update(META_TABLE_NAME, values, curSelection, curSelectionArgs)
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,226 +0,0 @@
|
|||
package com.simplemobiletools.calendar.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.Toast
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.activities.SimpleActivity
|
||||
import com.simplemobiletools.calendar.extensions.dbHelper
|
||||
import com.simplemobiletools.calendar.helpers.IcsImporter.ImportResult.*
|
||||
import com.simplemobiletools.calendar.models.Event
|
||||
import com.simplemobiletools.calendar.models.EventType
|
||||
import com.simplemobiletools.commons.extensions.areDigitsOnly
|
||||
import com.simplemobiletools.commons.extensions.showErrorToast
|
||||
import java.io.File
|
||||
|
||||
class IcsImporter(val activity: SimpleActivity) {
|
||||
enum class ImportResult {
|
||||
IMPORT_FAIL, IMPORT_OK, IMPORT_PARTIAL
|
||||
}
|
||||
|
||||
private var curStart = -1
|
||||
private var curEnd = -1
|
||||
private var curTitle = ""
|
||||
private var curDescription = ""
|
||||
private var curImportId = ""
|
||||
private var curFlags = 0
|
||||
private var curReminderMinutes = ArrayList<Int>()
|
||||
private var curRepeatExceptions = ArrayList<Int>()
|
||||
private var curRepeatInterval = 0
|
||||
private var curRepeatLimit = 0
|
||||
private var curRepeatRule = 0
|
||||
private var curEventType = DBHelper.REGULAR_EVENT_TYPE_ID
|
||||
private var curLastModified = 0L
|
||||
private var curLocation = ""
|
||||
private var curCategoryColor = -2
|
||||
private var isNotificationDescription = false
|
||||
private var isProperReminderAction = false
|
||||
private var curReminderTriggerMinutes = -1
|
||||
|
||||
private var eventsImported = 0
|
||||
private var eventsFailed = 0
|
||||
|
||||
fun importEvents(path: String, defaultEventType: Int): ImportResult {
|
||||
try {
|
||||
val existingEvents = activity.dbHelper.getEventsWithImportIds()
|
||||
var prevLine = ""
|
||||
|
||||
val inputStream = if (path.contains("/")) {
|
||||
File(path).inputStream()
|
||||
} else {
|
||||
activity.assets.open(path)
|
||||
}
|
||||
|
||||
inputStream.bufferedReader().use {
|
||||
while (true) {
|
||||
var line = it.readLine() ?: break
|
||||
if (line.trim().isEmpty())
|
||||
continue
|
||||
|
||||
if (line.substring(0, 1) == " ") {
|
||||
line = prevLine + line.trim()
|
||||
eventsFailed--
|
||||
}
|
||||
|
||||
if (line == BEGIN_EVENT) {
|
||||
resetValues()
|
||||
curEventType = defaultEventType
|
||||
} else if (line.startsWith(DTSTART)) {
|
||||
curStart = getTimestamp(line.substring(DTSTART.length))
|
||||
} else if (line.startsWith(DTEND)) {
|
||||
curEnd = getTimestamp(line.substring(DTEND.length))
|
||||
} else if (line.startsWith(DURATION)) {
|
||||
val duration = line.substring(DURATION.length)
|
||||
curEnd = curStart + Parser().parseDurationSeconds(duration)
|
||||
} else if (line.startsWith(SUMMARY) && !isNotificationDescription) {
|
||||
curTitle = line.substring(SUMMARY.length)
|
||||
curTitle = getTitle(curTitle).replace("\\n", "\n")
|
||||
} else if (line.startsWith(DESCRIPTION) && !isNotificationDescription) {
|
||||
curDescription = line.substring(DESCRIPTION.length).replace("\\n", "\n")
|
||||
} else if (line.startsWith(UID)) {
|
||||
curImportId = line.substring(UID.length).trim()
|
||||
} else if (line.startsWith(RRULE)) {
|
||||
val repeatRule = Parser().parseRepeatInterval(line.substring(RRULE.length), curStart)
|
||||
curRepeatRule = repeatRule.repeatRule
|
||||
curRepeatInterval = repeatRule.repeatInterval
|
||||
curRepeatLimit = repeatRule.repeatLimit
|
||||
} else if (line.startsWith(ACTION)) {
|
||||
isNotificationDescription = true
|
||||
isProperReminderAction = line.substring(ACTION.length) == DISPLAY
|
||||
} else if (line.startsWith(TRIGGER)) {
|
||||
curReminderTriggerMinutes = Parser().parseDurationSeconds(line.substring(TRIGGER.length)) / 60
|
||||
} else if (line.startsWith(CATEGORY_COLOR)) {
|
||||
val color = line.substring(CATEGORY_COLOR.length)
|
||||
if (color.trimStart('-').areDigitsOnly()) {
|
||||
curCategoryColor = Integer.parseInt(color)
|
||||
}
|
||||
} else if (line.startsWith(CATEGORIES)) {
|
||||
val categories = line.substring(CATEGORIES.length)
|
||||
tryAddCategories(categories, activity)
|
||||
} else if (line.startsWith(LAST_MODIFIED)) {
|
||||
curLastModified = getTimestamp(line.substring(LAST_MODIFIED.length)) * 1000L
|
||||
} else if (line.startsWith(EXDATE)) {
|
||||
var value = line.substring(EXDATE.length)
|
||||
if (value.endsWith('}'))
|
||||
value = value.substring(0, value.length - 1)
|
||||
|
||||
curRepeatExceptions.add(getTimestamp(value))
|
||||
} else if (line.startsWith(LOCATION)) {
|
||||
curLocation = line.substring(LOCATION.length)
|
||||
} else if (line == END_ALARM) {
|
||||
if (isProperReminderAction && curReminderTriggerMinutes != -1) {
|
||||
curReminderMinutes.add(curReminderTriggerMinutes)
|
||||
}
|
||||
} else if (line == END_EVENT) {
|
||||
if (curStart != -1 && curEnd == -1)
|
||||
curEnd = curStart
|
||||
|
||||
if (curTitle.isEmpty() || curStart == -1)
|
||||
continue
|
||||
|
||||
val eventToUpdate = existingEvents.firstOrNull { curImportId.isNotEmpty() && curImportId == it.importId }
|
||||
if (eventToUpdate != null && eventToUpdate.lastUpdated >= curLastModified) {
|
||||
continue
|
||||
}
|
||||
|
||||
val event = Event(0, curStart, curEnd, curTitle, curDescription, curReminderMinutes.getOrElse(0, { -1 }),
|
||||
curReminderMinutes.getOrElse(1, { -1 }), curReminderMinutes.getOrElse(2, { -1 }), curRepeatInterval,
|
||||
curImportId, curFlags, curRepeatLimit, curRepeatRule, curEventType, lastUpdated = curLastModified,
|
||||
source = SOURCE_IMPORTED_ICS, location = curLocation)
|
||||
|
||||
if (event.getIsAllDay() && curEnd > curStart) {
|
||||
event.endTS -= DAY
|
||||
}
|
||||
|
||||
if (eventToUpdate == null) {
|
||||
activity.dbHelper.insert(event, false) {
|
||||
for (exceptionTS in curRepeatExceptions) {
|
||||
activity.dbHelper.addEventRepeatException(it, exceptionTS)
|
||||
}
|
||||
existingEvents.add(event)
|
||||
}
|
||||
} else {
|
||||
event.id = eventToUpdate.id
|
||||
activity.dbHelper.update(event, true) {}
|
||||
}
|
||||
eventsImported++
|
||||
resetValues()
|
||||
}
|
||||
prevLine = line
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
activity.showErrorToast(e, Toast.LENGTH_LONG)
|
||||
eventsFailed++
|
||||
}
|
||||
|
||||
return when {
|
||||
eventsImported == 0 -> IMPORT_FAIL
|
||||
eventsFailed > 0 -> IMPORT_PARTIAL
|
||||
else -> IMPORT_OK
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTimestamp(fullString: String): Int {
|
||||
return try {
|
||||
if (fullString.startsWith(';')) {
|
||||
val value = fullString.substring(fullString.lastIndexOf(':') + 1)
|
||||
if (!value.contains("T"))
|
||||
curFlags = curFlags or FLAG_ALL_DAY
|
||||
|
||||
Parser().parseDateTimeValue(value)
|
||||
} else {
|
||||
Parser().parseDateTimeValue(fullString.substring(1))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
activity.showErrorToast(e, Toast.LENGTH_LONG)
|
||||
eventsFailed++
|
||||
-1
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryAddCategories(categories: String, context: Context) {
|
||||
val eventTypeTitle = if (categories.contains(",")) {
|
||||
categories.split(",")[0]
|
||||
} else {
|
||||
categories
|
||||
}
|
||||
|
||||
val eventId = context.dbHelper.getEventTypeIdWithTitle(eventTypeTitle)
|
||||
curEventType = if (eventId == -1) {
|
||||
val newTypeColor = if (curCategoryColor == -2) context.resources.getColor(R.color.color_primary) else curCategoryColor
|
||||
val eventType = EventType(0, eventTypeTitle, newTypeColor)
|
||||
context.dbHelper.insertEventType(eventType)
|
||||
} else {
|
||||
eventId
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTitle(title: String): String {
|
||||
return if (title.startsWith(";") && title.contains(":")) {
|
||||
title.substring(title.lastIndexOf(':') + 1)
|
||||
} else {
|
||||
title.substring(1, Math.min(title.length, 80))
|
||||
}
|
||||
}
|
||||
|
||||
private fun resetValues() {
|
||||
curStart = -1
|
||||
curEnd = -1
|
||||
curTitle = ""
|
||||
curDescription = ""
|
||||
curImportId = ""
|
||||
curFlags = 0
|
||||
curReminderMinutes = ArrayList()
|
||||
curRepeatExceptions = ArrayList()
|
||||
curRepeatInterval = 0
|
||||
curRepeatLimit = 0
|
||||
curRepeatRule = 0
|
||||
curEventType = DBHelper.REGULAR_EVENT_TYPE_ID
|
||||
curLastModified = 0L
|
||||
curCategoryColor = -2
|
||||
curLocation = ""
|
||||
isNotificationDescription = false
|
||||
isProperReminderAction = false
|
||||
curReminderTriggerMinutes = -1
|
||||
}
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
package com.simplemobiletools.calendar.helpers
|
||||
|
||||
import android.content.Context
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.calendar.extensions.dbHelper
|
||||
import com.simplemobiletools.calendar.extensions.getFilteredEvents
|
||||
import com.simplemobiletools.calendar.extensions.seconds
|
||||
import com.simplemobiletools.calendar.interfaces.MonthlyCalendar
|
||||
import com.simplemobiletools.calendar.models.DayMonthly
|
||||
import com.simplemobiletools.calendar.models.Event
|
||||
import org.joda.time.DateTime
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class MonthlyCalendarImpl(val mCallback: MonthlyCalendar, val mContext: Context) {
|
||||
private val DAYS_CNT = 42
|
||||
private val YEAR_PATTERN = "YYYY"
|
||||
|
||||
private val mToday: String = DateTime().toString(Formatter.DAYCODE_PATTERN)
|
||||
private var mEvents = ArrayList<Event>()
|
||||
private var mFilterEventTypes = true
|
||||
|
||||
lateinit var mTargetDate: DateTime
|
||||
|
||||
fun updateMonthlyCalendar(targetDate: DateTime, filterEventTypes: Boolean = true) {
|
||||
mFilterEventTypes = filterEventTypes
|
||||
mTargetDate = targetDate
|
||||
val startTS = mTargetDate.minusMonths(1).seconds()
|
||||
val endTS = mTargetDate.plusMonths(1).seconds()
|
||||
mContext.dbHelper.getEvents(startTS, endTS) {
|
||||
gotEvents(it as ArrayList<Event>)
|
||||
}
|
||||
}
|
||||
|
||||
fun getMonth(targetDate: DateTime) {
|
||||
updateMonthlyCalendar(targetDate)
|
||||
}
|
||||
|
||||
fun getDays(markDaysWithEvents: Boolean) {
|
||||
val days = ArrayList<DayMonthly>(DAYS_CNT)
|
||||
val currMonthDays = mTargetDate.dayOfMonth().maximumValue
|
||||
var firstDayIndex = mTargetDate.withDayOfMonth(1).dayOfWeek
|
||||
if (!mContext.config.isSundayFirst)
|
||||
firstDayIndex -= 1
|
||||
val prevMonthDays = mTargetDate.minusMonths(1).dayOfMonth().maximumValue
|
||||
|
||||
var isThisMonth = false
|
||||
var isToday: Boolean
|
||||
var value = prevMonthDays - firstDayIndex + 1
|
||||
var curDay: DateTime = mTargetDate
|
||||
|
||||
for (i in 0 until DAYS_CNT) {
|
||||
when {
|
||||
i < firstDayIndex -> {
|
||||
isThisMonth = false
|
||||
curDay = mTargetDate.withDayOfMonth(1).minusMonths(1)
|
||||
}
|
||||
i == firstDayIndex -> {
|
||||
value = 1
|
||||
isThisMonth = true
|
||||
curDay = mTargetDate
|
||||
}
|
||||
value == currMonthDays + 1 -> {
|
||||
value = 1
|
||||
isThisMonth = false
|
||||
curDay = mTargetDate.withDayOfMonth(1).plusMonths(1)
|
||||
}
|
||||
}
|
||||
|
||||
isToday = isThisMonth && isToday(mTargetDate, value)
|
||||
|
||||
val newDay = curDay.withDayOfMonth(value)
|
||||
val dayCode = Formatter.getDayCodeFromDateTime(newDay)
|
||||
val day = DayMonthly(value, isThisMonth, isToday, dayCode, newDay.weekOfWeekyear, ArrayList())
|
||||
days.add(day)
|
||||
value++
|
||||
}
|
||||
|
||||
if (markDaysWithEvents) {
|
||||
markDaysWithEvents(days)
|
||||
} else {
|
||||
mCallback.updateMonthlyCalendar(mContext, monthName, days, false)
|
||||
}
|
||||
}
|
||||
|
||||
// it works more often than not, dont touch
|
||||
private fun markDaysWithEvents(days: ArrayList<DayMonthly>) {
|
||||
mContext.dbHelper.getEventTypes {
|
||||
val dayEvents = HashMap<String, ArrayList<Event>>()
|
||||
mEvents.forEach {
|
||||
val startDateTime = Formatter.getDateTimeFromTS(it.startTS)
|
||||
val endDateTime = Formatter.getDateTimeFromTS(it.endTS)
|
||||
val endCode = Formatter.getDayCodeFromDateTime(endDateTime)
|
||||
|
||||
var currDay = startDateTime
|
||||
var dayCode = Formatter.getDayCodeFromDateTime(currDay)
|
||||
var currDayEvents = (dayEvents[dayCode] ?: ArrayList()).apply { add(it) }
|
||||
dayEvents.put(dayCode, currDayEvents)
|
||||
|
||||
while (Formatter.getDayCodeFromDateTime(currDay) != endCode) {
|
||||
currDay = currDay.plusDays(1)
|
||||
dayCode = Formatter.getDayCodeFromDateTime(currDay)
|
||||
currDayEvents = (dayEvents[dayCode] ?: ArrayList()).apply { add(it) }
|
||||
dayEvents.put(dayCode, currDayEvents)
|
||||
}
|
||||
}
|
||||
|
||||
days.filter { dayEvents.keys.contains(it.code) }.forEach {
|
||||
it.dayEvents = dayEvents[it.code]!!
|
||||
}
|
||||
mCallback.updateMonthlyCalendar(mContext, monthName, days, true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isToday(targetDate: DateTime, curDayInMonth: Int): Boolean {
|
||||
return if (curDayInMonth > targetDate.dayOfMonth().maximumValue)
|
||||
false
|
||||
else
|
||||
targetDate.withDayOfMonth(curDayInMonth).toString(Formatter.DAYCODE_PATTERN) == mToday
|
||||
}
|
||||
|
||||
private val monthName: String
|
||||
get() {
|
||||
var month = Formatter.getMonthName(mContext, mTargetDate.monthOfYear)
|
||||
val targetYear = mTargetDate.toString(YEAR_PATTERN)
|
||||
if (targetYear != DateTime().toString(YEAR_PATTERN)) {
|
||||
month += " $targetYear"
|
||||
}
|
||||
return month
|
||||
}
|
||||
|
||||
private fun gotEvents(events: ArrayList<Event>) {
|
||||
mEvents = if (mFilterEventTypes) {
|
||||
mContext.getFilteredEvents(events) as ArrayList<Event>
|
||||
} else {
|
||||
events
|
||||
}
|
||||
|
||||
getDays(true)
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package com.simplemobiletools.calendar.helpers
|
||||
|
||||
import android.content.Context
|
||||
import com.simplemobiletools.calendar.extensions.dbHelper
|
||||
import com.simplemobiletools.calendar.interfaces.WeeklyCalendar
|
||||
import com.simplemobiletools.calendar.models.Event
|
||||
import java.util.*
|
||||
|
||||
class WeeklyCalendarImpl(val mCallback: WeeklyCalendar, val mContext: Context) {
|
||||
var mEvents = ArrayList<Event>()
|
||||
|
||||
fun updateWeeklyCalendar(weekStartTS: Int) {
|
||||
val startTS = weekStartTS
|
||||
val endTS = startTS + WEEK_SECONDS
|
||||
mContext.dbHelper.getEvents(startTS, endTS) {
|
||||
mEvents = it as ArrayList<Event>
|
||||
mCallback.updateWeeklyCalendar(it)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package com.simplemobiletools.calendar.interfaces
|
||||
|
||||
import com.simplemobiletools.calendar.models.EventType
|
||||
import java.util.*
|
||||
|
||||
interface DeleteEventTypesListener {
|
||||
fun deleteEventTypes(eventTypes: ArrayList<EventType>, deleteEvents: Boolean)
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package com.simplemobiletools.calendar.interfaces
|
||||
|
||||
import java.util.*
|
||||
|
||||
interface DeleteEventsListener {
|
||||
fun deleteItems(ids: ArrayList<Int>)
|
||||
|
||||
fun addEventRepeatException(parentIds: ArrayList<Int>, timestamps: ArrayList<Int>)
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package com.simplemobiletools.calendar.interfaces
|
||||
|
||||
import android.content.Context
|
||||
import com.simplemobiletools.calendar.models.DayMonthly
|
||||
|
||||
interface MonthlyCalendar {
|
||||
fun updateMonthlyCalendar(context: Context, month: String, days: List<DayMonthly>, checkedEvents: Boolean)
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package com.simplemobiletools.calendar.interfaces
|
||||
|
||||
import com.simplemobiletools.calendar.models.Event
|
||||
|
||||
interface WeeklyCalendar {
|
||||
fun updateWeeklyCalendar(events: ArrayList<Event>)
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package com.simplemobiletools.calendar.models
|
||||
|
||||
data class CalDAVCalendar(val id: Int, val displayName: String, val accountName: String, val ownerName: String, val color: Int, val accessLevel: Int) {
|
||||
fun canWrite() = accessLevel >= 500
|
||||
|
||||
fun getFullTitle() = "$displayName ($accountName)"
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
package com.simplemobiletools.calendar.models
|
||||
|
||||
import com.simplemobiletools.calendar.extensions.seconds
|
||||
import com.simplemobiletools.calendar.helpers.*
|
||||
import com.simplemobiletools.calendar.helpers.Formatter
|
||||
import org.joda.time.DateTime
|
||||
import java.io.Serializable
|
||||
import java.util.*
|
||||
|
||||
data class Event(var id: Int = 0, var startTS: Int = 0, var endTS: Int = 0, var title: String = "", var description: String = "",
|
||||
var reminder1Minutes: Int = -1, var reminder2Minutes: Int = -1, var reminder3Minutes: Int = -1, var repeatInterval: Int = 0,
|
||||
var importId: String = "", var flags: Int = 0, var repeatLimit: Int = 0, var repeatRule: Int = 0,
|
||||
var eventType: Int = DBHelper.REGULAR_EVENT_TYPE_ID, var ignoreEventOccurrences: ArrayList<Int> = ArrayList(),
|
||||
var offset: String = "", var isDstIncluded: Boolean = false, var parentId: Int = 0, var lastUpdated: Long = 0L,
|
||||
var source: String = SOURCE_SIMPLE_CALENDAR, var color: Int = 0, var location: String = "") : Serializable {
|
||||
|
||||
companion object {
|
||||
private val serialVersionUID = -32456795132345616L
|
||||
}
|
||||
|
||||
fun addIntervalTime(original: Event) {
|
||||
val currStart = Formatter.getDateTimeFromTS(startTS)
|
||||
val newStart: DateTime
|
||||
newStart = when (repeatInterval) {
|
||||
DAY -> currStart.plusDays(1)
|
||||
else -> {
|
||||
when {
|
||||
repeatInterval % YEAR == 0 -> currStart.plusYears(repeatInterval / YEAR)
|
||||
repeatInterval % MONTH == 0 -> when (repeatRule) {
|
||||
REPEAT_MONTH_SAME_DAY -> addMonthsWithSameDay(currStart, original)
|
||||
REPEAT_MONTH_ORDER_WEEKDAY_USE_LAST -> addXthDayInterval(currStart, original, true)
|
||||
REPEAT_MONTH_ORDER_WEEKDAY -> addXthDayInterval(currStart, original, false)
|
||||
else -> currStart.plusMonths(repeatInterval / MONTH).dayOfMonth().withMaximumValue()
|
||||
}
|
||||
repeatInterval % WEEK == 0 -> {
|
||||
// step through weekly repetition by days too, as events can trigger multiple times a week
|
||||
currStart.plusDays(1)
|
||||
}
|
||||
else -> currStart.plusSeconds(repeatInterval)
|
||||
}
|
||||
}
|
||||
}
|
||||
val newStartTS = newStart.seconds()
|
||||
val newEndTS = newStartTS + (endTS - startTS)
|
||||
startTS = newStartTS
|
||||
endTS = newEndTS
|
||||
}
|
||||
|
||||
// if an event should happen on 31st with Same Day monthly repetition, dont show it at all at months with 30 or less days
|
||||
private fun addMonthsWithSameDay(currStart: DateTime, original: Event): DateTime {
|
||||
var newDateTime = currStart.plusMonths(repeatInterval / MONTH)
|
||||
if (newDateTime.dayOfMonth == currStart.dayOfMonth) {
|
||||
return newDateTime
|
||||
}
|
||||
|
||||
while (newDateTime.dayOfMonth().maximumValue < Formatter.getDateTimeFromTS(original.startTS).dayOfMonth().maximumValue) {
|
||||
newDateTime = newDateTime.plusMonths(repeatInterval / MONTH)
|
||||
newDateTime = newDateTime.withDayOfMonth(newDateTime.dayOfMonth().maximumValue)
|
||||
}
|
||||
return newDateTime
|
||||
}
|
||||
|
||||
// handle monthly repetitions like Third Monday
|
||||
private fun addXthDayInterval(currStart: DateTime, original: Event, forceLastWeekday: Boolean): DateTime {
|
||||
val day = currStart.dayOfWeek
|
||||
var order = (currStart.dayOfMonth - 1) / 7
|
||||
val properMonth = currStart.withDayOfMonth(7).plusMonths(repeatInterval / MONTH).withDayOfWeek(day)
|
||||
var firstProperDay = properMonth.dayOfMonth % 7
|
||||
if (firstProperDay == 0)
|
||||
firstProperDay = properMonth.dayOfMonth
|
||||
|
||||
// check if it should be for example Fourth Monday, or Last Monday
|
||||
if (forceLastWeekday && (order == 3 || order == 4)) {
|
||||
val originalDateTime = Formatter.getDateTimeFromTS(original.startTS)
|
||||
val isLastWeekday = originalDateTime.monthOfYear != originalDateTime.plusDays(7).monthOfYear
|
||||
if (isLastWeekday)
|
||||
order = -1
|
||||
}
|
||||
|
||||
val daysCnt = properMonth.dayOfMonth().maximumValue
|
||||
var wantedDay = firstProperDay + order * 7
|
||||
if (wantedDay > daysCnt)
|
||||
wantedDay -= 7
|
||||
|
||||
if (order == -1) {
|
||||
wantedDay = firstProperDay + ((daysCnt - firstProperDay) / 7) * 7
|
||||
}
|
||||
|
||||
return properMonth.withDayOfMonth(wantedDay)
|
||||
}
|
||||
|
||||
fun getIsAllDay() = flags and FLAG_ALL_DAY != 0
|
||||
|
||||
fun getReminders() = setOf(reminder1Minutes, reminder2Minutes, reminder3Minutes).filter { it != REMINDER_OFF }
|
||||
|
||||
// properly return the start time of all-day events as midnight
|
||||
fun getEventStartTS(): Int {
|
||||
return if (getIsAllDay()) {
|
||||
Formatter.getDateTimeFromTS(startTS).withTime(0, 0, 0, 0).seconds()
|
||||
} else {
|
||||
startTS
|
||||
}
|
||||
}
|
||||
|
||||
fun getCalDAVEventId(): Long {
|
||||
return try {
|
||||
(importId.split("-").lastOrNull() ?: "0").toString().toLong()
|
||||
} catch (e: NumberFormatException) {
|
||||
0L
|
||||
}
|
||||
}
|
||||
|
||||
fun getCalDAVCalendarId() = if (source.startsWith(CALDAV)) (source.split("-").lastOrNull() ?: "0").toString().toInt() else 0
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
package com.simplemobiletools.calendar.models
|
||||
|
||||
data class EventType(var id: Int = 0, var title: String, var color: Int, var caldavCalendarId: Int = 0, var caldavDisplayName: String = "", var caldavEmail: String = "") {
|
||||
fun getDisplayTitle() = if (caldavCalendarId == 0) title else "$caldavDisplayName ($caldavEmail)"
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
package com.simplemobiletools.calendar.models
|
||||
|
||||
class ListEvent(var id: Int = 0, var startTS: Int = 0, var endTS: Int = 0, var title: String = "", var description: String = "",
|
||||
var isAllDay: Boolean, var color: Int, var location: String = "") : ListItem()
|
|
@ -1,3 +0,0 @@
|
|||
package com.simplemobiletools.calendar.models
|
||||
|
||||
open class ListItem
|
|
@ -1,5 +0,0 @@
|
|||
package com.simplemobiletools.calendar.models
|
||||
|
||||
class ListSection(val title: String, val isToday: Boolean = false) : ListItem() {
|
||||
override fun toString() = "ListSection {title=$title, isToday=$isToday}"
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
package com.simplemobiletools.calendar.models
|
||||
|
||||
data class RepeatRule(val repeatInterval: Int, val repeatRule: Int, val repeatLimit: Int)
|
|
@ -0,0 +1,11 @@
|
|||
package com.simplemobiletools.calendar.pro
|
||||
|
||||
import androidx.multidex.MultiDexApplication
|
||||
import com.simplemobiletools.commons.extensions.checkUseEnglish
|
||||
|
||||
class App : MultiDexApplication() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
checkUseEnglish()
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,16 +1,17 @@
|
|||
package com.simplemobiletools.calendar.activities
|
||||
package com.simplemobiletools.calendar.pro.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.adapters.ManageEventTypesAdapter
|
||||
import com.simplemobiletools.calendar.dialogs.UpdateEventTypeDialog
|
||||
import com.simplemobiletools.calendar.extensions.dbHelper
|
||||
import com.simplemobiletools.calendar.interfaces.DeleteEventTypesListener
|
||||
import com.simplemobiletools.calendar.models.EventType
|
||||
import com.simplemobiletools.calendar.pro.R
|
||||
import com.simplemobiletools.calendar.pro.adapters.ManageEventTypesAdapter
|
||||
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.helpers.ensureBackgroundThread
|
||||
import kotlinx.android.synthetic.main.activity_manage_event_types.*
|
||||
import java.util.*
|
||||
|
||||
|
@ -24,25 +25,23 @@ class ManageEventTypesActivity : SimpleActivity(), DeleteEventTypesListener {
|
|||
}
|
||||
|
||||
private fun showEventTypeDialog(eventType: EventType? = null) {
|
||||
UpdateEventTypeDialog(this, eventType?.copy()) {
|
||||
EditEventTypeDialog(this, eventType?.copy()) {
|
||||
getEventTypes()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getEventTypes() {
|
||||
dbHelper.getEventTypes {
|
||||
runOnUiThread {
|
||||
eventsHelper.getEventTypes(this, false) {
|
||||
val adapter = ManageEventTypesAdapter(this, it, this, manage_event_types_list) {
|
||||
showEventTypeDialog(it as EventType)
|
||||
}
|
||||
adapter.setupDragListener(true)
|
||||
manage_event_types_list.adapter = adapter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_event_types, menu)
|
||||
updateMenuItemColors(menu)
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -54,15 +53,17 @@ class ManageEventTypesActivity : SimpleActivity(), DeleteEventTypesListener {
|
|||
return true
|
||||
}
|
||||
|
||||
override fun deleteEventTypes(eventTypes: ArrayList<EventType>, deleteEvents: Boolean) {
|
||||
override fun deleteEventTypes(eventTypes: ArrayList<EventType>, deleteEvents: Boolean): Boolean {
|
||||
if (eventTypes.any { it.caldavCalendarId != 0 }) {
|
||||
toast(R.string.unsync_caldav_calendar)
|
||||
if (eventTypes.size == 1) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
dbHelper.deleteEventTypes(eventTypes, deleteEvents) {
|
||||
if (it == 0) {
|
||||
toast(R.string.unknown_error_occurred)
|
||||
}
|
||||
}
|
||||
ensureBackgroundThread {
|
||||
eventsHelper.deleteEventTypes(eventTypes, deleteEvents)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue