Improving preferences design and offline calendar

This commit is contained in:
Dominik Schürmann 2020-01-09 00:18:30 +01:00
parent c48e5cb56f
commit 33a5d64509
38 changed files with 434 additions and 637 deletions

View File

@ -19,15 +19,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ws.xsoh.etar"
android:installLocation="auto"
android:versionCode="21"
android:versionName="1.0.19">
<!-- android:sharedUserLabel="@string/app_label"> -->
<!--
NOTE: and original-package cannot be used, since the Eclair
version was using a shared user ID with the provider.
-->
android:installLocation="auto">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
@ -141,14 +133,6 @@
</intent-filter>
</activity>
<activity android:name="com.android.calendar.selectcalendars.SelectVisibleCalendarsActivity"
android:label="@string/select_visible_calendars_title"
android:theme="@style/Base.CalendarAppThemeWithActionBar" />
<activity android:name="com.android.calendar.selectcalendars.SelectSyncedCalendarsMultiAccountActivity"
android:label="@string/select_synced_calendars_title"
android:theme="@style/Base.CalendarAppThemeWithActionBar" />
<activity
android:name="com.android.calendar.settings.SettingsActivity"
android:label="@string/preferences_title"

View File

@ -166,6 +166,9 @@ android {
defaultConfig {
minSdkVersion 19
targetSdkVersion 29
versionCode 21
versionName "1.0.19"
applicationId "ws.xsoh.etar"
}
useLibrary 'org.apache.http.legacy'

View File

@ -1,5 +1,6 @@
#Sat Jan 11 14:20:57 CET 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000"
android:pathData="M15.07,11.25L14.17,12.17C13.45,12.89 13,13.5 13,15H11V14.5C11,13.39 11.45,12.39 12.17,11.67L13.41,10.41C13.78,10.05 14,9.55 14,9C14,7.89 13.1,7 12,7A2,2 0 0,0 10,9H8A4,4 0 0,1 12,5A4,4 0 0,1 16,9C16,9.88 15.64,10.67 15.07,11.25M13,19H11V17H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z" />
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M20,13H4c-0.55,0 -1,0.45 -1,1v6c0,0.55 0.45,1 1,1h16c0.55,0 1,-0.45 1,-1v-6c0,-0.55 -0.45,-1 -1,-1zM7,19c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM20,3H4c-0.55,0 -1,0.45 -1,1v6c0,0.55 0.45,1 1,1h16c0.55,0 1,-0.45 1,-1V4c0,-0.55 -0.45,-1 -1,-1zM7,9c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2z"/>
</vector>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#fff"
android:pathData="M20,4H14V10L16.24,7.76C17.32,8.85 18,10.34 18,12C18,13 17.75,13.94 17.32,14.77L18.78,16.23C19.55,15 20,13.56 20,12C20,9.79 19.09,7.8 17.64,6.36L20,4M2.86,5.41L5.22,7.77C4.45,9 4,10.44 4,12C4,14.21 4.91,16.2 6.36,17.64L4,20H10V14L7.76,16.24C6.68,15.15 6,13.66 6,12C6,11 6.25,10.06 6.68,9.23L14.76,17.31C14.5,17.44 14.26,17.56 14,17.65V19.74C14.79,19.53 15.54,19.2 16.22,18.78L18.58,21.14L19.85,19.87L4.14,4.14L2.86,5.41M10,6.35V4.26C9.2,4.47 8.45,4.8 7.77,5.22L9.23,6.68C9.5,6.56 9.73,6.44 10,6.35Z" />
</vector>

View File

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project
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
http://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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/calendars"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<TextView android:id="@+id/account_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dip"
android:layout_marginRight="16dip"
android:layout_gravity="center"
style="?android:attr/textAppearanceMedium" />
<Button android:id="@+id/sync_settings"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@android:string/ok" />
<include android:id="@+id/calendar_list" layout="@android:layout/list_content"/>
</LinearLayout>

View File

@ -1,42 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 The Android Open Source Project
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
http://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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft"
android:paddingRight="?android:attr/scrollbarSize">
<TextView
android:id="@+id/account"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:singleLine="true"
android:ellipsize="marquee"
android:paddingTop="6dip"
style="?android:attr/textAppearanceLarge"
android:duplicateParentState="true" />
<TextView
android:id="@+id/account_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:maxLines="2"
android:textAppearance="?android:attr/textAppearanceSmall"
android:duplicateParentState="true" />
</LinearLayout>

View File

@ -6,6 +6,7 @@
android:padding="16dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/offline_calendar_name_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/preferences_list_add_offline_name">
@ -13,7 +14,8 @@
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/offline_calendar_name"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
android:layout_height="wrap_content"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>

View File

@ -1,73 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project
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
http://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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:orientation="horizontal"
android:layout_marginRight="6dip"
android:layout_marginTop="6dip"
android:layout_marginBottom="6dip">
<com.android.calendar.selectcalendars.CalendarColorSquare
android:id="@+id/color"
android:layout_height="32dip"
android:layout_width="32dip"
android:layout_marginLeft="13dip"
android:layout_gravity="center_vertical"
android:contentDescription="@string/calendar_square_color_picker_description"
style="?android:attr/quickContactBadgeStyleWindowMedium" />
<LinearLayout
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="8dip"
android:orientation="vertical"
android:layout_gravity="center_vertical">
<TextView
android:id="@+id/calendar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
style="?android:attr/textAppearanceMedium"
android:duplicateParentState="true" />
<TextView
android:id="@+id/status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceSmall"
android:duplicateParentState="true" />
</LinearLayout>
<CheckBox
android:id="@+id/sync"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="4dip"
android:layout_marginRight="14dip"
android:contentDescription="@string/accessibility_sync_cal"
android:clickable="false"
android:longClickable="false"
android:focusable="false" />
</LinearLayout>

View File

@ -1,74 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 The Android Open Source Project
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
http://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.
-->
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<LinearLayout
android:id="@+id/calendars"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ExpandableListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="0dip"
android:clickable="true"
android:layout_weight="1" />
<LinearLayout android:id="@+id/loading"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:gravity="center"
android:visibility="gone">
<ProgressBar
style="?android:attr/progressBarStyle"
android:indeterminate="true"
android:layout_width="32dp"
android:layout_height="32dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLargeInverse"
android:textColor="@android:color/black"
android:layout_marginBottom="1dip"
android:paddingLeft="5dip"
android:text="@string/loading"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
style="@android:style/Holo.ButtonBar">
<Button
android:id="@+id/btn_discard"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@android:string/cancel" />
<Button
android:id="@+id/btn_done"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@android:string/ok" />
</LinearLayout>
</LinearLayout>
</androidx.drawerlayout.widget.DrawerLayout>

View File

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project
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
http://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.
-->
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/timezone_footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingLeft="10dip"
android:paddingRight="10dip"
style="?android:attr/textAppearanceMedium" />

View File

@ -27,6 +27,11 @@
android:alphabeticShortcut="s"
android:icon="@drawable/ic_menu_settings"
android:title="@string/menu_preferences" />
<item
android:id="@+id/action_about"
android:icon="@drawable/ic_menu_help"
android:title="@string/preferences_menu_about" />
</group>
</menu>

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 The Android Open Source Project
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
http://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.
-->
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/action_add_account"
android:alphabeticShortcut="a"
android:title="@string/add_account"
android:showAsAction="withText|always" />
</menu>

View File

@ -41,5 +41,6 @@
<attr name="ic_menu_email" format="reference"/>
<attr name="calendar_future_bg_color" format="color"/>
<attr name="month_other_bgcolor" format="color"/>
<attr name="settings_calendar_offline" format="reference"/>
</declare-styleable>
</resources>

View File

@ -399,4 +399,32 @@
<!-- Overwrite external chips colors -->
<color name="chips_dropdown_text_default_dark">#9e9e9e</color>
<color name="chips_dropdown_text_highlighted_dark">@android:color/holo_blue_light</color>
<!-- default calendar/event color palette -->
<array name="defaultCalendarColors">
<item>#FFD1270C</item>
<item>#FF11AB64</item>
<item>#FF1454B9</item>
<item>#FF4EA719</item>
<item>#FF62B492</item>
<item>#FF6365CC</item>
<item>#FF6E96B9</item>
<item>#FF6EB3B9</item>
<item>#FF7449B5</item>
<item>#FF8363CC</item>
<item>#FF85B03C</item>
<item>#FF8A4D38</item>
<item>#FF9B9B9B</item>
<item>#FF9E41B8</item>
<item>#FFA29496</item>
<item>#FFA37C82</item>
<item>#FFA63D36</item>
<item>#FFC55C7E</item>
<item>#FFC61600</item>
<item>#FFC81E02</item>
<item>#FFC89D2D</item>
<item>#FFC9B64C</item>
<item>#FFCC3F00</item>
<item>#FFCC770C</item>
</array>
</resources>

View File

@ -140,16 +140,11 @@
<!-- This is a label on a menu item. Pressing this menu
item opens new dialog shown the date that the user wants to go. -->
<string name="goto_date">"Go to…"</string>
<!-- This is a label on a menu item. Pressing this menu item allows the
user to see the list of calendars that he is viewing and to then add
or remove selected calendars. -->
<!-- This is a label on a menu item. Pressing this menu item allows the
user to view and edit his Settings (or Preferences) -->
<string name="menu_preferences">"Settings"</string>
<!-- This is a label on a menu item. Pressing this menu item allows the
user to select the calendars to display [CHAR LIMIT=20] -->
<string name="menu_select_visible_calendars">"Calendars to display"</string>
<!-- This is a label on a menu item. Pressing this menu item allows the
user to select the calendars to display [CHAR LIMIT=20] -->
<string name="search">"Search"</string>
@ -169,36 +164,11 @@
<!-- Select Visible Calendars activity -->
<skip/>
<!-- Title of "My calendars" screen -->
<string name="select_visible_calendars_title">"Calendars to display"</string>
<!-- Synced and visible status message -->
<!-- Synced but not visible status message -->
<!-- not Synced or visible status message -->
<!-- Synced status message displayed when the given calendar is stored/synced on the device
[CHAR LIMIT=60] -->
<string name="synced"> synced</string>
<!-- Not synced status message displayed when the given calendar is not stored/synced on the
device [CHAR LIMIT=60] -->
<string name="not_synced"> not synced</string>
<!-- Message displayed to user when an account with Calendars is not being auto-synced
[CHAR LIMIT=120]-->
<string name="acct_not_synced">This account isn\'t being synced so your calendars may
not be up-to-date.</string>
<!-- Label on button that takes user to the Accounts and Sync settings page [CHAR LIMIT=60] -->
<string name="accounts">Accounts &amp; sync</string>
<!-- Select Synced Calendars activity -->
<!-- Select the set of calendars to sync [CHAR LIMIT=60] -->
<string name="select_synced_calendars_title">Calendars to sync</string>
<!-- Select the set of calendars to sync [CHAR LIMIT=60] -->
<string name="select_synced_calendars_button">Calendars to sync</string>
<!-- Event edit activity -->
<skip/>
<!-- The title of the screen where the user edits an event [CHAR LIMIT=17] -->
<!-- Default value of What field (as a hint to the user) [CHAR LIMIT=15] -->
<string name="hint_what">"Event name"</string>
@ -230,13 +200,6 @@
<string name="rsvp_declined">"Responded no."</string>
<!-- Title of message displayed to indicate available calendars are being loaded when creating
a new event -->
<!-- Body of message displayed to indicate available calendars are being loaded when creating
a new event -->
<!-- Create event dialog -->
<skip/>
<!-- Create event dialog save button [CHAR LIMIT=10] -->
@ -276,7 +239,6 @@
<!-- Label for choosing one of the calendars -->
<string name="edit_event_calendar_label">Calendar</string>
<!-- Menu item to show all choices [CHAR LIMIT=22]-->
<string name="edit_event_show_all">Show all</string>
<!-- Label for the event description -->
<string name="description_label">Description</string>
<!-- Label for the 'Presence' of an event, which can be either 'busy' (the default)
@ -292,7 +254,6 @@
<!-- Body of alert shown if the user tries to create an event and has no calendars. Users can start adding an account here. [CHAR LIMIT=NONE] -->
<string name="no_calendars_found">Before you can add an event, you must add at least one Calendar account to your device and make a calendar visible. Touch Add Account to add an account (if you just added an account, wait for it to finish syncing and try again). Or touch Cancel and make sure at least one calendar is visible.</string>
<!-- Body of dialog prompting the user to create an account.[CHAR LIMIT=NONE] -->
<string name="create_an_account_desc">"Calendar works better with an Account.\n\n\u2022 Access it from any web browser\n\u2022 Back up your events securely"</string>
<!-- Title of a button shown when there is no account available and the system prompt a user to add one. [CHAR LIMIT=none] -->
<string name="add_account">Add account</string>
@ -302,8 +263,6 @@
<string name="view_event_calendar_label">Calendar:</string>
<!-- Label for the event organizer -->
<string name="view_event_organizer_label">Organizer:</string>
<!-- Label for the local timezone -->
<!-- Label for showing event color picker -->
<string name="choose_event_color_label">Choose event color</string>
<!-- Title for event color picker dialog -->
@ -349,7 +308,6 @@
<!-- Summary of the quick response item in Settings [CHAR LIMIT=80]-->
<string name="quick_response_settings_summary">Edit default responses when emailing guests</string>
<!-- Title of the quick response screen in Settings->Quick Response [CHAR LIMIT=27]-->
<string name="quick_response_settings_title">Edit quick responses</string>
<!-- Title of the quick response item in Settings [CHAR LIMIT=18]-->
<string name="quick_response_settings_edit_title">Quick response</string>
@ -368,9 +326,6 @@
<string name="quick_response_custom_msg">Write your own\u2026</string>
<!-- Event Info strings-->
<!-- Time Zone Label [CHAR LIMIT=12]-->
<!-- Repetition Label [CHAR LIMIT=12]-->
<!-- Organizer Label [CHAR LIMIT=12]-->
<string name="event_info_organizer">Organizer:</string>
@ -418,7 +373,6 @@
<skip/>
<!-- The button label for making the reminder alarms go away temporarily.
The reminder alarms will fire off again in 5 minutes. -->
<string name="snooze_all_label">"Snooze all"</string>
<!-- The button label for dismissing all the current reminder alarms. This
causes them to disappear from the notification screen. -->
<string name="dismiss_all_label">"Dismiss all"</string>
@ -462,15 +416,6 @@
<string name="monthly">Monthly</string>
<!-- Calendar spinner item, to select that an event recurs every year. -->
<string name="yearly_plain">Yearly</string>
<!-- Example: "Monthly (on day 15)" -->
<string name="monthly_on_day">"Monthly (on day <xliff:g id="day_of_month">%s</xliff:g>)"</string>
<!-- Example: "Yearly (on April 15)" -->
<string name="yearly">"Yearly (on <xliff:g id="dates">%s</xliff:g>)"</string>
<!-- This is a label for telling the user that this event repeats in
custom (non-standard) way from the usual repeat rates (such as daily,
weekly, etc.) and that the user cannot change this on the phone
(but only on the web). -->
<!-- This is a label for telling the user that this event repeats in
custom (non-standard) way from the usual repeat rates (such as daily,
weekly, etc.) and that the user cannot change this on the phone
@ -510,16 +455,6 @@
changing the response to an invitation. -->
<string name="change_response_title">Change response</string>
<!-- This the title of a menu for General Preferences.
Pressing the menu item lets user to view and edit his general settings
(or preferences) [CHAR LIMIT=30] -->
<string name="menu_general_preferences">General settings</string>
<!-- This the title of a menu for "About Calendar" Preferences.
Pressing the menu item lets user to view the current settings
[CHAR LIMIT=30] -->
<string name="menu_about_preferences">About Etar</string>
<!-- This is the title of the screen for setting user preferences. -->
<string name="preferences_title">"Settings"</string>
<!-- This is the title of a section in the Settings screen for settings
@ -626,7 +561,6 @@
<!-- Widget -->
<skip/>
<!-- Title for calendar gadget when displayed in list of all other gadgets -->
<string name="gadget_title">Calendar</string>
<!-- Shown in month view next to event icon when additional events exist for that day, but no
room remaining -->
@ -641,36 +575,14 @@
<!-- Caption to show on gadget when there are no upcoming calendar events -->
<string name="gadget_no_events">No upcoming calendar events</string>
<!-- Text to show on gadget when an event is currently in progress -->
<!-- Text to show on gadget when an all-day event is in progress -->
<!-- DO NOT TRANSLATE -->
<string name="tardis" translatable="false">TARDIS</string>
<!-- Experimental settings [CHAR LIMIT = 30]-->
<string name="preferences_experimental_category">Experimental</string>
<!-- Reminders settings [CHAR LIMIT = 30]-->
<string name="preferences_reminders_category">Reminders</string>
<!-- Preference label for when to skip reminders [CHAR LIMIT = 25] -->
<string name="preferences_reminders_responded_label">Skip Reminders</string>
<!-- Dialog title for when to skip reminders [CHAR LIMIT = 25] -->
<string name="preferences_reminders_responded_dialog">Skip Reminders</string>
<!-- Preference label for quiet hours [CHAR LIMIT = 25]-->
<string name="preferences_reminders_quiet_hours_label">Quiet hours</string>
<!-- Preference description for quiet hours [CHAR LIMIT = NONE]-->
<string name="preferences_reminders_quiet_hours_description">Silence event reminders during specified time.</string>
<!-- Preference label for quiet hours start time [CHAR LIMIT = 25]-->
<string name="preferences_reminders_quiet_hours_start">Quiet hours start time</string>
<!-- Preference label for quiet hours end time [CHAR LIMIT = 25]-->
<string name="preferences_reminders_quiet_hours_end">Quiet hours end time</string>
<!-- Preferences used for debugging purposes [CHAR LIMIT = 30]-->
<string name="preferences_debug_category">Debugging</string>
<!-- Send a copy of the database to developers for debugging [CHAR LIMIT="NONE"] -->
<string name="copy_db">Send database</string>
@ -703,13 +615,11 @@
<!-- Add a new attendee to an event [CHAR LIMIT = NONE]-->
<string name="accessibility_add_attendee">Add attendee</string>
<!-- Choose if to sync/unsync this calendar with its server [CHAR LIMIT = NONE]-->
<string name="accessibility_sync_cal">Sync calendar</string>
<!-- Mark this event as an "all day event" [CHAR LIMIT = NONE]-->
<string name="accessibility_all_day">All day event</string>
<!-- Refresh the data in the calendar [CHAR LIMIT = NONE]-->
<!-- Choose the type of repetition for the event (daily, weekly, etc.[CHAR LIMIT = NONE]-->
<string name="accessibility_repeats">Repetition</string>
<!-- Set the time for the reminder[CHAR LIMIT = NONE]-->
<string name="accessibility_reminder_time">Reminder time</string>
<!-- Set the type of the reminder (popup/email/sms)[CHAR LIMIT = NONE]-->
@ -718,13 +628,6 @@
<string name="accessibility_reminder_showmeas">Show me as</string>
<!-- Set the event as private/public/default [CHAR LIMIT = NONE]-->
<string name="accessibility_reminder_privacy">Privacy</string>
<!-- Calendar notification [CHAR LIMIT = NONE]-->
<string name="accessibility_cal_notification">Calendar Notification</string>
<!-- Calendar notification snooze button [CHAR LIMIT = NONE]-->
<string name="accessibility_snooze_notification">Snooze Notification</string>
<!-- Calendar notification email button [CHAR LIMIT = NONE]-->
<string name="accessibility_email_notification">Email guests</string>
<!-- A "new event" hint for the user when selecting a specific hour in the day view [CHAR LIMIT = 30]-->
<string name="day_view_new_event_hint">+ New event</string>
@ -754,12 +657,9 @@
<string name="acessibility_selected_marker_description">Selected event</string>
<!-- Tell user not to check a checkbox [CHAR LIMIT=30] -->
<string name="do_not_check">Do NOT check -></string>
<!-- Dialog title for recurrence picker for configuring a repeating event[CHAR LIMIT=20] -->
<string name="recurrence_dialog_title">Repeat</string>
<!-- Dialog title for recurrence picker when one-time event is selected [CHAR LIMIT=20] -->
<string name="recurrence_dialog_title_never">Never repeats</string>
<!-- Strings to describe how frequently to repeat an event (e.g. every 5 days) -->
<plurals name="recurrence_interval_daily">
@ -862,10 +762,10 @@
<string name="preferences_list_calendar_summary_sync_off">Not synchronized</string>
<string name="preferences_list_calendar_summary_invisible">Events are not displayed</string>
<string name="preferences_list_general">General settings</string>
<string name="preferences_list_about">About Etar</string>
<string name="preferences_list_add_remote">Add remote calendar (CalDAV)</string>
<string name="preferences_list_add_offline">Add offline calendar</string>
<string name="preferences_list_add_offline_title">Add offline calendar</string>
<string name="preferences_list_add_offline_error_empty">Enter a calendar name!</string>
<string name="preferences_list_add_offline_message">Offline calendars are NOT synchronized to a cloud service and only available on your phone.</string>
<string name="preferences_list_add_offline_button">Add calendar</string>
<string name="preferences_list_add_offline_name">Name</string>
@ -876,6 +776,7 @@
<string name="preferences_calendar_delete_message">Do you really want to delete this calendar?</string>
<string name="preferences_calendar_delete_delete">Delete calendar</string>
<string name="preferences_calendar_delete_cancel">Cancel</string>
<string name="preferences_menu_about">About Etar</string>
<string name="offline_account_name">Offline Calendar</string>

View File

@ -60,6 +60,7 @@
<item name="ic_menu_email">@drawable/ic_menu_email_holo_light</item>
<item name="calendar_future_bg_color">@color/calendar_future_bg_color</item>
<item name="month_other_bgcolor">@color/month_other_bgcolor</item>
<item name="settings_calendar_offline">@drawable/ic_sync_off_light</item>
</style>
<style name="Base.CalendarAppThemeWithActionBar" parent="Theme.AppCompat.Light.DarkActionBar">

View File

@ -36,6 +36,7 @@
<item name="ic_menu_email">@drawable/ic_menu_email_holo_dark</item>
<item name="calendar_future_bg_color">@color/calendar_future_bg_color_dark</item>
<item name="month_other_bgcolor">@color/month_other_bgcolor_dark</item>
<item name="settings_calendar_offline">@drawable/ic_sync_off_dark</item>
</style>
<style name="CalendarAppThemeBlack" parent="Theme.AppCompat.NoActionBar">
@ -73,6 +74,7 @@
<item name="ic_menu_email">@drawable/ic_menu_email_holo_dark</item>
<item name="calendar_future_bg_color">@color/calendar_future_bg_color_black</item>
<item name="month_other_bgcolor">@color/month_other_bgcolor_black</item>
<item name="settings_calendar_offline">@drawable/ic_sync_off_dark</item>
</style>

View File

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project
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
http://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.
-->
<preference-headers
xmlns:android="http://schemas.android.com/apk/res/android">
<header android:fragment="com.android.calendar.GeneralPreferences"
android:title="@string/menu_general_preferences" />
<header android:fragment="com.android.calendar.AboutPreferences"
android:title="@string/menu_about_preferences" />
</preference-headers>

View File

@ -46,6 +46,7 @@ import android.provider.CalendarContract.Attendees;
import android.provider.CalendarContract.Events;
import com.android.calendar.settings.SettingsActivity;
import com.android.calendar.settings.AboutPreferences;
import com.android.calendar.settings.GeneralPreferences;
import com.android.calendar.settings.SettingsActivityKt;
import com.android.calendar.settings.ViewDetailsPreferences;
@ -949,6 +950,11 @@ public class AllInOneActivity extends AbstractCalendarActivity implements EventH
case R.id.action_settings:
mController.sendEvent(this, EventType.LAUNCH_SETTINGS, null, null, 0, 0);
break;
case R.id.action_about:
Intent intent = new Intent(this, SettingsActivity.class);
intent.putExtra(SettingsActivityKt.EXTRA_SHOW_FRAGMENT, AboutPreferences.class.getName());
startActivity(intent);
break;
}
mDrawerLayout.closeDrawers();
return false;

View File

@ -40,7 +40,7 @@ public class CalendarBackupAgent extends BackupAgentHelper
@Override
public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
throws IOException {
// See Utils.getRingTonePreference for more info
// See Utils.getRingtonePreference for more info
final Editor editor = getSharedPreferences(
GeneralPreferences.SHARED_PREFS_NAME_NO_BACKUP, Context.MODE_PRIVATE).edit();
editor.putString(GeneralPreferences.KEY_ALERTS_RINGTONE,

View File

@ -377,7 +377,7 @@ public class Utils {
// At backup manager "restore" time (which should happen before launcher
// comes up for the first time), the value will be set/reset to default
// ringtone.
public static String getRingTonePreference(Context context) {
public static String getRingtonePreference(Context context) {
SharedPreferences prefs = context.getSharedPreferences(
GeneralPreferences.SHARED_PREFS_NAME_NO_BACKUP, Context.MODE_PRIVATE);
String ringtone = prefs.getString(GeneralPreferences.KEY_ALERTS_RINGTONE, null);
@ -391,13 +391,13 @@ public class Utils {
GeneralPreferences.DEFAULT_RINGTONE);
// Write it to the new place
setRingTonePreference(context, ringtone);
setRingtonePreference(context, ringtone);
}
return ringtone;
}
public static void setRingTonePreference(Context context, String value) {
public static void setRingtonePreference(Context context, String value) {
SharedPreferences prefs = context.getSharedPreferences(
GeneralPreferences.SHARED_PREFS_NAME_NO_BACKUP, Context.MODE_PRIVATE);
prefs.edit().putString(GeneralPreferences.KEY_ALERTS_RINGTONE, value).apply();

View File

@ -1086,7 +1086,7 @@ public class AlertService extends Service {
if (quietUpdate) {
ringtone = EMPTY_RINGTONE;
} else {
ringtone = Utils.getRingTonePreference(context);
ringtone = Utils.getRingtonePreference(context);
}
}
String retVal = ringtone;

View File

@ -18,6 +18,9 @@
package com.android.calendar.persistence
/**
* @property isLocal This calendar is stored locally.
*/
data class Calendar(val id: Long,
val accountName: String,
val accountType: String,
@ -26,4 +29,5 @@ data class Calendar(val id: Long,
val color: Int,
val visible: Boolean,
val syncEvents: Boolean,
val isPrimary: Boolean)
val isPrimary: Boolean,
val isLocal: Boolean)

View File

@ -26,6 +26,8 @@ import android.content.Context
import android.net.Uri
import android.provider.CalendarContract
import androidx.lifecycle.LiveData
import ws.xsoh.etar.R
/**
* Repository as in
@ -66,8 +68,9 @@ internal class CalendarRepository(val application: Application) {
val visible = it.getInt(PROJECTION_INDEX_VISIBLE) == 1
val syncEvents = it.getInt(PROJECTION_INDEX_SYNC_EVENTS) == 1
val isPrimary = it.getInt(PROJECTION_INDEX_IS_PRIMARY) == 1
val isLocal = accountType == CalendarContract.ACCOUNT_TYPE_LOCAL
calendars.add(Calendar(id, accountName, accountType, name, calName, color, visible, syncEvents, isPrimary))
calendars.add(Calendar(id, accountName, accountType, name, calName, color, visible, syncEvents, isPrimary, isLocal))
}
}
return calendars
@ -76,8 +79,6 @@ internal class CalendarRepository(val application: Application) {
companion object {
private val uri = CalendarContract.Calendars.CONTENT_URI
private const val IS_PRIMARY = "primary"
private val PROJECTION = arrayOf(
CalendarContract.Calendars._ID,
CalendarContract.Calendars.ACCOUNT_NAME,
@ -88,8 +89,7 @@ internal class CalendarRepository(val application: Application) {
CalendarContract.Calendars.CALENDAR_COLOR,
CalendarContract.Calendars.VISIBLE,
CalendarContract.Calendars.SYNC_EVENTS,
"(" + CalendarContract.Calendars.ACCOUNT_NAME + "=" + CalendarContract.Calendars.OWNER_ACCOUNT + ") " +
"AS \"" + IS_PRIMARY + "\""
CalendarContract.Calendars.IS_PRIMARY
)
const val PROJECTION_INDEX_ID = 0
const val PROJECTION_INDEX_ACCOUNT_NAME = 1
@ -105,45 +105,90 @@ internal class CalendarRepository(val application: Application) {
}
/**
* Operations only work if they are made "under" the correct account name
* Operations only work if they are made "under" the correct account
*/
private fun buildLocalCalendarUri(accountName: String): Uri {
return CalendarContract.Calendars.CONTENT_URI.buildUpon()
private fun buildLocalCalendarUri(accountName: String, uri: Uri): Uri {
return uri.buildUpon()
.appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
.appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, accountName)
.appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, CalendarContract.ACCOUNT_TYPE_LOCAL).build()
}
private fun buildLocalCalendarContentValues(accountName: String, displayName: String, color: Int): ContentValues {
val uniqueName = "etar_local_" + displayName + "_" + System.currentTimeMillis()
private fun buildLocalCalendarContentValues(accountName: String, displayName: String): ContentValues {
val internalName = "etar_local_" + displayName.replace("[^a-zA-Z0-9]".toRegex(), "")
return ContentValues().apply {
put(CalendarContract.Calendars.ACCOUNT_NAME, accountName)
put(CalendarContract.Calendars.ACCOUNT_TYPE, CalendarContract.ACCOUNT_TYPE_LOCAL)
put(CalendarContract.Calendars.NAME, uniqueName)
put(CalendarContract.Calendars.OWNER_ACCOUNT, accountName)
put(CalendarContract.Calendars.NAME, internalName)
put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, displayName)
put(CalendarContract.Calendars.CALENDAR_COLOR, color)
put(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL, CalendarContract.Calendars.CAL_ACCESS_OWNER)
// put(CalendarContract.Calendars.OWNER_ACCOUNT, accountName) // primary calendar for this account
put(CalendarContract.Calendars.OWNER_ACCOUNT, "") // non-primary
put(CalendarContract.Calendars.CALENDAR_COLOR_KEY, DEFAULT_COLOR_KEY)
put(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL, CalendarContract.Calendars.CAL_ACCESS_ROOT)
put(CalendarContract.Calendars.VISIBLE, 1)
put(CalendarContract.Calendars.SYNC_EVENTS, 1)
put(CalendarContract.Calendars.IS_PRIMARY, 0)
put(CalendarContract.Calendars.CAN_ORGANIZER_RESPOND, 0)
put(CalendarContract.Calendars.CAN_MODIFY_TIME_ZONE, 1)
// from Android docs: "the device will only process METHOD_DEFAULT and METHOD_ALERT reminders"
put(CalendarContract.Calendars.ALLOWED_REMINDERS, CalendarContract.Reminders.METHOD_ALERT.toString())
put(CalendarContract.Calendars.ALLOWED_ATTENDEE_TYPES, CalendarContract.Attendees.TYPE_NONE.toString())
}
}
/**
* Add calendar with given name and color
*/
fun addLocalCalendar(accountName: String, displayName: String, color: Int): Uri {
val cv = buildLocalCalendarContentValues(accountName, displayName, color)
return contentResolver.insert(buildLocalCalendarUri(accountName), cv)
private fun buildLocalCalendarColorsContentValues(accountName: String, colorType: Int, colorKey: String, color: Int): ContentValues {
return ContentValues().apply {
put(CalendarContract.Colors.ACCOUNT_NAME, accountName)
put(CalendarContract.Colors.ACCOUNT_TYPE, CalendarContract.ACCOUNT_TYPE_LOCAL)
put(CalendarContract.Colors.COLOR_TYPE, colorType)
put(CalendarContract.Colors.COLOR_KEY, colorKey)
put(CalendarContract.Colors.COLOR, color)
}
}
fun addLocalCalendar(accountName: String, displayName: String): Uri {
maybeAddCalendarAndEventColors(accountName)
val cv = buildLocalCalendarContentValues(accountName, displayName)
return contentResolver.insert(buildLocalCalendarUri(accountName, CalendarContract.Calendars.CONTENT_URI), cv)
?: throw IllegalArgumentException()
}
private fun maybeAddCalendarAndEventColors(accountName: String) {
if (areCalendarColorsExisting(accountName)) {
return
}
val defaultColors: IntArray = application.resources.getIntArray(R.array.defaultCalendarColors)
val insertBulk = mutableListOf<ContentValues>()
for ((i, color) in defaultColors.withIndex()) {
val colorKey = i.toString()
val colorCvCalendar = buildLocalCalendarColorsContentValues(accountName, CalendarContract.Colors.TYPE_CALENDAR, colorKey, color)
val colorCvEvent = buildLocalCalendarColorsContentValues(accountName, CalendarContract.Colors.TYPE_EVENT, colorKey, color)
insertBulk.add(colorCvCalendar)
insertBulk.add(colorCvEvent)
}
contentResolver.bulkInsert(buildLocalCalendarUri(accountName, CalendarContract.Colors.CONTENT_URI), insertBulk.toTypedArray())
}
private fun areCalendarColorsExisting(accountName: String): Boolean {
contentResolver.query(CalendarContract.Colors.CONTENT_URI,
null,
CalendarContract.Colors.ACCOUNT_NAME + "=? AND " + CalendarContract.Colors.ACCOUNT_TYPE + "=?",
arrayOf(accountName, CalendarContract.ACCOUNT_TYPE_LOCAL),
null).use {
if (it!!.moveToFirst()) {
return true
}
}
return false
}
/**
* @return true iff exactly one row is deleted
*/
fun deleteLocalCalendar(accountName: String, id: Long): Boolean {
val calUri = ContentUris.withAppendedId(buildLocalCalendarUri(accountName), id)
val calUri = ContentUris.withAppendedId(buildLocalCalendarUri(accountName, CalendarContract.Calendars.CONTENT_URI), id)
return contentResolver.delete(calUri, null, null) == 1
}
@ -166,6 +211,8 @@ internal class CalendarRepository(val application: Application) {
)
const val ACCOUNT_INDEX_NAME = 0
const val ACCOUNT_INDEX_TYPE = 1
const val DEFAULT_COLOR_KEY = "1"
}
}

View File

@ -215,50 +215,20 @@ public class SelectCalendarsSimpleAdapter extends BaseAdapter implements ListAda
}
calendarName.setTextColor(textColor);
CheckBox syncCheckBox = (CheckBox) view.findViewById(R.id.sync);
if (syncCheckBox != null) {
// Full screen layout
syncCheckBox.setChecked(selected);
colorView.setEnabled(hasMoreColors(position));
LayoutParams layoutParam = calendarName.getLayoutParams();
TextView secondaryText = (TextView) view.findViewById(R.id.status);
if (!TextUtils.isEmpty(mData[position].ownerAccount)
&& !mData[position].ownerAccount.equals(name)
&& !mData[position].ownerAccount.endsWith("calendar.google.com")) {
int secondaryColor;
if (selected) {
secondaryColor = mColorCalendarSecondaryVisible;
} else {
secondaryColor = mColorCalendarSecondaryHidden;
}
secondaryText.setText(mData[position].ownerAccount);
secondaryText.setTextColor(secondaryColor);
secondaryText.setVisibility(View.VISIBLE);
layoutParam.height = LayoutParams.WRAP_CONTENT;
} else {
secondaryText.setVisibility(View.GONE);
layoutParam.height = LayoutParams.MATCH_PARENT;
}
calendarName.setLayoutParams(layoutParam);
// Tablet layout
view.findViewById(R.id.color).setEnabled(selected && hasMoreColors(position));
view.setBackgroundDrawable(getBackground(position, selected));
ViewGroup.LayoutParams newParams = view.getLayoutParams();
if (position == mData.length - 1) {
newParams.height = BOTTOM_ITEM_HEIGHT;
} else {
// Tablet layout
view.findViewById(R.id.color).setEnabled(selected && hasMoreColors(position));
view.setBackgroundDrawable(getBackground(position, selected));
ViewGroup.LayoutParams newParams = view.getLayoutParams();
if (position == mData.length - 1) {
newParams.height = BOTTOM_ITEM_HEIGHT;
} else {
newParams.height = NORMAL_ITEM_HEIGHT;
}
view.setLayoutParams(newParams);
CheckBox visibleCheckBox = (CheckBox) view.findViewById(R.id.visible_check_box);
if (visibleCheckBox != null) {
visibleCheckBox.setChecked(selected);
}
newParams.height = NORMAL_ITEM_HEIGHT;
}
view.setLayoutParams(newParams);
CheckBox visibleCheckBox = (CheckBox) view.findViewById(R.id.visible_check_box);
if (visibleCheckBox != null) {
visibleCheckBox.setChecked(selected);
}
view.invalidate();
return view;

View File

@ -19,16 +19,22 @@ package com.android.calendar.settings
import android.annotation.SuppressLint
import android.app.Dialog
import android.content.DialogInterface
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.widget.EditText
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import com.android.calendar.persistence.CalendarRepository
import com.google.android.material.textfield.TextInputLayout
import ws.xsoh.etar.R
class AddOfflineCalendarDialogFragment : DialogFragment() {
private lateinit var nameEditText: EditText
private lateinit var nameEditTextLayout: TextInputLayout
@SuppressLint("InflateParams")
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
@ -36,28 +42,58 @@ class AddOfflineCalendarDialogFragment : DialogFragment() {
val inflater = requireActivity().layoutInflater
val view = inflater.inflate(R.layout.add_offline_calendar_dialog, null)
nameEditText = view.findViewById(R.id.offline_calendar_name)
nameEditTextLayout = view.findViewById(R.id.offline_calendar_name_layout)
nameEditText.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable) {
nameEditTextLayout.error = null
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
})
val builder = AlertDialog.Builder(it).apply {
setView(view)
setTitle(R.string.preferences_list_add_offline_title)
setMessage(R.string.preferences_list_add_offline_message)
setPositiveButton(R.string.preferences_list_add_offline_button) { _, _ ->
addCalendar()
}
setNegativeButton(R.string.preferences_list_add_offline_cancel) { dialog, _ ->
dialog.cancel()
}
}
val dialog = builder.create()
builder.create()
// set listener in onResume to work around auto-dismiss of AlertDialog.Builder
// https://stackoverflow.com/a/10661281/1600685
val emptyClickListener: DialogInterface.OnClickListener? = null
dialog.setButton(AlertDialog.BUTTON_POSITIVE, getString(R.string.preferences_list_add_offline_button), emptyClickListener)
dialog.setButton(AlertDialog.BUTTON_NEGATIVE, getString(R.string.preferences_list_add_offline_cancel), emptyClickListener)
return dialog
} ?: throw IllegalStateException("Activity cannot be null")
}
override fun onResume() {
super.onResume()
val alertDialog = dialog as AlertDialog
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
addCalendar()
}
alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener {
alertDialog.cancel()
}
}
private fun addCalendar() {
val accountName = getString(R.string.offline_account_name)
val displayName = nameEditText.text.toString()
val color = -10308462
if (displayName.isEmpty()) {
nameEditTextLayout.error = getString(R.string.preferences_list_add_offline_error_empty)
return
}
val repository = CalendarRepository(activity!!.application)
repository.addLocalCalendar(accountName, displayName, color)
repository.addLocalCalendar(accountName, displayName)
dismiss()
}
}

