* LocalAddressBook: move contacts when renaming the address book account
* Don't make contacts dirty when moving
* Move isDirty to tests because it's only required for tests
* We don't have to set the user-data twice
* Add test for groups
* Always show "WiFi SSID card" in account settings when SSID restriction is active and adapt content according to whether all conditions are met or not
* Move explanation to top and add paragraph
* Remove unnecessary parenthesis
* Use two text composables and no spacer
* Fix preview
* Fixed surface color in dark theme
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Account screen: higher contrast for collection cards
* Account screen: use normal instead of elevated cards
* Adapt colors of card lists
---------
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Syncer: make sure collections which are deleted are not synced
* Syncer: log when local collection is removed
* Update KDoc and tests
* Handle all CRUD work in updateCollections
* Update naming, KDoc, tests
* Minor changes (KDoc, naming)
* Log warning instead of throwing exception when not possible to find account for address book account
* Run sync and accounts cleanup in migration
* Rename accounts in migration
* Run account settings migrations on background thread
* Revert "Run account settings migrations on background thread"
This reverts commit 6b578da4f1.
* Add tests for AccountsCleanupWorker
* Move companion object to end of class
* Don't use AccountRepository for address book accounts
* Update account user data in LocalAddressBook
* Minor changes (naming etc)
* Add log line when migrating
* Try to fix test error
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Upgrade dav4jvm
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* separate CalendarTimezone and CalendarTimezoneId
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Fixed timezone name setting
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Fixed `VTIMEZONE` conversion
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Using text instead of CDATA
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Fixed spec
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Added comment
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Renamed `timezoneDef` to `timezoneId`
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Upgrade dav4jvm
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* separate CalendarTimezone and CalendarTimezoneId
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Fixed timezone name setting
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Fixed `VTIMEZONE` conversion
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Using text instead of CDATA
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Fixed spec
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Added comment
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Renamed `timezoneDef` to `timezoneId`
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* [CI] Update workflows to Java 21
* Set default value of the timezone state to null
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
---------
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Add account name to address book account name
* Add parenthesis for account name and a hashtag for the collection id
* Use the correct id
* Move DI entry point to where it is used
* Sync worker management: move logic from companion object to new class
* Fix tests
* Move re-sync inputs from [OneTimeSyncWorker] to [BaseSyncWorker] as they're processed there
* Remove useless Companion
* Document that AccountSettings shouldn't be used in the main thread
* Throw exception when AccountSettings are used on the main thread
* Don't access AccountSettings on main thread
* Don't access AccountSettings on main thread
* Don't access AccountSettings on main thread
* Acquire account settings via address book account
* Extract the code to find an address books main account to the account repository
* Use collection id as reference in address book account
* Remove obsolete baos
* Find main account directly from collection in SyncManager
* Require main account to get account settings
* Stop deleting address book accounts without a main account, since they may exist on their own now
* Require content provider and introduce static deleteByCollection method
* Update KDoc
* Show all address book accounts separately
* Drop mainAccount method
* [DI] Use AssistedInject for LocalAddressBook
* Renaming, remove "main account" concept
* Fix debug info
* AccountsCleanupWorker: Rename main account to account
* Further remove main accounts
* Reduce redundancy
* AccountSettings: check account type
* AccountSettingsMigrations: drop v5 -> v6 migration (not tested anyway)
* AccountRepository: directly delete accounts
* Remove obsolete workerAccount
* Get all address books, even if not sync enabled
* Delete orphan address book accounts
* Rename two more occurrences of main account concept
* AccountSettings: allow test accounts
* Syncer: rename methods for clarity, add KDoc
* Drop empty test class
* Make code more readable and add comment
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Disabled `CoroutineCreationDuringComposition` in lint
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Moved disable
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
---------
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Update ical4android
* Use standard content provider in TaskSyncer
* Check version instead of acquiring TaskProvider
* Add sync result error
---------
Co-authored-by: Arnau Mora <arnyminerz@proton.me>
* Fix overlapping method name and use interface everywhere
* Fix overlapping property name
* Update logger usage
---------
Co-authored-by: Arnau Mora Gras <arnyminerz@proton.me>
* Passing `collection` directly
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Fixed imports
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Fix tests
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Log sync time using repository; no need for account/service check anymore
* SyncManagerTest: don't write SyncStats to DB
---------
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Use address book contacts content provider provided by syncer
* Close any acquired content provider after sync
* Acquire/Check task provider provider as preparation step
* Provide sync arguments at syncer creation
* Acquire ContentProviderClient in syncer implementations
* Generalize sync algorithm in Syncer
* Use contacts authority for address books
* Generalize sync algorithm in CalendarSyncer
* Generalize sync algorithm in SyncerTest
* Generalize sync algorithm in TaskSyncer
* Rename preparation method and add an after sync method
* Generalize sync algorithm in JtxSyncer
* Generalize sync algorithm in AddressBookSyncer
* Use repositories instead of DAOs
* Replace deprecated log statements
* Use generic type for collection types
* Infer authorities when possible and pass only task authorities along
* No need to close TaskProvider explicitly
* Use colors only where needed
* Use provider with auto closable
* Get sync collections in syncer implementations
* Delete syncer test
* Pass provider through methods instead of using lateinit property
* Reorder constructor arguments
* Remove trailing commas
* Remove obsolete undocumented conditional
* Reorder methods
* Reorder methods
* Abort sync when preparations fail
* Drop obsolete permission check
* Use generics for url and delete
* Use generic for update
* Use generic for syncCollection
* Rename create to createCollection for consistency
* Revert "Rename create to createCollection for consistency"
This reverts commit 0fee4fe7fcf3ec8ef965c9a2e0db991a1bbbbcf7.
* Revert "Use generic for syncCollection"
This reverts commit ae129fd17e06146a1e9f8631e3cdbd2dc0a4db06.
* Revert "Use generic for update"
This reverts commit 42dd665851ba83a75bb498b98bd56624e2b09647.
* Revert "Use generics for url and delete"
This reverts commit 7ae1425039656d4a9937628ca1799ce8c59ceebb.
* Move delete() to LocalCollection
* Move url to LocalCollection
* Fix local test collection
* Minor changes
* Minor changes
- make sync private
- use to autoclose provider
* Query for sync collections once only
* Add KDoc and update comments
* Make property a local variable
* Update KDoc
* Add back ose conditional
* Remove blank line at beginning of method
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Use test account type (without sync adapters as side effects) for instrumented tests
* Provide standardized way to get test account; re-enable LocalAddressBookTest
* [WIP] Use NotificationRegistry to post notifications
* Replace NotificationUtils by NotificationRegistry
* Re-factor SyncConditions; move tests to default location
* Describe notification channels
* Use per-resource Guava cache with weak keys and values as WebDAV page cache
* Replace ExtendedLruCache by Guava cache
* Use injected logger in DavDocumentsProvider
* Use DI for RandomAccessCallback, move Wrapper to outer class
* Fix tests
* Use Hilt for more classes
* Use Guava LoadingCache as page cache
* Fix tests
* Minor code change
* Update dnsjava, use desugaring with nio, refactor DNS resolving
* KDoc
* Rewrite bestSRVRecord test
* Add pathsFromTXTRecords tests
* Add desugaring note
* Rename @AssistedFactory method to "create"
* testBestSRVRecord_MultipleRecords_Priority_Same: broaden range for distribution
* Use DI for AccountSettings
* AccountSettings: clarify different account variables
* Fix tests
* Inject @ApplicationContext instead of Application
* Add Hilt rule to various tests
* Fix tests
* Consequently use injected @ApplicationContext in Android tests; fix Hilt rules
* LogcatHandler: log source class as tag and not in the text, remove max length
* Separate LogManager and Logger usage
* Improve StringHandler for DavResourceFinder
* Tests, KDoc
* Provide collection to CalendarSyncManager
* Provide collection to ContactsSyncManager
* Provide collection to JtxSyncManager
* Provide collection to TasksSyncManager
* Provide collection to SyncManager
* Fix test
* Minor changes
* Add kdoc
* Minor changes
- added KDoc
- SyncManager can never handle address book authority (content
authority for contacts is contacts authority)
- moved @UsesThreadContextClassLoader to respective sync manager
* Mock collection in test
* Add comments separating the sync process into separate steps
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Drop address book provider
* Drop address book sync adapter service
* Replace address books authority with contacts authority
* Update kdoc
* Revert "Update kdoc"
This reverts commit dfb14d466f6c58d9422e59c770e0a5348a497b7d.
* Revert "Replace address books authority with contacts authority"
This reverts commit 0e15bf11b3235dfbc38696741100210fbe497dbd.
* Don't enable addressbook sync for main account
* Acquire content provider in Syncer
* Use contacts authority instead of address book authority when acquiring content provider
* Set default sync interval for address book authority again
* Minor re-ordering of lines
* Add comment, rename variable
* Move SyncAdapterServices out of adapter package
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Migrated into to compose
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Got rid of AppIntro
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Imports cleanup
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Imports cleanup
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Removed padding
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* When launching intro, going back closes the app
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Added content description
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Moved IntroActivity.Model to IntroModel
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Given fixed padding
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Moved intro composables together
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Do not create new task
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Minor changes
* Remove last XML styles that were required for AppIntro
---------
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* [wip] Create worker for push registration and call it from someplace in UI
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* [wip] Subscription registration request
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Don't enqueue push registration worker from UI
* Enqueue PushRegistrationWorker on collection changes
* Fix tests
* Update dav4jvm; Use new post method
* Remove obsolete context
* Add get and deleteAll methods to serviceRepository and update usages
* requestPushRegistration: make endpoint an argument
* Update push subscription fields in DB on successful registration
* Don't create notification channels in test class
* Remove workmanager init and provide empty set of listeners in tests
* Require network connection to run PushRegistrationWorker
* Move module declaration to a separate TestModules interface
---------
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
Co-authored-by: Sunik Kupfer <kupfer@bitfire.at>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Call collection updates and setters only from repository
* Make collection repository changes observable
* Add kdoc
* Add basic test
* Extract RefreshCollectionsWorker; move some HomeSetDao calls to DavHomeSetRepository
* Replace more HomeSetDao calls
* Remove duplicate copyright notice
* Drop weak reference for observers
* Rename method
* Remove test service after run
* Verify notifying works with mockk
* Rename test
* Use construction injection
* Remove unused SettingsManager
* Remove obsolete mockk rule
* Use runBlocking instead of runTest
* Change to observer linkedList to mutableSetOf, remove synchronized calls
* Change to hilt multibinding
* Remove some unnecessary lines; allow empty set by Hilt
* CollectionListRefresher: delete collections using repository
* deleteRemote: call callback too; adapt KDoc
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* MKCALENDAR: wrap supported compoents in <CALDAV:supported-calendar-component-set>
* MKCALENDAR/MKCOL body generation: use Property.Name from dav4jvm instead of own strings
* [WIP] Colors
* Update navigation drawer
* Update colors
* [WIP] PermissionSwitchRow night mode
* Fix PermissionSwitchRow icon in night mode
* Use more intense colors for FABs
* Use correct account name when retrieving service
* Rename method, add kdoc
* Address books: require main account and use as Account
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Fixed padding for "Show only personal checkbox"
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Aligned text correctly
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
---------
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Select nextcloud login type on nextcloud setup intent
* Fix linting error
* Add documentation
* Move model creation to compose LoginScreen
* Minor changes
- Use boolean to decide on skipping startPage
- Move login type selection logic to login types provider
* Minor changes
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Extract composables
* Drop sub component previews and minor adjustment
* Fix preview
* Extract view model
* Switch to M3
* Extract URI to Constant
* Minor changes
* We alway have AccountSettings
* Replace LiveData by State
* Use Snapshot.withMutableSnapshot in reload
* Don't show empty OAuth setting
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Refine chips in collection list
* Refine PermissionSwitchRow
* Collections list
* Fix WelcomePage and IntroActivity background color in dark mode
* Fix RadioWithSwitch in dark mode
* Drawer handler: branding in dark mode
* Extract composables
* Extract model and companion object
* Switch to M3
* Linting
* Drop previews for sub composables
* Minor adjustments for readability
* Minor changes
- use manual URL from Constants
- use M3 in some Composables
* Create PreferenceRepository (for now only for verbose logging)
* Move actual settings to model; M3 Composables
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* [WIP] More hilt
* Use assisted inject for AccountSettingsMigrations
* DavDocumentsProvider: inject CredentialsStore
* Create a new WebdavScope and scope caches and credentials store to it
* Fix CredentialsStoreTest
* Convert M2 calls to M3
* Extract composable to screen
* Extract viewmodel
* Make screen model independent
* Use only primitive types in screen
* Introduce uiState class and switch to compose state where easy
* Switch remaining live data to compose state
* Add kdoc
* Add scrolling, adapt buttons to M3
* Move Intent logic to Activity
- create/handle Intent in Activity (may be replaced by NavGraph in future)
- Activity: pass unpacked initial data to Screen
- Screen: use hiltViewModel (adds hilt-navigation-compose dependency) to
create model with initial data
- Screen: use Column instead of LazyColumn
* Fix test
* Optimize imports
* Minor changes
* Move AppTheme, fix showDebugInfo
* View instead of share logs; make local/remote resource smaller; make remote resource selectable
* Leave space for scrolling down past the FAB; don't show "Local resource: null"
* Re-order composables
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Added `canAccessWifiSsidLive`
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Fixed initial state
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Cleaned up code
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* More cleanup
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Removed inspection check
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Renamed function
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Using `broadcastReceiverFlow`
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Simplified check
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Using `MODE_CHANGED_ACTION`
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Updated comment
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Set default value for immediate
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Use derivedStateOf instead of produceState; correctly collect broadcastReceiverFlow
* Always show WifiSSID Card in Preview (otherwise Preview won't render)
* Don't call flow.map in Composable
---------
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Soft fail sync on DeadObjectException so that it is retried without immediate error message
* Handle DeadObjectException (→ retries sync); Syncer: generalize all-catch
* Migrated to M3
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Replaced preview theme
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Fixed theme
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Forced all sets to be private
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Moved Composables and Model to individual files
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Fixed naming
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Theme / M3 changes
* Observe lifecycle from within Screen
* Minor changes
---------
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* [WIP] Separate AccountScreen, use M3 elements
* [WIP] Use UseCases for complex flow calculations
* [WIP] Move account deletion logic into AccountRepository
* Move rename operation to repository
* Adapt FABs
* Don't use snackbars to show when the collection list is refreshed
* New collection list layout (bitfireAT/davx5#159)
* [WIP] Create AccountModel from within screen
* [WIP] Clean up AccountScreen
* [WIP] CreateAddressBook
* [WIP] Create address book / calendar screen
* [WIP] Begin CollectionScreen
* [WIP] CollectionScreen
* Error handling
* String resources
* Optimizations, remove unnecessary things
* WebDavMountsScreen: M3, refactoring
* [WIP] AddWebDavMount
* Use M3 pull-to-refresh
* AddWebDavMount, move logic to WebDavMountRepository
* Show loading state in LinearProgressBar
* Add WebDAV mount: IME action and focus requester
* Move "test WebDAV" logic from model to repository
* Move "refresh quota" logic to repository
* Move querying and deleting mounts to repository; IME navigation
* KDoc
* Move hasWebDav tests to repository
* [WIP] Rewrite login to M3 and better UI states
* Use AccountRepository to create account
* LoginModel is SSOT for page navigation
* Support forced group method
* Show progress bar when account is being created
* Make account name suggestions work again
* Use M3 text field supportText for errors
* Refactor: login by URL, login by email, advanced login
* Refactor Nextcloud login, move login flow logic to separate class
* Refactor Google login, move OAuth logic to separate class
* Fix errors when navigating back after successful resource detection
* Make PasswordTextField M3
* ManagedLogin: M3, UiState
* Updated theme; managed login functionality
* Improve back navigation
* Rename AppTheme to M2Theme, add M3 theme
* Rewrite AboutActivity to M3
* Apply M3 theme; minor optimizations
* Use M3 version of AboutLibraries
* Use material3 instead of material3-android dependency
* Use reversed theme
* [WIP] Use broadcastReceiverFlow and packageReceiverFlow
to make sure that broadcast receivers are unregistered
* Rewrite remaining BroadcastReceivers to use broadcastReceiverFlow
* TasksAppWatcher: minor coroutine changes
* KDoc
* TasksActivity: use Compose state instead of LiveData
* Check if keep-permissions changed when user comes back from settings app
* Use one model only
* Use mutable state flows
* Use compose mutable state
* [CI] Improve caching behavior
* Freshly created model can never be null
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Use Compose state instead of LiveData; reset token before starting Login flow
* [WIP] Reset state variables when needed
* Always run postForJson in IO dispatcher; show progress when polling for login data
* Reset login URL in onReturnFromBrowser
* Do not show existing password when changing
* Use PasswordTextField for password input dialogs
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Added custom Compose theme
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Got rid of accompanist theme adapter
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Removed unused import
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Added actionbar to the activities that didn't have one
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Theme now always hides actionbar
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Added back string
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Got rid of all color definitions
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Moved color definition to drawable
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Using Compose colors
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Using AppCompat theme
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Removed XML theme
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Moved color definition
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Added bars coloring in Compose
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Added dark theme
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Added custom Compose theme
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Got rid of accompanist theme adapter
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Removed unused import
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Added actionbar to the activities that didn't have one
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Theme now always hides actionbar
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Added back string
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Got rid of all color definitions
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Moved color definition to drawable
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Using Compose colors
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Using AppCompat theme
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Removed XML theme
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Moved color definition
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Added bars coloring in Compose
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Added dark theme
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Changed content description
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Using `onSupportNavigateUp`
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Changed color on top of primary green
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Added up navigation
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Made `onSupportNavigateUp` optional
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Typo
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Got rid of edge-to-edge
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Added back some XML styles
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Simplify TasksCard calling
* Move theme colors to flavor-specific ThemeColors file
* Remove global AppTheme paddings for now
* Optimize imports
---------
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Don't use Gradle build and configuration cache for releases
- don't enable Gradle build and configuration cache for the project, but recommend it for the developer
- explicitly enable Gradle build and configuration cache for CI test jobs
- let AboutLibraries generate lib definitions itself again
- also don't archive test results (sometimes fails and we never use the results)
* Add encryption key for gradle cache
* Only warn on configuration cache problems (caused by AboutLibraries)
The list was computed in an automated way and includes:
intro_battery_not_whitelisted
intro_battery_whitelisted
permissions_jtx_status_off
permissions_jtx_status_on
about_flavor_info
about_translations_thanks
install_email_client
accounts_global_sync_disabled
accounts_global_sync_enable
app_settings_tasks_provider_synchronizing_with
account_no_address_books
account_no_calendars
account_no_webcals
account_swipe_down
account_create_new_address_book
account_create_new_calendar
settings_title
settings_enter_username
settings_enter_password
settings_key_default_alarm
certificate_notification_connection_security
trust_certificate_unknown_certificate_found
- OneTimeSyncWorker is also started by sync framework, so it should take network restrictions into consideration
- add "manual" flag for manual syncs that ignore network restrictions
* [WIP] Don't create a separate SyncWorker for every sync (run directly within onetime/periodic sync instead)
* [WIP] address books
* Account(s)Activity: don't show pending workers
* Migration to set new periodic sync worker tags
* Fix tests
* ContactsSyncAdapter issues address book sync on main account (not contacts sync)
* SyncAdapterService: optimize blocking with Flow instead of LiveData
* Refactoring
* Better live handling of (un)installed task apps
* Minor changes
* SettingsManager: explicitly mark possibility of null LiveData values
* Fix tests
* Move homepage and other Web URLs to Constants; minor refactoring
* Use AppTheme with built-in safe LocalUriHandler instead of MdcTheme; minor refactoring
* Account settings: add TODO for Compose rewrite
* Use UriHandler instead of UiUtils.launch when possible
* Migrated AddWebdavMountActivity to Compose
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Minor changes, use PasswordTextField
---------
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* [WIP] Add AccountActivity2 in Compose
* Make paging collections work when data changes
* [WIP] Add ProgressIndicator TODO
* [WIP] CardDAV: add swipe-to-refresh
* [WIP] Correctly use Pager
* [WIP] Only show Webcal tab when there are subscriptions
* [WIP] Implement collection properties dialog
* Implement "create collection" and "show only personal collection"
* [WIP] Add collection overflow menu items
* Show color as left border, max. 2 icons per row
* [WIP] Delete collection dialog
* Add "delete collection"
* Implement "Force read-only"
* Delete old XML classes and resources
* Add permissions warning
* Implement "Rename account"
* Case-insensitive sorting, minor changes
* Horizontal arrangement
* Less integration of Webcal subscriptions (other layout)
* Accessibility
* Collection list: provide ID als key for lazy list
* Only show "Create addressbook/calendar" when there's at least one writable homeset
* Make readOnly a LocalCollection property
* Move readOnly detection to SyncManager
* Add readOnly state access to LocalCalendar
* Add not implemented error to readOnly state access of LocalJtxCollection
* Handle read-only state of calendar at dirty events upload
* Handle read-only state of calendar at processing of locally deleted events
* Remove todo and update kdoc
* Fix indenting
* Add read-only prop to LocalTestCollection
* Add read-only state access to LocalTaskList
* LocalTestCollection: don't set read-only
* Update ical4android (for new KDoc)
* Make LocalCollection readOnly-API read only and take value from content provider during populate()
* SyncManager: use readOnly direct from localCollection
* Lift resetDeleted up to LocalResource
* Override and use resetDeleted for LocalEvent
* Add resetDeleted to LocalJtxICalObject
* Add resetDeleted to LocalTask
* Add resetDeleted to LocalTask
* Add resetDeleted to LocalTestResource
* Provide default access level
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Migrated to Jetpack Compose
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Added `observeBoolean`
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Simplified settings interaction
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Migrated to Jetpack Compose
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Added `observeBoolean`
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Simplified settings interaction
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Use SafeAndroidUriHandler instead of UiUtils.launchUri
* Removed animation for manufacturerWarning
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Removed animation for manufacturerWarning
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Added `getBooleanLive`
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Using `getBooleanLive`
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Moved UI definitions to file scope
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Don't use specific times for waiting in tests
* Renamed function
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* More exact naming
---------
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Add foreground notification type to expedited workers (required for Android 14)
* Make SyncWorker a long-running worker
* Don't use expedited SyncWorker for everything; handle foreground service launch restriction
* AddressBookSyncer: only request expedited for sub-jobs when parent job is expedited, too
* RefreshCollectionsWorker is not long-running -> no foreground service type needed
* Fix tests
* Don't use foreground service type in ForegroundInfo
* Make SyncWorker not long-running
* Rewrite RenameAccountFragment to compose
* Add padding to text field, disable RENAME button when old name = new name
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Show battery saver warning in account list and debug info
* Move app warnings to model class
* Debug info: more verbose text
* Restore previous strings for sync enqueued/started
* Make ranged GET requests cancellable; reduce notification update frequency
* Include original exception as a cause in WebDAV ErrnoException
* Add KDoc for threading
* Gave more flexibility
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Migrated to Compose
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Adjusted paddings
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Added missing observer
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* CardWithImagE: add another preview with subtitle, icon and content
* Made buttons uppercase
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Adjusted spacings
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Changed snackbar host state
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Changed nullable expression
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Using shareFile for zip
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Minor changes (comments/formatting)
* Switched to view instead of sharing files
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Adapted image height for landscape
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* CardView: allow to pass image alignment; use card_theme_max_height
* DebugInfoActivity: paddings, images
---------
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* WebDAV: don't try to load 0-byte segments
* Extracted segmentation logic to SegmentedReader for testability
* Reorganize and simplify caches
* Refactor thumbnail cache
* Use coroutines with Dispatchers.IO instead of custom Executor
* Remove obsolete classes
* Fix tests, simplify DiskCache
* Paging reader: cache current page
* PagingReader tests
* Thumbnails: timeout for generation and not only for waiting
* openDocumentThumbnail: actually cancel HTTP request when method is cancelled
* Better KDoc
* Add further tests
* Renamed LoginCredentialsFragmentFactory to LoginFragmentFactory
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Fixed fragment name
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Rename LoginInitFragment (managed) to ManagedLoginInitFragment
---------
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* RefreshCollectionsWorker: use runInterruptible instead of interrupting manually
* SyncWorker: use CoroutineWorker + runInterruptible
* Use global SyncWorkDispatcher that guarantees classLoader to be set
* Set SyncWorkDispatcher for whole SyncWorker's doWork
* Remove obsolete test
* SyncManager: add structured concurrency again
* Use up to <number of processors> threads for synchronization
---------
Co-authored-by: Sunik Kupfer <kupfer@bitfire.at>
- Rewrite DetectConfigurationFragment to Compose
- Use coroutines and runInterruptible instead of Thread
- Only cancel service detection when back is pressed
* RandomAccessCallback.Wrapper: support multiple state machine instances at same time
- support multiple state machine instances at same time
- provide explicit Exception/error code when the remote server doesn't support ranged requests
* Only use RandomAccessCallback when server explicitly advertises range requests
---------
Co-authored-by: Arnau Mora <arnyminerz@proton.me>
* Minor changes
- update kdoc
- rename method and variables
* Add proxy parents to related resource detection
* Rename argument, query ResourceType
* Remove unnecessary utility method
* Change parentOf to extension function; Always return URL with trailing slash
* Use calendar-proxy-read/write ResourceType from new dav4jvm
* Use max. two levels of recursion to detect shared Google calendars
* Revise test and adapt method
* Simplify HttpUrl.parent()
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* LoginActivity: refactor menu to MenuProvider; LoginModel: add contact group type
* Take LoginModel group method into account when creating the account; Nextcloud login: set preferred contact group type
* Replace onActivityResult by contract
* Add Nextcloud option to default login screen
* Decouple NextcloudLoginFlowComposable from model
* UI and model changes
* Single-line URL field
* Add progress indicator and other secondary UI
* [WIP] Add timeout for RandomAccessCallback
* Use state machine to handle timeout
* Use sealed class for states, guard callback access with correct states
* Use tags instead of uniqueWorkNames for work queries.
* Also include address book accounts, when querying sync status.
Give address book account sync workers their parent (main account) sync workers tag too, such that they will be included at the query for sync status of their parent account.
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Low storage: don't show notification anymore, adapt info message
- The impact of low storage is not as critical anymore that a notification is required.
- Info message adapted
* Update "account settings: ignore VPN" strings
* Update "No internet" string
- use Google Play In-App Review API for private feedback on -gplay (fall back to email)
- start email intent again when "beta feedback" is selected in navigation drawer
* Doubled bottom padding
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Account activity: increase margin for two FABs even more
---------
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Add tests for internetAvailable()
* Add tests for wifiAvailable()
* Add TODO for test case
* Add tests for internetAvailable() covering multiple network connections
* Minor KDoc
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
If a WebDAV server is misconfigured (for example, behind an HTTP proxy that
strips a URL prefix and doesn't correctly forward this to the WebDAV server)
then PROPFIND can return resources whose URLs don't match the request URL. These
are resolved by dav4jvm as HrefRelation.OTHER.
Currently this situation produces no output at all in DAVx5 (logs or app) and
the WebDAV share appears accessible but empty. It is possible to create files in
the share, but not to see them again afterwards!
Of course a misconfigured server isn't the WebDAV client's responsibility to
resolve, but adding a warning in the log provides an extra clue for anyone
trying to debug it.
* Use appropriate delayUntil value for retrying syncs on 503s.
Crop server suggested retryAfter value to self defined min/max values and use a reasonable default value if non-existent.
* Add tests for getDelayUntil
* Wait appropriate delay, before retrying sync after a soft error happened
* Increase max and default sync delays after soft errors
* Increase initial backoff time for SyncWorker retries
* Minor getDelayUntil changes
* Minor changes
- store delayUntil in seconds
- pass duration instead of timestamp to Thread.sleep
- other minor changes
* Use Instant instead of Long timestamps
* Correct calculation of blocking duration
* Indicate soft error occurred on 503 server message
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Update dependencies (including cert4android and vcard4android)
* Migrated to new version of ical4android
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Increased compileSdk
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Upgraded browser
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Only use `appInForeground` for `customCertsUi`
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Removed unnecessary variable and fixed trust manager
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Cleaned up trust manager factory
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Update dependencies (including cert4android and vcard4android)
* Migrated to new version of ical4android
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Increased compileSdk
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Upgraded browser
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Only use `appInForeground` for `customCertsUi`
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Removed unnecessary variable and fixed trust manager
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Cleaned up trust manager factory
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Minor changes
* Fixed build for SDK 34
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Migrated certificate trusting
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* NetworkConfigProvider: handle invalid trusted certificate
---------
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
Co-authored-by: Arnau Mora <arnyminerz@proton.me>
* Add setting to ignore VPNs at connection detection
* Minor changes
- move methods to ConnectionUtils to keep SyncWorker class compact
- always use "ignore VPNs" as Boolean
- other minor changes
* Show ignore VPNs setting only below api lvl 23
* Change strings
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
Hopefully fixesbitfireAT/davx5#308
* Add new setAndVerifyUserData extension function to AccountManager
* Use new setAndVerifyUserData extension function instead of insecure setUserData
* Update KDoc [skip CI]
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
- use Kotlin and CompletableDeferred instead of Java synchronization
- signal cancellation by completing CompletableDeferred instead of Thread.currentThread.interrupt()
* Upgraded AGP
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Enabled automatic locale config generation
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Added fallback language
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Added legacy service
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Added `Accept-Language` header to custom tabs
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Nextcloud Login Flow/Google OAuth: also send language tag for default locale
---------
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Added refresh collections fab
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Added listener for clicks on refresh collections fab
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Adjusted sizing
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Updated tooltip and description for collections sync
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Removed Snackbar
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Added warning for null serviceId
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Changed refresh collections service id fetching method
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Tooltip updates on refresh collections list
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Migrate to ViewPager2; show "Refresh collections" for WebCal, too
* Added refresh collections fab
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Added listener for clicks on refresh collections fab
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Adjusted sizing
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Updated tooltip and description for collections sync
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Removed Snackbar
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Added warning for null serviceId
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Changed refresh collections service id fetching method
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Tooltip updates on refresh collections list
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Migrate to ViewPager2; show "Refresh collections" for WebCal, too
* Changed collections refresh action update method
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
* Use lambda syntax for observers
---------
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
Signed-off-by: Arnau Mora <arnyminerz@proton.me>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
Co-authored-by: Sunik Kupfer <kupfer@bitfire.at>
* Comment out failing test
* Check internet connection before syncing for API 23+
* [Skip CI] Amend comments
* Comment out whole test class
* Comment out whole test class
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Hide/Show auth settings instead of removing them prevents NPE
* Provide original OAuth login email as default value for GoogleLoginFragment started from account settings
* Account settings: explicitly trim empty user name to null
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Block sync framework until SyncWorker finishes
* Bump version code for 4.3.3 (previous version code was never released publicly)
* Fetch translations from Transifex
* Release internal version automatically [skip ci]
* Update periodic sync workers when "Sync only on WiFi" flag is changed (#282)
* Update periodic sync workers when "sync only on WiFi" flag is changed
* Remove BootCompletedReceiver which was only needed to repair sync intervals (not required with WorkManager anymore)
* Bump version code to 403030006 (stays 4.3.3)
* Use unique worker name, Java notify/wait and observeForever
* Remove observer when sync finished
* Catch and ignore, but log interruption exceptions
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Move GoogleOAuth members into GoogleLoginFragment
* Require login flow capable browser and notify user if missing
* Receive AppAuth redirects only in standard and gplay flavor
* Set davx5 as user-agent for AppAuth connection builder
* Re-authentication in Account settings
* Catch unauthorized exceptions at collection refresh and notify user to re-authenticate
* Suggest email address on account creation
* Set contact groups default setting as per-contact categories for oauth logins
* Add authentication to debug info, minor other changes
* Better error handling; don't pre-set group type
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* When renaming show a toast when account with new name exists already
* Replace toasts with snackbars
* Apply code styling hints
* Move lambdas out of parentheses
* Inject application instead of context
* Replace Toast with Snackbar
* Shorten messages shown in snackbars
* Show Toast in UI instead of model; use AndroidViewModel
* Move account name check out of lock; don't close activity if not successful
* Duplicate account name check: only check for our account type
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Add new preselect_collections option and deprecate sync_all_collections option
* Optimize imports
* At refresh, decide on whether a collection should be preselected
* Add preselect_collections_blacklist setting and restriction
* Adhere to preselect_collections_blacklist setting
* Add preselect_collections values
* Also check for empty regex string and use new setting values
* Add unit tests
* Remove sync_all_collections setting and restriction
* Blacklist nextclouds recently contacted addressbook in restriction and setting by default
* Improve kdoc
* KDoc, changed setting names, minor code optimizations
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Update periodic sync workers when "sync only on WiFi" flag is changed
* Remove BootCompletedReceiver which was only needed to repair sync intervals (not required with WorkManager anymore)
* Make it clear that the first call of recursive method queryHomeSets is for the current-user-principal home set
* Update whitespace in kdoc
* Update kdoc
* Add last synced time to collection properties
* Show last synced time for every to the collection relevant authority
* Try finding the application name for given package name
* Resolve authority to package name before finding application label
* Use AndroidViewModel instead of ViewModel; change model LiveData to val
* Rewrite to Compose, use relative time description
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* AccountSettings: prevent redundant calls, move migrations to separate class
* Don't create AccountSettings while migrating
* Double thread sleep time to wait for sync framework to get disabled, and update logging
* Remove manual testing helper
* Fix tests
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Fixed toast threading
* Added `AndroidViewModel.context`
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Moved to `AndroidViewModel`
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Changed error invocation
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Added back constructor inject
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
* Save Application with val instead of util method
* Use LiveData for error message
---------
Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Implement proper network check before manual sync
Do a proper connectivity check, to show a message to the user, about the sync being scheduled for when connectivity is available, before enqueueing the SyncWorker.
* Update the sync status in accounts adapter to include pending syncs
This is relevant for when a manual sync is triggered without connectivity.
* Replace Toast by Snackbar
* Replace ViewModel by AndroidViewModel
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
- disable per-app language preference for now (will be enabled again with bitfireAT/davx5#245)
- disable Jetifier (doesn't seem to be explicitly required for in-app rating API anymore)
- remove Locator dependency
- update ical4android
- add JetPack Compose dependencies
- use existing XML theme as Compose MdcTheme
- update AboutLibraries to newest version (uses Compose)
- embed AboutLibraries Compose into existing Fragment layout
ClosesbitfireAT/davx5#14
* extract WorkManager util functions and kdoc
* add PeriodicSyncWorker
* refactor and some kdoc
* use PeriodicSyncWorker and add todos
* allow SyncAdapter arguments to be passed to SyncWorker and have re-synchronization use SyncWorker
* handle sync cancellation in AccountSetting migration
* handle sync cancellation when account is renamed
* remove sync frameworks global sync setting and sync state awareness for the GUI
* Observe sync worker status in AccountListFragment
* Create setup for stepwise refactor of the sync adapters. This should keep the app from failing to build.
* Create new abstract BaseSyncer class for generic sync code. Adapt consumers and tests to use the new class.
* Move calender sync code to new CalenderSyncer class which is independent from the sync framework
* In CalendarSyncAdapterService pass sync requests from Sync Adapter Framework to SyncWorker
* Use CalenderSyncer in SyncWorker
* Move contacts sync code to new ContactsSyncer class.
* Move address book sync code to new AddressBookSyncer class
* Move jtx sync code to new JtxSyncer class
* Move tasks sync code to new TaskSyncer class
* Remove duplicate code in inherited sync adapters.
* Remove refactoring helper interface, duplicate generic sync code and some linting.
* Adapt tests for new Syncer class and move to the new package
* Remove remaining duplicate code in SyncAdapterService, add todos and edit kdoc.
* Move all the single line sync adapter services into one file.
* Remove concurrent sync runner code and its test, as we now use WorkManagers one time work requests.
* Remove SAF manual sync flag usage where unnecessary.
* Drop ability to prioritise collections for sync, as not used and hindering removal of sync adapter arguments.
* Pass simple string array to SyncWorker instead of bundle to simplify code.
* Restructure work query code.
* Get debug info from account settings and WorkManager.
* Write tests for PeriodicSyncWorker
* Test account creation will set a default sync interval for CardDAV and CalDAV
* Throw an exception if accountManager returns null for sync interval value
* Do proper interval check and add tests for AccountSettings
* Use work manager query to determine whether work is in a specific state
* [WIP] Add test to check that task provider is configured correctly on account creation
* Edit test checking that task sync is configured correctly on account creation with/without installed task app(s), by mocking TaskUtil
* Edit test such that it does not require a flaky flag
* Remove periodic sync when tasks app is uninstalled
* Bring back content triggered syncs
* Rename enqueueSyncWorker method to enqueue only for clarity
* Enable SyncAdapterFramework to cancel running SyncWorker
* Add test ensuring that SyncWorker.onStopped() interrupts the running sync thread
* Add retry policy sync on soft errors
* Check users sync conditions before enqueueing SyncWorker
* Add test for whether user sync conditions are treated correctly and kdoc
* Rename ambiguous shorthand "SAF" to "SyncFramework", as SAF usually means StorageAccessFramework
* Migration: Disable sync framework periodic syncs when interval is changed for specified authority
* Add Workers info to debug info
* Use WorkInfo.runAttemptCount to fail work after 20 soft errors
* Notify user if retry limit for soft errors has been reached
* Remove left over concurrency sync run tests prevention
* Migration: Continue to remove periodic sync framework syncs until user migration to PeriodicSyncWorker syncs is complete
* Kdoc and small changes
* Migration: Change to hard migration strategy
* Drop repairSyncIntervals method in favor of hard migration strategy
* Improve debug info of workers
* Remove sync framework periodic syncs, created by enabling content triggered syncs
* Change minimum sync interval to 15 min; minor other changes
* Fix tests
* Implement requested changes and update kdoc
* Add network connectivity restrictions to PeriodicSyncWorker
* Minor changes
* Move back sync classes to syncadapter package for now (can be separated later)
* Add KDoc
* Changes from review
* Rename test methods
* Add back global sync status warning
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Log warning if principal URL does not provide CalDAV/CardDAV service
* Unified log messages for identical cases
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Alter the SyncWorker sync request to allow passing sync arguments along
* Request sync in SettingsActivity via SyncWorker instead of ContentResolver
* Don't use catch-all arguments as worker arguments
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Changed `password` with `token`
Signed-off-by: Arnau Mora <arnyminer.z@gmail.com>
* Fetch script: don't use --minimum-perc 20 because it's in .tx/config
---------
Signed-off-by: Arnau Mora <arnyminer.z@gmail.com>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* check sync workers properly
* Move utils around
* Merge live data, instead of observing in view, to recalculate account list.
* Update LiveData with same value
* Remove unused context property.
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* provide owner url in jtx collection
* Updated contract, added owner displayname to collections sync
* Update ical4android
---------
Co-authored-by: Patrick Lang <72232737+patrickunterwegs@users.noreply.github.com>
* add principal table with dao
* add principal table with dao
* collection saves ownerId instead of owner URL
* save and refresh principals
* show display name of collection owner in GUI
* show only the owner name (preferably) or respective url
* remove principals which do not own any collections
* Don't mock AppDatabase
* ensure we are really dealing with a principal and save it even without its display name
* ensure owner label is hidden when neither owner-displayname nor owner-url are available
* save principal urls without trailing slash
* use a custom query to find principals without collections
* Some changes
- insertOrUpdateByUrl
- don't explicitly set id=0 when not necessary,
- make it work when there are already entries with trailing slahes
- added TODOs
* Small changes
- Update principal only if display name changed
- Rename methods
- Kdoc
- Tests
* stop using simple methods with vague names
* rename method insertOrUpdateOrGet to insertOrUpdate and leave existing kdoc for explanation
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* adapted JtxSyncManager, added new method in LocalJtxCollection
* minor code improvement
* inserting recurring entry as well, as the series might not have been processed yet
* version bump (preliminarily)
* version bump (preliminarily)
* Enabled automatic popup of the custom certificate dialog
Signed-off-by: Arnau Mora <arnyminer.z@gmail.com>
* Use chaining instead of .let
---------
Signed-off-by: Arnau Mora <arnyminer.z@gmail.com>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* add test fixtures
* Use direct DB access instead of DaoTools
* minor changes and kdoc
* minor changes and kdoc
* remove obsolete DaoTools, SyncableDao and IdEntity classes
* KDoc
* use hashmap instead of list and added kdoc
* always load from database
* add a test and make test structur more flexible for future tests
* minor KDoc
---------
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Reformat code
* Use sync-adapter URI to count jtx Board entries
* Debug info: restrict entry counts per withSyncAdapter URI and not over WHERE clause
* [WIP] refactor
* [WIP] refactor
* save, update and delete homesets one by one
* save, update and delete collections one by one
* cleaner code
* prevent jumps in row ids
* [WIP] small changes and kdoc
* remove duplicate code and add kdoc
* improve kdoc
* remove redundancy based on service type in resource finder
* tests setup
* handle cancellation
* add tests
* Don't use IdEntity for service detection anymore
* HomeSetDao: getByUrl requires a service (there may be two accounts with the same homeset URLs, for instance with different credentials)
* Deprecate DaoTools
* Minor changes
* Add TODO
* use self explanatory variables instead of a pair
* update kdoc
* add unfinished tests
* add test for updating a collection
* add test for preserving collection flags
* mark collections as homeless if not rediscovered in its homeset
* proper implementation of update and delete of homeless collections with test
* minor changes and kdoc
* Tests: adapt mock server 404
* KDoc
* get collections by service and url, deprecate getByUrl()
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Added `GetETag.NAME` fetching when `PROPFIND`ing
Signed-off-by: Arnau Mora <arnyminer.z@gmail.com>
* `GetETag.eTag` is only taken if tag is not weak
Signed-off-by: Arnau Mora <arnyminer.z@gmail.com>
* Using `GetETag` instead of `QuotedStringUtils` and ignoring weak eTags
Signed-off-by: Arnau Mora <arnyminer.z@gmail.com>
* Updated `dav4jvm`
Signed-off-by: Arnau Mora <arnyminer.z@gmail.com>
* Fixed checks
Signed-off-by: Arnau Mora <arnyminer.z@gmail.com>
* Use new dav4jvm where weak can't be null
Signed-off-by: Arnau Mora <arnyminer.z@gmail.com>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* added language selection
* PermissionsFragment: Hide notification permission switch on Android < 13
* Retrieve locales with a function
* Added locales flavoring
Signed-off-by: Arnau Mora <arnyminer.z@gmail.com>
* Moved locales functions to `locales.gradle`
Signed-off-by: Arnau Mora <arnyminer.z@gmail.com>
* Added `locales_config.xml` generation
Signed-off-by: Arnau Mora <arnyminer.z@gmail.com>
* Now gets generated automatically
Signed-off-by: Arnau Mora <arnyminer.z@gmail.com>
* Added `android:localeConfig`
Signed-off-by: Arnau Mora <arnyminer.z@gmail.com>
* Updated submodules
Signed-off-by: Arnau Mora <arnyminer.z@gmail.com>
* Using `logger` instead of `println`
Signed-off-by: Arnau Mora <arnyminer.z@gmail.com>
Signed-off-by: Arnau Mora <arnyminer.z@gmail.com>
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
Co-authored-by: Arnau Mora <arnyminer.z@gmail.com>
* rabase with dev branch
* added test for checking whether manual work-manager sync queues worker
* overwrite getForegroundInfo to show a "sync running" notification, to run expedited work on Android <12
* basic error state with sensible feedback from syncframework
* remove integer state flags and pass SyncResult as string
* Manual sync cancellation
* rabase with dev branch
* Minor changes
- add Jtx Board sync adapter to sync worker
- use new notification ID for sync worker
* status bar reflects sync of SyncWorker and sync framework correctly
* [WIP] custom hilt SyncComponent
* fix autoclose cast not available below api24
* SyncScope implementation using WeakReference
* Remove unnecessary logging call
* AddressBooksSyncAdapter.sync uses SyncWorker instead of ContentResolve to call requestSync
* add some code documentation
* move all utility objects into one package
* Also check SyncWorker state for accounts list sync status bar
* clean up imports
* Remove duplicate copyright notices
* Minor changes
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* LoginSetupActivity: allow http/https in intent filter
Initially introduced in 054f1ece61,
this `intent-filter` breaks login from the Nextcloud app, as we send the server URI as `http`/`https`.
Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
* Update intent-filter for login flow on api lvl 33 (closesbitfireAT/davx5#172)
Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
Co-authored-by: Sunik Kupfer <kupfer@bitfire.at>
* Remove forced wifi-only sync when Data Saver is active
* move data saver warning to AppWarningsManager
* Minor changes
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* move warning notification logic into a warning class
* Move Warnings to UI package
* Minor changes
* Move "global sync disabled" warning to AccountListFragment, too
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* SyncManager: remove retry intent
* refactor DavService to RefreshCollectionsWorker now using WorkManager
* move DavResourceFinder to new service detection package
* Optimize imports
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* [WIP] save task list access level to android task list for tasks.org to use
* Disrecommend using OpenTasks in selection dialog
* Update string, use matching ical4android
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* check for notify permission before notifying
* [WIP] add notification permission request
* Revert "check for notify permission before notifying"
This reverts commit ed8e046d73163bef5684622bd877f08b9ee781c6.
* add notification permission request
* [WIP] add notifications disabled card in accounts view
* add notifications disabled card in accounts view
* reorder permissions
* use dp instead of mm for image max height in permissions view
* stop using array to bundle notification permissions
* Use new permissions contract for PermissionsFragment
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* [WIP] add managed restriction to force read-only addressbooks
* Honor app-wide read-only address book setting when syncing address books
* reflect status of force read-only address books setting in the GUI
Co-authored-by: Sunik Kupfer <kupfer@bitfire.at>
* use FragmentComponentManagers findActivity method provided by hilt (closesbitfireAT/davx5#106)
* WebCalFragment CalendarViewHolder: Pass Fragment instead of FragmentManager so that requireActivity() can be used
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Removed update related to from JtxSyncManager
updateRelatedTo is now done implicitely in the sync content provider for every inserted or updated icalobject/relatedto
* Update ical4android
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* [WIP] initialization code to make tests non-flaky
* init code as junit rule and remove flaky annotations
* remove exception for flaky tests in Github test workflow
* ensure correct class rule execution order
* Sync adapter: share single HttpClient between all SyncManagers (should fixbitfireAT/davx5#99)
* HttpClient: use producer for CertManager
* Call setAccountVisibility only when necessary
* Fix tests
* Use Hilt for DI
* Use Hilt for settings providers
* Use Hilt for login credentials fragment
* Use Hilt instead of ServiceLoader for intro fragments
* Rewrite from Koin to Hilt
* Tests
* Use more Hilt modules for service loading (account drawer, intro fragments)
* Lint
* WebDAV provider: don't listen to changes in onCreate (causes problems with Hilt and tests)
* Add intent filter for caldav(s)://, carddav(s):// and davx5:// schemes
* Define intent-filter only for standard and gplay flavors
* Merge manifest; remove Espresso tests (further tests should be added)
* Lint
ClosesbitfireAT/davx5#77
* Service detection: update properties of already existing collections which are not in homesets
* Trigger service detection after creating a collection because the server may change properties
* jtx sync: query tasks/journals only when supported
Should fixbitfireAT/davx5#78
* Set InputType for proxy_host and proxy_port programmatically
Since AndroidX it is no longer sufficient to simply specify
android:inputType in settings_app.xml.
* Drop custom IntEditTextPreference.kt
Doesn't appear to be necessary anymore.
* Updated queryCapabilities to use the same code as in TasksSyncManager
Might solve #59
* Added try-catch block for sync-method
updated min version for JtxBoard in TaskProvider.kt
Should solve #59
* removed syncResult.databaseError = true
* Changed wrong file before
* Created TasksSyncUtils to put notifyProviderTooOld method
* Cleaned up imports
* Added Version check in JtxSyncAdapterService.kt, required TaskProvider.checkVersion to be public
* Minor changes
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
* Make "Battery optimization whitelisting" a global DAVx5 setting
* Make "Keep in foreground" setting dependent of "Battery optimization whitelisting" setting
* if foreground service is enabled, remind user to enable battery optimization whitelisting too, before starting the foreground service
Co-authored-by: Ricki Hirner <hirner@bitfire.at>
- WebDAV service detection: accept compliance class 2 or 3, because they both imply class 1 (there are servers which don't show class 1 although they MUST)
- WebDAV random access: fix division by zero when file size reported by HEAD is zero
With the recent move to GitHub, the AboutInfo override for dav4jvm was
broken as it still used com_gitlab_bitfireAT__dav4jvm whereas it is now:
```
$ ./gradlew findLibraries | grep dav4jvm
bitfireAT/dav4jvm (f1d9354a41) -> com_github_bitfireAT__dav4jvm
Manually requested license: mpl_2_0
```
Since the autogenerated dav4jvm AboutInfo looks fine (see attached
screenshot), remove the override.
- Android 8 to 10: use all DNS servers; prioritize resolvers of active connections
(before: use only DNS servers of "active" connection, which may be a VPN connection without servers)
- Android 10+: use new DnsResolver API so that we don't need to know DNS servers anymore (also supports DoT etc.)
We typically provide a dark variant for icons that are used on a light
background. The current share icon sticks out a bit, so add a dark
variant of that icon and use that in the Debug activity.
- set isSyncable(AddressBooks)=0 at account creation when there is no CardDAV service
- OpenTasksWatcher: enumerate real accounts and not services from DB -> isSyncable(tasks) will be set to 0 correctly for accounts without CalDAV service
- SyncAdapter base class: set autoInitialize to true, although it should not be needed regularly
The battery optimization screen used some additional padding which made
it look out of place when swiping through the intro screens.
Instead of applying app:cardUseCompatPadding="true" to the other
screens, we remove it from intro_battery_optimizations.xml.
While at it, fix the indentation of the TextView element.
Recent okhttp versions require Android 5. Also, a lot of workarounds
(like non-vector graphics for notification icons) which are cumbersome
to maintain have accumulated.
So, DAVx5 will require Android 5 (SDK level 21) from the next release,
which will probably tagged as 3.0.
2.6.x (currently 2.6.5) will be the last branch which supports Android 4.4.
Maybe there will never be a version after 2.6.5, which will still be offered for
Android 4.4 devices. If there's big need for a maintenance release (like severe security
problems), there may be further 2.6.x releases (branched from 2.6.5), but
development and new features will only go to the master branch.
Recent okhttp versions require Android 5. Also, a lot of workarounds
(like non-vector graphics for notification icons) which are cumbersome
to maintain have accumulated.
So, DAVx5 will require Android 5 (SDK level 21) from the next release,
which will probably tagged as 3.0.
2.6.x (currently 2.6.5) will be the last branch which supports Android 4.4.
Maybe there will never be a version after 2.6.5, which will still be offered for
Android 4.4 devices. If there's big need for a maintenance release (like severe security
problems), there may be further 2.6.x releases (branched from 2.6.5), but
development and new features will only go to the master branch.
- Collection sync: don't save new sync state before downloading is finished
- throw exception when waiting for completion times out
- always use multi-get, even for single vCards/iCalendars
* move .ui.AccountSettingsActivity to .ui.account.SettingsActivity
* add setting for default alarms
* add sync extra: SyncAdapterService.SYNC_EXTRAS_RELOAD_ALL (forces full re-synchronization of all members)
* LocalCollection: add forgetETags() which resets the ETags of members
* account settings: automatic reloading of members when certain settings are modified
- ask for ACCESS_FINE_LOCATION/ACCESS_BACKGROUND_LOCATION when sync is restricted to specific WiFi SSIDs
- use Android 5+ way to determine active network connections, if possible
* remove external storage permissions because logs are now written to the app data directory
* ical4android: use ical4j 2.2.3 with built-in RFC 7986 properties
* don't use a separate :sync process anymore, so that settings management doesn't need IPC
* remove Settings service and IPC, use singleton with application Context instead
* adapt default number of sync worker threads
* library updates
* service DB: split readOnly into privWriteContent and privUnbind
* collections: use privWriteContent (DAV:write-content privilege) for read-only detection
* AccountActivity: allow collection deletion only when privUnbind (DAV:unbind privilege) is set
* new About activity using AboutLibraries library
* include DAVdroid version and other non-personal information in URL when DAVdroid homepage is opened
(so that we know what DAVdroid versions are used out there and maybe can provide version-specific help)
* HttpUrl is the preferred class because we use URLs mainly for okhttp
* don't use URI or String for URLs, if possible
* HttpUrl is not Serializable, so use Parcelable for data classes with HttpUrl
X
* fixes removed eventColor_index fields when there is at least one DAVdroid
account with enabled calendar colors and at least one account with disabled
calendar colors
* refactor checking for cancelled sync
* notify on SSLHandshakeException (except when a certificate was rejected by cert4android)
* show exception cause in debug info
* setup UI: login with URL and client certificate
* account settings UI: show either username/password or client certificate alias
* AccountSettings: serve credentials in generalized Credentials objects
* HttpClient: use Credentials (instead of username/password) for authentication
* HttpClient: always use CustomTlsSocketFactory
* CustomTlsSocketFactory: support client certificates
* raise API level to 19 (required by ical4j)
* make HttpClient use Settings to get sync working again
* don't use vector graphics for notification icons (crashes on Android 4.x)
* various fixes and improvements
* library and build tools updates
* ask for confirmation when group method is changed in account settings activity
* reset address books/force reload when contact group method has changed since last sync
In Android < 4.1 (< level 16), android.database.Cursor doesn't implement Closeable,
although it provides close(). Since we now use the Kotlin .use() idiom (which requires
a Closeable) instead of calling close() manually or via Lombok, we need Closeable
Cursors and it's not worth to work around this because Android 4.0.4 is now very old.
* migration from old address book to new address book accounts (5 -> 6)
* support renaming of address book accounts
* change address book accounts properly when the main account is renamed
* new account type: "DAVdroid address book", which is assigned to a DAVdroid main account
* stub content provider "Address books", which enumerates all DAVdroid address book accounts and runs contacts sync for them
* move file name/UID generation from SyncManager to LocalContact, LocalEvent, LocalTask
* rename updateFileNameAndUID() to prepareForUpload()
* use random UUID for contacts, UidGenerator with Android device ID for events/tasks
* LocalEvent.prepareForUpload(): use existing UID_2445 if available
* contact data hash code = hash code of data fields and group memberships
* Before every contact sync, all dirty contacts are checked whether they're
"really dirty" (= data hash code has changed). If they're not, the DIRTY
flag is reset. Works around Android 7 behavior of setting contacts to DIRTY
even if onky meta data has been updated (for instance, lastContacted after
a call or SMS),
* When an "upload" sync is initiated by notifyChange and there are no
"really dirty" contacts, the sync is ignored.
* contact upload: clearDirty() saves hash code, too
* contact download: create()/update() saves hash code, too
* debugging: sync flags (extras) are now logged
* AccountDetailsFragment: at account creation, enable task sync only when OpenTasks is installed
* PackageChangedReceiver: when packages are (un)installed, check for OpenTasks availability and (de)activate task sync for all accounts accordingly
* LocalTaskList: don't cache OpenTasks availability
* sync_*.xml: don't activate sync by default
* share debug info: always use attachment (before: send inline if it was small enough)
* use FileProvider for debug info attachment (for Android 7 compatibility)
* dav4android, ical4android fixes
* use cert4android instead of MemorizingTrustManager
* new app setting: distrust system certificates
* add network security config to manifest so that user-installed CAs will be accepted in Android 7 again
* update gradle
Please delete this paragraph and other repeating text (like the examples) after reading and before submitting the PR.
The PR should be in _Draft_ state during development. As soon as it's finished, it should be marked as _Ready for review_ and a reviewer should be chosen.
See also: [Writing A Great Pull Request Description](https://www.pullrequest.com/blog/writing-a-great-pull-request-description/)
### Purpose
What this PR is intended to do and why this is desirable.
Example:
> Adds support for AAA in BBB, as requested by several people in issue #XX.
### Short description
A short description of the chosen approach to achieve the purpose.
Example:
> - Added authentication option _Some authentication_ to _some module_.
> - Added support for _Some authentication_ to _some content provider_.
> - Added UI support for _Some authentication_ in account settings.
Related information (links to Android docs and other resources that help to understand/review
the changes) can also be put here.
### Checklist
- [ ] The PR has a proper title, description and label.
- [ ] I have [self-reviewed the PR](https://patrickdinh.medium.com/review-your-own-pull-requests-5634cad10b7a).
- [ ] I have added documentation to complex functions and functions that can be used by other modules.
- [ ] I have added reasonable tests or consciously decided to not add tests.
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `accountName` TEXT NOT NULL, `type` TEXT NOT NULL, `principal` TEXT)",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"accountName",
"columnName":"accountName",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"type",
"columnName":"type",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"principal",
"columnName":"principal",
"affinity":"TEXT",
"notNull":false
}
],
"primaryKey":{
"columnNames":[
"id"
],
"autoGenerate":true
},
"indices":[
{
"name":"index_service_accountName_type",
"unique":true,
"columnNames":[
"accountName",
"type"
],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_service_accountName_type` ON `${TABLE_NAME}` (`accountName`, `type`)"
}
],
"foreignKeys":[]
},
{
"tableName":"homeset",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `serviceId` INTEGER NOT NULL, `personal` INTEGER NOT NULL, `url` TEXT NOT NULL, `privBind` INTEGER NOT NULL, `displayName` TEXT, FOREIGN KEY(`serviceId`) REFERENCES `service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"serviceId",
"columnName":"serviceId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"personal",
"columnName":"personal",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"url",
"columnName":"url",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"privBind",
"columnName":"privBind",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"displayName",
"columnName":"displayName",
"affinity":"TEXT",
"notNull":false
}
],
"primaryKey":{
"columnNames":[
"id"
],
"autoGenerate":true
},
"indices":[
{
"name":"index_homeset_serviceId_url",
"unique":true,
"columnNames":[
"serviceId",
"url"
],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_homeset_serviceId_url` ON `${TABLE_NAME}` (`serviceId`, `url`)"
}
],
"foreignKeys":[
{
"table":"service",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"serviceId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"collection",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `serviceId` INTEGER NOT NULL, `homeSetId` INTEGER, `type` TEXT NOT NULL, `url` TEXT NOT NULL, `privWriteContent` INTEGER NOT NULL, `privUnbind` INTEGER NOT NULL, `forceReadOnly` INTEGER NOT NULL, `displayName` TEXT, `description` TEXT, `owner` TEXT, `color` INTEGER, `timezone` TEXT, `supportsVEVENT` INTEGER, `supportsVTODO` INTEGER, `supportsVJOURNAL` INTEGER, `source` TEXT, `sync` INTEGER NOT NULL, FOREIGN KEY(`serviceId`) REFERENCES `service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`homeSetId`) REFERENCES `homeset`(`id`) ON UPDATE NO ACTION ON DELETE SET NULL )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"serviceId",
"columnName":"serviceId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"homeSetId",
"columnName":"homeSetId",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"type",
"columnName":"type",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"url",
"columnName":"url",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"privWriteContent",
"columnName":"privWriteContent",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"privUnbind",
"columnName":"privUnbind",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"forceReadOnly",
"columnName":"forceReadOnly",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"displayName",
"columnName":"displayName",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"description",
"columnName":"description",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"owner",
"columnName":"owner",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"color",
"columnName":"color",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"timezone",
"columnName":"timezone",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"supportsVEVENT",
"columnName":"supportsVEVENT",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"supportsVTODO",
"columnName":"supportsVTODO",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"supportsVJOURNAL",
"columnName":"supportsVJOURNAL",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"source",
"columnName":"source",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"sync",
"columnName":"sync",
"affinity":"INTEGER",
"notNull":true
}
],
"primaryKey":{
"columnNames":[
"id"
],
"autoGenerate":true
},
"indices":[
{
"name":"index_collection_serviceId_type",
"unique":false,
"columnNames":[
"serviceId",
"type"
],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_serviceId_type` ON `${TABLE_NAME}` (`serviceId`, `type`)"
},
{
"name":"index_collection_homeSetId_type",
"unique":false,
"columnNames":[
"homeSetId",
"type"
],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_homeSetId_type` ON `${TABLE_NAME}` (`homeSetId`, `type`)"
},
{
"name":"index_collection_url",
"unique":false,
"columnNames":[
"url"
],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_url` ON `${TABLE_NAME}` (`url`)"
}
],
"foreignKeys":[
{
"table":"service",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"serviceId"
],
"referencedColumns":[
"id"
]
},
{
"table":"homeset",
"onDelete":"SET NULL",
"onUpdate":"NO ACTION",
"columns":[
"homeSetId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"syncstats",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `collectionId` INTEGER NOT NULL, `authority` TEXT NOT NULL, `lastSync` INTEGER NOT NULL, FOREIGN KEY(`collectionId`) REFERENCES `collection`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"collectionId",
"columnName":"collectionId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"authority",
"columnName":"authority",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"lastSync",
"columnName":"lastSync",
"affinity":"INTEGER",
"notNull":true
}
],
"primaryKey":{
"columnNames":[
"id"
],
"autoGenerate":true
},
"indices":[
{
"name":"index_syncstats_collectionId_authority",
"unique":true,
"columnNames":[
"collectionId",
"authority"
],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_syncstats_collectionId_authority` ON `${TABLE_NAME}` (`collectionId`, `authority`)"
}
],
"foreignKeys":[
{
"table":"collection",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"collectionId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"webdav_mount",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL)",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"name",
"columnName":"name",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"url",
"columnName":"url",
"affinity":"TEXT",
"notNull":true
}
],
"primaryKey":{
"columnNames":[
"id"
],
"autoGenerate":true
},
"indices":[],
"foreignKeys":[]
}
],
"views":[],
"setupQueries":[
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '6fcabe50cbd00a4215dbe536a565dd2a')"
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `accountName` TEXT NOT NULL, `type` TEXT NOT NULL, `principal` TEXT)",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"accountName",
"columnName":"accountName",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"type",
"columnName":"type",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"principal",
"columnName":"principal",
"affinity":"TEXT",
"notNull":false
}
],
"primaryKey":{
"columnNames":[
"id"
],
"autoGenerate":true
},
"indices":[
{
"name":"index_service_accountName_type",
"unique":true,
"columnNames":[
"accountName",
"type"
],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_service_accountName_type` ON `${TABLE_NAME}` (`accountName`, `type`)"
}
],
"foreignKeys":[]
},
{
"tableName":"homeset",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `serviceId` INTEGER NOT NULL, `personal` INTEGER NOT NULL, `url` TEXT NOT NULL, `privBind` INTEGER NOT NULL, `displayName` TEXT, FOREIGN KEY(`serviceId`) REFERENCES `service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"serviceId",
"columnName":"serviceId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"personal",
"columnName":"personal",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"url",
"columnName":"url",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"privBind",
"columnName":"privBind",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"displayName",
"columnName":"displayName",
"affinity":"TEXT",
"notNull":false
}
],
"primaryKey":{
"columnNames":[
"id"
],
"autoGenerate":true
},
"indices":[
{
"name":"index_homeset_serviceId_url",
"unique":true,
"columnNames":[
"serviceId",
"url"
],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_homeset_serviceId_url` ON `${TABLE_NAME}` (`serviceId`, `url`)"
}
],
"foreignKeys":[
{
"table":"service",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"serviceId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"collection",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `serviceId` INTEGER NOT NULL, `homeSetId` INTEGER, `type` TEXT NOT NULL, `url` TEXT NOT NULL, `privWriteContent` INTEGER NOT NULL, `privUnbind` INTEGER NOT NULL, `forceReadOnly` INTEGER NOT NULL, `displayName` TEXT, `description` TEXT, `owner` TEXT, `color` INTEGER, `timezone` TEXT, `supportsVEVENT` INTEGER, `supportsVTODO` INTEGER, `supportsVJOURNAL` INTEGER, `source` TEXT, `sync` INTEGER NOT NULL, FOREIGN KEY(`serviceId`) REFERENCES `service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`homeSetId`) REFERENCES `homeset`(`id`) ON UPDATE NO ACTION ON DELETE SET NULL )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"serviceId",
"columnName":"serviceId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"homeSetId",
"columnName":"homeSetId",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"type",
"columnName":"type",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"url",
"columnName":"url",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"privWriteContent",
"columnName":"privWriteContent",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"privUnbind",
"columnName":"privUnbind",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"forceReadOnly",
"columnName":"forceReadOnly",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"displayName",
"columnName":"displayName",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"description",
"columnName":"description",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"owner",
"columnName":"owner",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"color",
"columnName":"color",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"timezone",
"columnName":"timezone",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"supportsVEVENT",
"columnName":"supportsVEVENT",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"supportsVTODO",
"columnName":"supportsVTODO",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"supportsVJOURNAL",
"columnName":"supportsVJOURNAL",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"source",
"columnName":"source",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"sync",
"columnName":"sync",
"affinity":"INTEGER",
"notNull":true
}
],
"primaryKey":{
"columnNames":[
"id"
],
"autoGenerate":true
},
"indices":[
{
"name":"index_collection_serviceId_type",
"unique":false,
"columnNames":[
"serviceId",
"type"
],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_serviceId_type` ON `${TABLE_NAME}` (`serviceId`, `type`)"
},
{
"name":"index_collection_homeSetId_type",
"unique":false,
"columnNames":[
"homeSetId",
"type"
],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_homeSetId_type` ON `${TABLE_NAME}` (`homeSetId`, `type`)"
},
{
"name":"index_collection_url",
"unique":false,
"columnNames":[
"url"
],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_url` ON `${TABLE_NAME}` (`url`)"
}
],
"foreignKeys":[
{
"table":"service",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"serviceId"
],
"referencedColumns":[
"id"
]
},
{
"table":"homeset",
"onDelete":"SET NULL",
"onUpdate":"NO ACTION",
"columns":[
"homeSetId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"syncstats",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `collectionId` INTEGER NOT NULL, `authority` TEXT NOT NULL, `lastSync` INTEGER NOT NULL, FOREIGN KEY(`collectionId`) REFERENCES `collection`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"collectionId",
"columnName":"collectionId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"authority",
"columnName":"authority",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"lastSync",
"columnName":"lastSync",
"affinity":"INTEGER",
"notNull":true
}
],
"primaryKey":{
"columnNames":[
"id"
],
"autoGenerate":true
},
"indices":[
{
"name":"index_syncstats_collectionId_authority",
"unique":true,
"columnNames":[
"collectionId",
"authority"
],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_syncstats_collectionId_authority` ON `${TABLE_NAME}` (`collectionId`, `authority`)"
}
],
"foreignKeys":[
{
"table":"collection",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"collectionId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"webdav_document",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `mountId` INTEGER NOT NULL, `parentId` INTEGER, `name` TEXT NOT NULL, `isDirectory` INTEGER NOT NULL, `displayName` TEXT, `mimeType` TEXT, `eTag` TEXT, `lastModified` INTEGER, `size` INTEGER, `mayBind` INTEGER, `mayUnbind` INTEGER, `mayWriteContent` INTEGER, `quotaAvailable` INTEGER, `quotaUsed` INTEGER, FOREIGN KEY(`mountId`) REFERENCES `webdav_mount`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`parentId`) REFERENCES `webdav_document`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `accountName` TEXT NOT NULL, `type` TEXT NOT NULL, `principal` TEXT)",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"accountName",
"columnName":"accountName",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"type",
"columnName":"type",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"principal",
"columnName":"principal",
"affinity":"TEXT",
"notNull":false
}
],
"primaryKey":{
"autoGenerate":true,
"columnNames":[
"id"
]
},
"indices":[
{
"name":"index_service_accountName_type",
"unique":true,
"columnNames":[
"accountName",
"type"
],
"orders":[],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_service_accountName_type` ON `${TABLE_NAME}` (`accountName`, `type`)"
}
],
"foreignKeys":[]
},
{
"tableName":"homeset",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `serviceId` INTEGER NOT NULL, `personal` INTEGER NOT NULL, `url` TEXT NOT NULL, `privBind` INTEGER NOT NULL, `displayName` TEXT, FOREIGN KEY(`serviceId`) REFERENCES `service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"serviceId",
"columnName":"serviceId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"personal",
"columnName":"personal",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"url",
"columnName":"url",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"privBind",
"columnName":"privBind",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"displayName",
"columnName":"displayName",
"affinity":"TEXT",
"notNull":false
}
],
"primaryKey":{
"autoGenerate":true,
"columnNames":[
"id"
]
},
"indices":[
{
"name":"index_homeset_serviceId_url",
"unique":true,
"columnNames":[
"serviceId",
"url"
],
"orders":[],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_homeset_serviceId_url` ON `${TABLE_NAME}` (`serviceId`, `url`)"
}
],
"foreignKeys":[
{
"table":"service",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"serviceId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"collection",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `serviceId` INTEGER NOT NULL, `homeSetId` INTEGER, `ownerId` INTEGER, `type` TEXT NOT NULL, `url` TEXT NOT NULL, `privWriteContent` INTEGER NOT NULL, `privUnbind` INTEGER NOT NULL, `forceReadOnly` INTEGER NOT NULL, `displayName` TEXT, `description` TEXT, `color` INTEGER, `timezone` TEXT, `supportsVEVENT` INTEGER, `supportsVTODO` INTEGER, `supportsVJOURNAL` INTEGER, `source` TEXT, `sync` INTEGER NOT NULL, FOREIGN KEY(`serviceId`) REFERENCES `service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`homeSetId`) REFERENCES `homeset`(`id`) ON UPDATE NO ACTION ON DELETE SET NULL , FOREIGN KEY(`ownerId`) REFERENCES `principal`(`id`) ON UPDATE NO ACTION ON DELETE SET NULL )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"serviceId",
"columnName":"serviceId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"homeSetId",
"columnName":"homeSetId",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"ownerId",
"columnName":"ownerId",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"type",
"columnName":"type",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"url",
"columnName":"url",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"privWriteContent",
"columnName":"privWriteContent",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"privUnbind",
"columnName":"privUnbind",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"forceReadOnly",
"columnName":"forceReadOnly",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"displayName",
"columnName":"displayName",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"description",
"columnName":"description",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"color",
"columnName":"color",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"timezone",
"columnName":"timezone",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"supportsVEVENT",
"columnName":"supportsVEVENT",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"supportsVTODO",
"columnName":"supportsVTODO",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"supportsVJOURNAL",
"columnName":"supportsVJOURNAL",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"source",
"columnName":"source",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"sync",
"columnName":"sync",
"affinity":"INTEGER",
"notNull":true
}
],
"primaryKey":{
"autoGenerate":true,
"columnNames":[
"id"
]
},
"indices":[
{
"name":"index_collection_serviceId_type",
"unique":false,
"columnNames":[
"serviceId",
"type"
],
"orders":[],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_serviceId_type` ON `${TABLE_NAME}` (`serviceId`, `type`)"
},
{
"name":"index_collection_homeSetId_type",
"unique":false,
"columnNames":[
"homeSetId",
"type"
],
"orders":[],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_homeSetId_type` ON `${TABLE_NAME}` (`homeSetId`, `type`)"
},
{
"name":"index_collection_url",
"unique":false,
"columnNames":[
"url"
],
"orders":[],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_url` ON `${TABLE_NAME}` (`url`)"
}
],
"foreignKeys":[
{
"table":"service",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"serviceId"
],
"referencedColumns":[
"id"
]
},
{
"table":"homeset",
"onDelete":"SET NULL",
"onUpdate":"NO ACTION",
"columns":[
"homeSetId"
],
"referencedColumns":[
"id"
]
},
{
"table":"principal",
"onDelete":"SET NULL",
"onUpdate":"NO ACTION",
"columns":[
"ownerId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"principal",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `serviceId` INTEGER NOT NULL, `url` TEXT NOT NULL, `displayName` TEXT, FOREIGN KEY(`serviceId`) REFERENCES `service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"serviceId",
"columnName":"serviceId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"url",
"columnName":"url",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"displayName",
"columnName":"displayName",
"affinity":"TEXT",
"notNull":false
}
],
"primaryKey":{
"autoGenerate":true,
"columnNames":[
"id"
]
},
"indices":[
{
"name":"index_principal_serviceId_url",
"unique":true,
"columnNames":[
"serviceId",
"url"
],
"orders":[],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_principal_serviceId_url` ON `${TABLE_NAME}` (`serviceId`, `url`)"
}
],
"foreignKeys":[
{
"table":"service",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"serviceId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"syncstats",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `collectionId` INTEGER NOT NULL, `authority` TEXT NOT NULL, `lastSync` INTEGER NOT NULL, FOREIGN KEY(`collectionId`) REFERENCES `collection`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"collectionId",
"columnName":"collectionId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"authority",
"columnName":"authority",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"lastSync",
"columnName":"lastSync",
"affinity":"INTEGER",
"notNull":true
}
],
"primaryKey":{
"autoGenerate":true,
"columnNames":[
"id"
]
},
"indices":[
{
"name":"index_syncstats_collectionId_authority",
"unique":true,
"columnNames":[
"collectionId",
"authority"
],
"orders":[],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_syncstats_collectionId_authority` ON `${TABLE_NAME}` (`collectionId`, `authority`)"
}
],
"foreignKeys":[
{
"table":"collection",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"collectionId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"webdav_document",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `mountId` INTEGER NOT NULL, `parentId` INTEGER, `name` TEXT NOT NULL, `isDirectory` INTEGER NOT NULL, `displayName` TEXT, `mimeType` TEXT, `eTag` TEXT, `lastModified` INTEGER, `size` INTEGER, `mayBind` INTEGER, `mayUnbind` INTEGER, `mayWriteContent` INTEGER, `quotaAvailable` INTEGER, `quotaUsed` INTEGER, FOREIGN KEY(`mountId`) REFERENCES `webdav_mount`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`parentId`) REFERENCES `webdav_document`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `accountName` TEXT NOT NULL, `type` TEXT NOT NULL, `principal` TEXT)",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"accountName",
"columnName":"accountName",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"type",
"columnName":"type",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"principal",
"columnName":"principal",
"affinity":"TEXT",
"notNull":false
}
],
"primaryKey":{
"autoGenerate":true,
"columnNames":[
"id"
]
},
"indices":[
{
"name":"index_service_accountName_type",
"unique":true,
"columnNames":[
"accountName",
"type"
],
"orders":[],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_service_accountName_type` ON `${TABLE_NAME}` (`accountName`, `type`)"
}
],
"foreignKeys":[]
},
{
"tableName":"homeset",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `serviceId` INTEGER NOT NULL, `personal` INTEGER NOT NULL, `url` TEXT NOT NULL, `privBind` INTEGER NOT NULL, `displayName` TEXT, FOREIGN KEY(`serviceId`) REFERENCES `service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"serviceId",
"columnName":"serviceId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"personal",
"columnName":"personal",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"url",
"columnName":"url",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"privBind",
"columnName":"privBind",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"displayName",
"columnName":"displayName",
"affinity":"TEXT",
"notNull":false
}
],
"primaryKey":{
"autoGenerate":true,
"columnNames":[
"id"
]
},
"indices":[
{
"name":"index_homeset_serviceId_url",
"unique":true,
"columnNames":[
"serviceId",
"url"
],
"orders":[],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_homeset_serviceId_url` ON `${TABLE_NAME}` (`serviceId`, `url`)"
}
],
"foreignKeys":[
{
"table":"service",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"serviceId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"collection",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `serviceId` INTEGER NOT NULL, `homeSetId` INTEGER, `ownerId` INTEGER, `type` TEXT NOT NULL, `url` TEXT NOT NULL, `privWriteContent` INTEGER NOT NULL, `privUnbind` INTEGER NOT NULL, `forceReadOnly` INTEGER NOT NULL, `displayName` TEXT, `description` TEXT, `color` INTEGER, `timezone` TEXT, `supportsVEVENT` INTEGER, `supportsVTODO` INTEGER, `supportsVJOURNAL` INTEGER, `source` TEXT, `sync` INTEGER NOT NULL, `pushTopic` TEXT, `supportsWebPush` INTEGER NOT NULL DEFAULT 0, `pushSubscription` TEXT, `pushSubscriptionCreated` INTEGER, FOREIGN KEY(`serviceId`) REFERENCES `service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`homeSetId`) REFERENCES `homeset`(`id`) ON UPDATE NO ACTION ON DELETE SET NULL , FOREIGN KEY(`ownerId`) REFERENCES `principal`(`id`) ON UPDATE NO ACTION ON DELETE SET NULL )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"serviceId",
"columnName":"serviceId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"homeSetId",
"columnName":"homeSetId",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"ownerId",
"columnName":"ownerId",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"type",
"columnName":"type",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"url",
"columnName":"url",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"privWriteContent",
"columnName":"privWriteContent",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"privUnbind",
"columnName":"privUnbind",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"forceReadOnly",
"columnName":"forceReadOnly",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"displayName",
"columnName":"displayName",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"description",
"columnName":"description",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"color",
"columnName":"color",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"timezone",
"columnName":"timezone",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"supportsVEVENT",
"columnName":"supportsVEVENT",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"supportsVTODO",
"columnName":"supportsVTODO",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"supportsVJOURNAL",
"columnName":"supportsVJOURNAL",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"source",
"columnName":"source",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"sync",
"columnName":"sync",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"pushTopic",
"columnName":"pushTopic",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"supportsWebPush",
"columnName":"supportsWebPush",
"affinity":"INTEGER",
"notNull":true,
"defaultValue":"0"
},
{
"fieldPath":"pushSubscription",
"columnName":"pushSubscription",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"pushSubscriptionCreated",
"columnName":"pushSubscriptionCreated",
"affinity":"INTEGER",
"notNull":false
}
],
"primaryKey":{
"autoGenerate":true,
"columnNames":[
"id"
]
},
"indices":[
{
"name":"index_collection_serviceId_type",
"unique":false,
"columnNames":[
"serviceId",
"type"
],
"orders":[],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_serviceId_type` ON `${TABLE_NAME}` (`serviceId`, `type`)"
},
{
"name":"index_collection_homeSetId_type",
"unique":false,
"columnNames":[
"homeSetId",
"type"
],
"orders":[],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_homeSetId_type` ON `${TABLE_NAME}` (`homeSetId`, `type`)"
},
{
"name":"index_collection_url",
"unique":false,
"columnNames":[
"url"
],
"orders":[],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_url` ON `${TABLE_NAME}` (`url`)"
}
],
"foreignKeys":[
{
"table":"service",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"serviceId"
],
"referencedColumns":[
"id"
]
},
{
"table":"homeset",
"onDelete":"SET NULL",
"onUpdate":"NO ACTION",
"columns":[
"homeSetId"
],
"referencedColumns":[
"id"
]
},
{
"table":"principal",
"onDelete":"SET NULL",
"onUpdate":"NO ACTION",
"columns":[
"ownerId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"principal",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `serviceId` INTEGER NOT NULL, `url` TEXT NOT NULL, `displayName` TEXT, FOREIGN KEY(`serviceId`) REFERENCES `service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"serviceId",
"columnName":"serviceId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"url",
"columnName":"url",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"displayName",
"columnName":"displayName",
"affinity":"TEXT",
"notNull":false
}
],
"primaryKey":{
"autoGenerate":true,
"columnNames":[
"id"
]
},
"indices":[
{
"name":"index_principal_serviceId_url",
"unique":true,
"columnNames":[
"serviceId",
"url"
],
"orders":[],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_principal_serviceId_url` ON `${TABLE_NAME}` (`serviceId`, `url`)"
}
],
"foreignKeys":[
{
"table":"service",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"serviceId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"syncstats",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `collectionId` INTEGER NOT NULL, `authority` TEXT NOT NULL, `lastSync` INTEGER NOT NULL, FOREIGN KEY(`collectionId`) REFERENCES `collection`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"collectionId",
"columnName":"collectionId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"authority",
"columnName":"authority",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"lastSync",
"columnName":"lastSync",
"affinity":"INTEGER",
"notNull":true
}
],
"primaryKey":{
"autoGenerate":true,
"columnNames":[
"id"
]
},
"indices":[
{
"name":"index_syncstats_collectionId_authority",
"unique":true,
"columnNames":[
"collectionId",
"authority"
],
"orders":[],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_syncstats_collectionId_authority` ON `${TABLE_NAME}` (`collectionId`, `authority`)"
}
],
"foreignKeys":[
{
"table":"collection",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"collectionId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"webdav_document",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `mountId` INTEGER NOT NULL, `parentId` INTEGER, `name` TEXT NOT NULL, `isDirectory` INTEGER NOT NULL, `displayName` TEXT, `mimeType` TEXT, `eTag` TEXT, `lastModified` INTEGER, `size` INTEGER, `mayBind` INTEGER, `mayUnbind` INTEGER, `mayWriteContent` INTEGER, `quotaAvailable` INTEGER, `quotaUsed` INTEGER, FOREIGN KEY(`mountId`) REFERENCES `webdav_mount`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`parentId`) REFERENCES `webdav_document`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `accountName` TEXT NOT NULL, `type` TEXT NOT NULL, `principal` TEXT)",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"accountName",
"columnName":"accountName",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"type",
"columnName":"type",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"principal",
"columnName":"principal",
"affinity":"TEXT",
"notNull":false
}
],
"primaryKey":{
"autoGenerate":true,
"columnNames":[
"id"
]
},
"indices":[
{
"name":"index_service_accountName_type",
"unique":true,
"columnNames":[
"accountName",
"type"
],
"orders":[],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_service_accountName_type` ON `${TABLE_NAME}` (`accountName`, `type`)"
}
],
"foreignKeys":[]
},
{
"tableName":"homeset",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `serviceId` INTEGER NOT NULL, `personal` INTEGER NOT NULL, `url` TEXT NOT NULL, `privBind` INTEGER NOT NULL, `displayName` TEXT, FOREIGN KEY(`serviceId`) REFERENCES `service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"serviceId",
"columnName":"serviceId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"personal",
"columnName":"personal",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"url",
"columnName":"url",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"privBind",
"columnName":"privBind",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"displayName",
"columnName":"displayName",
"affinity":"TEXT",
"notNull":false
}
],
"primaryKey":{
"autoGenerate":true,
"columnNames":[
"id"
]
},
"indices":[
{
"name":"index_homeset_serviceId_url",
"unique":true,
"columnNames":[
"serviceId",
"url"
],
"orders":[],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_homeset_serviceId_url` ON `${TABLE_NAME}` (`serviceId`, `url`)"
}
],
"foreignKeys":[
{
"table":"service",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"serviceId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"collection",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `serviceId` INTEGER NOT NULL, `homeSetId` INTEGER, `ownerId` INTEGER, `type` TEXT NOT NULL, `url` TEXT NOT NULL, `privWriteContent` INTEGER NOT NULL, `privUnbind` INTEGER NOT NULL, `forceReadOnly` INTEGER NOT NULL, `displayName` TEXT, `description` TEXT, `color` INTEGER, `timezone` TEXT, `supportsVEVENT` INTEGER, `supportsVTODO` INTEGER, `supportsVJOURNAL` INTEGER, `source` TEXT, `sync` INTEGER NOT NULL, `pushTopic` TEXT, `supportsWebPush` INTEGER NOT NULL DEFAULT 0, `pushSubscription` TEXT, `pushSubscriptionCreated` INTEGER, FOREIGN KEY(`serviceId`) REFERENCES `service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`homeSetId`) REFERENCES `homeset`(`id`) ON UPDATE NO ACTION ON DELETE SET NULL , FOREIGN KEY(`ownerId`) REFERENCES `principal`(`id`) ON UPDATE NO ACTION ON DELETE SET NULL )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"serviceId",
"columnName":"serviceId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"homeSetId",
"columnName":"homeSetId",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"ownerId",
"columnName":"ownerId",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"type",
"columnName":"type",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"url",
"columnName":"url",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"privWriteContent",
"columnName":"privWriteContent",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"privUnbind",
"columnName":"privUnbind",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"forceReadOnly",
"columnName":"forceReadOnly",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"displayName",
"columnName":"displayName",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"description",
"columnName":"description",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"color",
"columnName":"color",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"timezone",
"columnName":"timezone",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"supportsVEVENT",
"columnName":"supportsVEVENT",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"supportsVTODO",
"columnName":"supportsVTODO",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"supportsVJOURNAL",
"columnName":"supportsVJOURNAL",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"source",
"columnName":"source",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"sync",
"columnName":"sync",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"pushTopic",
"columnName":"pushTopic",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"supportsWebPush",
"columnName":"supportsWebPush",
"affinity":"INTEGER",
"notNull":true,
"defaultValue":"0"
},
{
"fieldPath":"pushSubscription",
"columnName":"pushSubscription",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"pushSubscriptionCreated",
"columnName":"pushSubscriptionCreated",
"affinity":"INTEGER",
"notNull":false
}
],
"primaryKey":{
"autoGenerate":true,
"columnNames":[
"id"
]
},
"indices":[
{
"name":"index_collection_serviceId_type",
"unique":false,
"columnNames":[
"serviceId",
"type"
],
"orders":[],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_serviceId_type` ON `${TABLE_NAME}` (`serviceId`, `type`)"
},
{
"name":"index_collection_homeSetId_type",
"unique":false,
"columnNames":[
"homeSetId",
"type"
],
"orders":[],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_homeSetId_type` ON `${TABLE_NAME}` (`homeSetId`, `type`)"
},
{
"name":"index_collection_ownerId_type",
"unique":false,
"columnNames":[
"ownerId",
"type"
],
"orders":[],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_ownerId_type` ON `${TABLE_NAME}` (`ownerId`, `type`)"
},
{
"name":"index_collection_pushTopic_type",
"unique":false,
"columnNames":[
"pushTopic",
"type"
],
"orders":[],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_pushTopic_type` ON `${TABLE_NAME}` (`pushTopic`, `type`)"
},
{
"name":"index_collection_url",
"unique":false,
"columnNames":[
"url"
],
"orders":[],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_url` ON `${TABLE_NAME}` (`url`)"
}
],
"foreignKeys":[
{
"table":"service",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"serviceId"
],
"referencedColumns":[
"id"
]
},
{
"table":"homeset",
"onDelete":"SET NULL",
"onUpdate":"NO ACTION",
"columns":[
"homeSetId"
],
"referencedColumns":[
"id"
]
},
{
"table":"principal",
"onDelete":"SET NULL",
"onUpdate":"NO ACTION",
"columns":[
"ownerId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"principal",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `serviceId` INTEGER NOT NULL, `url` TEXT NOT NULL, `displayName` TEXT, FOREIGN KEY(`serviceId`) REFERENCES `service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"serviceId",
"columnName":"serviceId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"url",
"columnName":"url",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"displayName",
"columnName":"displayName",
"affinity":"TEXT",
"notNull":false
}
],
"primaryKey":{
"autoGenerate":true,
"columnNames":[
"id"
]
},
"indices":[
{
"name":"index_principal_serviceId_url",
"unique":true,
"columnNames":[
"serviceId",
"url"
],
"orders":[],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_principal_serviceId_url` ON `${TABLE_NAME}` (`serviceId`, `url`)"
}
],
"foreignKeys":[
{
"table":"service",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"serviceId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"syncstats",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `collectionId` INTEGER NOT NULL, `authority` TEXT NOT NULL, `lastSync` INTEGER NOT NULL, FOREIGN KEY(`collectionId`) REFERENCES `collection`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"collectionId",
"columnName":"collectionId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"authority",
"columnName":"authority",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"lastSync",
"columnName":"lastSync",
"affinity":"INTEGER",
"notNull":true
}
],
"primaryKey":{
"autoGenerate":true,
"columnNames":[
"id"
]
},
"indices":[
{
"name":"index_syncstats_collectionId_authority",
"unique":true,
"columnNames":[
"collectionId",
"authority"
],
"orders":[],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_syncstats_collectionId_authority` ON `${TABLE_NAME}` (`collectionId`, `authority`)"
}
],
"foreignKeys":[
{
"table":"collection",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"collectionId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"webdav_document",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `mountId` INTEGER NOT NULL, `parentId` INTEGER, `name` TEXT NOT NULL, `isDirectory` INTEGER NOT NULL, `displayName` TEXT, `mimeType` TEXT, `eTag` TEXT, `lastModified` INTEGER, `size` INTEGER, `mayBind` INTEGER, `mayUnbind` INTEGER, `mayWriteContent` INTEGER, `quotaAvailable` INTEGER, `quotaUsed` INTEGER, FOREIGN KEY(`mountId`) REFERENCES `webdav_mount`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`parentId`) REFERENCES `webdav_document`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `accountName` TEXT NOT NULL, `type` TEXT NOT NULL, `principal` TEXT)",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"accountName",
"columnName":"accountName",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"type",
"columnName":"type",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"principal",
"columnName":"principal",
"affinity":"TEXT",
"notNull":false
}
],
"primaryKey":{
"columnNames":[
"id"
],
"autoGenerate":true
},
"indices":[
{
"name":"index_service_accountName_type",
"unique":true,
"columnNames":[
"accountName",
"type"
],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_service_accountName_type` ON `${TABLE_NAME}` (`accountName`, `type`)"
}
],
"foreignKeys":[]
},
{
"tableName":"homeset",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `serviceId` INTEGER NOT NULL, `personal` INTEGER NOT NULL, `url` TEXT NOT NULL, `privBind` INTEGER NOT NULL, `displayName` TEXT, FOREIGN KEY(`serviceId`) REFERENCES `service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"serviceId",
"columnName":"serviceId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"personal",
"columnName":"personal",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"url",
"columnName":"url",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"privBind",
"columnName":"privBind",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"displayName",
"columnName":"displayName",
"affinity":"TEXT",
"notNull":false
}
],
"primaryKey":{
"columnNames":[
"id"
],
"autoGenerate":true
},
"indices":[
{
"name":"index_homeset_serviceId_url",
"unique":true,
"columnNames":[
"serviceId",
"url"
],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_homeset_serviceId_url` ON `${TABLE_NAME}` (`serviceId`, `url`)"
}
],
"foreignKeys":[
{
"table":"service",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"serviceId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"collection",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `serviceId` INTEGER NOT NULL, `homeSetId` INTEGER, `type` TEXT NOT NULL, `url` TEXT NOT NULL, `privWriteContent` INTEGER NOT NULL, `privUnbind` INTEGER NOT NULL, `forceReadOnly` INTEGER NOT NULL, `displayName` TEXT, `description` TEXT, `owner` TEXT, `color` INTEGER, `timezone` TEXT, `supportsVEVENT` INTEGER, `supportsVTODO` INTEGER, `supportsVJOURNAL` INTEGER, `source` TEXT, `sync` INTEGER NOT NULL, FOREIGN KEY(`serviceId`) REFERENCES `service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`homeSetId`) REFERENCES `homeset`(`id`) ON UPDATE NO ACTION ON DELETE SET NULL )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"serviceId",
"columnName":"serviceId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"homeSetId",
"columnName":"homeSetId",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"type",
"columnName":"type",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"url",
"columnName":"url",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"privWriteContent",
"columnName":"privWriteContent",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"privUnbind",
"columnName":"privUnbind",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"forceReadOnly",
"columnName":"forceReadOnly",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"displayName",
"columnName":"displayName",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"description",
"columnName":"description",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"owner",
"columnName":"owner",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"color",
"columnName":"color",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"timezone",
"columnName":"timezone",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"supportsVEVENT",
"columnName":"supportsVEVENT",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"supportsVTODO",
"columnName":"supportsVTODO",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"supportsVJOURNAL",
"columnName":"supportsVJOURNAL",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"source",
"columnName":"source",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"sync",
"columnName":"sync",
"affinity":"INTEGER",
"notNull":true
}
],
"primaryKey":{
"columnNames":[
"id"
],
"autoGenerate":true
},
"indices":[
{
"name":"index_collection_serviceId_type",
"unique":false,
"columnNames":[
"serviceId",
"type"
],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_serviceId_type` ON `${TABLE_NAME}` (`serviceId`, `type`)"
},
{
"name":"index_collection_homeSetId_type",
"unique":false,
"columnNames":[
"homeSetId",
"type"
],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_homeSetId_type` ON `${TABLE_NAME}` (`homeSetId`, `type`)"
}
],
"foreignKeys":[
{
"table":"service",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"serviceId"
],
"referencedColumns":[
"id"
]
},
{
"table":"homeset",
"onDelete":"SET NULL",
"onUpdate":"NO ACTION",
"columns":[
"homeSetId"
],
"referencedColumns":[
"id"
]
}
]
}
],
"views":[],
"setupQueries":[
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'b8699ef3cc4c62e8851df4360fb69e00')"
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `accountName` TEXT NOT NULL, `type` TEXT NOT NULL, `principal` TEXT)",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"accountName",
"columnName":"accountName",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"type",
"columnName":"type",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"principal",
"columnName":"principal",
"affinity":"TEXT",
"notNull":false
}
],
"primaryKey":{
"columnNames":[
"id"
],
"autoGenerate":true
},
"indices":[
{
"name":"index_service_accountName_type",
"unique":true,
"columnNames":[
"accountName",
"type"
],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_service_accountName_type` ON `${TABLE_NAME}` (`accountName`, `type`)"
}
],
"foreignKeys":[]
},
{
"tableName":"homeset",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `serviceId` INTEGER NOT NULL, `personal` INTEGER NOT NULL, `url` TEXT NOT NULL, `privBind` INTEGER NOT NULL, `displayName` TEXT, FOREIGN KEY(`serviceId`) REFERENCES `service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"serviceId",
"columnName":"serviceId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"personal",
"columnName":"personal",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"url",
"columnName":"url",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"privBind",
"columnName":"privBind",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"displayName",
"columnName":"displayName",
"affinity":"TEXT",
"notNull":false
}
],
"primaryKey":{
"columnNames":[
"id"
],
"autoGenerate":true
},
"indices":[
{
"name":"index_homeset_serviceId_url",
"unique":true,
"columnNames":[
"serviceId",
"url"
],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_homeset_serviceId_url` ON `${TABLE_NAME}` (`serviceId`, `url`)"
}
],
"foreignKeys":[
{
"table":"service",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"serviceId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"collection",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `serviceId` INTEGER NOT NULL, `homeSetId` INTEGER, `type` TEXT NOT NULL, `url` TEXT NOT NULL, `privWriteContent` INTEGER NOT NULL, `privUnbind` INTEGER NOT NULL, `forceReadOnly` INTEGER NOT NULL, `displayName` TEXT, `description` TEXT, `owner` TEXT, `color` INTEGER, `timezone` TEXT, `supportsVEVENT` INTEGER, `supportsVTODO` INTEGER, `supportsVJOURNAL` INTEGER, `source` TEXT, `sync` INTEGER NOT NULL, FOREIGN KEY(`serviceId`) REFERENCES `service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`homeSetId`) REFERENCES `homeset`(`id`) ON UPDATE NO ACTION ON DELETE SET NULL )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"serviceId",
"columnName":"serviceId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"homeSetId",
"columnName":"homeSetId",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"type",
"columnName":"type",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"url",
"columnName":"url",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"privWriteContent",
"columnName":"privWriteContent",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"privUnbind",
"columnName":"privUnbind",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"forceReadOnly",
"columnName":"forceReadOnly",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"displayName",
"columnName":"displayName",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"description",
"columnName":"description",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"owner",
"columnName":"owner",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"color",
"columnName":"color",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"timezone",
"columnName":"timezone",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"supportsVEVENT",
"columnName":"supportsVEVENT",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"supportsVTODO",
"columnName":"supportsVTODO",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"supportsVJOURNAL",
"columnName":"supportsVJOURNAL",
"affinity":"INTEGER",
"notNull":false
},
{
"fieldPath":"source",
"columnName":"source",
"affinity":"TEXT",
"notNull":false
},
{
"fieldPath":"sync",
"columnName":"sync",
"affinity":"INTEGER",
"notNull":true
}
],
"primaryKey":{
"columnNames":[
"id"
],
"autoGenerate":true
},
"indices":[
{
"name":"index_collection_serviceId_type",
"unique":false,
"columnNames":[
"serviceId",
"type"
],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_serviceId_type` ON `${TABLE_NAME}` (`serviceId`, `type`)"
},
{
"name":"index_collection_homeSetId_type",
"unique":false,
"columnNames":[
"homeSetId",
"type"
],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_homeSetId_type` ON `${TABLE_NAME}` (`homeSetId`, `type`)"
},
{
"name":"index_collection_url",
"unique":false,
"columnNames":[
"url"
],
"createSql":"CREATE INDEX IF NOT EXISTS `index_collection_url` ON `${TABLE_NAME}` (`url`)"
}
],
"foreignKeys":[
{
"table":"service",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"serviceId"
],
"referencedColumns":[
"id"
]
},
{
"table":"homeset",
"onDelete":"SET NULL",
"onUpdate":"NO ACTION",
"columns":[
"homeSetId"
],
"referencedColumns":[
"id"
]
}
]
},
{
"tableName":"syncstats",
"createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `collectionId` INTEGER NOT NULL, `authority` TEXT NOT NULL, `lastSync` INTEGER NOT NULL, FOREIGN KEY(`collectionId`) REFERENCES `collection`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields":[
{
"fieldPath":"id",
"columnName":"id",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"collectionId",
"columnName":"collectionId",
"affinity":"INTEGER",
"notNull":true
},
{
"fieldPath":"authority",
"columnName":"authority",
"affinity":"TEXT",
"notNull":true
},
{
"fieldPath":"lastSync",
"columnName":"lastSync",
"affinity":"INTEGER",
"notNull":true
}
],
"primaryKey":{
"columnNames":[
"id"
],
"autoGenerate":true
},
"indices":[
{
"name":"index_syncstats_collectionId_authority",
"unique":true,
"columnNames":[
"collectionId",
"authority"
],
"createSql":"CREATE UNIQUE INDEX IF NOT EXISTS `index_syncstats_collectionId_authority` ON `${TABLE_NAME}` (`collectionId`, `authority`)"
}
],
"foreignKeys":[
{
"table":"collection",
"onDelete":"CASCADE",
"onUpdate":"NO ACTION",
"columns":[
"collectionId"
],
"referencedColumns":[
"id"
]
}
]
}
],
"views":[],
"setupQueries":[
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '7e4bfdf7f9fa3529c333cf9485f8cf50')"
<stringname="notification_channel_sync_io_errors">Xarxa i errors E/S</string>
<stringname="notification_channel_sync_status">Estat dels misatges</string>
<!--startup dialogs-->
<stringname="startup_battery_optimization_disable">Desactiva per DAVdroid</string>
<stringname="startup_dont_show_again">No mostrar de nou</string>
<stringname="startup_donate">Informació de Codi Obert</string>
<stringname="startup_donate_message">Som feliços de que utilitzis DAVdroid, el qual és programari lliure (GPLv3). Desenvolupar DAVdroid ens porte moltes hores i molta feina, si us plau, considera fer una donació.</string>
<stringname="startup_donate_now">Mostra la pàgina de donació</string>
<stringname="startup_donate_message">Jsme velice rádi že používáte DAVdroid, software s otevřeným zdrojovým kódem (GPLv3). Vývoj této aplikace je náročný a trval již několik tisíc hodin, velice nás potěší přispějete-li na jeho vývoj.</string>
<stringname="startup_donate_now">Zobrazit stránku pro obdarování</string>
<stringname="startup_google_play_accounts_removed">Informace o chybě DRM Obchodu Play</string>
<stringname="startup_google_play_accounts_removed_message">Za určitých podmínek může dojít po restartu nebo aktualizaci aplikace DAVdroid k vymazání účtů kvůli chybě DRM Obchodu Play. Pokud jste postiženi touto chybou (ale pouze v tomto případě), nainstalujte prosím z Obchodu Play aplikaci \"DAVdroid JB Workaround\".</string>
<stringname="startup_opentasks_not_installed">OpenTasks není nainstalován</string>
<stringname="startup_opentasks_reinstall_davdroid">Po instalaci OpenTasks musíte PŘEINSTALOVAT DAVdroid a přidat znovu své účty (Android chyba).</string>
<stringname="about_license_info_no_warranty">Tento program je distribuován BEZ JAKÉKOLIV ZÁRUKY. Je to volně dostupný software a lze jej za určitých podmínek dále distribuovat.</string>
<!--global settings-->
<stringname="logging_davdroid_file_logging">DAVdroid logování do souboru</string>
<stringname="logging_to_external_storage">Logování do externího úložiště: %s</string>
<stringname="logging_couldnt_create_file">Nelze vytvořit externí soubor logu: %s</string>
<stringname="account_rename_new_name">Neuložená místní data mohou být vynechána. Po přejmenování je vyžadována nová synchronizace. Nové jméno účtu:</string>
<stringname="login_account_name_info">Pro jméno účtu použijte svou emailovou adresu, protože Android bude brát jméno účtu jako údaj pro ORGANIZÁTORA vytvořených událostí. Nelze mít dva účty stejného jména.</string>
<itemquantity="one">Ignorovat události starší než 1 den</item>
<itemquantity="few">Ignorovat události starší než %d dny</item>
<itemquantity="many">Ignorovat události starší než %d dnů</item>
<itemquantity="other">Ignorovat události starší než %d dnů</item>
</plurals>
<stringname="settings_sync_time_range_past_message">Události z minulosti starší než vyznačený počet dnů budou ignorovány (lze zadat 0). Ponechte prázdné pro synchronizaci všech událostí.</string>
<stringname="settings_manage_calendar_colors">Spravovat barvy kalendářů</string>
<stringname="startup_donate_message">Det glæder os, at du bruger DAVdroid, som er open source-software (GPLv3). Det er hårdt arbejde at udvikle DAVdroid og taget tusindvis af arbejdstimer, så overvej at donere til projektet.</string>
<stringname="startup_google_play_accounts_removed">Play Store DRM fejl information</string>
<stringname="startup_google_play_accounts_removed_message">Under visse tekniske omstændigheder kan DRM fra Play Store bevirke, at alle DAVdroid-konti er væk efter en genstart eller opgradering af DAVdroid. Hvis du er udsat for dette problem (og ellers ikke), opfordres du til at installere DAVDroid JB Workaround\" fra Play Store.</string>
<stringname="startup_opentasks_not_installed">OpenTasks ikke installeret</string>
<stringname="startup_opentasks_not_installed_message">Du er nødt til at have den gratis app OpenTasks for at kunne synkronisere opgaver. (Ikke påkrævet for kontakter/begivenheder.)</string>
<stringname="startup_opentasks_reinstall_davdroid">Efter at have installeret OpenTasks, vil du være nødt til at GENINSTALLERE DAVdroid og dine konti igen (en fejl i Android).</string>
<stringname="about_license_info_no_warranty">Dette program leveres ABSOLUT UDEN GARANTI. Det er fri software, og du er velkommen til at videredistribuere det under visse betingelse.</string>
<stringname="login_account_name_info">Brug emailadressen som kontonavn, for Android vil bruge kontonavnet til ORGANIZER-feltet for aktiviteter, som du opretter. Du kan ikke have to konti med samme navn.</string>
<stringname="login_account_contact_group_method">Gruppering af kontakter:</string>
<stringname="settings_sync_wifi_only_ssids_on">Synkroniserer kun over %s</string>
<stringname="settings_sync_wifi_only_ssids_off">Alle WiFi-forbindelser vil blive anvendt</string>
<stringname="settings_sync_wifi_only_ssids_message">Kommaseparerede navne (SSID\'er) over tilladte WiFi-netværk (efterlad blank for at bruge alle)</string>
<stringname="settings_carddav">CardDAV</string>
<stringname="settings_contact_group_method">Gruppering af kontakter</string>
<stringname="settings_contact_group_method_change_reload_contacts">Dette kræver, at alle kontakter genindlæses. Lokale ændringer, der ikke er gemt, vil blive slettet.</string>
<stringname="settings_caldav">CalDAV</string>
<stringname="settings_sync_time_range_past">Tidsafgrænsning for tidligere begivenheder</string>
<stringname="settings_sync_time_range_past_none">Alle begivenheder vil blive synkroniseret</string>
<itemquantity="one">Begivenheder ældre end en dag vil blive ignoreret</item>
<itemquantity="other">Begivenheder, der er mere end %d dage gamle, vil blive ignoreret</item>
</plurals>
<stringname="settings_sync_time_range_past_message">Begivenheder, som er mere end dette antal dage gamle vil blive ignoreret (kan også være 0). Hvis feltet ikke er udfyldt, vil alle begivenheder blive synkroniseret.</string>
<stringname="settings_manage_calendar_colors">Administrer farver for kalender</string>
<stringname="settings_manage_calendar_colors_on">Kalenderfarver administreres af DAVdroid</string>
<stringname="settings_manage_calendar_colors_off">Kalenderfarver sættes ikke fra DAVdroid</string>
<stringname="settings_event_colors">Farver for begivenheder</string>
<stringname="settings_event_colors_on">Synkroniser farver for begivenheder</string>
<stringname="settings_event_colors_off">Synkroniser ikke farver for begivenheder</string>
<stringname="settings_event_colors_off_confirm">Fjernes farver for begivenheder kan det fjerne farver, der allerede er synkroniseret.</string>
<stringname="notification_channel_sync_errors">Errores de sincronización</string>
<stringname="notification_channel_sync_io_errors">Errores de Red y E/S</string>
<stringname="notification_channel_sync_status">Mensajes de estado</string>
<!--startup dialogs-->
<stringname="startup_battery_optimization_disable">Apagar para DAVdroid</string>
<stringname="startup_dont_show_again">No mostrar de nuevo</string>
<stringname="startup_donate">Información de código abierto</string>
<stringname="startup_donate_message">Nos alegra que uses DAVdroid, que es software de código abierto (GPLv3). Debido al duro trabajo que supone el desarrollo de DAVdroid y los cientos de horas de trabajo, por favor, considera hacer una donación.</string>
<stringname="startup_donate_now">Mostrar página de donación</string>
<stringname="startup_google_play_accounts_removed">Información de error de DRM de Play Store</string>
<stringname="startup_google_play_accounts_removed_message">Bajo ciertas condiciones, el DRM de Play Store puede causar que todas las cuentas de DAVdroid se desconfiguren tras un reinicio o una actualización de DAVdroid. Si esto le afecta (y sólo en ese caso), por favor, instale \"DAVdroid JB Workaround\" desde Play Store.</string>
<stringname="startup_opentasks_not_installed">OpenTasks no está instalado</string>
<stringname="startup_opentasks_not_installed_message">Para sincronizar tareas, la aplicación libre OpenTasks es requerida. (No necesaria para contactos/eventos.)</string>
<stringname="startup_opentasks_reinstall_davdroid">Tras instalar OpenTasks, tendrás que re-instalar DAVdroid y añadir tus cuentas de nuevo (por un error de Android).</string>
<stringname="about_license_info_no_warranty">Este programa viene sin NINGÚN TIPO DE GARANTÍA. Es software libre, y cualquier contribución es bienvenida y redistribuida bajo ciertas condiciones.</string>
<!--global settings-->
<stringname="logging_davdroid_file_logging">Archivo de registro de DAVdroid</string>
<stringname="logging_to_external_storage">Registrar en almacenamiento externo: %s</string>
<stringname="logging_couldnt_create_file">No se puede crear el archivo de registro externo: %s</string>
<stringname="logging_no_external_storage">Almacenamiento externo no encontrado</string>
<!--AccountsActivity-->
<stringname="navigation_drawer_open">Abrir panel de navegación</string>
<stringname="navigation_drawer_close">Cerrar panel de navegación</string>
<stringname="navigation_drawer_subtitle">Adaptador de sincronización CalDAV/CardDAV</string>
<stringname="navigation_drawer_about">Acerca de / Licencia</string>
<stringname="app_settings_distrust_system_certs">Invalidar los certificados del sistema</string>
<stringname="app_settings_distrust_system_certs_on">Los CA del sistema y los añadidos por el usuario no serán válidos</string>
<stringname="app_settings_distrust_system_certs_off">Los CA del sistema y los añadidos por el usuario serán usados y de confianza (recomendado)</string>
<stringname="account_rename_new_name">Información local no guardada puede ser desechada. Se requiere resincronizar después de renombrar. Nuevo nombre de cuenta:</string>
<stringname="login_account_name">Nombre de cuenta</string>
<stringname="login_account_name_info">Usa tu dirección de correo como nombre de cuenta puesto que Android usará el nombre de la cuenta como campo de \"organizador\" en los eventos que cree. No puedes tener dos cuentas con el mismo nombre.</string>
<stringname="login_account_contact_group_method">Método de contacto de grupo:</string>
<stringname="login_account_name_required">Nombre de cuenta requerido</string>
<stringname="login_account_not_created">La cuenta no pudo ser creada</string>
<item>Los groups tienen una categoría por contacto</item>
</string-array>
<stringname="settings_contact_group_method_change">Cambie método de grupo</string>
<stringname="settings_contact_group_method_change_reload_contacts">Esto requiere recargar todos los contactos. Cambios locales sin guardar serán descartados.</string>
<stringname="settings_caldav">CalDAV</string>
<stringname="settings_sync_time_range_past">Límite de tiempo de eventos pasados</string>
<stringname="settings_sync_time_range_past_none">Todos los eventos serán sincronizados</string>
<itemquantity="one">Los eventos anteriores a un día serán ignorados</item>
<itemquantity="other">Los eventos anteriores a %d días serán ignorados</item>
</plurals>
<stringname="settings_sync_time_range_past_message">Los eventos anteriores a este número de días serán ignorados (puede ser 0). Deja en blanco el campo para sincronizar todos los eventos.</string>
<stringname="settings_manage_calendar_colors">Colores de calendario</string>
<stringname="settings_manage_calendar_colors_on">Los colores de los calendarios son administrados por DAVdroid</string>
<stringname="settings_manage_calendar_colors_off">Los colores de los calendarios no son establecidos por DAVdroid</string>
<stringname="settings_event_colors">Soporte de colores en eventos</string>
<stringname="settings_event_colors_on">Sincronizar colores de eventos</string>
<stringname="settings_event_colors_off">No sincronizar colores de eventos</string>
<stringname="settings_event_colors_off_confirm">Desactivar colores de eventos podría remover colores de eventos ya sincronizados.</string>
<!--collection management-->
<stringname="create_addressbook">Crear nueva agenda</string>
<stringname="startup_donate_message">Nous sommes heureux que vous utilisez DAVdroid, qui est un logiciel open-source (GPLv3). Parce que développer DAVdroid est un travail difficile et nous a pris de nombreuses heures, s\'il vous plaît envisager de faire un don.</string>
<stringname="startup_donate_now">Faire un don</string>
<stringname="startup_google_play_accounts_removed">Erreur information Play Store DRM</string>
<stringname="startup_google_play_accounts_removed_message">Dans certaines conditions, Play Store DRM peut provoquer la disparition de tous les comptes DAVdroid après un redémarrage ou après la mise à niveau de DAVdroid. Si vous êtes concerné par ce problème (et seulement alors), s\'il vous plaît installer \"DAVdroid JB Solution\" du Play Store.</string>
<stringname="startup_opentasks_not_installed">L\'application OpenTasks n\'est pas installée</string>
<stringname="startup_opentasks_reinstall_davdroid">Après l\'installation OpenTasks, vous devez RE-INSTALLER DAVdroid et ajoutez vos comptes à nouveau (bug Android).</string>
<stringname="about_license_info_no_warranty">Ce programme est fourni sans AUCUNE GARANTIE. C\'est un logiciel libre, et vous êtes en droit de le redistribuer sous certaines conditions.</string>
<!--global settings-->
<stringname="logging_davdroid_file_logging">DAVdroid fichier de journalisation</string>
<stringname="logging_to_external_storage">Se connecter au stockage externe: %s</string>
<stringname="logging_couldnt_create_file">Impossible de créer le fichier journal externe: %s</string>
<stringname="app_settings_distrust_system_certs">Révoquer les certificats du système</string>
<stringname="app_settings_distrust_system_certs_on">Les certificats du système et ceux ajoutés par l\'utilisateur ne seront pas dignes de confiance</string>
<stringname="app_settings_distrust_system_certs_off">Les certificats du système et ceux ajoutés par l\'utilisateur seront dignes de confiance (recommandé)</string>
<stringname="app_settings_reset_certificates">Réinitialiser les certificats de (non)confiance</string>
<stringname="app_settings_reset_certificates_summary">Réinitialiser la confiance de tous les certificats personnalisés</string>
<stringname="app_settings_reset_certificates_success">Tous les certificats personnalisés ont été effacés</string>
<stringname="account_synchronizing_now">Synchronisation en cours</string>
<stringname="account_settings">Paramètres du compte</string>
<stringname="account_rename">Renommer le compte</string>
<stringname="account_rename_new_name">Les données locales non enregistrées pourraient être perdues. Une re-synchronisation est nécessaire après avoir renommé le compte. Nouveau nom du compte : </string>
<stringname="account_delete">Supprimer le compte</string>
<stringname="account_delete_confirmation_title">Voulez-vous vraiment supprimer le compte?</string>
<stringname="account_delete_confirmation_text">Toutes les copies locales des carnets d\'adresses, des calendriers et des listes de tâches seront supprimées.</string>
<stringname="login_create_account">Créer un compte</string>
<stringname="login_account_name">Nom du compte</string>
<stringname="login_account_name_info">Utilisez votre adresse e-mail comme nom de compte car Android utilisera ce nom en tant que champ ORGANISATEUR pour les événements que vous créerez. Vous ne pouvez pas avoir deux comptes avec le même nom.</string>
<stringname="login_account_contact_group_method">Méthode pour les contacts de type groupe :</string>
<stringname="login_account_name_required">Nom du compte requis</string>
<stringname="login_account_not_created">Le compte n\'a pas pu être créé</string>
<stringname="login_configuration_detection">Détection de la configuration</string>
<stringname="login_querying_server">Veuillez patienter, nous interrogeons le serveur ...</string>
<stringname="login_no_caldav_carddav">Aucun accès possible au service CalDAV ou CardDAV.</string>
<stringname="settings_sync_summary_periodically"tools:ignore="PluralsCandidate">Toutes les %d minutes et immédiatement après un changement local</string>
<stringname="settings_sync_interval_calendars">Intervalle de synchronisation des agendas</string>
<stringname="settings_sync_interval_tasks">Intervalle de synchronisation des tâches</string>
<string-arrayname="settings_sync_interval_names">
<item>Manuellement</item>
<item>Tous les quarts d\'heure</item>
<item>Toutes les demi-heures</item>
<item>Toutes les heures</item>
<item>Toutes les deux heures</item>
<item>Toutes les quatre heures</item>
<item>Une fois par jour</item>
</string-array>
<stringname="settings_sync_wifi_only">Synchronisation en Wifi seulement</string>
<stringname="settings_sync_wifi_only_on">La synchronisation est limitée aux connexions WiFi</string>
<stringname="settings_sync_wifi_only_off">Le type de connexion n\'est pas pris en charge</string>
<stringname="settings_sync_wifi_only_ssids_on">Synchronisation possible seulement en %s</string>
<stringname="settings_sync_wifi_only_ssids_off">Toutes les connexions WiFi seront utilisées</string>
<stringname="settings_sync_wifi_only_ssids_message">Liste des points d\'accès WiFi (SSID) autorisés, séparés par des virgules. (Laissez vide pour tous)</string>
<stringname="settings_carddav">CardDAV</string>
<stringname="settings_contact_group_method">Méthode pour les contacts de type groupe</string>
<itemquantity="one">Les événements de plus d’un jour passé seront ignorés</item>
<itemquantity="other">Les événements de plus de %d jours passés seront ignorés</item>
</plurals>
<stringname="settings_sync_time_range_past_message">Les événements antérieurs à ce nombre de jours seront ignorés (peut être 0). Laissez vide pour synchroniser tous les événements.</string>
<stringname="settings_manage_calendar_colors">Choisir couleur du calendrier</string>
<stringname="settings_manage_calendar_colors_on">Les couleurs de calendrier sont gérées par DAVdroid</string>
<stringname="settings_manage_calendar_colors_off">Les couleurs de calendrier ne sont pas gérées par DAVdroid</string>
<stringname="settings_event_colors">Couleur associée aux événements</string>
<stringname="settings_event_colors_on">Synchroniser la couleur associée aux événements</string>
<stringname="settings_event_colors_off">Ne pas synchroniser la couleur associée aux événements</string>
<stringname="settings_event_colors_off_confirm">Modifier la couleur associée aux événements peut affecter les valeurs déjà synchronisées.</string>
<!--collection management-->
<stringname="create_addressbook">Créer un carnet d\'adresses</string>
<stringname="certificate_notification_connection_security">DAVdroid : Sécurité de la connexion</string>
<stringname="trust_certificate_unknown_certificate_found">DAVdroid a rencontré un certificat inconnu. Voulez-vous lui faire confiance?</string>
</resources>
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.