View File

@ -40,13 +40,11 @@ import java.util.*
* - extends ColorPickerDialogX for androidx compatibility
* - added OnCalendarColorSelectedListener
* - handle calendars where no additional colors are provided by the account
* - handle local accounts
*/
class CalendarColorPickerDialogX : ColorPickerDialogX() {
private var queryService: QueryService? = null
private val colorKeyMap = SparseIntArray()
private var calendarId: Long = 0
private var isLocalAccount: Boolean = false
private var calendarColorListener: OnCalendarColorSelectedListener? = null
@ -159,8 +157,6 @@ class CalendarColorPickerDialogX : ColorPickerDialogX() {
mSelectedColor = Utils.getDisplayColorFromColor(cursor.getInt(CALENDARS_INDEX_CALENDAR_COLOR))
val account = Account(cursor.getString(CALENDARS_INDEX_ACCOUNT_NAME),
cursor.getString(CALENDARS_INDEX_ACCOUNT_TYPE))
isLocalAccount = account.type == ACCOUNT_TYPE_LOCAL
cursor.close()
startColorQuery(account)
@ -196,17 +192,16 @@ class CalendarColorPickerDialogX : ColorPickerDialogX() {
}
private fun useDefaultColors() {
if (!isLocalAccount) {
val warningDialog = AlertDialog.Builder(activity!!)
.setTitle(R.string.preferences_calendar_color_warning_title)
.setMessage(R.string.preferences_calendar_color_warning_message)
.setPositiveButton(R.string.preferences_calendar_color_warning_button) { dialogInterface, _ ->
dialogInterface.dismiss()
}
.create()
warningDialog.show()
}
setColorPalette(defaultColors)
val warningDialog = AlertDialog.Builder(activity!!)
.setTitle(R.string.preferences_calendar_color_warning_title)
.setMessage(R.string.preferences_calendar_color_warning_message)
.setPositiveButton(R.string.preferences_calendar_color_warning_button) { dialogInterface, _ ->
dialogInterface.dismiss()
}
.create()
warningDialog.show()
val defaultColors: IntArray = resources.getIntArray(R.array.defaultCalendarColors)
setColorPalette(defaultColors.toTypedArray())
showPaletteView()
}
@ -256,33 +251,6 @@ class CalendarColorPickerDialogX : ColorPickerDialogX() {
internal const val CALENDARS_INDEX_ACCOUNT_TYPE = 1
internal const val CALENDARS_INDEX_CALENDAR_COLOR = 2
internal val defaultColors = arrayOf(
-16742839,
-15619228,
-15444807,
-11622631,
-10308462,
-10263092,
-9529671,
-9522247,
-9156171,
-8166452,
-8015812,
-7713480,
-6579301,
-6405704,
-6122346,
-6062974,
-5882570,
-3842946,
-3795456,
-3662334,
-3629779,
-3557812,
-3391744,
-3377396
)
internal val COLORS_PROJECTION = arrayOf(
Colors.COLOR,
Colors.COLOR_KEY

View File

@ -20,17 +20,18 @@ package com.android.calendar.settings
import android.accounts.Account
import android.accounts.AccountManager
import android.accounts.AuthenticatorDescription
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.provider.CalendarContract
import android.util.Log
import android.util.TypedValue
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.preference.*
import com.android.calendar.Utils
import com.android.calendar.persistence.CalendarRepository
import ws.xsoh.etar.R
class CalendarPreferences : PreferenceFragmentCompat() {
private var calendarId: Long = -1
@ -58,7 +59,7 @@ class CalendarPreferences : PreferenceFragmentCompat() {
val synchronizePreference = SwitchPreference(context).apply {
key = SYNCHRONIZE_KEY
title = getString(R.string.preferences_calendar_synchronize)
isEnabled = !isLocalAccount
isVisible = !isLocalAccount
}
val visiblePreference = SwitchPreference(context).apply {
key = VISIBLE_KEY
@ -80,7 +81,7 @@ class CalendarPreferences : PreferenceFragmentCompat() {
key = DISPLAY_NAME_KEY
title = getString(R.string.preferences_calendar_display_name)
dialogTitle = getString(R.string.preferences_calendar_display_name)
isEnabled = isLocalAccount
isVisible = isLocalAccount
}
displayNamePreference.setOnPreferenceChangeListener { _, newValue ->
activity?.title = newValue as String
@ -88,7 +89,7 @@ class CalendarPreferences : PreferenceFragmentCompat() {
}
val deletePreference = Preference(context).apply {
title = getString(R.string.preferences_calendar_delete)
isEnabled = isLocalAccount
isVisible = isLocalAccount
}
deletePreference.setOnPreferenceClickListener {
deleteCalendar()
@ -110,7 +111,7 @@ class CalendarPreferences : PreferenceFragmentCompat() {
val localAccountInfoPreference = Preference(context).apply {
title = getString(R.string.preferences_list_add_offline_message)
isSelectable = false
icon = resources.getDrawable(R.drawable.sync_off)
icon = getThemeDrawable(R.attr.settings_calendar_offline)
}
accountCategory.addPreference(localAccountInfoPreference)
} else {
@ -120,6 +121,14 @@ class CalendarPreferences : PreferenceFragmentCompat() {
preferenceScreen = screen
}
private fun getThemeDrawable(attr: Int): Drawable {
val typedValue = TypedValue()
context!!.theme.resolveAttribute(attr, typedValue, true)
val imageResId = typedValue.resourceId
return ContextCompat.getDrawable(context!!, imageResId)
?: throw IllegalArgumentException("Cannot load drawable $imageResId")
}
private fun addConfigureAccountPreference(category: PreferenceCategory, account: Account) {
val description = getAuthenticatorDescription(account) ?: return
@ -143,8 +152,8 @@ class CalendarPreferences : PreferenceFragmentCompat() {
}
private fun getColorIcon(color: Int): Drawable {
val icon: Drawable = resources.getDrawable(R.drawable.circle)
icon.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN)
val icon: Drawable = ContextCompat.getDrawable(context!!, R.drawable.circle)!!
icon.mutate().setColorFilter(color, Mode.SRC_IN)
return icon
}

View File

@ -0,0 +1,105 @@
/*
* Copyright (C) 2020 Dominik Schürmann <dominik@schuermann.eu>
*
* 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.
*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.android.calendar.settings
import android.annotation.SuppressLint
import android.graphics.BlendMode
import android.graphics.BlendModeColorFilter
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable
import android.os.Build
/**
* From https://stackoverflow.com/a/57054627/1600685
*/
fun Drawable.setColorFilter(color: Int, mode: Mode = Mode.SRC_ATOP) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
colorFilter = BlendModeColorFilter(color, mode.getBlendMode())
} else {
@Suppress("DEPRECATION")
setColorFilter(color, mode.getPorterDuffMode())
}
}
// This class is needed to call the setColorFilter
// with different BlendMode on older API (before 29).
enum class Mode {
CLEAR,
SRC,
DST,
SRC_OVER,
DST_OVER,
SRC_IN,
DST_IN,
SRC_OUT,
DST_OUT,
SRC_ATOP,
DST_ATOP,
XOR,
DARKEN,
LIGHTEN,
MULTIPLY,
SCREEN,
ADD,
OVERLAY;
@SuppressLint("NewApi")
fun getBlendMode(): BlendMode =
when (this) {
CLEAR -> BlendMode.CLEAR
SRC -> BlendMode.SRC
DST -> BlendMode.DST
SRC_OVER -> BlendMode.SRC_OVER
DST_OVER -> BlendMode.DST_OVER
SRC_IN -> BlendMode.SRC_IN
DST_IN -> BlendMode.DST_IN
SRC_OUT -> BlendMode.SRC_OUT
DST_OUT -> BlendMode.DST_OUT
SRC_ATOP -> BlendMode.SRC_ATOP
DST_ATOP -> BlendMode.DST_ATOP
XOR -> BlendMode.XOR
DARKEN -> BlendMode.DARKEN
LIGHTEN -> BlendMode.LIGHTEN
MULTIPLY -> BlendMode.MULTIPLY
SCREEN -> BlendMode.SCREEN
ADD -> BlendMode.PLUS
OVERLAY -> BlendMode.OVERLAY
}
fun getPorterDuffMode(): PorterDuff.Mode =
when (this) {
CLEAR -> PorterDuff.Mode.CLEAR
SRC -> PorterDuff.Mode.SRC
DST -> PorterDuff.Mode.DST
SRC_OVER -> PorterDuff.Mode.SRC_OVER
DST_OVER -> PorterDuff.Mode.DST_OVER
SRC_IN -> PorterDuff.Mode.SRC_IN
DST_IN -> PorterDuff.Mode.DST_IN
SRC_OUT -> PorterDuff.Mode.SRC_OUT
DST_OUT -> PorterDuff.Mode.DST_OUT
SRC_ATOP -> PorterDuff.Mode.SRC_ATOP
DST_ATOP -> PorterDuff.Mode.DST_ATOP
XOR -> PorterDuff.Mode.XOR
DARKEN -> PorterDuff.Mode.DARKEN
LIGHTEN -> PorterDuff.Mode.LIGHTEN
MULTIPLY -> PorterDuff.Mode.MULTIPLY
SCREEN -> PorterDuff.Mode.SCREEN
ADD -> PorterDuff.Mode.ADD
OVERLAY -> PorterDuff.Mode.OVERLAY
}
}

View File

@ -34,9 +34,9 @@ import android.provider.CalendarContract.CalendarCache
import android.provider.SearchRecentSuggestions
import android.provider.Settings
import android.text.TextUtils
import android.text.format.Time
import android.util.SparseIntArray
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.preference.*
import com.android.calendar.*
import com.android.calendar.alerts.AlertReceiver
@ -44,6 +44,7 @@ import com.android.calendar.event.EventViewUtils
import com.android.timezonepicker.TimeZoneInfo
import com.android.timezonepicker.TimeZonePickerUtils
import ws.xsoh.etar.R
import java.util.*
class GeneralPreferences : PreferenceFragmentCompat(),
OnSharedPreferenceChangeListener, Preference.OnPreferenceChangeListener,
@ -111,14 +112,14 @@ class GeneralPreferences : PreferenceFragmentCompat(),
mAlertGroup!!.removePreference(mVibrate)
}
mRingtone = preferenceScreen.findPreference(KEY_ALERTS_RINGTONE)!!
val ringToneUri = Utils.getRingTonePreference(activity)
val ringtoneUriString = Utils.getRingtonePreference(activity)
// Set the ringToneUri to the backup-able shared pref only so that
// Set the ringtoneUri to the backup-able shared pref only so that
// the Ringtone dialog will open up with the correct value.
val editor = prefs.edit()
editor.putString(KEY_ALERTS_RINGTONE, ringToneUri).apply()
editor.putString(KEY_ALERTS_RINGTONE, ringtoneUriString).apply()
val ringtoneDisplayString = getRingtoneTitleFromUri(activity!!, ringToneUri)
val ringtoneDisplayString = getRingtoneTitleFromUri(activity!!, ringtoneUriString)
mRingtone.summary = ringtoneDisplayString ?: ""
}
@ -152,7 +153,7 @@ class GeneralPreferences : PreferenceFragmentCompat(),
// in the shared_pref if home time zone is disabled. So if home tz is
// off, we will explicitly read it.
if (!prefs.getBoolean(KEY_HOME_TZ_ENABLED, false)) {
mTimeZoneId = prefs.getString(KEY_HOME_TZ, Time.getCurrentTimezone())
mTimeZoneId = prefs.getString(KEY_HOME_TZ, TimeZone.getDefault().id)
}
if (mTzPickerUtils == null) {
@ -166,12 +167,7 @@ class GeneralPreferences : PreferenceFragmentCompat(),
.findFragmentByTag(FRAG_TAG_TIME_ZONE_PICKER) as TimeZonePickerDialogX?
tzpd?.setOnTimeZoneSetListener(this)
var skipPreferencesValue: String? = null
if (mSkipReminders != null) {
skipPreferencesValue = mSkipReminders.value
mSkipReminders.onPreferenceChangeListener = this
}
updateSkipRemindersSummary(skipPreferencesValue)
updateSkipRemindersSummary(mSkipReminders.value)
}
/**
@ -180,34 +176,33 @@ class GeneralPreferences : PreferenceFragmentCompat(),
* will be set, and the value will be set accordingly too.
*/
private fun updateSkipRemindersSummary(value: String?) {
if (mSkipReminders != null) { // Default to "declined". Must match with R.array.preferences_skip_reminders_values.
var index = 0
val values = mSkipReminders.entryValues
val entries = mSkipReminders.entries
for (value_i in values.indices) {
if (values[value_i] == value) {
index = value_i
break
}
}
mSkipReminders.summary = entries[index].toString()
if (value == null) { // Value was not known ahead of time, so the default value will be set.
mSkipReminders.value = values[index].toString()
// Default to "declined". Must match with R.array.preferences_skip_reminders_values.
var index = 0
val values = mSkipReminders.entryValues
val entries = mSkipReminders.entries
for (value_i in values.indices) {
if (values[value_i] == value) {
index = value_i
break
}
}
mSkipReminders.summary = entries[index].toString()
if (value == null) { // Value was not known ahead of time, so the default value will be set.
mSkipReminders.value = values[index].toString()
}
}
private fun showColorPickerDialog() {
val colorPickerDialog = ColorPickerDialogX()
val selectedColorName = Utils.getSharedPreference(activity, KEY_COLOR_PREF, "teal")
val selectedColor = resources.getColor(DynamicTheme.getColorId(selectedColorName))
val selectedColor = ContextCompat.getColor(context!!, DynamicTheme.getColorId(selectedColorName))
colorPickerDialog.initialize(R.string.preferences_color_pick,
intArrayOf(resources.getColor(R.color.colorPrimary),
resources.getColor(R.color.colorBluePrimary),
resources.getColor(R.color.colorPurplePrimary),
resources.getColor(R.color.colorRedPrimary),
resources.getColor(R.color.colorOrangePrimary),
resources.getColor(R.color.colorGreenPrimary)),
intArrayOf(ContextCompat.getColor(context!!, R.color.colorPrimary),
ContextCompat.getColor(context!!, R.color.colorBluePrimary),
ContextCompat.getColor(context!!, R.color.colorPurplePrimary),
ContextCompat.getColor(context!!, R.color.colorRedPrimary),
ContextCompat.getColor(context!!, R.color.colorOrangePrimary),
ContextCompat.getColor(context!!, R.color.colorGreenPrimary)),
selectedColor, 3, 2)
colorPickerDialog.setOnColorSelectedListener { colour ->
Utils.setSharedPreference(activity, KEY_COLOR_PREF, DynamicTheme.getColorName(colorMap.get(colour)))
@ -216,12 +211,12 @@ class GeneralPreferences : PreferenceFragmentCompat(),
}
private fun initializeColorMap() {
colorMap.put(resources.getColor(R.color.colorPrimary), R.color.colorPrimary)
colorMap.put(resources.getColor(R.color.colorBluePrimary), R.color.colorBluePrimary)
colorMap.put(resources.getColor(R.color.colorOrangePrimary), R.color.colorOrangePrimary)
colorMap.put(resources.getColor(R.color.colorGreenPrimary), R.color.colorGreenPrimary)
colorMap.put(resources.getColor(R.color.colorRedPrimary), R.color.colorRedPrimary)
colorMap.put(resources.getColor(R.color.colorPurplePrimary), R.color.colorPurplePrimary)
colorMap.put(ContextCompat.getColor(context!!, R.color.colorPrimary), R.color.colorPrimary)
colorMap.put(ContextCompat.getColor(context!!, R.color.colorBluePrimary), R.color.colorBluePrimary)
colorMap.put(ContextCompat.getColor(context!!, R.color.colorOrangePrimary), R.color.colorOrangePrimary)
colorMap.put(ContextCompat.getColor(context!!, R.color.colorGreenPrimary), R.color.colorGreenPrimary)
colorMap.put(ContextCompat.getColor(context!!, R.color.colorRedPrimary), R.color.colorRedPrimary)
colorMap.put(ContextCompat.getColor(context!!, R.color.colorPurplePrimary), R.color.colorPurplePrimary)
}
private fun showTimezoneDialog() {
@ -261,6 +256,7 @@ class GeneralPreferences : PreferenceFragmentCompat(),
mSnoozeDelay.onPreferenceChangeListener = listener
mHideDeclined.onPreferenceChangeListener = listener
mDefaultEventDuration.onPreferenceChangeListener = listener
mSkipReminders.onPreferenceChangeListener = listener
if (Utils.isOreoOrLater()) {
mNotification!!.onPreferenceChangeListener = listener
} else {
@ -379,9 +375,7 @@ class GeneralPreferences : PreferenceFragmentCompat(),
}
override fun onPreferenceTreeClick(preference: Preference?): Boolean {
val key = preference!!.key;
when (key) {
when (preference!!.key) {
KEY_HOME_TZ -> {
showTimezoneDialog()
return true
@ -444,11 +438,12 @@ class GeneralPreferences : PreferenceFragmentCompat(),
putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, Settings.System.DEFAULT_NOTIFICATION_URI)
}
val existingValue = Utils.getRingTonePreference(activity)
val existingValue = Utils.getRingtonePreference(activity)
if (existingValue != null) {
if (existingValue.isEmpty()) {
// Select "Silent"
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, null as Uri)
val empty: Uri? = null
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, empty)
} else {
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, Uri.parse(existingValue))
}
@ -463,14 +458,11 @@ class GeneralPreferences : PreferenceFragmentCompat(),
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == REQUEST_CODE_ALERT_RINGTONE && data != null) {
val ringtone = data.getParcelableExtra<Uri>(RingtoneManager.EXTRA_RINGTONE_PICKED_URI)
if (ringtone != null) {
Utils.setRingTonePreference(activity, ringtone.toString())
} else {
// "Silent" was selected
Utils.setRingTonePreference(activity, "")
}
// ringtone is null when "Silent" was selected
val ringtoneString = ringtone?.toString() ?: ""
val ringtoneDisplayString = getRingtoneTitleFromUri(activity!!, ringtone.toString())
Utils.setRingtonePreference(activity, ringtoneString)
val ringtoneDisplayString = getRingtoneTitleFromUri(activity!!, ringtoneString)
mRingtone.summary = ringtoneDisplayString ?: ""
} else {
super.onActivityResult(requestCode, resultCode, data)
@ -564,10 +556,10 @@ class GeneralPreferences : PreferenceFragmentCompat(),
fun setDefaultValues(context: Context) {
if (Utils.isOreoOrLater()) {
PreferenceManager.setDefaultValues(context, SHARED_PREFS_NAME, Context.MODE_PRIVATE,
R.xml.general_preferences_oreo_and_up, true);
R.xml.general_preferences_oreo_and_up, true)
} else {
PreferenceManager.setDefaultValues(context, SHARED_PREFS_NAME, Context.MODE_PRIVATE,
R.xml.general_preferences_below_oreo, true);
R.xml.general_preferences_nougat_and_less, true)
}
}
}

View File

@ -18,12 +18,12 @@
package com.android.calendar.settings
import android.content.Intent
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.preference.Preference
@ -59,11 +59,11 @@ class MainListPreferences : PreferenceFragmentCompat() {
// The onChanged() method fires when the observed data changes and the activity is
// in the foreground.
mainListViewModel.getCalendarsOrderedByAccount().observe(viewLifecycleOwner, Observer<List<Calendar>> { calendars ->
updateAccountsPreferences(preferenceScreen, calendars)
updateCalendarPreferences(preferenceScreen, calendars)
})
}
private fun updateAccountsPreferences(screen: PreferenceScreen, allCalendars: List<Calendar>) {
private fun updateCalendarPreferences(screen: PreferenceScreen, allCalendars: List<Calendar>) {
val newCalendars = mutableSetOf<Long>()
for (calendar in allCalendars) {
@ -76,7 +76,8 @@ class MainListPreferences : PreferenceFragmentCompat() {
accountCategory = PreferenceCategory(context).apply {
key = accountCategoryUniqueKey
title = calendar.accountName
isOrderingAsAdded = false
order = if (calendar.isLocal) 10 else 11 // show offline calendar first
isOrderingAsAdded = false // use alphabetic ordering for children
}
screen.addPreference(accountCategory)
}
@ -92,7 +93,7 @@ class MainListPreferences : PreferenceFragmentCompat() {
key = calendarUniqueKey
title = calendar.displayName
fragment = CalendarPreferences::class.java.name
order = if (calendar.isPrimary) 2 else 3 // primary calendar is first, others are alphabetically ordered below
order = if (calendar.isPrimary) 1 else 2 // primary calendar is first, others are alphabetically ordered below
icon = getCalendarIcon(calendar.color, calendar.visible, calendar.syncEvents)
summary = getCalendarSummary(calendar.visible, calendar.syncEvents)
}
@ -101,11 +102,26 @@ class MainListPreferences : PreferenceFragmentCompat() {
}
// remove preferences for calendars no longer existing
val toDelete = currentCalendars.subtract(newCalendars)
toDelete.forEach {
val calendarsToDelete = currentCalendars.subtract(newCalendars)
calendarsToDelete.forEach {
val calendarUniqueKey = "calendar_preference_${it}"
screen.removePreferenceRecursively(calendarUniqueKey)
}
// remove empty account categories
val categoriesToDelete = mutableSetOf<PreferenceCategory>()
for (i in 0 until screen.preferenceCount) {
val pref = screen.getPreference(i)
if (pref is PreferenceCategory) {
if (pref.preferenceCount == 0) {
categoriesToDelete.add(pref)
}
}
}
categoriesToDelete.forEach {
screen.removePreference(it)
}
currentCalendars = newCalendars
}
@ -121,14 +137,14 @@ class MainListPreferences : PreferenceFragmentCompat() {
private fun getCalendarIcon(color: Int, visible: Boolean, syncEvents: Boolean): Drawable {
val icon = if (!syncEvents) {
resources.getDrawable(R.drawable.sync_off)
ContextCompat.getDrawable(context!!, R.drawable.ic_sync_off_light)
} else if (visible) {
resources.getDrawable(R.drawable.circle)
ContextCompat.getDrawable(context!!, R.drawable.circle)
} else {
resources.getDrawable(R.drawable.circle_outline)
ContextCompat.getDrawable(context!!, R.drawable.circle_outline)
}
icon.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN)
icon!!.mutate().setColorFilter(color, Mode.SRC_IN)
return icon
}
@ -151,14 +167,9 @@ class MainListPreferences : PreferenceFragmentCompat() {
addOfflineCalendar()
true
}
val aboutPreference = Preference(context).apply {
title = getString(R.string.preferences_list_about)
fragment = AboutPreferences::class.java.name
}
screen.addPreference(generalPreference)
screen.addPreference(addCaldavPreference)
screen.addPreference(addOfflinePreference)
screen.addPreference(aboutPreference)
}
private fun addOfflineCalendar() {

View File

@ -25,6 +25,7 @@ import androidx.lifecycle.ViewModelProvider
class MainListViewModelFactory(private val application: Application) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
@NonNull
override fun <T : ViewModel> create(@NonNull modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(MainListViewModel::class.java)) {

View File

@ -30,6 +30,12 @@ private const val TITLE_TAG = "settingsActivityTitle"
const val EXTRA_SHOW_FRAGMENT = "settingsShowFragment"
/**
* Based on the official Kotlin example for AndroidX preferences:
* https://github.com/android/user-interface-samples/blob/master/PreferencesKotlin/app/src/main/java/com/example/androidx/preference/sample/MainActivity.kt
*
* Extended by EXTRA_SHOW_FRAGMENT
*/
class SettingsActivity : AppCompatActivity(),
PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {

View File

@ -29,6 +29,8 @@ import androidx.fragment.app.DialogFragment;
import com.android.timezonepicker.TimeZoneInfo;
import com.android.timezonepicker.TimeZonePickerView;
import org.jetbrains.annotations.NotNull;
/**
* 1-to-1 Copy of TimeZonePickerDialog but using androidx classes
*/
@ -62,8 +64,8 @@ public class TimeZonePickerDialogX extends DialogFragment implements
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
public View onCreateView(@NotNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
long timeMillis = 0;
String timeZone = null;
Bundle b = getArguments();
@ -80,14 +82,14 @@ public class TimeZonePickerDialogX extends DialogFragment implements
hideFilterSearch);
if (savedInstanceState != null && savedInstanceState.getBoolean(KEY_HAS_RESULTS, false)) {
mView.showFilterResults(savedInstanceState.getInt(KEY_LAST_FILTER_TYPE),
savedInstanceState.getString(KEY_LAST_FILTER_STRING),
savedInstanceState.getInt(KEY_LAST_FILTER_TIME));
savedInstanceState.getString(KEY_LAST_FILTER_STRING),
savedInstanceState.getInt(KEY_LAST_FILTER_TIME));
}
return mView;
}
@Override
public void onSaveInstanceState(Bundle outState) {
public void onSaveInstanceState(@NotNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(KEY_HAS_RESULTS, mView != null && mView.hasResults());
if (mView != null) {
@ -98,6 +100,7 @@ public class TimeZonePickerDialogX extends DialogFragment implements
}
}
@NotNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);

View File

@ -56,20 +56,20 @@ class ViewDetailsPreferences : PreferenceFragmentCompat() {
val KEY_MAX_NUMBER_OF_LINES: String)
private class PreferenceConfiguration(val mKeys: PreferenceKeys) {
private var mDisplayTime: ListPreference? = null
private lateinit var mDisplayTime: ListPreference
fun onCreate(preferenceScreen: PreferenceScreen, activity: Activity?) {
mDisplayTime = preferenceScreen.findPreference<Preference>(mKeys.KEY_DISPLAY_TIME) as ListPreference?
mDisplayTime = preferenceScreen.findPreference(mKeys.KEY_DISPLAY_TIME)!!
initDisplayTime(activity)
}
private fun initDisplayTime(activity: Activity?) {
if (!Utils.getConfigBool(activity, R.bool.show_time_in_month)) {
val entries = mDisplayTime!!.entries
val entries = mDisplayTime.entries
val newEntries = Arrays.copyOf(entries, entries.size - 1)
mDisplayTime!!.entries = newEntries
mDisplayTime.entries = newEntries
}
if (mDisplayTime!!.entry == null || mDisplayTime!!.entry.length == 0) {
mDisplayTime!!.value = getDefaultTimeToShow(activity).toString()
if (mDisplayTime.entry == null || mDisplayTime.entry.isEmpty()) {
mDisplayTime.value = getDefaultTimeToShow(activity).toString()
}
}
@ -156,7 +156,7 @@ class ViewDetailsPreferences : PreferenceFragmentCompat() {
private val LANDSCAPE_PREFS = PreferenceKeys(KEY_DISPLAY_TIME_H_PREF, KEY_DISPLAY_LOCATION_H_PREF, KEY_MAX_NUMBER_OF_LINES_H_PREF)
private val PORTRAIT_PREFS = PreferenceKeys(KEY_DISPLAY_TIME_V_PREF, KEY_DISPLAY_LOCATION_V_PREF, KEY_MAX_NUMBER_OF_LINES_V_PREF)
protected fun getDefaultTimeToShow(context: Context?): Int {
private fun getDefaultTimeToShow(context: Context?): Int {
return if (Utils.getConfigBool(context, R.bool.show_time_in_month)) TimeVisibility.SHOW_TIME_RANGE_BELOW.value else TimeVisibility.SHOW_NONE.value
}