Repo created
This commit is contained in:
parent
61d62cabdf
commit
ad3df69bdb
872 changed files with 65976 additions and 2 deletions
145
app/build.gradle
Normal file
145
app/build.gradle
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
compileSdk 35
|
||||
namespace 'it.niedermann.nextcloud.deck'
|
||||
|
||||
defaultConfig {
|
||||
applicationId "it.niedermann.nextcloud.deck"
|
||||
minSdk 24
|
||||
targetSdk 35
|
||||
versionCode 1024005
|
||||
versionName "1.24.5"
|
||||
vectorDrawables.useSupportLibrary true
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
javaCompileOptions {
|
||||
annotationProcessorOptions {
|
||||
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
|
||||
}
|
||||
}
|
||||
}
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
buildConfig true
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
coreLibraryDesugaringEnabled true
|
||||
sourceCompatibility JavaVersion.VERSION_17
|
||||
targetCompatibility JavaVersion.VERSION_17
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '17'
|
||||
}
|
||||
flavorDimensions = ["version"]
|
||||
productFlavors {
|
||||
fdroid {
|
||||
dimension "version"
|
||||
}
|
||||
dev {
|
||||
dimension "version"
|
||||
applicationIdSuffix ".dev"
|
||||
}
|
||||
play {
|
||||
dimension "version"
|
||||
applicationIdSuffix ".play"
|
||||
}
|
||||
pfungstadt {
|
||||
dimension "version"
|
||||
applicationIdSuffix ".pfungstadt"
|
||||
}
|
||||
mdm {
|
||||
dimension "version"
|
||||
applicationIdSuffix ".mdm"
|
||||
}
|
||||
}
|
||||
testOptions {
|
||||
unitTests {
|
||||
includeAndroidResources true
|
||||
}
|
||||
}
|
||||
lint {
|
||||
abortOnError false
|
||||
disable 'MissingTranslation'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
def cameraVersion = "1.4.1"
|
||||
def lifecycleVersion = "2.8.7"
|
||||
def roomVersion = "2.6.1"
|
||||
def glideVersion = "4.16.0"
|
||||
def nextcloudCommonsVersion = "2.3.5"
|
||||
def androidCommonsVersion = "1.0.4"
|
||||
|
||||
implementation project(path: ':cross-tab-drag-and-drop')
|
||||
implementation project(path: ':tab-layout-helper')
|
||||
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.4'
|
||||
|
||||
// Android X
|
||||
implementation 'androidx.appcompat:appcompat:1.7.0'
|
||||
implementation "androidx.camera:camera-camera2:$cameraVersion"
|
||||
implementation "androidx.camera:camera-lifecycle:$cameraVersion"
|
||||
implementation "androidx.camera:camera-view:$cameraVersion"
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
|
||||
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion"
|
||||
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVersion"
|
||||
implementation 'androidx.preference:preference-ktx:1.2.1'
|
||||
implementation "androidx.room:room-runtime:$roomVersion"
|
||||
annotationProcessor "androidx.room:room-compiler:$roomVersion"
|
||||
implementation 'androidx.core:core-splashscreen:1.0.1'
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||
implementation 'androidx.work:work-runtime:2.10.0'
|
||||
implementation "com.google.android.material:material:$rootProject.materialVersion"
|
||||
|
||||
// Glide
|
||||
implementation "com.github.bumptech.glide:glide:$glideVersion"
|
||||
annotationProcessor "com.github.bumptech.glide:compiler:$glideVersion"
|
||||
|
||||
// Image compression
|
||||
implementation 'id.zelory:compressor:3.0.1'
|
||||
|
||||
// Single-Sign-On
|
||||
implementation 'com.github.nextcloud:Android-SingleSignOn:1.3.2'
|
||||
implementation 'com.github.nextcloud:android-common:0.24.0'
|
||||
implementation "com.github.stefan-niedermann.nextcloud-commons:sso-glide:$nextcloudCommonsVersion"
|
||||
implementation "com.github.stefan-niedermann.nextcloud-commons:exception:$nextcloudCommonsVersion"
|
||||
implementation("com.github.stefan-niedermann.nextcloud-commons:markdown:$nextcloudCommonsVersion") {
|
||||
exclude group: 'org.jetbrains', module: 'annotations-java5'
|
||||
}
|
||||
implementation "com.github.stefan-niedermann.android-commons:util:$androidCommonsVersion"
|
||||
implementation "com.github.stefan-niedermann.android-commons:shared-preferences:$androidCommonsVersion"
|
||||
implementation "com.github.stefan-niedermann.android-commons:reactive-livedata:$androidCommonsVersion"
|
||||
|
||||
// Custom Date / Time Picker for branding support
|
||||
implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
|
||||
|
||||
// Flexbox
|
||||
implementation 'com.google.android.flexbox:flexbox:3.0.0'
|
||||
|
||||
// Custom Color Picker
|
||||
implementation 'com.github.skydoves:colorpickerview:2.3.0'
|
||||
|
||||
// Gson
|
||||
implementation 'com.google.code.gson:gson:2.11.0'
|
||||
|
||||
// Retrofit
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.11.0'
|
||||
|
||||
// Zoom Layout
|
||||
implementation("com.otaliastudios:zoomlayout:1.9.0")
|
||||
|
||||
// Tests
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation 'org.robolectric:robolectric:4.14.1'
|
||||
testImplementation 'org.mockito:mockito-core:5.15.2'
|
||||
testImplementation 'androidx.test:core:1.6.1'
|
||||
testImplementation 'androidx.arch.core:core-testing:2.2.0'
|
||||
}
|
||||
41
app/src/dev/res/drawable/ic_launcher_foreground.xml
Normal file
41
app/src/dev/res/drawable/ic_launcher_foreground.xml
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="38.268356"
|
||||
android:viewportHeight="38.268356">
|
||||
<group android:translateX="-2.4874432"
|
||||
android:translateY="-2.4874432">
|
||||
<group
|
||||
android:translateX="13.621622"
|
||||
android:translateY="13.621622">
|
||||
<path
|
||||
android:pathData="M2,7L14,7A1,1 0,0 1,15 8L15,14A1,1 0,0 1,14 15L2,15A1,1 0,0 1,1 14L1,8A1,1 0,0 1,2 7z"
|
||||
android:fillColor="#fff" />
|
||||
<path
|
||||
android:pathData="M2.5,5L13.5,5A0.5,0.5 0,0 1,14 5.5L14,5.5A0.5,0.5 0,0 1,13.5 6L2.5,6A0.5,0.5 0,0 1,2 5.5L2,5.5A0.5,0.5 0,0 1,2.5 5z"
|
||||
android:fillColor="#fff" />
|
||||
<path
|
||||
android:pathData="M3.5,3L12.5,3A0.5,0.5 0,0 1,13 3.5L13,3.5A0.5,0.5 0,0 1,12.5 4L3.5,4A0.5,0.5 0,0 1,3 3.5L3,3.5A0.5,0.5 0,0 1,3.5 3z"
|
||||
android:fillColor="#fff" />
|
||||
<path
|
||||
android:pathData="M4.5,1L11.5,1A0.5,0.5 0,0 1,12 1.5L12,1.5A0.5,0.5 0,0 1,11.5 2L4.5,2A0.5,0.5 0,0 1,4 1.5L4,1.5A0.5,0.5 0,0 1,4.5 1z"
|
||||
android:fillColor="#fff" />
|
||||
</group>
|
||||
</group>
|
||||
<group
|
||||
android:translateX="14.3"
|
||||
android:translateY="26.2"
|
||||
android:scaleX=".1"
|
||||
android:scaleY=".1">
|
||||
<path
|
||||
android:pathData="M11.908125 40h11.4c4.44 0 7.24 -1.04 9.2 -3.4 2.32 -2.72 3.56 -6.68 3.56 -11.2 0 -4.48 -1.24 -8.44 -3.56 -11.2 -1.96 -2.36 -4.72 -3.36 -9.2 -3.36h-11.4zm6 -5V15.84h5.4c4.52 0 6.76 3.16 6.76 9.6 0 6.4 -2.24 9.56 -6.76 9.56z"
|
||||
android:fillColor="#fff"/>
|
||||
<path
|
||||
android:pathData="M46.894375 27.44h13.96v-5h-13.96v-6.6h15.08v-5h-21.08V40h21.8v-5h-15.8z"
|
||||
android:fillColor="#fff"/>
|
||||
<path
|
||||
android:pathData="M80.333125 40l10 -29.16h-6.04l-6.36 21.96 -6.48 -21.96h-6.04l9.84 29.16z"
|
||||
android:fillColor="#fff"/>
|
||||
</group>
|
||||
</vector>
|
||||
15
app/src/dev/res/xml/shortcuts.xml
Normal file
15
app/src/dev/res/xml/shortcuts.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<shortcut
|
||||
android:enabled="true"
|
||||
android:icon="@drawable/ic_add_24dp"
|
||||
android:shortcutId="it.niedermann.nextcloud.deck"
|
||||
android:shortcutLongLabel="@string/add_card"
|
||||
android:shortcutShortLabel="@string/simple_add">
|
||||
<intent
|
||||
android:action="android.intent.action.VIEW"
|
||||
android:targetClass="it.niedermann.nextcloud.deck.ui.preparecreate.PrepareCreateActivity"
|
||||
android:targetPackage="it.niedermann.nextcloud.deck.dev" />
|
||||
<categories android:name="android.shortcut.conversation" />
|
||||
</shortcut>
|
||||
</shortcuts>
|
||||
264
app/src/main/AndroidManifest.xml
Normal file
264
app/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
|
||||
<uses-feature android:name="android.hardware.camera.any" android:required="false" />
|
||||
|
||||
<uses-sdk tools:overrideLibrary="androidx.camera.core, androidx.camera.camera2, androidx.camera.lifecycle, androidx.camera.view" />
|
||||
|
||||
<queries>
|
||||
<package android:name="com.nextcloud.client" />
|
||||
<package android:name="com.nextcloud.android.qa" />
|
||||
<package android:name="com.nextcloud.android.beta" />
|
||||
</queries>
|
||||
|
||||
<application
|
||||
android:name="it.niedermann.nextcloud.deck.DeckApplication"
|
||||
android:allowBackup="false"
|
||||
android:fullBackupContent="false"
|
||||
android:hardwareAccelerated="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
tools:ignore="GoogleAppIndexingWarning"
|
||||
tools:targetApi="tiramisu">
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/provider_paths" />
|
||||
</provider>
|
||||
|
||||
<activity
|
||||
android:name=".ui.main.MainActivity"
|
||||
android:label="@string/app_name_short"
|
||||
android:theme="@style/SplashTheme"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/shortcuts" />
|
||||
<meta-data
|
||||
android:name="android.app.searchable"
|
||||
android:resource="@xml/searchable" />
|
||||
<meta-data
|
||||
android:name="android.app.default_searchable"
|
||||
android:value=".ui.MainActivity" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".ui.manageaccounts.ManageAccountsActivity"
|
||||
android:label="@string/manage_accounts"
|
||||
android:parentActivityName=".ui.main.MainActivity"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.takephoto.TakePhotoActivity"
|
||||
android:theme="@style/TakePhotoTheme"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.sharetarget.ShareTargetActivity"
|
||||
android:label="@string/share_add_to_card"
|
||||
android:theme="@style/SplashTheme"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="*/*" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="*/*" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".ui.archivedboards.ArchivedBoardsActivity"
|
||||
android:label="@string/archived_boards"
|
||||
android:parentActivityName="it.niedermann.nextcloud.deck.ui.main.MainActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.upcomingcards.UpcomingCardsActivity"
|
||||
android:label="@string/widget_upcoming_title"
|
||||
android:parentActivityName="it.niedermann.nextcloud.deck.ui.main.MainActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.card.EditActivity"
|
||||
android:label="@string/edit"
|
||||
android:parentActivityName="it.niedermann.nextcloud.deck.ui.main.MainActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.attachments.AttachmentsActivity"
|
||||
android:label="@string/attachments"
|
||||
android:parentActivityName="it.niedermann.nextcloud.deck.ui.card.EditActivity"
|
||||
android:theme="@style/TransparentTheme" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.settings.SettingsActivity"
|
||||
android:label="@string/simple_settings"
|
||||
android:parentActivityName="it.niedermann.nextcloud.deck.ui.main.MainActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.ImportAccountActivity"
|
||||
android:label="@string/app_name" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.preparecreate.PrepareCreateActivity"
|
||||
android:description="@string/add_a_new_card_using_the_button"
|
||||
android:label="@string/add_card"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="text/*" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".ui.about.AboutActivity"
|
||||
android:label="@string/about"
|
||||
android:parentActivityName="it.niedermann.nextcloud.deck.ui.main.MainActivity" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.PushNotificationActivity"
|
||||
android:label="@string/app_name"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".ui.exception.ExceptionActivity"
|
||||
android:process=":error_activity" />
|
||||
|
||||
<!-- <receiver-->
|
||||
<!-- android:name="it.niedermann.nextcloud.deck.ui.widget.filter.FilterWidget"-->
|
||||
<!-- android:label="@string/widget_filter_title">-->
|
||||
|
||||
<!-- <intent-filter>-->
|
||||
<!-- <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />-->
|
||||
<!-- </intent-filter>-->
|
||||
|
||||
<!-- <meta-data-->
|
||||
<!-- android:name="android.appwidget.provider"-->
|
||||
<!-- android:resource="@xml/filter_widget_provider" />-->
|
||||
<!-- </receiver>-->
|
||||
|
||||
<service
|
||||
android:name=".ui.widget.upcoming.UpcomingWidgetService"
|
||||
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||
|
||||
<receiver
|
||||
android:name="it.niedermann.nextcloud.deck.ui.widget.upcoming.UpcomingWidget"
|
||||
android:label="@string/widget_upcoming_title"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/upcoming_widget_provider" />
|
||||
</receiver>
|
||||
|
||||
<activity android:name=".ui.widget.stack.StackWidgetConfigurationActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<receiver
|
||||
android:name="it.niedermann.nextcloud.deck.ui.widget.stack.StackWidget"
|
||||
android:label="@string/widget_stack_title"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/stack_widget_provider" />
|
||||
</receiver>
|
||||
|
||||
<service
|
||||
android:name=".ui.tiles.EditCardTileService"
|
||||
android:description="@string/add_a_new_card_using_the_button"
|
||||
android:icon="@drawable/ic_app_logo"
|
||||
android:label="@string/add_card"
|
||||
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.service.quicksettings.action.QS_TILE" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name=".ui.widget.stack.StackWidgetService"
|
||||
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.widget.singlecard.SelectCardForWidgetActivity"
|
||||
android:label="@string/share_add_to_card"
|
||||
android:theme="@style/SplashTheme"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service
|
||||
android:name=".ui.widget.singlecard.SingleCardWidgetService"
|
||||
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||
|
||||
<receiver
|
||||
android:name=".ui.widget.singlecard.SingleCardWidget"
|
||||
android:label="@string/single_card"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/widget_single_card_info" />
|
||||
</receiver>
|
||||
|
||||
<!-- Trigger Google Play services to install the backported photo picker module. -->
|
||||
<!-- https://developer.android.com/training/data-storage/shared/photopicker#device-availability -->
|
||||
<!--suppress AndroidDomInspection -->
|
||||
<service android:name="com.google.android.gms.metadata.ModuleDependencies"
|
||||
android:enabled="false" android:exported="false" tools:ignore="MissingClass">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.gms.metadata.MODULE_DEPENDENCIES" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="photopicker_activity:0:required" android:value="" />
|
||||
</service>
|
||||
|
||||
</application>
|
||||
</manifest>
|
||||
BIN
app/src/main/ic_launcher-web.png
Normal file
BIN
app/src/main/ic_launcher-web.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
|
|
@ -0,0 +1,52 @@
|
|||
package it.niedermann.nextcloud.deck;
|
||||
|
||||
import android.app.Application;
|
||||
import android.os.StrictMode;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import it.niedermann.nextcloud.deck.repository.PreferencesRepository;
|
||||
import it.niedermann.nextcloud.deck.util.CustomAppGlideModule;
|
||||
|
||||
public class DeckApplication extends Application {
|
||||
|
||||
private final ExecutorService executor = new ThreadPoolExecutor(0, 2, 0L, TimeUnit.SECONDS, new SynchronousQueue<>());
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
final var repo = new PreferencesRepository(this);
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
enableStrictModeLogging();
|
||||
}
|
||||
|
||||
repo.getAppThemeSetting().thenAcceptAsync(repo::setAppTheme, executor);
|
||||
repo.isDebugModeEnabled().thenAcceptAsync(DeckLog::enablePersistentLogs, executor);
|
||||
|
||||
super.onCreate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
DeckLog.error("--- Low memory: Clear Glide cache ---");
|
||||
CustomAppGlideModule.clearCache(this);
|
||||
DeckLog.error("--- Low memory: Clear debug log ---");
|
||||
DeckLog.clearDebugLog();
|
||||
}
|
||||
|
||||
private void enableStrictModeLogging() {
|
||||
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
|
||||
.detectAll()
|
||||
.permitDiskReads()
|
||||
.penaltyLog()
|
||||
.build());
|
||||
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
|
||||
.detectAll()
|
||||
.penaltyLog()
|
||||
.build());
|
||||
}
|
||||
}
|
||||
148
app/src/main/java/it/niedermann/nextcloud/deck/DeckLog.java
Normal file
148
app/src/main/java/it/niedermann/nextcloud/deck/DeckLog.java
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
package it.niedermann.nextcloud.deck;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
import it.niedermann.nextcloud.deck.util.MimeTypeUtil;
|
||||
|
||||
public class DeckLog {
|
||||
|
||||
private DeckLog() {
|
||||
throw new UnsupportedOperationException("This class must not get instantiated");
|
||||
}
|
||||
|
||||
private static final StringBuffer DEBUG_LOG = new StringBuffer();
|
||||
private static boolean PERSIST_LOGS = false;
|
||||
private static final String TAG = DeckLog.class.getSimpleName();
|
||||
private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
public static void enablePersistentLogs(boolean persistLogs) {
|
||||
PERSIST_LOGS = persistLogs;
|
||||
if (!persistLogs) {
|
||||
clearDebugLog();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getStacktraceAsString(Throwable e) {
|
||||
final var sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
public enum Severity {
|
||||
VERBOSE, DEBUG, LOG, INFO, WARN, ERROR, WTF
|
||||
}
|
||||
|
||||
public static void verbose(Object... message) {
|
||||
log(Severity.VERBOSE, 4, message);
|
||||
}
|
||||
|
||||
public static void log(Object... message) {
|
||||
log(Severity.DEBUG, 4, message);
|
||||
}
|
||||
|
||||
public static void info(Object... message) {
|
||||
log(Severity.INFO, 4, message);
|
||||
}
|
||||
|
||||
public static void warn(Object... message) {
|
||||
log(Severity.WARN, 4, message);
|
||||
}
|
||||
|
||||
public static void error(Object... message) {
|
||||
log(Severity.ERROR, 4, message);
|
||||
}
|
||||
|
||||
public static void wtf(Object... message) {
|
||||
log(Severity.WTF, 4, message);
|
||||
}
|
||||
|
||||
public static void log(@NonNull Severity severity, Object... message) {
|
||||
log(severity, 3, message);
|
||||
}
|
||||
|
||||
private static void log(@NonNull Severity severity, int stackTracePosition, Object... messages) {
|
||||
if (!(PERSIST_LOGS || BuildConfig.DEBUG)) {
|
||||
return;
|
||||
}
|
||||
final StackTraceElement caller = Thread.currentThread().getStackTrace()[stackTracePosition];
|
||||
final String print = "(" + caller.getFileName() + ":" + caller.getLineNumber() + ") " + caller.getMethodName() + "() → " + TextUtils.join(" ", messages);
|
||||
if (PERSIST_LOGS) {
|
||||
DEBUG_LOG
|
||||
.append(dtf.format(Instant.now().atZone(ZoneId.systemDefault())))
|
||||
.append(" ")
|
||||
.append(severity.name())
|
||||
.append(" ")
|
||||
.append(print)
|
||||
.append("\n");
|
||||
}
|
||||
switch (severity) {
|
||||
case DEBUG -> Log.d(TAG, print);
|
||||
case INFO -> Log.i(TAG, print);
|
||||
case WARN -> Log.w(TAG, print);
|
||||
case ERROR -> Log.e(TAG, print);
|
||||
case WTF -> Log.wtf(TAG, print);
|
||||
default -> Log.v(TAG, print);
|
||||
}
|
||||
}
|
||||
|
||||
public static void logError(@Nullable Throwable e) {
|
||||
if (!(PERSIST_LOGS || BuildConfig.DEBUG)) {
|
||||
return;
|
||||
}
|
||||
if (e == null) {
|
||||
error("Could not log error because given error was null");
|
||||
return;
|
||||
}
|
||||
final StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
final String stacktrace = sw.toString();
|
||||
final StackTraceElement caller = Thread.currentThread().getStackTrace()[3];
|
||||
final String print = "(" + caller.getFileName() + ":" + caller.getLineNumber() + ") " + caller.getMethodName() + "() → " + stacktrace;
|
||||
if (PERSIST_LOGS) {
|
||||
DEBUG_LOG.append(print).append("\n");
|
||||
}
|
||||
Log.e(TAG, print);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static String getDebugLog() {
|
||||
return DEBUG_LOG.toString();
|
||||
}
|
||||
|
||||
public static void clearDebugLog() {
|
||||
DEBUG_LOG.setLength(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the current log to a temporary file and starts a share intent.
|
||||
*/
|
||||
public static void shareLogAsFile(@NonNull Context context) throws IOException {
|
||||
Toast.makeText(context, R.string.copying_logs_to_file, Toast.LENGTH_LONG).show();
|
||||
final File logFile = new File(context.getCacheDir().getAbsolutePath() + "/log.txt");
|
||||
final FileWriter writer = new FileWriter(logFile);
|
||||
writer.write(DeckLog.getDebugLog());
|
||||
writer.close();
|
||||
context.startActivity(new Intent(Intent.ACTION_SEND)
|
||||
.putExtra(Intent.EXTRA_TITLE, context.getString(R.string.log_file))
|
||||
.putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", logFile))
|
||||
.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
.setType(MimeTypeUtil.TEXT_PLAIN));
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,262 @@
|
|||
package it.niedermann.nextcloud.deck.database;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.Database;
|
||||
import androidx.room.Room;
|
||||
import androidx.room.RoomDatabase;
|
||||
import androidx.room.TypeConverters;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
import it.niedermann.nextcloud.deck.DeckLog;
|
||||
import it.niedermann.nextcloud.deck.database.converter.DateTypeConverter;
|
||||
import it.niedermann.nextcloud.deck.database.converter.EnumConverter;
|
||||
import it.niedermann.nextcloud.deck.database.dao.AccessControlDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.AccountDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.ActivityDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.AttachmentDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.BoardDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.CardDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.CommentDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.JoinBoardWithLabelDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.JoinBoardWithPermissionDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.JoinBoardWithUserDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.JoinCardWithLabelDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.JoinCardWithUserDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.LabelDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.MentionDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.PermissionDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.StackDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.UserDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.UserInBoardDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.UserInGroupDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.projects.JoinCardWithOcsProjectDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.projects.OcsProjectDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.projects.OcsProjectResourceDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.widgets.SingleCardWidgetModelDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.widgets.filter.FilterWidgetAccountDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.widgets.filter.FilterWidgetBoardDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.widgets.filter.FilterWidgetDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.widgets.filter.FilterWidgetLabelDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.widgets.filter.FilterWidgetProjectDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.widgets.filter.FilterWidgetSortDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.widgets.filter.FilterWidgetStackDao;
|
||||
import it.niedermann.nextcloud.deck.database.dao.widgets.filter.FilterWidgetUserDao;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_10_11;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_11_12;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_12_13;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_13_14;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_14_15;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_15_16;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_16_17;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_17_18;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_18_19;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_19_20;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_20_21;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_21_22;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_22_23;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_23_24;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_24_25;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_25_26;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_26_27;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_27_28;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_28_29;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_29_30;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_30_31;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_31_32;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_32_33;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_33_34;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_8_9;
|
||||
import it.niedermann.nextcloud.deck.database.migration.Migration_9_10;
|
||||
import it.niedermann.nextcloud.deck.model.AccessControl;
|
||||
import it.niedermann.nextcloud.deck.model.Account;
|
||||
import it.niedermann.nextcloud.deck.model.Attachment;
|
||||
import it.niedermann.nextcloud.deck.model.Board;
|
||||
import it.niedermann.nextcloud.deck.model.Card;
|
||||
import it.niedermann.nextcloud.deck.model.JoinBoardWithLabel;
|
||||
import it.niedermann.nextcloud.deck.model.JoinBoardWithPermission;
|
||||
import it.niedermann.nextcloud.deck.model.JoinBoardWithUser;
|
||||
import it.niedermann.nextcloud.deck.model.JoinCardWithLabel;
|
||||
import it.niedermann.nextcloud.deck.model.JoinCardWithUser;
|
||||
import it.niedermann.nextcloud.deck.model.Label;
|
||||
import it.niedermann.nextcloud.deck.model.Permission;
|
||||
import it.niedermann.nextcloud.deck.model.Stack;
|
||||
import it.niedermann.nextcloud.deck.model.User;
|
||||
import it.niedermann.nextcloud.deck.model.ocs.Activity;
|
||||
import it.niedermann.nextcloud.deck.model.ocs.comment.DeckComment;
|
||||
import it.niedermann.nextcloud.deck.model.ocs.comment.Mention;
|
||||
import it.niedermann.nextcloud.deck.model.ocs.projects.JoinCardWithProject;
|
||||
import it.niedermann.nextcloud.deck.model.ocs.projects.OcsProject;
|
||||
import it.niedermann.nextcloud.deck.model.ocs.projects.OcsProjectResource;
|
||||
import it.niedermann.nextcloud.deck.model.relations.UserInBoard;
|
||||
import it.niedermann.nextcloud.deck.model.relations.UserInGroup;
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidget;
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetAccount;
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetBoard;
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetLabel;
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetProject;
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetSort;
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetStack;
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetUser;
|
||||
import it.niedermann.nextcloud.deck.model.widget.singlecard.SingleCardWidgetModel;
|
||||
import it.niedermann.nextcloud.deck.remote.api.LastSyncUtil;
|
||||
|
||||
@Database(
|
||||
entities = {
|
||||
Account.class,
|
||||
Attachment.class,
|
||||
AccessControl.class,
|
||||
Board.class,
|
||||
Card.class,
|
||||
JoinBoardWithLabel.class,
|
||||
JoinBoardWithPermission.class,
|
||||
JoinBoardWithUser.class,
|
||||
JoinCardWithLabel.class,
|
||||
JoinCardWithUser.class,
|
||||
Label.class,
|
||||
Permission.class,
|
||||
Stack.class,
|
||||
User.class,
|
||||
Activity.class,
|
||||
DeckComment.class,
|
||||
Mention.class,
|
||||
SingleCardWidgetModel.class,
|
||||
OcsProject.class,
|
||||
OcsProjectResource.class,
|
||||
JoinCardWithProject.class,
|
||||
UserInGroup.class,
|
||||
UserInBoard.class,
|
||||
FilterWidget.class,
|
||||
FilterWidgetAccount.class,
|
||||
FilterWidgetBoard.class,
|
||||
FilterWidgetStack.class,
|
||||
FilterWidgetLabel.class,
|
||||
FilterWidgetUser.class,
|
||||
FilterWidgetProject.class,
|
||||
FilterWidgetSort.class,
|
||||
},
|
||||
exportSchema = false,
|
||||
version = 34
|
||||
)
|
||||
@TypeConverters({DateTypeConverter.class, EnumConverter.class})
|
||||
public abstract class DeckDatabase extends RoomDatabase {
|
||||
|
||||
private static final String DECK_DB_NAME = "NC_DECK_DB.db";
|
||||
private static volatile DeckDatabase instance;
|
||||
|
||||
public static final RoomDatabase.Callback ON_CREATE_CALLBACK = new RoomDatabase.Callback() {
|
||||
@Override
|
||||
public void onCreate(@NonNull SupportSQLiteDatabase db) {
|
||||
super.onCreate(db);
|
||||
DeckLog.info("Database", DECK_DB_NAME, "created.");
|
||||
LastSyncUtil.resetAll();
|
||||
}
|
||||
};
|
||||
|
||||
public static synchronized DeckDatabase getInstance(Context context) {
|
||||
if (instance == null) {
|
||||
instance = create(context);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static DeckDatabase create(final Context context) {
|
||||
return Room.databaseBuilder(
|
||||
context,
|
||||
DeckDatabase.class,
|
||||
DECK_DB_NAME)
|
||||
.addMigrations(new Migration_8_9())
|
||||
.addMigrations(new Migration_9_10())
|
||||
.addMigrations(new Migration_10_11())
|
||||
.addMigrations(new Migration_11_12())
|
||||
.addMigrations(new Migration_12_13())
|
||||
.addMigrations(new Migration_13_14())
|
||||
.addMigrations(new Migration_14_15(context))
|
||||
.addMigrations(new Migration_15_16())
|
||||
.addMigrations(new Migration_16_17())
|
||||
.addMigrations(new Migration_17_18())
|
||||
.addMigrations(new Migration_18_19())
|
||||
.addMigrations(new Migration_19_20())
|
||||
.addMigrations(new Migration_20_21())
|
||||
.addMigrations(new Migration_21_22(context))
|
||||
.addMigrations(new Migration_22_23())
|
||||
.addMigrations(new Migration_23_24(context))
|
||||
.addMigrations(new Migration_24_25())
|
||||
.addMigrations(new Migration_25_26())
|
||||
.addMigrations(new Migration_26_27())
|
||||
.addMigrations(new Migration_27_28())
|
||||
.addMigrations(new Migration_28_29())
|
||||
.addMigrations(new Migration_29_30(context))
|
||||
.addMigrations(new Migration_30_31())
|
||||
.addMigrations(new Migration_31_32(context))
|
||||
.addMigrations(new Migration_32_33())
|
||||
.addMigrations(new Migration_33_34())
|
||||
.fallbackToDestructiveMigration()
|
||||
.addCallback(ON_CREATE_CALLBACK)
|
||||
.build();
|
||||
}
|
||||
|
||||
public abstract AccountDao getAccountDao();
|
||||
|
||||
public abstract AccessControlDao getAccessControlDao();
|
||||
|
||||
public abstract BoardDao getBoardDao();
|
||||
|
||||
public abstract CardDao getCardDao();
|
||||
|
||||
public abstract JoinBoardWithLabelDao getJoinBoardWithLabelDao();
|
||||
|
||||
public abstract JoinBoardWithPermissionDao getJoinBoardWithPermissionDao();
|
||||
|
||||
public abstract JoinBoardWithUserDao getJoinBoardWithUserDao();
|
||||
|
||||
public abstract JoinCardWithLabelDao getJoinCardWithLabelDao();
|
||||
|
||||
public abstract JoinCardWithUserDao getJoinCardWithUserDao();
|
||||
|
||||
public abstract LabelDao getLabelDao();
|
||||
|
||||
public abstract ActivityDao getActivityDao();
|
||||
|
||||
public abstract PermissionDao getPermissionDao();
|
||||
|
||||
public abstract StackDao getStackDao();
|
||||
|
||||
public abstract UserDao getUserDao();
|
||||
|
||||
public abstract AttachmentDao getAttachmentDao();
|
||||
|
||||
public abstract CommentDao getCommentDao();
|
||||
|
||||
public abstract MentionDao getMentionDao();
|
||||
|
||||
public abstract SingleCardWidgetModelDao getSingleCardWidgetModelDao();
|
||||
|
||||
public abstract OcsProjectDao getOcsProjectDao();
|
||||
|
||||
public abstract OcsProjectResourceDao getOcsProjectResourceDao();
|
||||
|
||||
public abstract JoinCardWithOcsProjectDao getJoinCardWithOcsProjectDao();
|
||||
|
||||
public abstract UserInGroupDao getUserInGroupDao();
|
||||
|
||||
public abstract UserInBoardDao getUserInBoardDao();
|
||||
|
||||
public abstract FilterWidgetDao getFilterWidgetDao();
|
||||
|
||||
public abstract FilterWidgetAccountDao getFilterWidgetAccountDao();
|
||||
|
||||
public abstract FilterWidgetBoardDao getFilterWidgetBoardDao();
|
||||
|
||||
public abstract FilterWidgetStackDao getFilterWidgetStackDao();
|
||||
|
||||
public abstract FilterWidgetLabelDao getFilterWidgetLabelDao();
|
||||
|
||||
public abstract FilterWidgetUserDao getFilterWidgetUserDao();
|
||||
|
||||
public abstract FilterWidgetProjectDao getFilterWidgetProjectDao();
|
||||
|
||||
public abstract FilterWidgetSortDao getFilterWidgetSortDao();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package it.niedermann.nextcloud.deck.database.converter;
|
||||
|
||||
import androidx.room.TypeConverter;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public class DateTypeConverter {
|
||||
|
||||
@TypeConverter
|
||||
public static Instant toInstant(Long value) {
|
||||
return value == null ? null : Instant.ofEpochMilli(value);
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
public static Long fromInstant(Instant value) {
|
||||
return value == null ? null : value.toEpochMilli();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package it.niedermann.nextcloud.deck.database.converter;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.room.TypeConverter;
|
||||
|
||||
import it.niedermann.nextcloud.deck.DeckLog;
|
||||
import it.niedermann.nextcloud.deck.model.enums.EAttachmentType;
|
||||
import it.niedermann.nextcloud.deck.model.enums.EDueType;
|
||||
import it.niedermann.nextcloud.deck.model.enums.ESortCriteria;
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.EWidgetType;
|
||||
|
||||
public class EnumConverter {
|
||||
// #### EWidgetType
|
||||
@TypeConverter
|
||||
public static EWidgetType toWidgetTypeEnum(Integer value) {
|
||||
try {
|
||||
return value == null ? null : EWidgetType.findById(value);
|
||||
} catch (IllegalArgumentException e) {
|
||||
DeckLog.error(EWidgetType.class.getSimpleName(), value, "not found. Falling back to generic", EWidgetType.FILTER_WIDGET);
|
||||
return EWidgetType.FILTER_WIDGET;
|
||||
}
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
public static Integer fromWidgetTypeEnum(EWidgetType value) {
|
||||
return value == null ? null : value.getId();
|
||||
}
|
||||
|
||||
// #### EDueType
|
||||
@TypeConverter
|
||||
@Nullable
|
||||
public static EDueType toDueTypeEnum(@Nullable Integer value) {
|
||||
return value == null ? null : EDueType.findById(value);
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
@Nullable
|
||||
public static Integer fromDueTypeEnum(@Nullable EDueType value) {
|
||||
return value == null ? null : value.getId();
|
||||
}
|
||||
|
||||
// #### ESortCriteria
|
||||
@TypeConverter
|
||||
@Nullable
|
||||
public static ESortCriteria toSortCriteriaEnum(@Nullable Integer value) {
|
||||
return value == null ? null : ESortCriteria.findById(value);
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
@Nullable
|
||||
public static Integer fromSortCriteriaEnum(@Nullable ESortCriteria value) {
|
||||
return value == null ? null : value.getId();
|
||||
}
|
||||
|
||||
// #### EAttachmentType
|
||||
@TypeConverter
|
||||
@Nullable
|
||||
public static EAttachmentType toEAttachmentType(@Nullable String value) {
|
||||
return value == null ? null : EAttachmentType.findByValue(value);
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
@Nullable
|
||||
public static String fromEAttachmentType(@Nullable EAttachmentType value) {
|
||||
return value == null ? null : value.getValue();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.AccessControl;
|
||||
|
||||
@Dao
|
||||
public interface AccessControlDao extends GenericDao<AccessControl> {
|
||||
|
||||
@Query("SELECT * FROM AccessControl WHERE accountId = :accountId and id = :remoteId")
|
||||
LiveData<AccessControl> getAccessControlByRemoteId(final long accountId, final long remoteId);
|
||||
|
||||
@Query("SELECT * FROM AccessControl WHERE accountId = :accountId and boardId = :localBoardId and status <> 3")
|
||||
LiveData<List<AccessControl>> getAccessControlByLocalBoardId(final long accountId, final long localBoardId);
|
||||
|
||||
@Query("SELECT * FROM AccessControl WHERE accountId = :accountId and boardId = :localBoardId and status <> 3")
|
||||
List<AccessControl> getAccessControlByLocalBoardIdDirectly(final long accountId, final long localBoardId);
|
||||
|
||||
@Query("SELECT * FROM AccessControl WHERE accountId = :accountId and id = :remoteId")
|
||||
AccessControl getAccessControlByRemoteIdDirectly(final long accountId, final long remoteId);
|
||||
|
||||
@Query("SELECT * FROM AccessControl WHERE accountId = :accountId and boardId = :boardId and (status<>1 or id is null or lastModified <> lastModifiedLocal)")
|
||||
List<AccessControl> getLocallyChangedAccessControl(long accountId, long boardId);
|
||||
|
||||
@Query("SELECT distinct boardId FROM AccessControl WHERE accountId = :accountId and (status<>1 or id is null or lastModified <> lastModifiedLocal)")
|
||||
List<Long> getBoardIDsOfLocallyChangedAccessControl(long accountId);
|
||||
|
||||
@Query("DELETE FROM AccessControl WHERE boardId = :localBoardId and localId not in (:idsToKeep)")
|
||||
void deleteAccessControlsForBoardWhereLocalIdsNotInDirectly(long localBoardId, Set<Long> idsToKeep);
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.Account;
|
||||
|
||||
@Dao
|
||||
public interface AccountDao extends GenericDao<Account> {
|
||||
@Query("SELECT count(*) FROM account")
|
||||
int countAccountsDirectly();
|
||||
|
||||
@Query("SELECT count(*) FROM account")
|
||||
LiveData<Integer> countAccounts();
|
||||
|
||||
@Query("DELETE from account where id = :id")
|
||||
void deleteById(long id);
|
||||
|
||||
@Query("SELECT * from account where id = :id")
|
||||
Account getAccountByIdDirectly(long id);
|
||||
|
||||
@Query("SELECT * from account where id = :id")
|
||||
LiveData<Account> getAccountById(long id);
|
||||
|
||||
@Query("SELECT * from account where name = :name")
|
||||
LiveData<Account> getAccountByName(String name);
|
||||
|
||||
@Query("SELECT * from account where name = :name")
|
||||
Account getAccountByNameDirectly(String name);
|
||||
|
||||
@Query("SELECT * from account")
|
||||
LiveData<List<Account>> getAllAccounts();
|
||||
|
||||
@Query("SELECT * from account")
|
||||
List<Account> getAllAccountsDirectly();
|
||||
|
||||
@Query("SELECT * from account a where a.url like :hostLike and exists (select 1 from board b where b.id = :boardRemoteId and a.id = b.accountId)")
|
||||
LiveData<List<Account>> readAccountsForHostWithReadAccessToBoard(String hostLike, long boardRemoteId);
|
||||
|
||||
@Query("SELECT * from account a where a.url like :hostLike and exists (select 1 from board b where b.id = :boardRemoteId and a.id = b.accountId)")
|
||||
List<Account> readAccountsForHostWithReadAccessToBoardDirectly(String hostLike, long boardRemoteId);
|
||||
|
||||
@Query("SELECT a.color FROM account a where a.id = :accountId")
|
||||
LiveData<Integer> getAccountColor(long accountId);
|
||||
|
||||
@Query("SELECT a.color FROM account a where a.id = :accountId")
|
||||
Integer getAccountColorDirectly(long accountId);
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.ocs.Activity;
|
||||
|
||||
@Dao
|
||||
public interface ActivityDao extends GenericDao<Activity> {
|
||||
|
||||
@Query("SELECT * FROM activity WHERE cardId = :localCardId order by lastModified desc")
|
||||
LiveData<List<Activity>> getActivitiesForCard(final long localCardId);
|
||||
|
||||
@Query("SELECT * FROM activity WHERE accountId = :accountId and id = :remoteActivityId")
|
||||
Activity getActivityByRemoteIdDirectly(long accountId, long remoteActivityId);
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.Attachment;
|
||||
|
||||
@Dao
|
||||
public interface AttachmentDao extends GenericDao<Attachment> {
|
||||
@Query("SELECT * FROM attachment where cardId = :cardId")
|
||||
LiveData<List<Attachment>> getAttachmentsForCard(long cardId);
|
||||
|
||||
@Query("SELECT * FROM attachment where accountId = :accountId and id = :remoteId")
|
||||
Attachment getAttachmentByRemoteIdDirectly(long accountId, Long remoteId);
|
||||
|
||||
@Query("SELECT * FROM attachment where accountId = :accountId and localId = :id")
|
||||
Attachment getAttachmentByLocalIdDirectly(long accountId, Long id);
|
||||
|
||||
@Query("SELECT * FROM attachment WHERE accountId = :accountId and cardId = :localCardId and (status<>1 or id is null or lastModified <> lastModifiedLocal)")
|
||||
List<Attachment> getLocallyChangedAttachmentsByLocalCardIdDirectly(long accountId, long localCardId);
|
||||
|
||||
@Query("SELECT * FROM attachment WHERE accountId = :accountId and (status<>1 or id is null or lastModified <> lastModifiedLocal)")
|
||||
List<Attachment> getLocallyChangedAttachmentsDirectly(long accountId);
|
||||
|
||||
@Query("SELECT a.* FROM attachment a inner join card c on c.localId = a.cardId " +
|
||||
"WHERE c.stackId = :localStackId and (a.status<>1 or a.id is null or a.lastModified <> a.lastModifiedLocal)")
|
||||
List<Attachment> getLocallyChangedAttachmentsForStackDirectly(long localStackId);
|
||||
|
||||
@Query("SELECT * FROM attachment WHERE accountId = :accountId and cardId = :localCardId")
|
||||
List<Attachment> getAttachmentsForLocalCardIdDirectly(long accountId, Long localCardId);
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
import androidx.room.Transaction;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.Board;
|
||||
import it.niedermann.nextcloud.deck.model.full.FullBoard;
|
||||
|
||||
@Dao
|
||||
public interface BoardDao extends GenericDao<Board> {
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM board WHERE accountId = :accountId and archived = :archived and (deletedAt = 0 or deletedAt is null) and status <> 3 order by title asc")
|
||||
LiveData<List<Board>> getNotDeletedBoards(long accountId, int archived);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM board WHERE accountId = :accountId and archived = :archived and (deletedAt = 0 or deletedAt is null) and status <> 3 order by title asc")
|
||||
List<Board> getNotDeletedBoardsDirectly(long accountId, int archived);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM board WHERE accountId = :accountId and archived = :archived and (deletedAt = 0 or deletedAt is null) and status <> 3 order by title asc")
|
||||
LiveData<List<FullBoard>> getNotDeletedFullBoards(long accountId, int archived);
|
||||
|
||||
@Query("SELECT * FROM board WHERE accountId = :accountId and id = :remoteId")
|
||||
LiveData<Board> getBoardByRemoteId(final long accountId, final long remoteId);
|
||||
|
||||
@Query("SELECT * FROM board WHERE accountId = :accountId and id = :remoteId")
|
||||
Board getBoardByRemoteIdDirectly(long accountId, long remoteId);
|
||||
|
||||
@Query("SELECT * FROM board WHERE localId = :localId")
|
||||
Board getBoardByLocalIdDirectly(long localId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM board WHERE accountId = :accountId and id = :remoteId")
|
||||
FullBoard getFullBoardByRemoteIdDirectly(long accountId, long remoteId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM board WHERE accountId = :accountId and localId = :localId")
|
||||
FullBoard getFullBoardByLocalIdDirectly(long accountId, long localId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM board WHERE accountId = :accountId and (status<>1 or id is null or lastModified <> lastModifiedLocal)")
|
||||
List<FullBoard> getLocallyChangedBoardsDirectly(long accountId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM board WHERE accountId = :accountId and localId = :localId")
|
||||
LiveData<FullBoard> getFullBoardById(final long accountId, final long localId);
|
||||
|
||||
@Query("SELECT b.* FROM board b JOIN stack s ON s.boardId = b.localId JOIN card c ON s.localId = c.stackId where c.localId = :localCardId")
|
||||
Board getBoardByLocalCardIdDirectly(long localCardId);
|
||||
|
||||
@Query("SELECT b.localId FROM board b JOIN stack s ON s.boardId = b.localId JOIN card c ON s.localId = c.stackId where c.localId = :localCardId")
|
||||
Long getBoardLocalIdByLocalCardIdDirectly(long localCardId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT b.* FROM board b JOIN stack s ON s.boardId = b.localId JOIN card c ON c.localId = :localCardId and c.stackId = s.localId")
|
||||
FullBoard getFullBoardByLocalCardIdDirectly(long localCardId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM board WHERE accountId = :accountId")
|
||||
List<FullBoard> getAllFullBoards(long accountId);
|
||||
|
||||
@Query("SELECT * FROM board WHERE accountId = :accountId and archived = 0 and permissionEdit = 1 and (deletedAt = 0 or deletedAt is null) and status <> 3 order by title asc")
|
||||
LiveData<List<Board>> getBoardsWithEditPermissionsForAccount(long accountId);
|
||||
|
||||
@Query("SELECT s.boardId " +
|
||||
"FROM card c " +
|
||||
"inner join stack s on s.localId = c.stackId " +
|
||||
"WHERE c.id = :cardRemoteId and c.accountId = :accountId")
|
||||
LiveData<Long> getLocalBoardIdByCardRemoteIdAndAccountId(long cardRemoteId, long accountId);
|
||||
|
||||
@Query("SELECT s.boardId " +
|
||||
"FROM card c " +
|
||||
"inner join stack s on s.localId = c.stackId " +
|
||||
"WHERE c.id = :cardRemoteId and c.accountId = :accountId")
|
||||
Long getBoardLocalIdByAccountAndCardRemoteIdDirectly(long accountId, long cardRemoteId);
|
||||
|
||||
@Query("SELECT count(*) FROM board WHERE accountId = :accountId and archived = 1 and (deletedAt = 0 or deletedAt is null) and status <> 3")
|
||||
LiveData<Integer> countArchivedBoards(long accountId);
|
||||
|
||||
@Query("SELECT * FROM board WHERE accountId = :accountId and title = :title")
|
||||
Board getBoardForAccountByNameDirectly(long accountId, String title);
|
||||
|
||||
@Query("SELECT b.color FROM board b where b.localId = :localBoardId and b.accountId = :accountId")
|
||||
Integer getBoardColorByLocalIdDirectly(long accountId, long localBoardId);
|
||||
|
||||
@Query("SELECT b.color FROM board b where b.localId = :localBoardId and b.accountId = :accountId")
|
||||
LiveData<Integer> getBoardColor(long accountId, long localBoardId);
|
||||
}
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
import androidx.room.RawQuery;
|
||||
import androidx.room.Transaction;
|
||||
import androidx.sqlite.db.SupportSQLiteQuery;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.Card;
|
||||
import it.niedermann.nextcloud.deck.model.full.FullCard;
|
||||
import it.niedermann.nextcloud.deck.model.full.FullCardWithProjects;
|
||||
|
||||
@Dao
|
||||
public interface CardDao extends GenericDao<Card> {
|
||||
|
||||
String QUERY_UPCOMING_CARDS = "SELECT c.* FROM card c " +
|
||||
"join stack s on s.localId = c.stackId " +
|
||||
"join board b on b.localId = s.boardId " +
|
||||
"WHERE b.archived = 0 and c.archived = 0 and b.status <> 3 and s.status <> 3 and c.status <> 3 " +
|
||||
"and (c.deletedAt is null or c.deletedAt = 0) " +
|
||||
"and (s.deletedAt is null or s.deletedAt = 0) " +
|
||||
"and (b.deletedAt is null or b.deletedAt = 0) " +
|
||||
"and (c.done is null or c.done = 0) " +
|
||||
// Full Logic: (hasDueDate AND isIn_PRIVATE_Board) OR (isInSharedBoard AND (assignedToMe OR (hasDueDate AND noAssignees)))
|
||||
"and (" +
|
||||
"(c.dueDate is not null AND NOT exists(select 1 from AccessControl ac where ac.boardId = b.localId and ac.status <> 3))" + //(hasDueDate AND isInPrivateBoard)
|
||||
"OR (" +
|
||||
"exists(select 1 from AccessControl ac where ac.boardId = b.localId and ac.status <> 3) " + //OR (isInSharedBoard AND
|
||||
"AND (" +
|
||||
"(c.dueDate is not null AND not exists(select 1 from JoinCardWithUser j where j.cardId = c.localId)) " + // hasDueDate AND noAssignees OR
|
||||
"OR exists(select 1 from JoinCardWithUser j where j.cardId = c.localId and j.userId in (select u.localId from user u where u.uid in (select a.userName from Account a)))" + //(assignedToMe
|
||||
")" +
|
||||
")" +
|
||||
")" +
|
||||
"ORDER BY c.dueDate asc";
|
||||
|
||||
@Query("SELECT * FROM card WHERE stackId = :localStackId order by `order`, createdAt asc")
|
||||
LiveData<List<Card>> getCardsForStack(final long localStackId);
|
||||
|
||||
@Query("SELECT * FROM card WHERE accountId = :accountId and id = :remoteId")
|
||||
LiveData<Card> getCardByRemoteId(final long accountId, final long remoteId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM card WHERE accountId = :accountId and id = :remoteId")
|
||||
FullCard getFullCardByRemoteIdDirectly(final long accountId, final long remoteId);
|
||||
|
||||
@Query("SELECT * FROM card WHERE accountId = :accountId and localId = :localId")
|
||||
Card getCardByLocalIdDirectly(final long accountId, final long localId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM card WHERE accountId = :accountId and localId = :localId")
|
||||
FullCard getFullCardByLocalIdDirectly(final long accountId, final long localId);
|
||||
|
||||
@Transaction
|
||||
// v not deleted!
|
||||
@Query("SELECT * FROM card WHERE accountId = :accountId AND archived = 0 AND stackId = :localStackId and status<>3 order by `order`, createdAt asc")
|
||||
LiveData<List<FullCard>> getFullCardsForStack(final long accountId, final long localStackId);
|
||||
|
||||
@Transaction
|
||||
@RawQuery(observedEntities = Card.class)
|
||||
LiveData<List<FullCard>> getFilteredFullCardsForStack(SupportSQLiteQuery query);
|
||||
|
||||
@Transaction
|
||||
@RawQuery(observedEntities = Card.class)
|
||||
List<FullCard> getFilteredFullCardsForStackDirectly(SupportSQLiteQuery query);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM card WHERE accountId = :accountId AND stackId = :localStackId order by `order`, createdAt asc")
|
||||
List<FullCard> getFullCardsForStackDirectly(final long accountId, final long localStackId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM card WHERE accountId = :accountId and localId = :localCardId")
|
||||
LiveData<FullCard> getFullCardByLocalId(final long accountId, final long localCardId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM card WHERE accountId = :accountId and localId = :localCardId")
|
||||
LiveData<FullCardWithProjects> getFullCardWithProjectsByLocalId(final long accountId, final long localCardId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM card WHERE accountId = :accountId and id = :remoteId")
|
||||
LiveData<FullCard> getFullCardByRemoteId(final long accountId, final long remoteId);
|
||||
|
||||
@Query("SELECT * FROM card WHERE accountId = :accountId and id = :remoteId")
|
||||
Card getCardByRemoteIdDirectly(long accountId, long remoteId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM card WHERE accountId = :accountId and (status<>1 or id is null or lastModified <> lastModifiedLocal)")
|
||||
List<FullCard> getLocallyChangedCardsDirectly(long accountId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM card WHERE accountId = :accountId and stackId = :localStackId and (status<>1 or id is null or lastModified <> lastModifiedLocal)")
|
||||
List<FullCard> getLocallyChangedCardsByLocalStackIdDirectly(long accountId, long localStackId);
|
||||
|
||||
@Query("SELECT * FROM card c WHERE accountId = :accountId and exists ( select 1 from DeckComment dc where dc.objectId = c.localId and dc.status<>1)")
|
||||
List<Card> getCardsWithLocallyChangedCommentsDirectly(Long accountId);
|
||||
|
||||
@Query("SELECT * FROM card c WHERE stackId = :localStackId and exists ( select 1 from DeckComment dc where dc.objectId = c.localId and dc.status<>1)")
|
||||
List<Card> getCardsWithLocallyChangedCommentsForStackDirectly(Long localStackId);
|
||||
|
||||
@Query("SELECT count(*) FROM card c WHERE accountId = :accountId and stackId = :localStackId and status <> 3")
|
||||
int countCardsInStackDirectly(long accountId, long localStackId);
|
||||
|
||||
@Query("SELECT coalesce(MAX(`order`), -1) FROM card c WHERE stackId = :localStackId and status <> 3")
|
||||
Integer getHighestOrderInStack(Long localStackId);
|
||||
|
||||
@Query("SELECT c.stackId FROM card c WHERE localId = :localCardId")
|
||||
Long getLocalStackIdByLocalCardId(Long localCardId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM card c WHERE " +
|
||||
"exists(select 1 from Stack s join Board b on s.boardId = b.localId where s.localId = c.stackId " +
|
||||
"and b.archived = 0 " +
|
||||
"and not exists(select 1 from AccessControl ac where ac.boardId = b.localId and status <> 3)) " +
|
||||
"and dueDate is not null " +
|
||||
"and (coalesce(:accountIds, null) is null or accountId in (:accountIds)) " +
|
||||
"and status <> 3 " +
|
||||
"and archived = 0")
|
||||
List<FullCard> getFullCardsForNonSharedBoardsWithDueDateForUpcomingCardsWidgetDirectly(List<Long> accountIds);
|
||||
|
||||
@Transaction
|
||||
@Query(QUERY_UPCOMING_CARDS)
|
||||
LiveData<List<FullCard>> getUpcomingCards();
|
||||
|
||||
@Transaction
|
||||
@Query(QUERY_UPCOMING_CARDS)
|
||||
List<FullCard> getUpcomingCardsDirectly();
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT c.* FROM card c " +
|
||||
"inner join Stack s on c.stackId = s.localId " +
|
||||
"WHERE s.boardId = :localBoardId " +
|
||||
"and (c.title like :term or c.description like :term) " +
|
||||
"and c.accountId = :accountId " +
|
||||
"and s.accountId = :accountId " +
|
||||
"and c.status <> 3 " +
|
||||
"and s.status <> 3 " +
|
||||
"and c.archived = 0 " +
|
||||
"order by s.`order`, c.`order`")
|
||||
LiveData<List<FullCard>> searchCard(long accountId, long localBoardId, String term);
|
||||
@Query("SELECT s.localId FROM card s")
|
||||
List<Long> getAllIDs();
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
import androidx.room.Transaction;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.ocs.comment.DeckComment;
|
||||
import it.niedermann.nextcloud.deck.model.ocs.comment.full.FullDeckComment;
|
||||
|
||||
@Dao
|
||||
public interface CommentDao extends GenericDao<DeckComment> {
|
||||
|
||||
@Query("SELECT * FROM DeckComment where accountId = :accountId and id = :remoteId")
|
||||
DeckComment getCommentByRemoteIdDirectly(long accountId, Long remoteId);
|
||||
|
||||
@Query("SELECT * FROM DeckComment where accountId = :accountId and localId = :id")
|
||||
DeckComment getCommentByLocalIdDirectly(long accountId, Long id);
|
||||
|
||||
@Query("SELECT * FROM DeckComment WHERE accountId = :accountId and objectId = :localCardId " +
|
||||
"and (status<>1 or id is null or lastModified <> lastModifiedLocal) order by localId asc")
|
||||
List<DeckComment> getLocallyChangedCommentsByLocalCardIdDirectly(long accountId, long localCardId);
|
||||
|
||||
@Query("SELECT * FROM DeckComment WHERE accountId = :accountId and (status<>1 or id is null or lastModified <> lastModifiedLocal)")
|
||||
List<DeckComment> getLocallyChangedCommentsDirectly(long accountId);
|
||||
|
||||
@Query("SELECT * FROM DeckComment WHERE accountId = :accountId and objectId = :localCardId")
|
||||
List<DeckComment> getCommentsForLocalCardIdDirectly(long accountId, Long localCardId);
|
||||
|
||||
@Query("SELECT * FROM DeckComment where objectId = :localCardId")
|
||||
List<DeckComment> getCommentByLocalCardIdDirectly(Long localCardId);
|
||||
|
||||
@Query("SELECT * FROM DeckComment where objectId = :localCardId order by creationDateTime desc")
|
||||
LiveData<List<DeckComment>> getCommentByLocalCardId(Long localCardId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM DeckComment where objectId = :localCardId order by creationDateTime desc, localId desc")
|
||||
LiveData<List<FullDeckComment>> getFullCommentByLocalCardId(Long localCardId);
|
||||
|
||||
@Query("SELECT id FROM DeckComment where localId = :localId")
|
||||
Long getRemoteCommentIdForLocalIdDirectly(Long localId);
|
||||
|
||||
@Query("SELECT localId FROM DeckComment where id = :remoteId and accountId = :accountId")
|
||||
Long getLocalCommentIdForRemoteIdDirectly(long accountId, Long remoteId);
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.room.Delete;
|
||||
import androidx.room.Insert;
|
||||
import androidx.room.Update;
|
||||
|
||||
public interface GenericDao<T> {
|
||||
|
||||
@Insert
|
||||
long insert(T entity);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Insert
|
||||
long[] insert(T... entity);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Update
|
||||
void update(T... entity);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Delete
|
||||
void delete(T... entity);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.JoinBoardWithLabel;
|
||||
|
||||
@Dao
|
||||
public interface JoinBoardWithLabelDao extends GenericDao<JoinBoardWithLabel> {
|
||||
@Query("DELETE FROM joinboardwithlabel WHERE boardId = :localId")
|
||||
void deleteByBoardId(long localId);
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.JoinBoardWithPermission;
|
||||
|
||||
@Dao
|
||||
public interface JoinBoardWithPermissionDao extends GenericDao<JoinBoardWithPermission> {
|
||||
@Query("DELETE FROM joinboardwithpermission WHERE boardId = :localId")
|
||||
void deleteByBoardId(long localId);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.JoinBoardWithUser;
|
||||
|
||||
@Dao
|
||||
public interface JoinBoardWithUserDao extends GenericDao<JoinBoardWithUser> {
|
||||
@Query("DELETE FROM joinboardwithuser WHERE boardId = :localId")
|
||||
void deleteByBoardId(long localId);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.JoinCardWithLabel;
|
||||
|
||||
@Dao
|
||||
public interface JoinCardWithLabelDao extends GenericDao<JoinCardWithLabel> {
|
||||
@Query("DELETE FROM joincardwithlabel WHERE cardId = :localCardId and status == 1") // only if UP_TO_DATE
|
||||
void deleteByCardId(long localCardId);
|
||||
|
||||
@Query("DELETE FROM joincardwithlabel WHERE cardId = :localCardId and labelId = :labelId")
|
||||
void deleteByCardIdAndLabelId(long localCardId, long labelId);
|
||||
|
||||
@Query("Update joincardwithlabel set status = :status WHERE cardId = :localCardId and labelId = :localLabelId")
|
||||
void setDbStatus(long localCardId, long localLabelId, int status);
|
||||
|
||||
@Query("select labelId from joincardwithlabel WHERE cardId = :localCardId and labelId IN (:localLabelIds) and status <> 3") // not LOCAL_DELETED
|
||||
List<Long> filterDeleted(long localCardId, List<Long> localLabelIds);
|
||||
|
||||
@Query("select * from joincardwithlabel WHERE cardId = :localCardId and labelId = :localLabelId")
|
||||
JoinCardWithLabel getJoin(Long localLabelId, Long localCardId);
|
||||
|
||||
@Query("select l.id as labelId, c.id as cardId, j.status from joincardwithlabel j " +
|
||||
"inner join card c on j.cardId = c.localId " +
|
||||
"inner join label l on j.labelId = l.localId " +
|
||||
"WHERE j.status <> 1") // not UP_TO_DATE
|
||||
List<JoinCardWithLabel> getAllDeletedJoinsWithRemoteIDs();
|
||||
|
||||
@Query("select l.id as labelId, c.id as cardId, j.status from joincardwithlabel j " +
|
||||
"inner join card c on j.cardId = c.localId " +
|
||||
"inner join label l on j.labelId = l.localId " +
|
||||
"WHERE j.cardId = :localCardId and j.labelId = :localLabelId") // not UP_TO_DATE
|
||||
JoinCardWithLabel getRemoteIdsForJoin(long localCardId, long localLabelId);
|
||||
|
||||
@Query("select * from joincardwithlabel WHERE status <> 1") // not UP_TO_DATE
|
||||
List<JoinCardWithLabel> getAllChangedJoins();
|
||||
|
||||
@Query("select j.* from joincardwithlabel j inner join card c on j.cardId = c.localId WHERE c.stackId = :localStackId and j.status <> 1") // not UP_TO_DATE
|
||||
List<JoinCardWithLabel> getAllChangedJoinsForStack(Long localStackId);
|
||||
|
||||
@Query("delete from joincardwithlabel " +
|
||||
"where cardId = (select c.localId from card c where c.accountId = :accountId and c.id = :remoteCardId) " +
|
||||
"and labelId = (select l.localId from label l where l.accountId = :accountId and l.id = :remoteLabelId)")
|
||||
void deleteJoinedLabelForCardPhysicallyByRemoteIDs(Long accountId, Long remoteCardId, Long remoteLabelId);
|
||||
|
||||
@Query("select count(*) from joincardwithlabel WHERE labelId = :localLabelId and status <> 3") // not locally deleted
|
||||
int countCardsWithLabelDirectly(long localLabelId);
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.JoinCardWithUser;
|
||||
|
||||
@Dao
|
||||
public interface JoinCardWithUserDao extends GenericDao<JoinCardWithUser> {
|
||||
@Query("DELETE FROM joincardwithuser WHERE cardId = :localId and status=1") // 1 = UP_TO_DATE
|
||||
void deleteByCardId(long localId);
|
||||
|
||||
@Query("Update joincardwithuser set status = :status WHERE cardId = :localCardId and userId = :localUserId")
|
||||
void setDbStatus(long localCardId, long localUserId, int status);
|
||||
|
||||
@Query("DELETE FROM joincardwithuser WHERE cardId = :localCardId and userId = :localUserId")
|
||||
void deleteByCardIdAndUserIdPhysically(long localCardId, long localUserId);
|
||||
|
||||
@Query("DELETE FROM joincardwithuser " +
|
||||
"WHERE cardid in (select c.localId from Card c join Stack s on c.stackId = s.localId and s.boardId = :localBoardId) " +
|
||||
"and userId not in (select userId from UserInBoard where boardId = :localBoardId)")
|
||||
void deleteJoinedUsersForCardsInBoardWithoutPermissionPhysically(long localBoardId);
|
||||
|
||||
@Query("select * FROM joincardwithuser WHERE cardId = :localCardId and userId = :localUserId")
|
||||
JoinCardWithUser getJoin(Long localUserId, Long localCardId);
|
||||
|
||||
@Query("select u.localId as userId, c.id as cardId, j.status from joincardwithuser j " +
|
||||
"inner join card c on j.cardId = c.localId " +
|
||||
"inner join user u on j.userId = u.localId " +
|
||||
"WHERE j.status <> 1") // not UP_TO_DATE
|
||||
List<JoinCardWithUser> getChangedJoinsWithRemoteIDs();
|
||||
|
||||
@Query("select u.localId as userId, c.id as cardId, j.status from joincardwithuser j " +
|
||||
"inner join card c on j.cardId = c.localId " +
|
||||
"inner join user u on j.userId = u.localId " +
|
||||
"WHERE c.stackId = :localStackId " +
|
||||
"AND j.status <> 1") // not UP_TO_DATE
|
||||
List<JoinCardWithUser> getChangedJoinsWithRemoteIDsForStack(Long localStackId);
|
||||
|
||||
@Query("delete from joincardwithuser " +
|
||||
"where cardId = (select c.localId from card c where c.accountId = :accountId and c.id = :remoteCardId) " +
|
||||
"and userId = (select u.localId from user u where u.accountId = :accountId and u.uid = :userUid)")
|
||||
void deleteJoinedUserForCardPhysicallyByRemoteIDs(Long accountId, Long remoteCardId, String userUid);
|
||||
|
||||
@Query("select userId from joincardwithuser WHERE cardId = :localCardId and userId IN (:assignedUserIDs) and status <> 3") // not LOCAL_DELETED
|
||||
List<Long> filterDeleted(long localCardId, List<Long> assignedUserIDs);
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.Label;
|
||||
|
||||
@Dao
|
||||
public interface LabelDao extends GenericDao<Label> {
|
||||
|
||||
// @Query("SELECT * FROM label WHERE stackId = :localStackId")
|
||||
// LiveData<List<Label>> getLabelsForStack(final long localStackId);
|
||||
|
||||
@Query("SELECT * FROM label WHERE accountId = :accountId and id = :remoteId")
|
||||
LiveData<Label> getLabelByRemoteId(final long accountId, final long remoteId);
|
||||
|
||||
@Query("SELECT * FROM label WHERE localId = :localId")
|
||||
LiveData<Label> getLabelByLocalId(final long localId);
|
||||
|
||||
@Query("SELECT * FROM label WHERE accountId = :accountId and id = :remoteId")
|
||||
Label getLabelByRemoteIdDirectly(final long accountId, final long remoteId);
|
||||
|
||||
@Query("SELECT * FROM label WHERE localId IN (:labelIDs) and status <> 3 order by title asc") // not LOCAL_DELETED
|
||||
List<Label> getLabelsByIdsDirectly(List<Long> labelIDs);
|
||||
|
||||
@Query("SELECT * FROM label WHERE localId = :localLabelID")
|
||||
Label getLabelsByIdDirectly(final long localLabelID);
|
||||
|
||||
@Query("SELECT l.* FROM label l WHERE accountId = :accountId" +
|
||||
" AND NOT EXISTS (" +
|
||||
"select 1 from joincardwithlabel jl where jl.labelId = l.localId " +
|
||||
"and jl.cardId = :notYetAssignedToLocalCardId AND status <> 3" + // not LOCAL_DELETED
|
||||
") " +
|
||||
" AND boardId = :boardId and title LIKE :searchTerm")
|
||||
LiveData<List<Label>> searchNotYetAssignedLabelsByTitle(final long accountId, final long boardId, final long notYetAssignedToLocalCardId, String searchTerm);
|
||||
|
||||
@Query("SELECT * FROM label WHERE accountId = :accountId and (status<>1 or id is null or lastModified <> lastModifiedLocal)")
|
||||
List<Label> getLocallyChangedLabelsDirectly(long accountId);
|
||||
|
||||
@Query("SELECT l.* " +
|
||||
"FROM label l LEFT JOIN joincardwithlabel j ON j.labelId = l.localId " +
|
||||
"WHERE l.accountId = :accountId AND l.boardId = :boardId " +
|
||||
"AND NOT EXISTS (" +
|
||||
"select 1 from joincardwithlabel jl where jl.labelId = l.localId " +
|
||||
"and jl.cardId = :notAssignedToLocalCardId AND status <> 3" + // not LOCAL_DELETED
|
||||
") " +
|
||||
"GROUP BY l.localId ORDER BY count(*) DESC")
|
||||
LiveData<List<Label>> findProposalsForLabelsToAssign(long accountId, long boardId, long notAssignedToLocalCardId);
|
||||
|
||||
|
||||
|
||||
@Query("select * from label WHERE boardId = :boardId and title = :title")
|
||||
Label getLabelByBoardIdAndTitleDirectly(long boardId, String title);
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.ocs.comment.Mention;
|
||||
|
||||
@Dao
|
||||
public interface MentionDao extends GenericDao<Mention> {
|
||||
|
||||
@Query("delete from mention WHERE commentId = :commentID")
|
||||
void clearMentionsForCommentId(long commentID);
|
||||
|
||||
@Query("select * from mention WHERE commentId = :commentID")
|
||||
List<Mention> getMentionsForCommentIdDirectly(long commentID);
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.room.Dao;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.Permission;
|
||||
|
||||
@Dao
|
||||
public interface PermissionDao extends GenericDao<Permission> {
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
import androidx.room.Transaction;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.Stack;
|
||||
import it.niedermann.nextcloud.deck.model.full.FullStack;
|
||||
|
||||
@Dao
|
||||
public interface StackDao extends GenericDao<Stack> {
|
||||
|
||||
@Query("SELECT * FROM stack WHERE accountId = :accountId AND boardId = :localBoardId and status<>3 and (deletedAt is null or deletedAt = 0) order by `order` asc")
|
||||
LiveData<List<Stack>> getStacksForBoard(final long accountId, final long localBoardId);
|
||||
|
||||
@Query("SELECT * FROM stack WHERE accountId = :accountId and boardId = :localBoardId and id = :remoteId")
|
||||
LiveData<Stack> getStackByRemoteId(final long accountId, final long localBoardId, final long remoteId);
|
||||
|
||||
@Query("SELECT * FROM stack WHERE localId = :localStackId")
|
||||
Stack getStackByLocalIdDirectly(final long localStackId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM stack WHERE localId = :localStackId")
|
||||
FullStack getFullStackByLocalIdDirectly(final long localStackId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM stack WHERE accountId = :accountId and boardId = :localBoardId and id = :remoteId")
|
||||
FullStack getFullStackByRemoteIdDirectly(final long accountId, final long localBoardId, final long remoteId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM stack WHERE accountId = :accountId and boardId = :localBoardId and id = :remoteId")
|
||||
LiveData<FullStack> getFullStackByRemoteId(final long accountId, final long localBoardId, final long remoteId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM stack WHERE accountId = :accountId and localId = :localId")
|
||||
LiveData<FullStack> getFullStack(long accountId, long localId);
|
||||
|
||||
@Query("SELECT localId FROM stack WHERE accountId = :accountId")
|
||||
List<Long> getLocalStackIdsByAccountIdDirectly(long accountId);
|
||||
|
||||
@Query("SELECT localId FROM stack WHERE boardId = :localBoardId")
|
||||
List<Long> getLocalStackIdsByLocalBoardIdDirectly(long localBoardId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM stack WHERE accountId = :accountId and boardId = :localBoardId and (status<>1 or id is null or lastModified <> lastModifiedLocal)")
|
||||
List<FullStack> getLocallyChangedStacksForBoardDirectly(long accountId, long localBoardId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM stack WHERE accountId = :accountId and (status<>1 or id is null or lastModified <> lastModifiedLocal)")
|
||||
List<FullStack> getLocallyChangedStacksDirectly(long accountId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM stack WHERE accountId = :accountId AND boardId = :localBoardId and status<>3 and (deletedAt is null or deletedAt = 0) order by `order` asc")
|
||||
List<FullStack> getFullStacksForBoardDirectly(long accountId, long localBoardId);
|
||||
|
||||
@Query("SELECT localId FROM stack s WHERE accountId = :accountId and id = :stackId")
|
||||
Long getLocalStackIdByRemoteStackIdDirectly(long accountId, Long stackId);
|
||||
|
||||
@Query("SELECT coalesce(MAX(`order`), -1) FROM stack s WHERE boardId = :localBoardId")
|
||||
Integer getHighestStackOrderInBoard(long localBoardId);
|
||||
|
||||
@Query("SELECT exists(select 1 from Stack s join Board b on s.boardId = b.localId where s.localId = :localStackId and exists(select 1 from AccessControl ac where ac.boardId = b.localId and status <> 3))")
|
||||
boolean isStackOnSharedBoardDirectly(Long localStackId);
|
||||
|
||||
@Query("SELECT s.localId FROM stack s join Board b on s.boardId = b.localId where b.archived <> 0 and b.accountId in (:accountIds)")
|
||||
List<Long> getLocalStackIdsInArchivedBoardsByAccountIdsDirectly(List<Long> accountIds);
|
||||
|
||||
@Query("SELECT s.localId FROM stack s")
|
||||
List<Long> getAllIDs();
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.User;
|
||||
|
||||
@Dao
|
||||
public interface UserDao extends GenericDao<User> {
|
||||
|
||||
@Query("SELECT * FROM user WHERE accountId = :accountId")
|
||||
LiveData<List<User>> getUsersForAccount(final long accountId);
|
||||
|
||||
@Query("SELECT * FROM user WHERE accountId = :accountId and localId = :localId")
|
||||
LiveData<User> getUserByLocalId(final long accountId, final long localId);
|
||||
|
||||
@Query("SELECT * FROM user WHERE accountId = :accountId and uid = :uid")
|
||||
LiveData<User> getUserByUid(final long accountId, final String uid);
|
||||
|
||||
@Query("SELECT u.displayname FROM user u WHERE accountId = :accountId and uid = :uid")
|
||||
String getUserNameByUidDirectly(final long accountId, final String uid);
|
||||
|
||||
@Query("SELECT u.* FROM user u WHERE accountId = :accountId " +
|
||||
" AND NOT EXISTS (" +
|
||||
" select 1 from joincardwithuser ju" +
|
||||
" where ju.userId = u.localId" +
|
||||
" and ju.cardId = :notYetAssignedToLocalCardId AND status <> 3" + // not LOCAL_DELETED
|
||||
" )" +
|
||||
" AND ( " +
|
||||
" EXISTS (" +
|
||||
" select 1 from userinboard where boardId = :boardId AND userId = u.localId" +
|
||||
" )" +
|
||||
" OR" +
|
||||
" EXISTS (" +
|
||||
" select 1 from accesscontrol" + // v GROUP!
|
||||
" where (userId = u.localId OR (type = 1 and exists(select 1 from UserInGroup uig where uig.memberId = u.localId and uig.groupId = userId))) " +
|
||||
" and boardId = :boardId and status <> 3" +
|
||||
" )" +
|
||||
" OR" +
|
||||
" EXISTS (" +
|
||||
" select 1 from board where localId = :boardId AND ownerId = u.localId" +
|
||||
" )" +
|
||||
")" +
|
||||
"and ( uid LIKE :searchTerm or displayname LIKE :searchTerm or primaryKey LIKE :searchTerm )")
|
||||
LiveData<List<User>> searchUserByUidOrDisplayName(final long accountId, final long boardId, final long notYetAssignedToLocalCardId, final String searchTerm);
|
||||
|
||||
@Query("SELECT u.* FROM user u WHERE accountId = :accountId " +
|
||||
" AND NOT EXISTS (" +
|
||||
" select 1 from accesscontrol ju" +
|
||||
" where ju.userId = u.localId and ju.boardId = :boardId and status <> 3" + // not LOCAL_DELETED
|
||||
" ) " +
|
||||
"and ( uid LIKE :searchTerm or displayname LIKE :searchTerm or primaryKey LIKE :searchTerm ) " +
|
||||
"and u.localId <> (select b.ownerId from board b where localId = :boardId)" +
|
||||
"ORDER BY u.displayname")
|
||||
LiveData<List<User>> searchUserByUidOrDisplayNameForACL(final long accountId, final long boardId, final String searchTerm);
|
||||
|
||||
@Query("SELECT * FROM user WHERE accountId = :accountId and uid = :uid")
|
||||
User getUserByUidDirectly(final long accountId, final String uid);
|
||||
|
||||
@Query("SELECT * FROM user WHERE localId IN (:assignedUserIDs) and status <> 3") // not LOCAL_DELETED
|
||||
List<User> getUsersByIdDirectly(List<Long> assignedUserIDs);
|
||||
|
||||
@Query("SELECT * FROM user WHERE localId = :localUserId")
|
||||
User getUserByLocalIdDirectly(long localUserId);
|
||||
|
||||
@Query(" SELECT u.* FROM user u" +
|
||||
" WHERE u.accountId = :accountId" +
|
||||
" AND NOT EXISTS (" +
|
||||
" select 1 from joincardwithuser ju" +
|
||||
" where ju.userId = u.localId" +
|
||||
" and ju.cardId = :notAssignedToLocalCardId AND status <> 3" + // not LOCAL_DELETED
|
||||
" )" +
|
||||
" AND ( " +
|
||||
" EXISTS (" +
|
||||
" select 1 from userinboard where boardId = :boardId AND userId = u.localId" +
|
||||
" )" +
|
||||
" OR" +
|
||||
" EXISTS (" +
|
||||
" select 1 from accesscontrol" + // v GROUP!
|
||||
" where (userId = u.localId OR (type = 1 and exists(select 1 from UserInGroup uig where uig.memberId = u.localId and uig.groupId = userId))) " +
|
||||
" and boardId = :boardId and status <> 3" +
|
||||
" )" +
|
||||
" OR" +
|
||||
" EXISTS (" +
|
||||
" select 1 from board where localId = :boardId AND ownerId = u.localId" +
|
||||
" )" +
|
||||
")" +
|
||||
" ORDER BY (" +
|
||||
" select count(*) from joincardwithuser j" +
|
||||
" where userId = u.localId and cardId in (select c.localId from card c inner join stack s on s.localId = c.stackId where s.boardId = :boardId)" +
|
||||
") DESC" +
|
||||
" LIMIT :topX")
|
||||
LiveData<List<User>> findProposalsForUsersToAssign(long accountId, long boardId, long notAssignedToLocalCardId, int topX);
|
||||
|
||||
|
||||
@Query("SELECT u.* FROM user u WHERE accountId = :accountId " +
|
||||
" AND NOT EXISTS (" +
|
||||
" select 1 from accesscontrol ju" +
|
||||
" where ju.userId = u.localId and ju.boardId = :boardId and status <> 3" + // not LOCAL_DELETED
|
||||
" ) " +
|
||||
"and u.localId <> (select b.ownerId from board b where localId = :boardId)" +
|
||||
"ORDER BY u.displayname " +
|
||||
"LIMIT :topX")
|
||||
LiveData<List<User>> findProposalsForUsersToAssignForACL(long accountId, long boardId, int topX);
|
||||
|
||||
|
||||
@Query("SELECT * FROM user WHERE localId IN (:userIDs) and status <> 3") // not LOCAL_DELETED
|
||||
List<User> getUsersByIdsDirectly(List<Long> userIDs);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.relations.UserInBoard;
|
||||
|
||||
@Dao
|
||||
public interface UserInBoardDao extends GenericDao<UserInBoard> {
|
||||
@Query("DELETE FROM userinboard WHERE boardId = :localId")
|
||||
void deleteByBoardId(long localId);
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
import androidx.room.RawQuery;
|
||||
import androidx.sqlite.db.SupportSQLiteQuery;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.ocs.user.UserForAssignment;
|
||||
import it.niedermann.nextcloud.deck.model.relations.UserInGroup;
|
||||
|
||||
@Dao
|
||||
public interface UserInGroupDao extends GenericDao<UserInGroup> {
|
||||
@Query("DELETE FROM useringroup WHERE groupId = :localId")
|
||||
void deleteByGroupId(long localId);
|
||||
|
||||
@RawQuery
|
||||
UserForAssignment getUserForAssignment(SupportSQLiteQuery query);
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao.projects;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.database.dao.GenericDao;
|
||||
import it.niedermann.nextcloud.deck.model.ocs.projects.JoinCardWithProject;
|
||||
|
||||
@Dao
|
||||
public interface JoinCardWithOcsProjectDao extends GenericDao<JoinCardWithProject> {
|
||||
@Query("select * from JoinCardWithProject where projectId = :localProjectId and cardId = :localCardId")
|
||||
JoinCardWithProject getAssignmentByCardIdAndProjectIdDirectly(Long localCardId, Long localProjectId);
|
||||
|
||||
@Query("delete from JoinCardWithProject where cardId = :localCardId and projectId NOT in (select p.localId from OcsProject p where p.accountId = :accountId and p.id in (:remoteProjectIDs))")
|
||||
void deleteProjectResourcesByCardIdExceptGivenProjectIdsDirectly(long accountId, Long localCardId, List<Long> remoteProjectIDs);
|
||||
|
||||
@Query("delete from JoinCardWithProject where cardId = :localCardId")
|
||||
void deleteProjectResourcesByCardIdDirectly(Long localCardId);
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao.projects;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import it.niedermann.nextcloud.deck.database.dao.GenericDao;
|
||||
import it.niedermann.nextcloud.deck.model.ocs.projects.OcsProject;
|
||||
|
||||
@Dao
|
||||
public interface OcsProjectDao extends GenericDao<OcsProject> {
|
||||
@Query("select * from OcsProject where accountId = :accountId and id = :remoteId")
|
||||
OcsProject getProjectByRemoteIdDirectly(long accountId, Long remoteId);
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao.projects;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.database.dao.GenericDao;
|
||||
import it.niedermann.nextcloud.deck.model.ocs.projects.OcsProjectResource;
|
||||
|
||||
@Dao
|
||||
public interface OcsProjectResourceDao extends GenericDao<OcsProjectResource> {
|
||||
@Query("delete from OcsProjectResource where projectId = :localProjectId")
|
||||
void deleteByProjectId(Long localProjectId);
|
||||
|
||||
@Query("select * from OcsProjectResource where projectId = :localProjectId")
|
||||
LiveData<List<OcsProjectResource>> getResourcesByLocalProjectId(Long localProjectId);
|
||||
|
||||
@Query("select count(id) from OcsProjectResource where projectId = :localProjectId")
|
||||
int countProjectResourcesInProjectDirectly(Long localProjectId);
|
||||
|
||||
@Query("select count(id) from OcsProjectResource where projectId = :localProjectId")
|
||||
LiveData<Integer> countProjectResourcesInProject(Long localProjectId);
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao.widgets;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
import androidx.room.Transaction;
|
||||
|
||||
import it.niedermann.nextcloud.deck.database.dao.GenericDao;
|
||||
import it.niedermann.nextcloud.deck.model.full.FullSingleCardWidgetModel;
|
||||
import it.niedermann.nextcloud.deck.model.widget.singlecard.SingleCardWidgetModel;
|
||||
|
||||
@Dao
|
||||
public interface SingleCardWidgetModelDao extends GenericDao<SingleCardWidgetModel> {
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM singlecardwidgetmodel WHERE widgetId = :widgetId")
|
||||
FullSingleCardWidgetModel getFullCardByRemoteIdDirectly(final int widgetId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT EXISTS (SELECT 1 FROM singlecardwidgetmodel WHERE cardId = :cardLocalId)")
|
||||
boolean containsCardLocalId(final Long cardLocalId);
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao.widgets;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
import androidx.room.Transaction;
|
||||
|
||||
import it.niedermann.nextcloud.deck.database.dao.GenericDao;
|
||||
import it.niedermann.nextcloud.deck.model.appwidgets.StackWidgetModel;
|
||||
|
||||
@Dao
|
||||
public interface StackWidgetModelDao extends GenericDao<StackWidgetModel> {
|
||||
|
||||
@Query("SELECT * FROM stackwidgetmodel WHERE appwidgetid = :appWidgetId")
|
||||
StackWidgetModel getStackWidgetByAppWidgetIdDirectly(final int appWidgetId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT EXISTS (SELECT 1 FROM stackwidgetmodel WHERE stackId in (:stackLocalIds))")
|
||||
boolean containsStackLocalId(final long... stackLocalIds);
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao.widgets.filter;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.database.dao.GenericDao;
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetAccount;
|
||||
|
||||
@Dao
|
||||
public interface FilterWidgetAccountDao extends GenericDao<FilterWidgetAccount> {
|
||||
@Query("DELETE FROM FilterWidgetAccount WHERE filterWidgetId = :filterWidgetId")
|
||||
void deleteByFilterWidgetId (Integer filterWidgetId);
|
||||
|
||||
@Query("select * FROM FilterWidgetAccount WHERE filterWidgetId = :filterWidgetId")
|
||||
List<FilterWidgetAccount> getFilterWidgetAccountsByFilterWidgetIdDirectly(Integer filterWidgetId);
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao.widgets.filter;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.database.dao.GenericDao;
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetBoard;
|
||||
|
||||
@Dao
|
||||
public interface FilterWidgetBoardDao extends GenericDao<FilterWidgetBoard> {
|
||||
@Query("SELECT * FROM FilterWidgetBoard where filterAccountId = :filterWidgetAccountId")
|
||||
List<FilterWidgetBoard> getFilterWidgetBoardsByFilterWidgetAccountIdDirectly(Long filterWidgetAccountId);
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao.widgets.filter;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
import androidx.room.Transaction;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.database.dao.GenericDao;
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.EWidgetType;
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidget;
|
||||
|
||||
@Dao
|
||||
public interface FilterWidgetDao extends GenericDao<FilterWidget> {
|
||||
@Query("DELETE FROM filterwidget WHERE id = :filterWidgetId")
|
||||
void delete (Integer filterWidgetId);
|
||||
|
||||
@Query("SELECT * FROM FilterWidget where id = :filterWidgetId")
|
||||
FilterWidget getFilterWidgetByIdDirectly(Integer filterWidgetId);
|
||||
|
||||
@Query("SELECT EXISTS (SELECT 1 FROM FilterWidget WHERE id = :filterWidgetId)")
|
||||
boolean filterWidgetExists(int filterWidgetId);
|
||||
|
||||
@Query("SELECT id FROM FilterWidget WHERE widgetType = :type")
|
||||
List<Integer> getFilterWidgetIdsByType(int type);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT DISTINCT w.widgetType " +
|
||||
"FROM FilterWidget w " +
|
||||
"LEFT JOIN FilterWidgetAccount a ON w.id = a.filterWidgetId " +
|
||||
"LEFT JOIN FilterWidgetBoard b ON a.id = b.filterAccountId " +
|
||||
"LEFT JOIN FilterWidgetStack s ON b.id = s.filterBoardId " +
|
||||
"LEFT JOIN FilterWidgetUser u ON a.id = u.filterAccountId " +
|
||||
"LEFT JOIN FilterWidgetProject p ON a.id = p.filterAccountId " +
|
||||
"LEFT JOIN FilterWidgetLabel l ON b.id = l.filterBoardId " +
|
||||
"WHERE (:changedEntityType = 'ACCOUNT' AND (a.accountId = :localIdOfChangedEntity OR a.accountId IS NULL)) " +
|
||||
"OR (:changedEntityType = 'BOARD' AND (b.boardId = :localIdOfChangedEntity OR b.boardId IS NULL)) " +
|
||||
"OR (:changedEntityType = 'STACK' AND (s.stackId = :localIdOfChangedEntity OR s.stackId IS NULL)) " +
|
||||
"OR (:changedEntityType = 'USER' AND (u.userId = :localIdOfChangedEntity OR u.userId IS NULL)) " +
|
||||
"OR (:changedEntityType = 'PROJECT' AND (p.projectId = :localIdOfChangedEntity OR p.projectId IS NULL)) " +
|
||||
"OR (:changedEntityType = 'LABEL' AND (l.labelId = :localIdOfChangedEntity OR l.labelId IS NULL)) "
|
||||
)
|
||||
List<EWidgetType> getChangedListTypesByEntity(String changedEntityType, Long localIdOfChangedEntity);
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao.widgets.filter;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.database.dao.GenericDao;
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetLabel;
|
||||
|
||||
@Dao
|
||||
public interface FilterWidgetLabelDao extends GenericDao<FilterWidgetLabel> {
|
||||
@Query("SELECT * FROM FilterWidgetLabel where filterBoardId = :filterWidgetBoardId")
|
||||
List<FilterWidgetLabel> getFilterWidgetLabelsByFilterWidgetBoardIdDirectly(Long filterWidgetBoardId);
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao.widgets.filter;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.database.dao.GenericDao;
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetProject;
|
||||
|
||||
@Dao
|
||||
public interface FilterWidgetProjectDao extends GenericDao<FilterWidgetProject> {
|
||||
@Query("SELECT * FROM FilterWidgetProject where filterAccountId = :filterWidgetAccountId")
|
||||
List<FilterWidgetProject> getFilterWidgetProjectsByFilterWidgetAccountIdDirectly(Long filterWidgetAccountId);
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao.widgets.filter;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.database.dao.GenericDao;
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetSort;
|
||||
|
||||
@Dao
|
||||
public interface FilterWidgetSortDao extends GenericDao<FilterWidgetSort> {
|
||||
@Query("DELETE FROM FilterWidgetSort WHERE filterWidgetId = :filterWidgetId")
|
||||
void deleteByFilterWidgetId (Integer filterWidgetId);
|
||||
|
||||
@Query("select * FROM FilterWidgetSort WHERE filterWidgetId = :filterWidgetId order by ruleOrder asc")
|
||||
List<FilterWidgetSort> getFilterWidgetSortByFilterWidgetIdDirectly(Integer filterWidgetId);
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao.widgets.filter;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.database.dao.GenericDao;
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetStack;
|
||||
|
||||
@Dao
|
||||
public interface FilterWidgetStackDao extends GenericDao<FilterWidgetStack> {
|
||||
@Query("SELECT * FROM FilterWidgetStack where filterBoardId = :filterWidgetBoardId")
|
||||
List<FilterWidgetStack> getFilterWidgetStacksByFilterWidgetBoardIdDirectly(Long filterWidgetBoardId);
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package it.niedermann.nextcloud.deck.database.dao.widgets.filter;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.niedermann.nextcloud.deck.database.dao.GenericDao;
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetUser;
|
||||
|
||||
@Dao
|
||||
public interface FilterWidgetUserDao extends GenericDao<FilterWidgetUser> {
|
||||
@Query("SELECT * FROM FilterWidgetUser where filterAccountId = :filterWidgetAccountId")
|
||||
List<FilterWidgetUser> getFilterWidgetUsersByFilterWidgetAccountIdDirectly(Long filterWidgetAccountId);
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import android.database.Cursor;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.enums.DBStatus;
|
||||
|
||||
/**
|
||||
* Removes duplicate labels and ensures uniqueness
|
||||
*/
|
||||
public class Migration_10_11 extends Migration {
|
||||
|
||||
public Migration_10_11() {
|
||||
super(10, 11);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||
// replace duplicates with the server-known ones
|
||||
Cursor duplucatesCursor = database.query("SELECT boardId, title, count(*) FROM Label group by boardid, title having count(*) > 1");
|
||||
if (duplucatesCursor != null && duplucatesCursor.moveToFirst()) {
|
||||
do {
|
||||
long boardId = duplucatesCursor.getLong(0);
|
||||
String title = duplucatesCursor.getString(1);
|
||||
Cursor singleDuplicateCursor = database.query("select localId from Label where boardId = ? and title = ? order by id desc", new Object[]{boardId, title});
|
||||
if (singleDuplicateCursor != null && singleDuplicateCursor.moveToFirst()) {
|
||||
long idToUse = -1;
|
||||
do {
|
||||
if (idToUse < 0) {
|
||||
// desc order -> first one is the one with remote ID or a random one. keep this one.
|
||||
idToUse = singleDuplicateCursor.getLong(0);
|
||||
continue;
|
||||
}
|
||||
long idToReplace = singleDuplicateCursor.getLong(0);
|
||||
Cursor cardsAssignedToDuplicateCursor = database.query("select cardId, exists(select 1 from JoinCardWithLabel ij where ij.labelId = ? and ij.cardId = cardId) " +
|
||||
"from JoinCardWithLabel where labelId = ?", new Object[]{idToUse, idToReplace});
|
||||
if (cardsAssignedToDuplicateCursor != null && cardsAssignedToDuplicateCursor.moveToFirst()) {
|
||||
do {
|
||||
long cardId = cardsAssignedToDuplicateCursor.getLong(0);
|
||||
boolean hasDestinationLabelAssigned = cardsAssignedToDuplicateCursor.getInt(1) > 0;
|
||||
database.execSQL("DELETE FROM JoinCardWithLabel where labelId = ? and cardId = ?", new Object[]{idToReplace, cardId});
|
||||
|
||||
if (!hasDestinationLabelAssigned) {
|
||||
database.execSQL("INSERT INTO JoinCardWithLabel (status,labelId,cardId) VALUES (?, ?, ?)", new Object[]{DBStatus.LOCAL_EDITED.getId(), idToUse, cardId});
|
||||
}
|
||||
} while (cardsAssignedToDuplicateCursor.moveToNext());
|
||||
}
|
||||
database.execSQL("DELETE FROM Label where localId = ?", new Object[]{idToReplace});
|
||||
} while (singleDuplicateCursor.moveToNext());
|
||||
}
|
||||
} while (duplucatesCursor.moveToNext());
|
||||
}
|
||||
// database.execSQL("DELETE FROM Label WHERE id IS NULL AND EXISTS(SELECT 1 FROM Label il WHERE il.boardId = boardId AND il.title = title AND id IS NOT NULL)");
|
||||
database.execSQL("CREATE UNIQUE INDEX idx_label_title_unique ON Label(boardId, title)");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* Adds support for the Single note widget
|
||||
*/
|
||||
public class Migration_11_12 extends Migration {
|
||||
|
||||
public Migration_11_12() {
|
||||
super(11, 12);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
database.execSQL("CREATE TABLE `SingleCardWidgetModel` (`widgetId` INTEGER PRIMARY KEY, `accountId` INTEGER, `boardId` INTEGER, `cardId` INTEGER, FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE, FOREIGN KEY(`boardId`) REFERENCES `Board`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE, FOREIGN KEY(`cardId`) REFERENCES `Card`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE )");
|
||||
database.execSQL("CREATE INDEX `index_SingleCardWidgetModel_cardId` ON `SingleCardWidgetModel` (`cardId`)");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
public class Migration_12_13 extends Migration {
|
||||
|
||||
public Migration_12_13() {
|
||||
super(12, 13);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
database.execSQL("CREATE INDEX `idx_cardWidgetModel_accountId` ON `SingleCardWidgetModel` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `idx_cardWidgetModel_boardId` ON `SingleCardWidgetModel` (`boardId`)");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* Adds support for comment responses
|
||||
*/
|
||||
public class Migration_13_14 extends Migration {
|
||||
|
||||
public Migration_13_14() {
|
||||
super(13, 14);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
database.execSQL("ALTER TABLE `DeckComment` ADD `parentId` INTEGER REFERENCES DeckComment(localId) ON DELETE CASCADE");
|
||||
database.execSQL("CREATE INDEX `idx_comment_parentID` ON DeckComment(parentId)");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
import it.niedermann.nextcloud.deck.remote.SyncWorker;
|
||||
|
||||
/**
|
||||
* @see <a href="https://github.com/stefan-niedermann/nextcloud-deck/issues/570">Reinitializes the background synchronization</a> and
|
||||
* <a href="https://github.com/stefan-niedermann/nextcloud-deck/issues/525">cleans up old shared preferences</a>
|
||||
*/
|
||||
public class Migration_14_15 extends Migration {
|
||||
|
||||
@NonNull
|
||||
private final Context context;
|
||||
|
||||
public Migration_14_15(@NonNull Context context) {
|
||||
super(14, 15);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||
SyncWorker.update(context);
|
||||
PreferenceManager
|
||||
.getDefaultSharedPreferences(context)
|
||||
.edit()
|
||||
.remove("it.niedermann.nextcloud.deck.theme_text")
|
||||
.apply();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* Adds support for Stack widget
|
||||
*/
|
||||
public class Migration_15_16 extends Migration {
|
||||
|
||||
public Migration_15_16() {
|
||||
super(15, 16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
database.execSQL("CREATE TABLE `StackWidgetModel` (`appWidgetId` INTEGER PRIMARY KEY, `accountId` INTEGER, `stackId` INTEGER, `darkTheme` INTEGER CHECK (`darkTheme` IN (0,1)) NOT NULL, " +
|
||||
"FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE, " +
|
||||
"FOREIGN KEY(`stackId`) REFERENCES `Stack`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE )");
|
||||
database.execSQL("CREATE INDEX `index_StackWidgetModel_stackId` ON `StackWidgetModel` (`stackId`)");
|
||||
database.execSQL("CREATE INDEX `index_StackWidgetModel_accountId` ON `StackWidgetModel` (`accountId`)");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* @see <a href="https://github.com/stefan-niedermann/nextcloud-deck/issues/573">Adds support for projects</a>
|
||||
*/
|
||||
public class Migration_16_17 extends Migration {
|
||||
|
||||
public Migration_16_17() {
|
||||
super(16, 17);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
database.execSQL("CREATE TABLE `OcsProject` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `name` TEXT NOT NULL, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `index_OcsProject_accountId_id` ON `OcsProject` (`accountId`, `id`)");
|
||||
database.execSQL("CREATE INDEX `index_project_accID` ON `OcsProject` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `index_OcsProject_id` ON `OcsProject` (`id`)");
|
||||
database.execSQL("CREATE INDEX `index_OcsProject_lastModifiedLocal` ON `OcsProject` (`lastModifiedLocal`)");
|
||||
|
||||
database.execSQL("CREATE TABLE `OcsProjectResource` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `name` TEXT, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER, `projectId` INTEGER NOT NULL, `type` TEXT , `link` TEXT , `path` TEXT, `iconUrl` TEXT , `previewAvailable` INTEGER, `mimetype` TEXT, FOREIGN KEY(`projectId`) REFERENCES `OcsProject`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE)");
|
||||
database.execSQL("CREATE INDEX `index_projectResource_accID` ON `OcsProjectResource` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `index_projectResource_projectId` ON `OcsProjectResource` (`projectId`)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `index_OcsProjectResource_accountId_id` ON `OcsProjectResource` (`accountId`, `id`, `projectId`)");
|
||||
database.execSQL("CREATE INDEX `index_OcsProjectResource_id` ON `OcsProjectResource` (`id`)");
|
||||
database.execSQL("CREATE INDEX `index_OcsProjectResource_lastModifiedLocal` ON `OcsProjectResource` (`lastModifiedLocal`)");
|
||||
|
||||
database.execSQL("CREATE TABLE `JoinCardWithProject` (`status` INTEGER NOT NULL, `projectId` INTEGER NOT NULL, `cardId` INTEGER NOT NULL, PRIMARY KEY (`projectId`, `cardId`), FOREIGN KEY(`cardId`) REFERENCES `Card`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE, FOREIGN KEY(`projectId`) REFERENCES `OcsProject`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE)");
|
||||
database.execSQL("CREATE INDEX `index_JoinCardWithProject_projectId` ON `JoinCardWithProject` (`projectId`)");
|
||||
database.execSQL("CREATE INDEX `index_JoinCardWithProject_cardId` ON `JoinCardWithProject` (`cardId`)");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* <a href="https://github.com/stefan-niedermann/nextcloud-deck/issues/435">Implement ETags for Capabilities endpoint</a>
|
||||
*/
|
||||
public class Migration_17_18 extends Migration {
|
||||
|
||||
public Migration_17_18() {
|
||||
super(17, 18);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
database.execSQL("ALTER TABLE `Account` ADD `etag` TEXT");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* @see <a href="https://github.com/stefan-niedermann/nextcloud-deck/issues/619">Handle unknown project types</a>
|
||||
*/
|
||||
public class Migration_18_19 extends Migration {
|
||||
|
||||
public Migration_18_19() {
|
||||
super(18, 19);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
database.execSQL("DROP INDEX `index_OcsProjectResource_accountId_id`");
|
||||
database.execSQL("ALTER TABLE `OcsProjectResource` ADD `idString` TEXT");
|
||||
database.execSQL("CREATE UNIQUE INDEX `index_OcsProjectResource_accountId_id` ON `OcsProjectResource` (`accountId`, `id`, `idString`, `projectId`)");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* Fixes issues with LDAP users when filtering
|
||||
* https://github.com/stefan-niedermann/nextcloud-deck/issues/492
|
||||
* https://github.com/stefan-niedermann/nextcloud-deck/issues/631
|
||||
*/
|
||||
public class Migration_19_20 extends Migration {
|
||||
|
||||
public Migration_19_20() {
|
||||
super(19, 20);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
database.execSQL("CREATE TABLE `UserInGroup` (`groupId` INTEGER NOT NULL, `memberId` INTEGER NOT NULL, " +
|
||||
"primary KEY(`groupId`, `memberId`), " +
|
||||
"FOREIGN KEY(`groupId`) REFERENCES `User`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE, " +
|
||||
"FOREIGN KEY(`memberId`) REFERENCES `User`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `unique_idx_group_member` ON `UserInGroup` (`groupId`, `memberId`)");
|
||||
database.execSQL("CREATE INDEX `index_UserInGroup_groupId` ON `UserInGroup` (`groupId`)");
|
||||
database.execSQL("CREATE INDEX `index_UserInGroup_memberId` ON `UserInGroup` (`memberId`)");
|
||||
|
||||
database.execSQL("CREATE TABLE `UserInBoard` (`userId` INTEGER NOT NULL, `boardId` INTEGER NOT NULL, " +
|
||||
"primary KEY(`userId`, `boardId`), " +
|
||||
"FOREIGN KEY(`userId`) REFERENCES `User`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE, " +
|
||||
"FOREIGN KEY(`boardId`) REFERENCES `Board`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `unique_idx_user_board` ON `UserInBoard` (`userId`, `boardId`)");
|
||||
database.execSQL("CREATE INDEX `index_UserInBoard_userId` ON `UserInBoard` (`userId`)");
|
||||
database.execSQL("CREATE INDEX `index_UserInBoard_boardId` ON `UserInBoard` (`boardId`)");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Color;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
import it.niedermann.android.util.ColorUtil;
|
||||
|
||||
/**
|
||||
* @see <a href="https://github.com/stefan-niedermann/nextcloud-deck/issues/556">Store colors as integer in database</a>
|
||||
*/
|
||||
public class Migration_20_21 extends Migration {
|
||||
|
||||
public Migration_20_21() {
|
||||
super(20, 21);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
String suffix = "_new";
|
||||
{
|
||||
String tableName = "Account";
|
||||
database.execSQL("CREATE TABLE `" + tableName + suffix + "` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` TEXT NOT NULL, `userName` TEXT NOT NULL, `url` TEXT NOT NULL, " +
|
||||
"`color` INTEGER NOT NULL DEFAULT 0, `textColor` INTEGER NOT NULL DEFAULT 0, `serverDeckVersion` TEXT NOT NULL DEFAULT '0.6.4', `maintenanceEnabled` INTEGER NOT NULL DEFAULT 0, `etag` TEXT)");
|
||||
Cursor cursor = database.query("select * from `" + tableName + "`");
|
||||
while (cursor.moveToNext()) {
|
||||
String colorAsString1 = cursor.getString(4); // color
|
||||
String colorAsString2 = cursor.getString(5); // textColor
|
||||
|
||||
@ColorInt int color1;
|
||||
@ColorInt int color2;
|
||||
try {
|
||||
color1 = Color.parseColor(ColorUtil.formatColorToParsableHexString(colorAsString1));
|
||||
color2 = Color.parseColor(ColorUtil.formatColorToParsableHexString(colorAsString2));
|
||||
} catch (Exception e) {
|
||||
color1 = Color.GRAY;
|
||||
color2 = Color.GRAY;
|
||||
}
|
||||
database.execSQL("Insert into `" + tableName + suffix + "` VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", new Object[]{
|
||||
cursor.getLong(0), cursor.getString(1), cursor.getString(2), cursor.getString(3),
|
||||
color1, color2, cursor.getString(6), cursor.getInt(7), cursor.getString(8)});
|
||||
|
||||
}
|
||||
|
||||
|
||||
database.execSQL("DROP TABLE `" + tableName + "`");
|
||||
database.execSQL("ALTER TABLE `" + tableName + suffix + "` RENAME TO `" + tableName + "`");
|
||||
database.execSQL("CREATE UNIQUE INDEX `index_Account_name` ON `" + tableName + "` (`name`)");
|
||||
database.execSQL("UPDATE SQLITE_SEQUENCE SET seq = (select max(id) from " + tableName + ") WHERE name = ?", new Object[]{tableName});
|
||||
}
|
||||
{
|
||||
String tableName = "Board";
|
||||
database.execSQL("CREATE TABLE `" + tableName + suffix + "` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, " +
|
||||
"`lastModified` INTEGER, `lastModifiedLocal` INTEGER, `title` TEXT, `ownerId` INTEGER NOT NULL, `color` INTEGER, " +
|
||||
"`archived` INTEGER NOT NULL, `shared` INTEGER NOT NULL, `deletedAt` INTEGER, `permissionRead` INTEGER NOT NULL, " +
|
||||
"`permissionEdit` INTEGER NOT NULL, `permissionManage` INTEGER NOT NULL, `permissionShare` INTEGER NOT NULL, " +
|
||||
"FOREIGN KEY(`ownerId`) REFERENCES `User`(`localId`) ON UPDATE NO ACTION ON DELETE SET NULL )");
|
||||
Cursor cursor = database.query("select * from `" + tableName + "`");
|
||||
while (cursor.moveToNext()) {
|
||||
String colorAsString1 = cursor.getString(8); // color
|
||||
|
||||
@ColorInt int color1;
|
||||
try {
|
||||
color1 = Color.parseColor(ColorUtil.formatColorToParsableHexString(colorAsString1));
|
||||
} catch (Exception e) {
|
||||
color1 = Color.GRAY;
|
||||
}
|
||||
database.execSQL("Insert into `" + tableName + suffix + "` VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", new Object[]{
|
||||
cursor.getLong(0), cursor.getLong(1), cursor.getLong(2), cursor.getInt(3),
|
||||
cursor.getLong(4), cursor.getLong(5), cursor.getString(6), cursor.getLong(7), color1,
|
||||
cursor.getInt(9), cursor.getInt(10), cursor.getInt(11), cursor.getInt(12),
|
||||
cursor.getInt(13), cursor.getInt(14), cursor.getInt(15)
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
database.execSQL("DROP TABLE `" + tableName + "`");
|
||||
database.execSQL("ALTER TABLE `" + tableName + suffix + "` RENAME TO `" + tableName + "`");
|
||||
database.execSQL("CREATE INDEX `index_Board_accountId` ON `" + tableName + "` (`accountId`)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `index_Board_accountId_id` ON `" + tableName + "` (`accountId`, `id`)");
|
||||
database.execSQL("CREATE INDEX `index_Board_id` ON `" + tableName + "` (`id`)");
|
||||
database.execSQL("CREATE INDEX `index_Board_ownerId` ON `" + tableName + "` (`ownerId`)");
|
||||
database.execSQL("CREATE INDEX `index_Board_lastModifiedLocal` ON `" + tableName + "` (`lastModifiedLocal`)");
|
||||
database.execSQL("UPDATE SQLITE_SEQUENCE SET seq = (select max(id) from " + tableName + ") WHERE name = ?", new Object[]{tableName});
|
||||
}
|
||||
{
|
||||
String tableName = "Label";
|
||||
database.execSQL("CREATE TABLE `" + tableName + suffix + "` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, " +
|
||||
"`lastModified` INTEGER, `lastModifiedLocal` INTEGER, `title` TEXT, `color` INTEGER NOT NULL DEFAULT 0, `boardId` INTEGER NOT NULL, " +
|
||||
"FOREIGN KEY(`boardId`) REFERENCES `Board`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE )");
|
||||
Cursor cursor = database.query("select * from `" + tableName + "`");
|
||||
while (cursor.moveToNext()) {
|
||||
String colorAsString1 = cursor.getString(7); // color
|
||||
|
||||
@ColorInt int color1;
|
||||
try {
|
||||
color1 = Color.parseColor(ColorUtil.formatColorToParsableHexString(colorAsString1));
|
||||
} catch (Exception e) {
|
||||
color1 = Color.GRAY;
|
||||
}
|
||||
database.execSQL("Insert into `" + tableName + suffix + "` VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", new Object[]{
|
||||
cursor.getLong(0), cursor.getLong(1), cursor.getLong(2), cursor.getInt(3),
|
||||
cursor.getLong(4), cursor.getLong(5), cursor.getString(6), color1, cursor.getLong(8)});
|
||||
|
||||
}
|
||||
|
||||
|
||||
database.execSQL("DROP TABLE `" + tableName + "`");
|
||||
database.execSQL("ALTER TABLE `" + tableName + suffix + "` RENAME TO `" + tableName + "`");
|
||||
database.execSQL("CREATE UNIQUE INDEX `index_Label_accountId_id` ON `" + tableName + "` (`accountId`, `id`)");
|
||||
database.execSQL("CREATE INDEX `index_Label_boardId` ON `" + tableName + "` (`boardId`)");
|
||||
database.execSQL("CREATE INDEX `index_Label_accountId` ON `" + tableName + "` (`accountId`)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `idx_label_title_unique` ON `" + tableName + "` (`boardId`, `title`)");
|
||||
database.execSQL("CREATE INDEX `index_Label_id` ON `" + tableName + "` (`id`)");
|
||||
database.execSQL("CREATE INDEX `index_Label_lastModifiedLocal` ON `" + tableName + "` (`lastModifiedLocal`)");
|
||||
database.execSQL("UPDATE SQLITE_SEQUENCE SET seq = (select max(id) from " + tableName + ") WHERE name = ?", new Object[]{tableName});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.Cursor;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* @see <a href="https://github.com/stefan-niedermann/nextcloud-deck/issues/715">Migrate from java.util.Date and java.util.Calendar to java.time.*</a>
|
||||
*/
|
||||
public class Migration_21_22 extends Migration {
|
||||
|
||||
@NonNull
|
||||
private final Context context;
|
||||
|
||||
public Migration_21_22(@NonNull Context context) {
|
||||
super(21, 22);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||
final SharedPreferences.Editor lastSyncPref = context.getApplicationContext().getSharedPreferences("it.niedermann.nextcloud.deck.last_sync", Context.MODE_PRIVATE).edit();
|
||||
final Cursor cursor = database.query("select id from `Account`");
|
||||
while (cursor.moveToNext()) {
|
||||
lastSyncPref.remove("lS_" + cursor.getLong(0));
|
||||
}
|
||||
cursor.close();
|
||||
lastSyncPref.apply();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* @see <a href="https://github.com/stefan-niedermann/nextcloud-deck/issues/359">Implement ETags for synchronization Speed-Up</a>
|
||||
*/
|
||||
public class Migration_22_23 extends Migration {
|
||||
|
||||
public Migration_22_23() {
|
||||
super(22, 23);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
database.execSQL("ALTER TABLE `Account` ADD `boardsEtag` TEXT");
|
||||
database.execSQL("ALTER TABLE `Board` ADD `etag` TEXT");
|
||||
database.execSQL("ALTER TABLE `Stack` ADD `etag` TEXT");
|
||||
database.execSQL("ALTER TABLE `Card` ADD `etag` TEXT");
|
||||
database.execSQL("ALTER TABLE `Label` ADD `etag` TEXT");
|
||||
database.execSQL("ALTER TABLE `AccessControl` ADD `etag` TEXT");
|
||||
database.execSQL("ALTER TABLE `Attachment` ADD `etag` TEXT");
|
||||
database.execSQL("ALTER TABLE `User` ADD `etag` TEXT");
|
||||
database.execSQL("ALTER TABLE `DeckComment` ADD `etag` TEXT");
|
||||
database.execSQL("ALTER TABLE `Activity` ADD `etag` TEXT");
|
||||
database.execSQL("ALTER TABLE `OcsProject` ADD `etag` TEXT");
|
||||
database.execSQL("ALTER TABLE `OcsProjectResource` ADD `etag` TEXT");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
import it.niedermann.nextcloud.deck.R;
|
||||
|
||||
/**
|
||||
* <a href="https://github.com/stefan-niedermann/nextcloud-deck/issues/392">Dark mode following system default</a>
|
||||
*/
|
||||
public class Migration_23_24 extends Migration {
|
||||
|
||||
@NonNull
|
||||
private final Context context;
|
||||
|
||||
public Migration_23_24(@NonNull Context context) {
|
||||
super(23, 24);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||
final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
final String themePref = context.getString(R.string.pref_key_dark_theme);
|
||||
|
||||
if (sharedPreferences.contains(themePref)) {
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
final boolean darkTheme = sharedPreferences.getBoolean(themePref, false);
|
||||
editor.remove(themePref);
|
||||
editor.putString(themePref, darkTheme ? context.getString(R.string.pref_value_theme_dark) : context.getString(R.string.pref_value_theme_light));
|
||||
editor.apply();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* Reset ETags (comments weren't loading due to bug)
|
||||
*/
|
||||
public class Migration_24_25 extends Migration {
|
||||
|
||||
public Migration_24_25() {
|
||||
super(24, 25);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
database.execSQL("UPDATE `Account` SET `boardsEtag` = NULL");
|
||||
database.execSQL("UPDATE `Board` SET `etag` = NULL");
|
||||
database.execSQL("UPDATE `Stack` SET `etag` = NULL");
|
||||
database.execSQL("UPDATE `Card` SET `etag` = NULL");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* Implement <a href="https://github.com/stefan-niedermann/nextcloud-deck/issues/597">Filter widget</a>
|
||||
*/
|
||||
public class Migration_25_26 extends Migration {
|
||||
|
||||
public Migration_25_26() {
|
||||
super(25, 26);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
database.execSQL("CREATE TABLE `FilterWidget` (`id` INTEGER PRIMARY KEY NOT NULL, `title` TEXT, `dueType` INTEGER, `widgetType` INTEGER NOT NULL)");
|
||||
database.execSQL("CREATE TABLE `FilterWidgetAccount` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterWidgetId` INTEGER, `accountId` INTEGER, `includeNoUser` INTEGER NOT NULL, `includeNoProject` INTEGER NOT NULL, FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterWidgetId`) REFERENCES `FilterWidget`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
|
||||
database.execSQL("CREATE TABLE `FilterWidgetBoard` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterAccountId` INTEGER, `boardId` INTEGER, `includeNoLabel` INTEGER NOT NULL, FOREIGN KEY(`boardId`) REFERENCES `Board`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterAccountId`) REFERENCES `FilterWidgetAccount`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
|
||||
database.execSQL("CREATE TABLE `FilterWidgetLabel` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterBoardId` INTEGER, `labelId` INTEGER, FOREIGN KEY(`labelId`) REFERENCES `Label`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterBoardId`) REFERENCES `FilterWidgetBoard`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
|
||||
database.execSQL("CREATE TABLE `FilterWidgetSort` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterWidgetId` INTEGER, `direction` INTEGER NOT NULL, `criteria` INTEGER NOT NULL, `ruleOrder` INTEGER NOT NULL, FOREIGN KEY(`filterWidgetId`) REFERENCES `FilterWidget`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
|
||||
database.execSQL("CREATE TABLE `FilterWidgetStack` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterBoardId` INTEGER, `stackId` INTEGER, FOREIGN KEY(`stackId`) REFERENCES `Stack`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterBoardId`) REFERENCES `FilterWidgetBoard`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
|
||||
database.execSQL("CREATE TABLE `FilterWidgetUser` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterAccountId` INTEGER, `userId` INTEGER, FOREIGN KEY(`userId`) REFERENCES `User`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterAccountId`) REFERENCES `FilterWidgetAccount`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
|
||||
database.execSQL("CREATE TABLE `FilterWidgetProject` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterAccountId` INTEGER, `projectId` INTEGER, FOREIGN KEY(`projectId`) REFERENCES `OcsProject`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterAccountId`) REFERENCES `FilterWidgetAccount`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
|
||||
database.execSQL("CREATE INDEX `index_FilterWidgetAccount_filterWidgetId` ON `FilterWidgetAccount` (`filterWidgetId`)");
|
||||
database.execSQL("CREATE INDEX `idx_FilterWidgetAccount_accountId` ON `FilterWidgetAccount` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `idx_FilterWidgetBoard_boardId` ON `FilterWidgetBoard` (`boardId`)");
|
||||
database.execSQL("CREATE INDEX `idx_FilterWidgetBoard_filterAccountId` ON `FilterWidgetBoard` (`filterAccountId`)");
|
||||
database.execSQL("CREATE INDEX `idx_FilterWidgetLabel_filterBoardId` ON `FilterWidgetLabel` (`filterBoardId`)");
|
||||
database.execSQL("CREATE INDEX `idx_FilterWidgetLabel_labelId` ON `FilterWidgetLabel` (`labelId`)");
|
||||
database.execSQL("CREATE INDEX `idx_FilterWidgetSort_filterWidgetId` ON `FilterWidgetSort` (`filterWidgetId`)");
|
||||
database.execSQL("CREATE INDEX `idx_FilterWidgetStack_filterBoardId` ON `FilterWidgetStack` (`filterBoardId`)");
|
||||
database.execSQL("CREATE INDEX `idx_FilterWidgetStack_stackId` ON `FilterWidgetStack` (`stackId`)");
|
||||
database.execSQL("CREATE INDEX `idx_FilterWidgetUser_filterAccountId` ON `FilterWidgetUser` (`filterAccountId`)");
|
||||
database.execSQL("CREATE INDEX `idx_FilterWidgetUser_userId` ON `FilterWidgetUser` (`userId`)");
|
||||
database.execSQL("CREATE INDEX `idx_FilterWidgetProject_filterAccountId` ON `FilterWidgetProject` (`filterAccountId`)");
|
||||
database.execSQL("CREATE INDEX `idx_FilterWidgetProject_projectId` ON `FilterWidgetProject` (`projectId`)");
|
||||
database.execSQL("CREATE INDEX `unique_idx_FilterWidgetSort_filterWidgetId_criteria` ON `FilterWidgetSort` (`filterWidgetId`, `criteria`)");
|
||||
database.execSQL("CREATE INDEX `unique_idx_FilterWidgetSort_filterWidgetId_ruleOrder` ON `FilterWidgetSort` (`filterWidgetId`, `ruleOrder`)");
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.widget.filter.EWidgetType;
|
||||
|
||||
/**
|
||||
* @see <a href="https://github.com/stefan-niedermann/nextcloud-deck/issues/767">Migrate Stack Widget to Filter Widget infrastructure</a>
|
||||
*/
|
||||
public class Migration_26_27 extends Migration {
|
||||
|
||||
public Migration_26_27() {
|
||||
super(26, 27);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
|
||||
Cursor cursor = database.query("select s.localId, s.boardId, s.accountId, w.appWidgetId from `StackWidgetModel` w inner join `Stack` s on s.localId = w.stackId");
|
||||
while (cursor.moveToNext()) {
|
||||
Long localStackId = cursor.getLong(0);
|
||||
Long localBoardId = cursor.getLong(1);
|
||||
Long accountId = cursor.getLong(2);
|
||||
Long filterWidgetId = cursor.getLong(3);
|
||||
|
||||
// widget
|
||||
ContentValues values = new ContentValues();
|
||||
values.put("widgetType", EWidgetType.STACK_WIDGET.getId());
|
||||
values.put("id", filterWidgetId);
|
||||
database.insert("FilterWidget", SQLiteDatabase.CONFLICT_NONE, values);
|
||||
|
||||
// account
|
||||
values = new ContentValues();
|
||||
values.put("filterWidgetId", filterWidgetId);
|
||||
values.put("accountId", accountId);
|
||||
values.put("includeNoUser", false);
|
||||
values.put("includeNoProject", false);
|
||||
long filterWidgetAccountId = database.insert("FilterWidgetAccount", SQLiteDatabase.CONFLICT_NONE, values);
|
||||
|
||||
// board
|
||||
values = new ContentValues();
|
||||
values.put("filterAccountId", filterWidgetAccountId);
|
||||
values.put("boardId", localBoardId);
|
||||
values.put("includeNoLabel", false);
|
||||
long filterWidgetBoardId = database.insert("FilterWidgetBoard", SQLiteDatabase.CONFLICT_NONE, values);
|
||||
|
||||
// stack
|
||||
values = new ContentValues();
|
||||
values.put("filterBoardId", filterWidgetBoardId);
|
||||
values.put("stackId", localStackId);
|
||||
database.insert("FilterWidgetStack", SQLiteDatabase.CONFLICT_NONE, values);
|
||||
}
|
||||
|
||||
// cleanup
|
||||
database.execSQL("DROP TABLE `StackWidgetModel`");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* Adds support for new attachment types with Deck server <code>1.3.0</code>
|
||||
*/
|
||||
public class Migration_27_28 extends Migration {
|
||||
|
||||
public Migration_27_28() {
|
||||
super(27, 28);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
database.execSQL("ALTER TABLE `Attachment` ADD COLUMN `fileId` INTEGER");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* Reset ETags for cards because <a href="https://github.com/nextcloud/deck/issues/2874">the attachments for this card might not be complete</a>.
|
||||
*/
|
||||
public class Migration_28_29 extends Migration {
|
||||
|
||||
public Migration_28_29() {
|
||||
super(28, 29);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
database.execSQL("UPDATE `Account` SET `boardsEtag` = NULL");
|
||||
database.execSQL("UPDATE `Board` SET `etag` = NULL");
|
||||
database.execSQL("UPDATE `Stack` SET `etag` = NULL");
|
||||
database.execSQL("UPDATE `Card` SET `etag` = NULL");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* <a href="https://github.com/stefan-niedermann/nextcloud-deck/issues/392">Dark mode following system default</a>
|
||||
*/
|
||||
public class Migration_29_30 extends Migration {
|
||||
|
||||
@NonNull
|
||||
private final Context context;
|
||||
|
||||
public Migration_29_30(@NonNull Context context) {
|
||||
super(29, 30);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||
PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.edit()
|
||||
.remove("branding")
|
||||
.apply();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* <strong><a href="https://github.com/stefan-niedermann/nextcloud-deck/issues/923">Foreign keys don't cascade (Cards stay in the database after deleting an Account)</a></strong>
|
||||
* <p>
|
||||
* This migration had two issues in the past:
|
||||
* <ul>
|
||||
* <li>
|
||||
* <a href="https://github.com/stefan-niedermann/nextcloud-deck/issues/936">1. Issue: SQLiteException</a>
|
||||
* <p>
|
||||
* <code>SQLiteException: table "Board" already exists (code 1): , while compiling: CREATE TABLE "Board" […]</code><br />
|
||||
* Caused by directly selecting the <code>CREATE</code> statements of the tables and executing them again.<br />
|
||||
* The problem with this approach was that various different Android environments had different String quotes
|
||||
* (<code>"</code>, <code>'</code>, <code>`</code>) which messed up table name replacement logic.<br />
|
||||
* Fixed by explicitly creating each table manually.
|
||||
* <p>
|
||||
* Affected app versions: <code>1017000 (1.17.0)</code> - <code>1017002 (1.17.2)</code>
|
||||
* </li>
|
||||
* <li>
|
||||
* <a href="https://github.com/stefan-niedermann/nextcloud-deck/issues/935">2. issue: SQLiteConstraintException</a>
|
||||
* <p>
|
||||
* <code>SQLiteConstraintException: NOT NULL constraint failed: Activity_tmp.type (code 1299 SQLITE_CONSTRAINT_NOTNULL[1299])</code><br />
|
||||
* Fixed by explicitly selecting the values of each column manually instead of using a wildcard
|
||||
* <p>
|
||||
* To fix states where the migration was partially successful, the <code>*_tmp</code> tables will be dropped, so a half migration can successfully continue.
|
||||
* <p>
|
||||
* Affected app versions: <code>1017000 (1.17.3)</code> - <code>1017002 (1.17.6)</code>
|
||||
* </li>
|
||||
* </ul>
|
||||
*/
|
||||
public class Migration_30_31 extends Migration {
|
||||
|
||||
public Migration_30_31() {
|
||||
super(30, 31);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||
database.execSQL("DROP TABLE IF EXISTS `AccessControl_tmp`");
|
||||
database.execSQL("CREATE TABLE `AccessControl_tmp` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER, `etag` TEXT, `type` INTEGER, `boardId` INTEGER, `owner` INTEGER NOT NULL, `permissionEdit` INTEGER NOT NULL, `permissionShare` INTEGER NOT NULL, `permissionManage` INTEGER NOT NULL, `userId` INTEGER, FOREIGN KEY(`boardId`) REFERENCES `Board`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON DELETE CASCADE )");
|
||||
database.execSQL("DELETE FROM `AccessControl` where accountId not in (select id from `Account`)");
|
||||
database.execSQL("INSERT INTO `AccessControl_tmp` (`localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `type`, `boardId`, `owner`, `permissionEdit`, `permissionShare`, `permissionManage`, `userId`) select `localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `type`, `boardId`, `owner`, `permissionEdit`, `permissionShare`, `permissionManage`, `userId` from `AccessControl`");
|
||||
database.execSQL("DROP TABLE `AccessControl`");
|
||||
database.execSQL("ALTER TABLE `AccessControl_tmp` RENAME TO `AccessControl`");
|
||||
database.execSQL("CREATE INDEX `acl_accId` ON `AccessControl` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `index_AccessControl_boardId` ON `AccessControl` (`boardId`)");
|
||||
database.execSQL("CREATE INDEX `index_AccessControl_accountId` ON `AccessControl` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `index_AccessControl_id` ON `AccessControl` (`id`)");
|
||||
database.execSQL("CREATE INDEX `index_AccessControl_lastModifiedLocal` ON `AccessControl` (`lastModifiedLocal`)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `index_AccessControl_accountId_id` ON `AccessControl` (`accountId`, `id`)");
|
||||
|
||||
database.execSQL("DROP TABLE IF EXISTS `Activity_tmp`");
|
||||
database.execSQL("CREATE TABLE `Activity_tmp` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER, `etag` TEXT, `cardId` INTEGER NOT NULL, `subject` TEXT, `type` INTEGER NOT NULL, FOREIGN KEY(`cardId`) REFERENCES `Card`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON DELETE CASCADE )");
|
||||
database.execSQL("DELETE FROM `Activity` where accountId not in (select id from `Account`)");
|
||||
database.execSQL("UPDATE `Activity` SET `type` = 2 WHERE `type` IS NULL");
|
||||
database.execSQL("INSERT INTO `Activity_tmp` (`localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `cardId`, `subject`, `type`) select `localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `cardId`, `subject`, COALESCE(`type`, 2) from `Activity`");
|
||||
database.execSQL("DROP TABLE `Activity`");
|
||||
database.execSQL("ALTER TABLE `Activity_tmp` RENAME TO `Activity`");
|
||||
database.execSQL("CREATE INDEX `activity_accID` ON `Activity` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `activity_cardID` ON `Activity` (`cardId`)");
|
||||
database.execSQL("CREATE INDEX `index_Activity_accountId` ON `Activity` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `index_Activity_id` ON `Activity` (`id`)");
|
||||
database.execSQL("CREATE INDEX `index_Activity_lastModifiedLocal` ON `Activity` (`lastModifiedLocal`)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `index_Activity_accountId_id` ON `Activity` (`accountId`, `id`)");
|
||||
|
||||
database.execSQL("DROP TABLE IF EXISTS `Attachment_tmp`");
|
||||
database.execSQL("CREATE TABLE `Attachment_tmp` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER, `etag` TEXT, `cardId` INTEGER NOT NULL, `type` TEXT, `data` TEXT, `createdAt` INTEGER, `createdBy` TEXT, `deletedAt` INTEGER, `filesize` INTEGER NOT NULL, `mimetype` TEXT, `dirname` TEXT, `basename` TEXT, `extension` TEXT, `filename` TEXT, `localPath` TEXT, `fileId` INTEGER, FOREIGN KEY(`cardId`) REFERENCES `Card`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON DELETE CASCADE )");
|
||||
database.execSQL("DELETE FROM `Attachment` where accountId not in (select id from `Account`)");
|
||||
database.execSQL("INSERT INTO `Attachment_tmp` (`localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `cardId`, `type`, `data`, `createdAt`, `createdBy`, `deletedAt`, `filesize`, `mimetype`, `dirname`, `basename`, `extension`, `filename`, `localPath`, `fileId`) select `localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `cardId`, `type`, `data`, `createdAt`, `createdBy`, `deletedAt`, `filesize`, `mimetype`, `dirname`, `basename`, `extension`, `filename`, `localPath`, `fileId` from `Attachment`");
|
||||
database.execSQL("DROP TABLE `Attachment`");
|
||||
database.execSQL("ALTER TABLE `Attachment_tmp` RENAME TO `Attachment`");
|
||||
database.execSQL("CREATE INDEX `index_Attachment_cardId` ON `Attachment` (`cardId`)");
|
||||
database.execSQL("CREATE INDEX `index_Attachment_accountId` ON `Attachment` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `index_Attachment_id` ON `Attachment` (`id`)");
|
||||
database.execSQL("CREATE INDEX `index_Attachment_lastModifiedLocal` ON `Attachment` (`lastModifiedLocal`)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `index_Attachment_accountId_id` ON `Attachment` (`accountId`, `id`)");
|
||||
|
||||
database.execSQL("DROP TABLE IF EXISTS `Board_tmp`");
|
||||
database.execSQL("CREATE TABLE `Board_tmp` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER, `etag` TEXT, `title` TEXT, `ownerId` INTEGER NOT NULL, `color` INTEGER, `archived` INTEGER NOT NULL, `shared` INTEGER NOT NULL, `deletedAt` INTEGER, `permissionRead` INTEGER NOT NULL, `permissionEdit` INTEGER NOT NULL, `permissionManage` INTEGER NOT NULL, `permissionShare` INTEGER NOT NULL, FOREIGN KEY(`ownerId`) REFERENCES `User`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON DELETE CASCADE )");
|
||||
database.execSQL("DELETE FROM `Board` where accountId not in (select id from `Account`)");
|
||||
database.execSQL("INSERT INTO `Board_tmp` (`localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `title`, `ownerId`, `color`, `archived`, `shared`, `deletedAt`, `permissionRead`, `permissionEdit`, `permissionManage`, `permissionShare`) select `localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `title`, `ownerId`, `color`, `archived`, `shared`, `deletedAt`, `permissionRead`, `permissionEdit`, `permissionManage`, `permissionShare` from `Board`");
|
||||
database.execSQL("DROP TABLE `Board`");
|
||||
database.execSQL("ALTER TABLE `Board_tmp` RENAME TO `Board`");
|
||||
database.execSQL("CREATE INDEX `index_Board_ownerId` ON `Board` (`ownerId`)");
|
||||
database.execSQL("CREATE INDEX `index_Board_accountId` ON `Board` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `index_Board_id` ON `Board` (`id`)");
|
||||
database.execSQL("CREATE INDEX `index_Board_lastModifiedLocal` ON `Board` (`lastModifiedLocal`)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `index_Board_accountId_id` ON `Board` (`accountId`, `id`)");
|
||||
|
||||
database.execSQL("DROP TABLE IF EXISTS `Card_tmp`");
|
||||
database.execSQL("CREATE TABLE `Card_tmp` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER, `etag` TEXT, `title` TEXT, `description` TEXT, `stackId` INTEGER NOT NULL, `type` TEXT, `createdAt` INTEGER, `deletedAt` INTEGER, `attachmentCount` INTEGER NOT NULL, `userId` INTEGER, `order` INTEGER NOT NULL, `archived` INTEGER NOT NULL, `dueDate` INTEGER, `notified` INTEGER NOT NULL, `overdue` INTEGER NOT NULL, `commentsUnread` INTEGER NOT NULL, FOREIGN KEY(`stackId`) REFERENCES `Stack`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON DELETE CASCADE )");
|
||||
database.execSQL("DELETE FROM `Card` where accountId not in (select id from `Account`)");
|
||||
database.execSQL("INSERT INTO `Card_tmp` (`localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `title`, `description`, `stackId`, `type`, `createdAt`, `deletedAt`, `attachmentCount`, `userId`, `order`, `archived`, `dueDate`, `notified`, `overdue`, `commentsUnread`) select `localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `title`, `description`, `stackId`, `type`, `createdAt`, `deletedAt`, `attachmentCount`, `userId`, `order`, `archived`, `dueDate`, `notified`, `overdue`, `commentsUnread` from `Card`");
|
||||
database.execSQL("DROP TABLE `Card`");
|
||||
database.execSQL("ALTER TABLE `Card_tmp` RENAME TO `Card`");
|
||||
database.execSQL("CREATE INDEX `card_accID` ON `Card` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `index_Card_stackId` ON `Card` (`stackId`)");
|
||||
database.execSQL("CREATE INDEX `index_Card_accountId` ON `Card` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `index_Card_id` ON `Card` (`id`)");
|
||||
database.execSQL("CREATE INDEX `index_Card_lastModifiedLocal` ON `Card` (`lastModifiedLocal`)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `index_Card_accountId_id` ON `Card` (`accountId`, `id`)");
|
||||
|
||||
database.execSQL("DROP TABLE IF EXISTS `DeckComment_tmp`");
|
||||
database.execSQL("CREATE TABLE `DeckComment_tmp` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER, `etag` TEXT, `objectId` INTEGER, `actorType` TEXT, `creationDateTime` INTEGER, `actorId` TEXT, `actorDisplayName` TEXT, `message` TEXT, `parentId` INTEGER, FOREIGN KEY(`objectId`) REFERENCES `Card`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`parentId`) REFERENCES `DeckComment`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON DELETE CASCADE )");
|
||||
database.execSQL("DELETE FROM `DeckComment` where accountId not in (select id from `Account`)");
|
||||
database.execSQL("INSERT INTO `DeckComment_tmp` (`localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `objectId`, `actorType`, `creationDateTime`, `actorId`, `actorDisplayName`, `message`, `parentId`) select `localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `objectId`, `actorType`, `creationDateTime`, `actorId`, `actorDisplayName`, `message`, `parentId` from `DeckComment`");
|
||||
database.execSQL("DROP TABLE `DeckComment`");
|
||||
database.execSQL("ALTER TABLE `DeckComment_tmp` RENAME TO `DeckComment`");
|
||||
database.execSQL("CREATE INDEX `comment_accID` ON `DeckComment` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `index_DeckComment_objectId` ON `DeckComment` (`objectId`)");
|
||||
database.execSQL("CREATE INDEX `idx_comment_parentID` ON `DeckComment` (`parentId`)");
|
||||
database.execSQL("CREATE INDEX `index_DeckComment_accountId` ON `DeckComment` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `index_DeckComment_id` ON `DeckComment` (`id`)");
|
||||
database.execSQL("CREATE INDEX `index_DeckComment_lastModifiedLocal` ON `DeckComment` (`lastModifiedLocal`)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `index_DeckComment_accountId_id` ON `DeckComment` (`accountId`, `id`)");
|
||||
|
||||
database.execSQL("DROP TABLE IF EXISTS `Label_tmp`");
|
||||
database.execSQL("CREATE TABLE `Label_tmp` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER, `etag` TEXT, `title` TEXT, `color` INTEGER NOT NULL DEFAULT 0, `boardId` INTEGER NOT NULL, FOREIGN KEY(`boardId`) REFERENCES `Board`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON DELETE CASCADE )");
|
||||
database.execSQL("DELETE FROM `Label` where accountId not in (select id from `Account`)");
|
||||
database.execSQL("INSERT INTO `Label_tmp` (`localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `title`, `color`, `boardId`) select `localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `title`, `color`, `boardId` from `Label`");
|
||||
database.execSQL("DROP TABLE `Label`");
|
||||
database.execSQL("ALTER TABLE `Label_tmp` RENAME TO `Label`");
|
||||
database.execSQL("CREATE INDEX `index_Label_boardId` ON `Label` (`boardId`)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `idx_label_title_unique` ON `Label` (`boardId`, `title`)");
|
||||
database.execSQL("CREATE INDEX `index_Label_accountId` ON `Label` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `index_Label_id` ON `Label` (`id`)");
|
||||
database.execSQL("CREATE INDEX `index_Label_lastModifiedLocal` ON `Label` (`lastModifiedLocal`)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `index_Label_accountId_id` ON `Label` (`accountId`, `id`)");
|
||||
|
||||
database.execSQL("DROP TABLE IF EXISTS `OcsProject_tmp`");
|
||||
database.execSQL("CREATE TABLE `OcsProject_tmp` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER, `etag` TEXT, `name` TEXT NOT NULL, FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON DELETE CASCADE )");
|
||||
database.execSQL("DELETE FROM `OcsProject` where accountId not in (select id from `Account`)");
|
||||
database.execSQL("INSERT INTO `OcsProject_tmp` (`localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `name`) select `localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `name` from `OcsProject`");
|
||||
database.execSQL("DROP TABLE `OcsProject`");
|
||||
database.execSQL("ALTER TABLE `OcsProject_tmp` RENAME TO `OcsProject`");
|
||||
database.execSQL("CREATE INDEX `index_project_accID` ON `OcsProject` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `index_OcsProject_accountId` ON `OcsProject` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `index_OcsProject_id` ON `OcsProject` (`id`)");
|
||||
database.execSQL("CREATE INDEX `index_OcsProject_lastModifiedLocal` ON `OcsProject` (`lastModifiedLocal`)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `index_OcsProject_accountId_id` ON `OcsProject` (`accountId`, `id`)");
|
||||
|
||||
database.execSQL("DROP TABLE IF EXISTS `OcsProjectResource_tmp`");
|
||||
database.execSQL("CREATE TABLE `OcsProjectResource_tmp` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER, `etag` TEXT, `type` TEXT, `name` TEXT, `link` TEXT, `path` TEXT, `iconUrl` TEXT, `mimetype` TEXT, `previewAvailable` INTEGER, `idString` TEXT, `projectId` INTEGER NOT NULL, FOREIGN KEY(`projectId`) REFERENCES `OcsProject`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON DELETE CASCADE )");
|
||||
database.execSQL("DELETE FROM `OcsProjectResource` where accountId not in (select id from `Account`)");
|
||||
database.execSQL("INSERT INTO `OcsProjectResource_tmp` (`localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `type`, `name`, `link`, `path`, `iconUrl`, `mimetype`, `previewAvailable`, `idString`, `projectId`) select `localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `type`, `name`, `link`, `path`, `iconUrl`, `mimetype`, `previewAvailable`, `idString`, `projectId` from `OcsProjectResource`");
|
||||
database.execSQL("DROP TABLE `OcsProjectResource`");
|
||||
database.execSQL("ALTER TABLE `OcsProjectResource_tmp` RENAME TO `OcsProjectResource`");
|
||||
database.execSQL("CREATE INDEX `index_OcsProjectResource_id` ON `OcsProjectResource` (`id`)");
|
||||
database.execSQL("CREATE INDEX `index_OcsProjectResource_lastModifiedLocal` ON `OcsProjectResource` (`lastModifiedLocal`)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `index_OcsProjectResource_accountId_id` ON `OcsProjectResource` (`accountId`, `id`, `idString`, `projectId`)");
|
||||
database.execSQL("CREATE INDEX `index_projectResource_accID` ON `OcsProjectResource` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `index_projectResource_projectId` ON `OcsProjectResource` (`projectId`)");
|
||||
|
||||
database.execSQL("DROP TABLE IF EXISTS `Stack_tmp`");
|
||||
database.execSQL("CREATE TABLE `Stack_tmp` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER, `etag` TEXT, `title` TEXT, `boardId` INTEGER NOT NULL, `deletedAt` INTEGER, `order` INTEGER NOT NULL, FOREIGN KEY(`boardId`) REFERENCES `Board`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON DELETE CASCADE )");
|
||||
database.execSQL("DELETE FROM `Stack` where accountId not in (select id from `Account`)");
|
||||
database.execSQL("INSERT INTO `Stack_tmp` (`localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `title`, `boardId`, `deletedAt`, `order`) select `localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `title`, `boardId`, `deletedAt`, `order` from `Stack`");
|
||||
database.execSQL("DROP TABLE `Stack`");
|
||||
database.execSQL("ALTER TABLE `Stack_tmp` RENAME TO `Stack`");
|
||||
database.execSQL("CREATE INDEX `index_Stack_boardId` ON `Stack` (`boardId`)");
|
||||
database.execSQL("CREATE INDEX `index_Stack_accountId` ON `Stack` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `index_Stack_id` ON `Stack` (`id`)");
|
||||
database.execSQL("CREATE INDEX `index_Stack_lastModifiedLocal` ON `Stack` (`lastModifiedLocal`)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `index_Stack_accountId_id` ON `Stack` (`accountId`, `id`)");
|
||||
|
||||
database.execSQL("DROP TABLE IF EXISTS `User_tmp`");
|
||||
database.execSQL("CREATE TABLE `User_tmp` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER, `etag` TEXT, `primaryKey` TEXT, `uid` TEXT, `displayname` TEXT, FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON DELETE CASCADE )");
|
||||
database.execSQL("DELETE FROM `User` where accountId not in (select id from `Account`)");
|
||||
database.execSQL("INSERT INTO `User_tmp` (`localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `primaryKey`, `uid`, `displayname`) select `localId`, `accountId`, `id`, `status`, `lastModified`, `lastModifiedLocal`, `etag`, `primaryKey`, `uid`, `displayname` from `User`");
|
||||
database.execSQL("DROP TABLE `User`");
|
||||
database.execSQL("ALTER TABLE `User_tmp` RENAME TO `User`");
|
||||
database.execSQL("CREATE INDEX `user_uid` ON `User` (`uid`)");
|
||||
database.execSQL("CREATE INDEX `index_User_accountId` ON `User` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `index_User_id` ON `User` (`id`)");
|
||||
database.execSQL("CREATE INDEX `index_User_lastModifiedLocal` ON `User` (`lastModifiedLocal`)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `index_User_accountId_id` ON `User` (`accountId`, `id`)");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class Migration_31_32 extends Migration {
|
||||
|
||||
@NonNull
|
||||
private final Context context;
|
||||
public Migration_31_32(@NonNull Context context) {
|
||||
super(31, 32);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||
PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.edit()
|
||||
.remove("it.niedermann.nextcloud.deck.theme_main")
|
||||
.remove("it.niedermann.nextcloud.deck.last_account_color")
|
||||
.apply();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* Adds support for marking a card as done: https://github.com/stefan-niedermann/nextcloud-deck/issues/1556
|
||||
*/
|
||||
public class Migration_32_33 extends Migration {
|
||||
|
||||
public Migration_32_33() {
|
||||
super(32, 33);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||
database.execSQL("ALTER TABLE `Card` add column done INTEGER");
|
||||
// Reset ETags: Refetch all cards to support Done state which did not change ETags
|
||||
database.execSQL("UPDATE `Account` SET `boardsEtag` = NULL");
|
||||
database.execSQL("UPDATE `Board` SET `etag` = NULL");
|
||||
database.execSQL("UPDATE `Stack` SET `etag` = NULL");
|
||||
database.execSQL("UPDATE `Card` SET `etag` = NULL");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* Adds support for marking a card as done: https://github.com/stefan-niedermann/nextcloud-deck/issues/1556
|
||||
*/
|
||||
public class Migration_33_34 extends Migration {
|
||||
|
||||
public Migration_33_34() {
|
||||
super(33, 34);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||
database.execSQL("ALTER TABLE `User` add column type INTEGER not null default 0");
|
||||
// Reset ETags to refetch Users
|
||||
database.execSQL("UPDATE `Account` SET `boardsEtag` = NULL");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* Adds support for comments
|
||||
*/
|
||||
public class Migration_8_9 extends Migration {
|
||||
|
||||
public Migration_8_9() {
|
||||
super(8, 9);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
database.execSQL("CREATE TABLE `DeckComment` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER, `objectId` INTEGER, `actorType` TEXT, `creationDateTime` INTEGER, `actorId` TEXT, `actorDisplayName` TEXT, `message` TEXT, FOREIGN KEY(`objectId`) REFERENCES `Card`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE )");
|
||||
database.execSQL("CREATE TABLE `Mention` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `commentId` INTEGER, `mentionId` TEXT, `mentionType` TEXT, `mentionDisplayName` TEXT, FOREIGN KEY(`commentId`) REFERENCES `DeckComment`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE )");
|
||||
database.execSQL("CREATE INDEX `index_DeckComment_accountId` ON `DeckComment` (`accountId`)");
|
||||
database.execSQL("CREATE INDEX `comment_accID` ON `DeckComment` (`accountId`)");
|
||||
database.execSQL("CREATE UNIQUE INDEX `index_DeckComment_accountId_id` ON `DeckComment` (`accountId`, `id`)");
|
||||
database.execSQL("CREATE INDEX `index_DeckComment_id` ON `DeckComment` (`id`)");
|
||||
database.execSQL("CREATE INDEX `index_DeckComment_lastModifiedLocal` ON `DeckComment` (`lastModifiedLocal`)");
|
||||
database.execSQL("CREATE INDEX `index_DeckComment_objectId` ON `DeckComment` (`objectId`)");
|
||||
database.execSQL("CREATE INDEX `index_Mention_commentId` ON `Mention` (`commentId`)");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package it.niedermann.nextcloud.deck.database.migration;
|
||||
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
/**
|
||||
* Adds support for account colors, deck server versions and Nextcloud maintenance mode
|
||||
*/
|
||||
public class Migration_9_10 extends Migration {
|
||||
|
||||
public Migration_9_10() {
|
||||
super(9, 10);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
database.execSQL("ALTER TABLE `Account` ADD `color` TEXT NOT NULL DEFAULT '#0082c9'");
|
||||
database.execSQL("ALTER TABLE `Account` ADD `textColor` TEXT NOT NULL DEFAULT '#ffffff'");
|
||||
database.execSQL("ALTER TABLE `Account` ADD `serverDeckVersion` TEXT NOT NULL DEFAULT '0.6.4'");
|
||||
database.execSQL("ALTER TABLE `Account` ADD `maintenanceEnabled` INTEGER NOT NULL DEFAULT 0");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package it.niedermann.nextcloud.deck.exceptions;
|
||||
|
||||
public class DeckException extends IllegalArgumentException {
|
||||
|
||||
public enum Hint {
|
||||
CAPABILITIES_NOT_PARSABLE,
|
||||
CAPABILITIES_VERSION_NOT_PARSABLE,
|
||||
UNKNOWN_ACCOUNT_USER_ID,
|
||||
DEPENDENCY_NOT_SYNCED_YET
|
||||
}
|
||||
|
||||
private final Hint hint;
|
||||
|
||||
public DeckException(Hint hint, String message) {
|
||||
super(message);
|
||||
this.hint = hint;
|
||||
}
|
||||
|
||||
public Hint getHint() {
|
||||
return hint;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package it.niedermann.nextcloud.deck.exceptions;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException;
|
||||
|
||||
public enum HandledServerErrors {
|
||||
UNKNOWN(1337, "hopefully won't occur"),
|
||||
LABELS_TITLE_MUST_BE_UNIQUE(400, "Title must be unique"),
|
||||
ATTACHMENTS_FILE_ALREADY_EXISTS(409, "File already exists."),
|
||||
;
|
||||
|
||||
private final int status;
|
||||
private final String message;
|
||||
|
||||
HandledServerErrors(int status, String message) {
|
||||
this.status = status;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public static HandledServerErrors fromThrowable(Throwable throwable) {
|
||||
if (throwable instanceof NextcloudHttpRequestFailedException requestFailedException) {
|
||||
if (requestFailedException.getCause() != null) {
|
||||
String errorString = requestFailedException.getCause().getMessage();
|
||||
try {
|
||||
JsonElement jsonElement = JsonParser.parseString(errorString);
|
||||
if (jsonElement.isJsonObject()){
|
||||
ServerError error = new ServerError();
|
||||
error.status = requestFailedException.getStatusCode();
|
||||
JsonObject errorObj = jsonElement.getAsJsonObject();
|
||||
if (errorObj.has("message")){
|
||||
error.message = errorObj.get("message").getAsString();
|
||||
}
|
||||
return findByServerError(error);
|
||||
}
|
||||
} catch (JsonSyntaxException e){
|
||||
return HandledServerErrors.UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
return HandledServerErrors.UNKNOWN;
|
||||
}
|
||||
|
||||
private static HandledServerErrors findByServerError(ServerError error) {
|
||||
for (HandledServerErrors value : HandledServerErrors.values()) {
|
||||
if (value.status == error.status && value.message.equals(error.message)){
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return HandledServerErrors.UNKNOWN;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
private static class ServerError {
|
||||
private int status;
|
||||
private String message;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package it.niedermann.nextcloud.deck.exceptions;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import it.niedermann.nextcloud.deck.R;
|
||||
|
||||
public class OfflineException extends IllegalStateException {
|
||||
|
||||
private final Reason reason;
|
||||
|
||||
public OfflineException() {
|
||||
this(Reason.OFFLINE);
|
||||
}
|
||||
|
||||
public OfflineException(@NonNull Reason reason) {
|
||||
super(reason.getKey());
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Reason getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
public enum Reason {
|
||||
OFFLINE("Device is currently offline", R.string.error_dialog_tip_offline_no_internet),
|
||||
CONNECTION_REFUSED("Connection refused", R.string.error_dialog_tip_offline_connection_refused),
|
||||
CONNECTION_TIMEOUT("Connection timeout", R.string.error_dialog_tip_offline_connection_timeout),
|
||||
CONNECTION_REJECTED("Connection rejected", R.string.error_dialog_tip_connection_rejected),
|
||||
;
|
||||
|
||||
private final String key;
|
||||
@StringRes
|
||||
private final int message;
|
||||
|
||||
Reason(@NonNull String key, @StringRes int message) {
|
||||
this.key = key;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@StringRes
|
||||
public int getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package it.niedermann.nextcloud.deck.exceptions;
|
||||
|
||||
import it.niedermann.nextcloud.deck.DeckLog;
|
||||
|
||||
public class TraceableException extends RuntimeException {
|
||||
|
||||
private TraceableException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public static void makeTraceableIfFails(Runnable runnable, Object... args) {
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (TraceableException t) {
|
||||
throw t;
|
||||
} catch (Throwable t) {
|
||||
final StringBuilder message = new StringBuilder("Sorry, a wild error appeared!\n\n" +
|
||||
"⚠️ If you want to tell us about the following issue, " +
|
||||
"please make sure to censor sensitive data beforehand! ⚠️\n\n" +
|
||||
"Failed to run traceable code");
|
||||
if (args != null && args.length > 0) {
|
||||
message.append(" with arguments:\n");
|
||||
for (Object arg : args) {
|
||||
message.append(arg == null ? "null" : arg.toString()).append("\n");
|
||||
}
|
||||
} else {
|
||||
message.append(":\n");
|
||||
}
|
||||
|
||||
message.append("Cause: ").append(t.getLocalizedMessage());
|
||||
TraceableException ex = new TraceableException(message.toString(), t);
|
||||
DeckLog.logError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package it.niedermann.nextcloud.deck.exceptions;
|
||||
|
||||
public class UploadAttachmentFailedException extends Exception {
|
||||
|
||||
public UploadAttachmentFailedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public UploadAttachmentFailedException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
package it.niedermann.nextcloud.deck.model;
|
||||
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Ignore;
|
||||
import androidx.room.Index;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.interfaces.AbstractRemoteEntity;
|
||||
import it.niedermann.nextcloud.deck.model.ocs.user.GroupMemberUIDs;
|
||||
|
||||
@Entity(inheritSuperIndices = true,
|
||||
indices = {
|
||||
@Index(value = "accountId", name = "acl_accId"),
|
||||
@Index("boardId")
|
||||
},
|
||||
foreignKeys = {
|
||||
@ForeignKey(
|
||||
entity = Board.class,
|
||||
parentColumns = "localId",
|
||||
childColumns = "boardId", onDelete = ForeignKey.CASCADE
|
||||
),
|
||||
@ForeignKey(
|
||||
entity = Account.class,
|
||||
parentColumns = "id",
|
||||
childColumns = "accountId", onDelete = ForeignKey.CASCADE
|
||||
|
||||
)
|
||||
}
|
||||
)
|
||||
public class AccessControl extends AbstractRemoteEntity {
|
||||
|
||||
private Long type;
|
||||
private Long boardId;
|
||||
private boolean owner;
|
||||
private boolean permissionEdit;
|
||||
private boolean permissionShare;
|
||||
private boolean permissionManage;
|
||||
|
||||
private Long userId;
|
||||
@Ignore
|
||||
@SerializedName("participant")
|
||||
private User user;
|
||||
@Ignore
|
||||
private GroupMemberUIDs groupMemberUIDs;
|
||||
|
||||
public AccessControl() {
|
||||
super();
|
||||
}
|
||||
|
||||
public AccessControl(AccessControl accessControl) {
|
||||
this.type = accessControl.getType();
|
||||
this.boardId = accessControl.getBoardId();
|
||||
this.owner = accessControl.isOwner();
|
||||
this.permissionEdit = accessControl.isPermissionEdit();
|
||||
this.permissionShare = accessControl.isPermissionShare();
|
||||
this.permissionManage = accessControl.isPermissionManage();
|
||||
this.userId = accessControl.getUserId();
|
||||
this.user = accessControl.getUser();
|
||||
}
|
||||
|
||||
public Long getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(Long type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Long getBoardId() {
|
||||
return boardId;
|
||||
}
|
||||
|
||||
public void setBoardId(Long boardId) {
|
||||
this.boardId = boardId;
|
||||
}
|
||||
|
||||
public boolean isOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(boolean owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public boolean isPermissionEdit() {
|
||||
return permissionEdit;
|
||||
}
|
||||
|
||||
public void setPermissionEdit(boolean permissionEdit) {
|
||||
this.permissionEdit = permissionEdit;
|
||||
}
|
||||
|
||||
public boolean isPermissionShare() {
|
||||
return permissionShare;
|
||||
}
|
||||
|
||||
public void setPermissionShare(boolean permissionShare) {
|
||||
this.permissionShare = permissionShare;
|
||||
}
|
||||
|
||||
public boolean isPermissionManage() {
|
||||
return permissionManage;
|
||||
}
|
||||
|
||||
public void setPermissionManage(boolean permissionManage) {
|
||||
this.permissionManage = permissionManage;
|
||||
}
|
||||
|
||||
public Long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(Long userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public GroupMemberUIDs getGroupMemberUIDs() {
|
||||
return groupMemberUIDs;
|
||||
}
|
||||
|
||||
public void setGroupMemberUIDs(GroupMemberUIDs groupMemberUIDs) {
|
||||
this.groupMemberUIDs = groupMemberUIDs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
|
||||
AccessControl that = (AccessControl) o;
|
||||
|
||||
if (owner != that.owner) return false;
|
||||
if (permissionEdit != that.permissionEdit) return false;
|
||||
if (permissionShare != that.permissionShare) return false;
|
||||
if (permissionManage != that.permissionManage) return false;
|
||||
if (!Objects.equals(type, that.type)) return false;
|
||||
if (!Objects.equals(boardId, that.boardId)) return false;
|
||||
if (!Objects.equals(userId, that.userId)) return false;
|
||||
return Objects.equals(user, that.user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + (type != null ? type.hashCode() : 0);
|
||||
result = 31 * result + (boardId != null ? boardId.hashCode() : 0);
|
||||
result = 31 * result + (owner ? 1 : 0);
|
||||
result = 31 * result + (permissionEdit ? 1 : 0);
|
||||
result = 31 * result + (permissionShare ? 1 : 0);
|
||||
result = 31 * result + (permissionManage ? 1 : 0);
|
||||
result = 31 * result + (userId != null ? userId.hashCode() : 0);
|
||||
result = 31 * result + (user != null ? user.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AccessControl{" +
|
||||
"type=" + type +
|
||||
", boardId=" + boardId +
|
||||
", owner=" + owner +
|
||||
", permissionEdit=" + permissionEdit +
|
||||
", permissionShare=" + permissionShare +
|
||||
", permissionManage=" + permissionManage +
|
||||
", userId=" + userId +
|
||||
", user=" + user +
|
||||
", localId=" + localId +
|
||||
", accountId=" + accountId +
|
||||
", id=" + id +
|
||||
", status=" + status +
|
||||
", lastModified=" + lastModified +
|
||||
", lastModifiedLocal=" + lastModifiedLocal +
|
||||
"} " + super.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,284 @@
|
|||
package it.niedermann.nextcloud.deck.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.Px;
|
||||
import androidx.room.ColumnInfo;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.Ignore;
|
||||
import androidx.room.Index;
|
||||
import androidx.room.PrimaryKey;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.nextcloud.android.sso.AccountImporter;
|
||||
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
|
||||
import com.nextcloud.android.sso.model.SingleSignOnAccount;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import it.niedermann.nextcloud.deck.DeckLog;
|
||||
import it.niedermann.nextcloud.deck.model.ocs.Capabilities;
|
||||
import it.niedermann.nextcloud.deck.model.ocs.Version;
|
||||
import it.niedermann.nextcloud.sso.glide.SingleSignOnUrl;
|
||||
|
||||
@Entity(indices = {@Index(value = "name", unique = true)})
|
||||
public class Account implements Serializable {
|
||||
@Ignore
|
||||
private static final long serialVersionUID = 0;
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
protected Long id;
|
||||
|
||||
@NonNull
|
||||
private String name;
|
||||
|
||||
@NonNull
|
||||
private String userName;
|
||||
|
||||
@Ignore
|
||||
@Nullable
|
||||
private String userDisplayName;
|
||||
|
||||
@NonNull
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* See {@link Capabilities#DEFAULT_COLOR}
|
||||
*/
|
||||
@NonNull
|
||||
@ColumnInfo(defaultValue = "0")
|
||||
private Integer color = Capabilities.DEFAULT_COLOR;
|
||||
|
||||
@NonNull
|
||||
@ColumnInfo(defaultValue = "0")
|
||||
private Integer textColor = Capabilities.DEFAULT_TEXT_COLOR;
|
||||
|
||||
@NonNull
|
||||
@ColumnInfo(defaultValue = "0.6.4")
|
||||
private String serverDeckVersion = "0.6.4";
|
||||
|
||||
@NonNull
|
||||
@ColumnInfo(defaultValue = "0")
|
||||
private boolean maintenanceEnabled = false;
|
||||
|
||||
private String etag;
|
||||
private String boardsEtag;
|
||||
|
||||
@Ignore
|
||||
public Account(Long id, @NonNull String name, @NonNull String userName, @NonNull String url) {
|
||||
this(name, userName, url);
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public Account(@NonNull String name, @NonNull String userName, @NonNull String url) {
|
||||
this.name = name;
|
||||
this.userName = userName;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public Account(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Account() {
|
||||
}
|
||||
|
||||
public void applyCapabilities(Capabilities capabilities, String eTag) {
|
||||
if (capabilities == null) {
|
||||
maintenanceEnabled = true;
|
||||
return;
|
||||
}
|
||||
maintenanceEnabled = capabilities.isMaintenanceEnabled();
|
||||
if (!isMaintenanceEnabled()) {
|
||||
try {
|
||||
// Nextcloud might return color format #000 which cannot be parsed by Color.parseColor()
|
||||
// https://github.com/stefan-niedermann/nextcloud-deck/issues/466
|
||||
color = capabilities.getColor();
|
||||
textColor = capabilities.getTextColor();
|
||||
} catch (Exception e) {
|
||||
DeckLog.logError(e);
|
||||
color = Capabilities.DEFAULT_COLOR;
|
||||
textColor = Capabilities.DEFAULT_TEXT_COLOR;
|
||||
}
|
||||
if (capabilities.getDeckVersion() != null) {
|
||||
serverDeckVersion = capabilities.getDeckVersion().getOriginalVersion();
|
||||
}
|
||||
if (eTag != null) {
|
||||
this.etag = eTag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(@NonNull String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(@NonNull String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(@NonNull String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public static long getSerialVersionUID() {
|
||||
return serialVersionUID;
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
@NonNull
|
||||
public Integer getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public void setColor(@NonNull Integer color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Integer getTextColor() {
|
||||
return textColor;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setTextColor(@NonNull Integer textColor) {
|
||||
this.textColor = textColor;
|
||||
}
|
||||
|
||||
public Version getServerDeckVersionAsObject() {
|
||||
return Version.of(serverDeckVersion);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getServerDeckVersion() {
|
||||
return serverDeckVersion;
|
||||
}
|
||||
|
||||
public void setServerDeckVersion(@NonNull String serverDeckVersion) {
|
||||
this.serverDeckVersion = serverDeckVersion;
|
||||
}
|
||||
|
||||
public boolean isMaintenanceEnabled() {
|
||||
return maintenanceEnabled;
|
||||
}
|
||||
|
||||
public void setMaintenanceEnabled(boolean maintenanceEnabled) {
|
||||
this.maintenanceEnabled = maintenanceEnabled;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getUserDisplayName() {
|
||||
return userDisplayName;
|
||||
}
|
||||
|
||||
public void setUserDisplayName(@Nullable String userDisplayName) {
|
||||
this.userDisplayName = userDisplayName;
|
||||
}
|
||||
|
||||
public String getEtag() {
|
||||
return etag;
|
||||
}
|
||||
|
||||
public void setEtag(String etag) {
|
||||
this.etag = etag;
|
||||
}
|
||||
|
||||
public String getBoardsEtag() {
|
||||
return boardsEtag;
|
||||
}
|
||||
|
||||
public void setBoardsEtag(String boardsEtag) {
|
||||
this.boardsEtag = boardsEtag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The {@link #getAvatarUrl(int, String)} of this {@link Account}
|
||||
*/
|
||||
public SingleSignOnUrl getAvatarUrl(@Px int size) {
|
||||
return getAvatarUrl(size, getUserName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a {@link SingleSignOnUrl} to fetch the avatar of the given <code>userName</code> from the instance of this {@link Account} via {@link Glide}.
|
||||
*/
|
||||
public SingleSignOnUrl getAvatarUrl(@Px int size, @NonNull String userName) {
|
||||
return new SingleSignOnUrl(getName(), getUrl() + "/index.php/avatar/" + Uri.encode(userName) + "/" + size);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Optional<SingleSignOnAccount> getSingleSignOnAccount(@NonNull Context context) {
|
||||
try {
|
||||
return Optional.of(AccountImporter.getSingleSignOnAccount(context, getName()));
|
||||
} catch (NextcloudFilesAppAccountNotFoundException e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Account account = (Account) o;
|
||||
return maintenanceEnabled == account.maintenanceEnabled &&
|
||||
Objects.equals(id, account.id) &&
|
||||
name.equals(account.name) &&
|
||||
userName.equals(account.userName) &&
|
||||
Objects.equals(userDisplayName, account.userDisplayName) &&
|
||||
url.equals(account.url) &&
|
||||
color.equals(account.color) &&
|
||||
textColor.equals(account.textColor) &&
|
||||
serverDeckVersion.equals(account.serverDeckVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, name, userName, userDisplayName, url, color, textColor, serverDeckVersion, maintenanceEnabled, etag, boardsEtag);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Account{" +
|
||||
"id=" + id +
|
||||
", name='" + name + '\'' +
|
||||
", userName='" + userName + '\'' +
|
||||
", url='" + url + '\'' +
|
||||
", color='" + color + '\'' +
|
||||
", textColor='" + textColor + '\'' +
|
||||
", serverDeckVersion='" + serverDeckVersion + '\'' +
|
||||
", maintenanceEnabled=" + maintenanceEnabled +
|
||||
", eTag='" + etag + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,247 @@
|
|||
package it.niedermann.nextcloud.deck.model;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Index;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.Objects;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.enums.EAttachmentType;
|
||||
import it.niedermann.nextcloud.deck.model.interfaces.AbstractRemoteEntity;
|
||||
|
||||
@Entity(inheritSuperIndices = true,
|
||||
indices = {@Index("cardId")},
|
||||
foreignKeys = {
|
||||
@ForeignKey(
|
||||
entity = Card.class,
|
||||
parentColumns = "localId",
|
||||
childColumns = "cardId",
|
||||
onDelete = ForeignKey.CASCADE
|
||||
),
|
||||
@ForeignKey(
|
||||
entity = Account.class,
|
||||
parentColumns = "id",
|
||||
childColumns = "accountId", onDelete = ForeignKey.CASCADE
|
||||
)
|
||||
}
|
||||
)
|
||||
public class Attachment extends AbstractRemoteEntity implements Comparable<Attachment>, Serializable {
|
||||
|
||||
private long cardId;
|
||||
// TODO use EAttachmentType
|
||||
private EAttachmentType type = EAttachmentType.DECK_FILE;
|
||||
private String data;
|
||||
private Instant createdAt;
|
||||
private String createdBy;
|
||||
private Instant deletedAt;
|
||||
private long filesize;
|
||||
private String mimetype;
|
||||
private String dirname;
|
||||
private String basename;
|
||||
private String extension;
|
||||
private String filename;
|
||||
private String localPath;
|
||||
@Nullable
|
||||
private Long fileId;
|
||||
|
||||
public long getCardId() {
|
||||
return cardId;
|
||||
}
|
||||
|
||||
public void setCardId(long cardId) {
|
||||
this.cardId = cardId;
|
||||
}
|
||||
|
||||
public EAttachmentType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(EAttachmentType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Instant getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(Instant createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public String getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
|
||||
public void setCreatedBy(String createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
}
|
||||
|
||||
public Instant getDeletedAt() {
|
||||
return deletedAt;
|
||||
}
|
||||
|
||||
public void setDeletedAt(Instant deletedAt) {
|
||||
this.deletedAt = deletedAt;
|
||||
}
|
||||
|
||||
public long getFilesize() {
|
||||
return filesize;
|
||||
}
|
||||
|
||||
public void setFilesize(long filesize) {
|
||||
this.filesize = filesize;
|
||||
}
|
||||
|
||||
public String getMimetype() {
|
||||
return mimetype;
|
||||
}
|
||||
|
||||
public void setMimetype(String mimetype) {
|
||||
this.mimetype = mimetype;
|
||||
}
|
||||
|
||||
public String getDirname() {
|
||||
return dirname;
|
||||
}
|
||||
|
||||
public void setDirname(String dirname) {
|
||||
this.dirname = dirname;
|
||||
}
|
||||
|
||||
public String getBasename() {
|
||||
return basename;
|
||||
}
|
||||
|
||||
public void setBasename(String basename) {
|
||||
this.basename = basename;
|
||||
}
|
||||
|
||||
public String getExtension() {
|
||||
return extension;
|
||||
}
|
||||
|
||||
public void setExtension(String extension) {
|
||||
this.extension = extension;
|
||||
}
|
||||
|
||||
public String getFilename() {
|
||||
return filename;
|
||||
}
|
||||
|
||||
public void setFilename(String filename) {
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
public String getLocalPath() {
|
||||
return localPath;
|
||||
}
|
||||
|
||||
public void setLocalPath(String localPath) {
|
||||
this.localPath = localPath;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Long getFileId() {
|
||||
return this.fileId;
|
||||
}
|
||||
|
||||
public void setFileId(@Nullable Long fileId) {
|
||||
this.fileId = fileId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
|
||||
Attachment that = (Attachment) o;
|
||||
|
||||
if (cardId != that.cardId) return false;
|
||||
if (filesize != that.filesize) return false;
|
||||
if (!Objects.equals(type, that.type)) return false;
|
||||
if (!Objects.equals(data, that.data)) return false;
|
||||
if (!Objects.equals(createdAt, that.createdAt))
|
||||
return false;
|
||||
if (!Objects.equals(createdBy, that.createdBy))
|
||||
return false;
|
||||
if (!Objects.equals(deletedAt, that.deletedAt))
|
||||
return false;
|
||||
if (!Objects.equals(mimetype, that.mimetype))
|
||||
return false;
|
||||
if (!Objects.equals(dirname, that.dirname)) return false;
|
||||
if (!Objects.equals(basename, that.basename))
|
||||
return false;
|
||||
if (!Objects.equals(extension, that.extension))
|
||||
return false;
|
||||
if (!Objects.equals(filename, that.filename))
|
||||
return false;
|
||||
return Objects.equals(localPath, that.localPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + (int) (cardId ^ (cardId >>> 32));
|
||||
result = 31 * result + (type != null ? type.hashCode() : 0);
|
||||
result = 31 * result + (data != null ? data.hashCode() : 0);
|
||||
result = 31 * result + (createdAt != null ? createdAt.hashCode() : 0);
|
||||
result = 31 * result + (createdBy != null ? createdBy.hashCode() : 0);
|
||||
result = 31 * result + (deletedAt != null ? deletedAt.hashCode() : 0);
|
||||
result = 31 * result + (int) (filesize ^ (filesize >>> 32));
|
||||
result = 31 * result + (mimetype != null ? mimetype.hashCode() : 0);
|
||||
result = 31 * result + (dirname != null ? dirname.hashCode() : 0);
|
||||
result = 31 * result + (basename != null ? basename.hashCode() : 0);
|
||||
result = 31 * result + (extension != null ? extension.hashCode() : 0);
|
||||
result = 31 * result + (filename != null ? filename.hashCode() : 0);
|
||||
result = 31 * result + (localPath != null ? localPath.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Attachment other) {
|
||||
// DESC order
|
||||
long res = other.getModificationTimeForComparsion() - getModificationTimeForComparsion();
|
||||
if (res == 0) {
|
||||
return longToComparsionResult(other.getCreationTimeForComparsion() - getCreationTimeForComparsion());
|
||||
}
|
||||
return longToComparsionResult(res);
|
||||
}
|
||||
|
||||
private static int longToComparsionResult(long diff) {
|
||||
if (diff > 0) {
|
||||
return 1;
|
||||
} else if (diff < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long getModificationTimeForComparsion() {
|
||||
if (lastModifiedLocal != null) {
|
||||
return lastModifiedLocal.toEpochMilli();
|
||||
}
|
||||
if (lastModified != null) {
|
||||
return lastModified.toEpochMilli();
|
||||
}
|
||||
return Instant.now().toEpochMilli();
|
||||
}
|
||||
|
||||
public long getCreationTimeForComparsion() {
|
||||
if (createdAt != null) {
|
||||
return createdAt.toEpochMilli();
|
||||
}
|
||||
return Instant.now().toEpochMilli();
|
||||
}
|
||||
}
|
||||
242
app/src/main/java/it/niedermann/nextcloud/deck/model/Board.java
Normal file
242
app/src/main/java/it/niedermann/nextcloud/deck/model/Board.java
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
package it.niedermann.nextcloud.deck.model;
|
||||
|
||||
import android.graphics.Color;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Ignore;
|
||||
import androidx.room.Index;
|
||||
|
||||
import com.google.gson.annotations.JsonAdapter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.Objects;
|
||||
|
||||
import it.niedermann.android.util.ColorUtil;
|
||||
import it.niedermann.nextcloud.deck.DeckLog;
|
||||
import it.niedermann.nextcloud.deck.model.enums.DBStatus;
|
||||
import it.niedermann.nextcloud.deck.model.interfaces.AbstractRemoteEntity;
|
||||
import it.niedermann.nextcloud.deck.remote.api.json.JsonColorSerializer;
|
||||
|
||||
@Entity(
|
||||
inheritSuperIndices = true,
|
||||
indices = {@Index("ownerId")},
|
||||
foreignKeys = {
|
||||
@ForeignKey(
|
||||
entity = User.class,
|
||||
parentColumns = "localId",
|
||||
childColumns = "ownerId", onDelete = ForeignKey.CASCADE
|
||||
),
|
||||
@ForeignKey(
|
||||
entity = Account.class,
|
||||
parentColumns = "id",
|
||||
childColumns = "accountId", onDelete = ForeignKey.CASCADE
|
||||
)
|
||||
}
|
||||
)
|
||||
public class Board extends AbstractRemoteEntity implements Serializable {
|
||||
|
||||
public Board() {
|
||||
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public Board(String title, @ColorInt int color) {
|
||||
setTitle(title);
|
||||
setColor(color);
|
||||
}
|
||||
|
||||
private String title;
|
||||
private long ownerId;
|
||||
@JsonAdapter(JsonColorSerializer.class)
|
||||
private Integer color;
|
||||
private boolean archived;
|
||||
private int shared;
|
||||
private Instant deletedAt;
|
||||
private boolean permissionRead = false;
|
||||
private boolean permissionEdit = false;
|
||||
private boolean permissionManage = false;
|
||||
private boolean permissionShare = false;
|
||||
|
||||
|
||||
@Override
|
||||
public Instant getLastModified() {
|
||||
return lastModified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastModified(Instant lastModified) {
|
||||
this.lastModified = lastModified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant getLastModifiedLocal() {
|
||||
return lastModifiedLocal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastModifiedLocal(Instant lastModifiedLocal) {
|
||||
this.lastModifiedLocal = lastModifiedLocal;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
public Integer getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
public void setColor(String color) {
|
||||
try {
|
||||
setColor(Color.parseColor(ColorUtil.formatColorToParsableHexString(color)));
|
||||
} catch (Exception e) {
|
||||
DeckLog.logError(e);
|
||||
setColor(Color.GRAY);
|
||||
}
|
||||
}
|
||||
|
||||
public void setColor(@ColorInt Integer color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public boolean isArchived() {
|
||||
return archived;
|
||||
}
|
||||
//
|
||||
// public String getAcl() {
|
||||
// return acl;
|
||||
// }
|
||||
//
|
||||
// public void setAcl(String acl) {
|
||||
// this.acl = acl;
|
||||
// }
|
||||
|
||||
public int getShared() {
|
||||
return shared;
|
||||
}
|
||||
|
||||
public void setShared(int shared) {
|
||||
this.shared = shared;
|
||||
}
|
||||
|
||||
public Instant getDeletedAt() {
|
||||
return deletedAt;
|
||||
}
|
||||
|
||||
public void setDeletedAt(Instant deletedAt) {
|
||||
this.deletedAt = deletedAt;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public DBStatus getStatusEnum() {
|
||||
return DBStatus.findById(status);
|
||||
}
|
||||
|
||||
public void setStatusEnum(DBStatus status) {
|
||||
this.status = status.getId();
|
||||
}
|
||||
|
||||
public void setStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
public long getOwnerId() {
|
||||
return this.ownerId;
|
||||
}
|
||||
|
||||
public void setOwnerId(long ownerId) {
|
||||
this.ownerId = ownerId;
|
||||
}
|
||||
|
||||
public void setArchived(boolean archived) {
|
||||
this.archived = archived;
|
||||
}
|
||||
|
||||
public boolean isPermissionRead() {
|
||||
return permissionRead;
|
||||
}
|
||||
|
||||
public void setPermissionRead(boolean permissionRead) {
|
||||
this.permissionRead = permissionRead;
|
||||
}
|
||||
|
||||
public boolean isPermissionEdit() {
|
||||
return permissionEdit;
|
||||
}
|
||||
|
||||
public void setPermissionEdit(boolean permissionEdit) {
|
||||
this.permissionEdit = permissionEdit;
|
||||
}
|
||||
|
||||
public boolean isPermissionManage() {
|
||||
return permissionManage;
|
||||
}
|
||||
|
||||
public void setPermissionManage(boolean permissionManage) {
|
||||
this.permissionManage = permissionManage;
|
||||
}
|
||||
|
||||
public boolean isPermissionShare() {
|
||||
return permissionShare;
|
||||
}
|
||||
|
||||
public void setPermissionShare(boolean permissionShare) {
|
||||
this.permissionShare = permissionShare;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
|
||||
Board board = (Board) o;
|
||||
|
||||
if (ownerId != board.ownerId) return false;
|
||||
if (archived != board.archived) return false;
|
||||
if (shared != board.shared) return false;
|
||||
if (permissionRead != board.permissionRead) return false;
|
||||
if (permissionEdit != board.permissionEdit) return false;
|
||||
if (permissionManage != board.permissionManage) return false;
|
||||
if (permissionShare != board.permissionShare) return false;
|
||||
if (!Objects.equals(title, board.title)) return false;
|
||||
if (!Objects.equals(color, board.color)) return false;
|
||||
return Objects.equals(deletedAt, board.deletedAt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + (title != null ? title.hashCode() : 0);
|
||||
result = 31 * result + (int) (ownerId ^ (ownerId >>> 32));
|
||||
result = 31 * result + (color != null ? color.hashCode() : 0);
|
||||
result = 31 * result + (archived ? 1 : 0);
|
||||
result = 31 * result + shared;
|
||||
result = 31 * result + (deletedAt != null ? deletedAt.hashCode() : 0);
|
||||
result = 31 * result + (permissionRead ? 1 : 0);
|
||||
result = 31 * result + (permissionEdit ? 1 : 0);
|
||||
result = 31 * result + (permissionManage ? 1 : 0);
|
||||
result = 31 * result + (permissionShare ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
340
app/src/main/java/it/niedermann/nextcloud/deck/model/Card.java
Normal file
340
app/src/main/java/it/niedermann/nextcloud/deck/model/Card.java
Normal file
|
|
@ -0,0 +1,340 @@
|
|||
package it.niedermann.nextcloud.deck.model;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Ignore;
|
||||
import androidx.room.Index;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.enums.DBStatus;
|
||||
import it.niedermann.nextcloud.deck.model.interfaces.AbstractRemoteEntity;
|
||||
|
||||
@Entity(inheritSuperIndices = true,
|
||||
indices = {
|
||||
@Index(value = "accountId", name = "card_accID"),
|
||||
@Index("stackId")
|
||||
},
|
||||
foreignKeys = {
|
||||
@ForeignKey(
|
||||
entity = Stack.class,
|
||||
parentColumns = "localId",
|
||||
childColumns = "stackId", onDelete = ForeignKey.CASCADE
|
||||
),
|
||||
@ForeignKey(
|
||||
entity = Account.class,
|
||||
parentColumns = "id",
|
||||
childColumns = "accountId", onDelete = ForeignKey.CASCADE
|
||||
)
|
||||
}
|
||||
)
|
||||
public class Card extends AbstractRemoteEntity {
|
||||
|
||||
private static Pattern PATTERN_MD_TASK = Pattern.compile("\\[([xX ])]");
|
||||
|
||||
public static class TaskStatus {
|
||||
public int taskCount;
|
||||
public int doneCount;
|
||||
|
||||
public TaskStatus(int taskCount, int doneCount) {
|
||||
this.taskCount = taskCount;
|
||||
this.doneCount = doneCount;
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore
|
||||
private TaskStatus taskStatus = null;
|
||||
|
||||
private String title;
|
||||
private String description;
|
||||
@NonNull
|
||||
private Long stackId;
|
||||
private String type;
|
||||
private Instant createdAt;
|
||||
private Instant deletedAt;
|
||||
private Instant done;
|
||||
private int attachmentCount;
|
||||
|
||||
private Long userId;
|
||||
private int order;
|
||||
private boolean archived;
|
||||
@SerializedName("duedate")
|
||||
private Instant dueDate;
|
||||
private boolean notified;
|
||||
private int overdue;
|
||||
private int commentsUnread;
|
||||
|
||||
public Card() {
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public Card(String title, String description, long stackId) {
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.stackId = stackId;
|
||||
}
|
||||
|
||||
public Card(Card card) {
|
||||
super(card);
|
||||
this.title = card.getTitle();
|
||||
this.description = card.getDescription();
|
||||
this.stackId = card.getStackId();
|
||||
this.type = card.getType();
|
||||
this.createdAt = card.getCreatedAt();
|
||||
this.deletedAt = card.getDeletedAt();
|
||||
this.attachmentCount = card.getAttachmentCount();
|
||||
this.userId = card.getUserId();
|
||||
this.order = card.getOrder();
|
||||
this.archived = card.isArchived();
|
||||
this.dueDate = card.getDueDate();
|
||||
this.done = card.getDone();
|
||||
this.notified = card.isNotified();
|
||||
this.overdue = card.getOverdue();
|
||||
this.commentsUnread = card.getCommentsUnread();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public TaskStatus getTaskStatus() {
|
||||
if (taskStatus == null) {
|
||||
int count = 0, done = 0;
|
||||
if (description != null) {
|
||||
final Matcher matcher = PATTERN_MD_TASK.matcher(description);
|
||||
while (matcher.find()) {
|
||||
count++;
|
||||
char c = matcher.group().charAt(1);
|
||||
if (c == 'x' || c == 'X') {
|
||||
done++;
|
||||
}
|
||||
}
|
||||
}
|
||||
taskStatus = new TaskStatus(count, done);
|
||||
}
|
||||
return taskStatus;
|
||||
}
|
||||
|
||||
public boolean isNotified() {
|
||||
return notified;
|
||||
}
|
||||
|
||||
public void setNotified(boolean notified) {
|
||||
this.notified = notified;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public DBStatus getStatusEnum() {
|
||||
return DBStatus.findById(status);
|
||||
}
|
||||
|
||||
public void setStatusEnum(DBStatus status) {
|
||||
this.status = status.getId();
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
this.taskStatus = null;
|
||||
}
|
||||
|
||||
public Long getStackId() {
|
||||
return stackId;
|
||||
}
|
||||
|
||||
public void setStackId(Long stackId) {
|
||||
this.stackId = stackId;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Instant getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(Instant createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public Instant getDeletedAt() {
|
||||
return deletedAt;
|
||||
}
|
||||
|
||||
public void setDeletedAt(Instant deletedAt) {
|
||||
this.deletedAt = deletedAt;
|
||||
}
|
||||
|
||||
public int getAttachmentCount() {
|
||||
return attachmentCount;
|
||||
}
|
||||
|
||||
public void setAttachmentCount(int attachmentCount) {
|
||||
this.attachmentCount = attachmentCount;
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
public boolean isArchived() {
|
||||
return archived;
|
||||
}
|
||||
|
||||
public void setArchived(boolean archived) {
|
||||
this.archived = archived;
|
||||
}
|
||||
|
||||
public Instant getDueDate() {
|
||||
return dueDate;
|
||||
}
|
||||
|
||||
public void setDueDate(Instant dateTime) {
|
||||
this.dueDate = dateTime;
|
||||
}
|
||||
|
||||
public int getOverdue() {
|
||||
return overdue;
|
||||
}
|
||||
|
||||
public void setOverdue(int overdue) {
|
||||
this.overdue = overdue;
|
||||
}
|
||||
|
||||
public int getCommentsUnread() {
|
||||
return commentsUnread;
|
||||
}
|
||||
|
||||
public void setCommentsUnread(int commentsUnread) {
|
||||
this.commentsUnread = commentsUnread;
|
||||
}
|
||||
|
||||
public void setStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
public Long getUserId() {
|
||||
return this.userId;
|
||||
}
|
||||
|
||||
public void setUserId(Long userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
public Instant getDone() {
|
||||
return done;
|
||||
}
|
||||
|
||||
public void setDone(Instant done) {
|
||||
this.done = done;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
Card card = (Card) o;
|
||||
|
||||
if (stackId != card.stackId) return false;
|
||||
if (attachmentCount != card.attachmentCount) return false;
|
||||
if (order != card.order) return false;
|
||||
if (archived != card.archived) return false;
|
||||
if (notified != card.notified) return false;
|
||||
if (overdue != card.overdue) return false;
|
||||
if (commentsUnread != card.commentsUnread) return false;
|
||||
if (!Objects.equals(title, card.title)) return false;
|
||||
if (!Objects.equals(description, card.description))
|
||||
return false;
|
||||
if (!Objects.equals(type, card.type)) return false;
|
||||
if (!Objects.equals(createdAt, card.createdAt))
|
||||
return false;
|
||||
if (!Objects.equals(deletedAt, card.deletedAt))
|
||||
return false;
|
||||
if (!Objects.equals(done, card.done))
|
||||
return false;
|
||||
if (!Objects.equals(userId, card.userId)) return false;
|
||||
return Objects.equals(dueDate, card.dueDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = title != null ? title.hashCode() : 0;
|
||||
result = 31 * result + (description != null ? description.hashCode() : 0);
|
||||
result = 31 * result + (int) (stackId ^ (stackId >>> 32));
|
||||
result = 31 * result + (type != null ? type.hashCode() : 0);
|
||||
result = 31 * result + (createdAt != null ? createdAt.hashCode() : 0);
|
||||
result = 31 * result + (deletedAt != null ? deletedAt.hashCode() : 0);
|
||||
result = 31 * result + (done != null ? done.hashCode() : 0);
|
||||
result = 31 * result + attachmentCount;
|
||||
result = 31 * result + (userId != null ? userId.hashCode() : 0);
|
||||
result = 31 * result + order;
|
||||
result = 31 * result + (archived ? 1 : 0);
|
||||
result = 31 * result + (dueDate != null ? dueDate.hashCode() : 0);
|
||||
result = 31 * result + (notified ? 1 : 0);
|
||||
result = 31 * result + overdue;
|
||||
result = 31 * result + commentsUnread;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Card{" +
|
||||
"title='" + title + '\'' +
|
||||
", description='" + description + '\'' +
|
||||
", stackId=" + stackId +
|
||||
", type='" + type + '\'' +
|
||||
", createdAt=" + createdAt +
|
||||
", deletedAt=" + deletedAt +
|
||||
", done=" + done +
|
||||
", attachmentCount=" + attachmentCount +
|
||||
", userId=" + userId +
|
||||
", order=" + order +
|
||||
", archived=" + archived +
|
||||
", dueDate=" + dueDate +
|
||||
", notified=" + notified +
|
||||
", overdue=" + overdue +
|
||||
", commentsUnread=" + commentsUnread +
|
||||
", localId=" + localId +
|
||||
", accountId=" + accountId +
|
||||
", id=" + id +
|
||||
", status=" + status +
|
||||
", lastModified=" + lastModified +
|
||||
", lastModifiedLocal=" + lastModifiedLocal +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package it.niedermann.nextcloud.deck.model;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Index;
|
||||
import it.niedermann.nextcloud.deck.model.interfaces.AbstractJoinEntity;
|
||||
|
||||
@Entity(
|
||||
primaryKeys = {"labelId", "boardId"},
|
||||
indices = {@Index("boardId"), @Index("labelId")},
|
||||
foreignKeys = {
|
||||
@ForeignKey(entity = Board.class,
|
||||
parentColumns = "localId",
|
||||
childColumns = "boardId", onDelete = ForeignKey.CASCADE),
|
||||
@ForeignKey(entity = Label.class,
|
||||
parentColumns = "localId",
|
||||
childColumns = "labelId", onDelete = ForeignKey.CASCADE)
|
||||
})
|
||||
public class JoinBoardWithLabel extends AbstractJoinEntity {
|
||||
@NonNull
|
||||
private Long boardId;
|
||||
@NonNull
|
||||
private Long labelId;
|
||||
|
||||
|
||||
public Long getLabelId() {
|
||||
return labelId;
|
||||
}
|
||||
|
||||
public void setLabelId(Long labelId) {
|
||||
this.labelId = labelId;
|
||||
}
|
||||
|
||||
public Long getBoardId() {
|
||||
return boardId;
|
||||
}
|
||||
|
||||
public void setBoardId(Long boardId) {
|
||||
this.boardId = boardId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
JoinBoardWithLabel that = (JoinBoardWithLabel) o;
|
||||
|
||||
if (!boardId.equals(that.boardId)) return false;
|
||||
return labelId.equals(that.labelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = boardId.hashCode();
|
||||
result = 31 * result + labelId.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package it.niedermann.nextcloud.deck.model;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Index;
|
||||
import it.niedermann.nextcloud.deck.model.interfaces.AbstractJoinEntity;
|
||||
|
||||
@Entity(
|
||||
primaryKeys = {"permissionId", "boardId"},
|
||||
indices = {@Index("boardId"), @Index("permissionId")},
|
||||
foreignKeys = {
|
||||
@ForeignKey(entity = Board.class,
|
||||
parentColumns = "localId",
|
||||
childColumns = "boardId", onDelete = ForeignKey.CASCADE),
|
||||
@ForeignKey(entity = Permission.class,
|
||||
parentColumns = "id",
|
||||
childColumns = "permissionId", onDelete = ForeignKey.CASCADE)
|
||||
})
|
||||
public class JoinBoardWithPermission extends AbstractJoinEntity {
|
||||
@NonNull
|
||||
private Long permissionId;
|
||||
@NonNull
|
||||
private Long boardId;
|
||||
|
||||
public Long getPermissionId() {
|
||||
return permissionId;
|
||||
}
|
||||
|
||||
public void setPermissionId(Long permissionId) {
|
||||
this.permissionId = permissionId;
|
||||
}
|
||||
|
||||
public Long getBoardId() {
|
||||
return boardId;
|
||||
}
|
||||
|
||||
public void setBoardId(Long boardId) {
|
||||
this.boardId = boardId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
JoinBoardWithPermission that = (JoinBoardWithPermission) o;
|
||||
|
||||
if (!permissionId.equals(that.permissionId)) return false;
|
||||
return boardId.equals(that.boardId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = permissionId.hashCode();
|
||||
result = 31 * result + boardId.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package it.niedermann.nextcloud.deck.model;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Index;
|
||||
import it.niedermann.nextcloud.deck.model.interfaces.AbstractJoinEntity;
|
||||
|
||||
@Entity(
|
||||
primaryKeys = {"userId", "boardId"},
|
||||
indices = {@Index("boardId"), @Index("userId")},
|
||||
foreignKeys = {
|
||||
@ForeignKey(entity = Board.class,
|
||||
parentColumns = "localId",
|
||||
childColumns = "boardId", onDelete = ForeignKey.CASCADE),
|
||||
@ForeignKey(entity = User.class,
|
||||
parentColumns = "localId",
|
||||
childColumns = "userId", onDelete = ForeignKey.CASCADE)
|
||||
})
|
||||
public class JoinBoardWithUser extends AbstractJoinEntity {
|
||||
@NonNull
|
||||
private Long userId;
|
||||
@NonNull
|
||||
private Long boardId;
|
||||
|
||||
public Long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(Long userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public Long getBoardId() {
|
||||
return boardId;
|
||||
}
|
||||
|
||||
public void setBoardId(Long boardId) {
|
||||
this.boardId = boardId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
JoinBoardWithUser that = (JoinBoardWithUser) o;
|
||||
|
||||
if (!userId.equals(that.userId)) return false;
|
||||
return boardId.equals(that.boardId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = userId.hashCode();
|
||||
result = 31 * result + boardId.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package it.niedermann.nextcloud.deck.model;
|
||||
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Index;
|
||||
import androidx.annotation.NonNull;
|
||||
import it.niedermann.nextcloud.deck.model.interfaces.AbstractJoinEntity;
|
||||
|
||||
@Entity(
|
||||
primaryKeys = {"labelId", "cardId"},
|
||||
indices = {@Index("cardId"), @Index("labelId")},
|
||||
foreignKeys = {
|
||||
@ForeignKey(entity = Label.class,
|
||||
parentColumns = "localId",
|
||||
childColumns = "labelId",
|
||||
onDelete = ForeignKey.CASCADE
|
||||
),
|
||||
@ForeignKey(entity = Card.class,
|
||||
parentColumns = "localId",
|
||||
childColumns = "cardId",
|
||||
onDelete = ForeignKey.CASCADE
|
||||
)
|
||||
})
|
||||
public class JoinCardWithLabel extends AbstractJoinEntity {
|
||||
@NonNull
|
||||
private Long labelId;
|
||||
@NonNull
|
||||
private Long cardId;
|
||||
|
||||
public Long getLabelId() {
|
||||
return labelId;
|
||||
}
|
||||
|
||||
public void setLabelId(Long labelId) {
|
||||
this.labelId = labelId;
|
||||
}
|
||||
|
||||
public Long getCardId() {
|
||||
return cardId;
|
||||
}
|
||||
|
||||
public void setCardId(Long cardId) {
|
||||
this.cardId = cardId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
JoinCardWithLabel that = (JoinCardWithLabel) o;
|
||||
|
||||
if (!labelId.equals(that.labelId)) return false;
|
||||
return cardId.equals(that.cardId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = labelId.hashCode();
|
||||
result = 31 * result + cardId.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package it.niedermann.nextcloud.deck.model;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Index;
|
||||
import it.niedermann.nextcloud.deck.model.interfaces.AbstractJoinEntity;
|
||||
|
||||
@Entity(
|
||||
primaryKeys = {"userId", "cardId"},
|
||||
indices = {@Index("cardId"), @Index("userId")},
|
||||
foreignKeys = {
|
||||
@ForeignKey(entity = User.class,
|
||||
parentColumns = "localId",
|
||||
childColumns = "userId", onDelete = ForeignKey.CASCADE),
|
||||
@ForeignKey(entity = Card.class,
|
||||
parentColumns = "localId",
|
||||
childColumns = "cardId", onDelete = ForeignKey.CASCADE)
|
||||
})
|
||||
public class JoinCardWithUser extends AbstractJoinEntity {
|
||||
@NonNull
|
||||
private Long userId;
|
||||
@NonNull
|
||||
private Long cardId;
|
||||
|
||||
public Long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(Long userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public Long getCardId() {
|
||||
return cardId;
|
||||
}
|
||||
|
||||
public void setCardId(Long cardId) {
|
||||
this.cardId = cardId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
JoinCardWithUser that = (JoinCardWithUser) o;
|
||||
|
||||
if (!userId.equals(that.userId)) return false;
|
||||
return cardId.equals(that.cardId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = userId.hashCode();
|
||||
result = 31 * result + cardId.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
128
app/src/main/java/it/niedermann/nextcloud/deck/model/Label.java
Normal file
128
app/src/main/java/it/niedermann/nextcloud/deck/model/Label.java
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
package it.niedermann.nextcloud.deck.model;
|
||||
|
||||
import android.graphics.Color;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.ColumnInfo;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Index;
|
||||
|
||||
import com.google.gson.annotations.JsonAdapter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
import it.niedermann.android.util.ColorUtil;
|
||||
import it.niedermann.nextcloud.deck.DeckLog;
|
||||
import it.niedermann.nextcloud.deck.model.interfaces.AbstractRemoteEntity;
|
||||
import it.niedermann.nextcloud.deck.remote.api.json.JsonColorSerializer;
|
||||
|
||||
@Entity(inheritSuperIndices = true,
|
||||
indices = {@Index("boardId"), @Index(value = {"boardId", "title"}, unique = true, name = "idx_label_title_unique")},
|
||||
foreignKeys = {
|
||||
@ForeignKey(
|
||||
entity = Board.class,
|
||||
parentColumns = "localId",
|
||||
childColumns = "boardId",
|
||||
onDelete = ForeignKey.CASCADE
|
||||
),
|
||||
@ForeignKey(
|
||||
entity = Account.class,
|
||||
parentColumns = "id",
|
||||
childColumns = "accountId", onDelete = ForeignKey.CASCADE
|
||||
)
|
||||
}
|
||||
)
|
||||
public class Label extends AbstractRemoteEntity implements Serializable {
|
||||
private String title;
|
||||
|
||||
@JsonAdapter(JsonColorSerializer.class)
|
||||
@NonNull
|
||||
@ColumnInfo(defaultValue = "0")
|
||||
private Integer color;
|
||||
private long boardId;
|
||||
|
||||
public Label() {
|
||||
}
|
||||
|
||||
public Label(Label labelToCopy) {
|
||||
super(labelToCopy);
|
||||
this.title = labelToCopy.getTitle();
|
||||
this.color = labelToCopy.getColor();
|
||||
this.boardId = labelToCopy.getBoardId();
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@ColorInt
|
||||
public Integer getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public void setColor(@NonNull @ColorInt Integer color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public void setColor(String color) {
|
||||
try {
|
||||
setColor(Color.parseColor(ColorUtil.formatColorToParsableHexString(color)));
|
||||
} catch (Exception e) {
|
||||
DeckLog.logError(e);
|
||||
setColor(Color.GRAY);
|
||||
}
|
||||
}
|
||||
|
||||
public long getBoardId() {
|
||||
return boardId;
|
||||
}
|
||||
|
||||
public void setBoardId(long boardId) {
|
||||
this.boardId = boardId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
|
||||
Label label = (Label) o;
|
||||
|
||||
if (boardId != label.boardId) return false;
|
||||
if (!Objects.equals(title, label.title)) return false;
|
||||
return color.equals(label.color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + (title != null ? title.hashCode() : 0);
|
||||
result = 31 * result + color.hashCode();
|
||||
result = 31 * result + (int) (boardId ^ (boardId >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Label{" +
|
||||
"title='" + title + '\'' +
|
||||
", color='" + color + '\'' +
|
||||
", boardId=" + boardId +
|
||||
", localId=" + localId +
|
||||
", accountId=" + accountId +
|
||||
", id=" + id +
|
||||
", status=" + status +
|
||||
", lastModified=" + lastModified +
|
||||
", lastModifiedLocal=" + lastModifiedLocal +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package it.niedermann.nextcloud.deck.model;
|
||||
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.PrimaryKey;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.enums.PermissionType;
|
||||
|
||||
@Entity(inheritSuperIndices = true)
|
||||
public class Permission {
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
private long id;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public PermissionType getType() {
|
||||
return PermissionType.findById(id);
|
||||
}
|
||||
|
||||
public void setType(PermissionType type) {
|
||||
this.id = type.getId();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Permission that = (Permission) o;
|
||||
|
||||
return id == that.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (int) (id ^ (id >>> 32));
|
||||
}
|
||||
}
|
||||
123
app/src/main/java/it/niedermann/nextcloud/deck/model/Stack.java
Normal file
123
app/src/main/java/it/niedermann/nextcloud/deck/model/Stack.java
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
package it.niedermann.nextcloud.deck.model;
|
||||
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Ignore;
|
||||
import androidx.room.Index;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Objects;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.interfaces.AbstractRemoteEntity;
|
||||
|
||||
@Entity(
|
||||
inheritSuperIndices = true,
|
||||
indices = {@Index("boardId")},
|
||||
foreignKeys = {
|
||||
@ForeignKey(
|
||||
entity = Board.class,
|
||||
parentColumns = "localId",
|
||||
childColumns = "boardId", onDelete = ForeignKey.CASCADE
|
||||
),
|
||||
@ForeignKey(
|
||||
entity = Account.class,
|
||||
parentColumns = "id",
|
||||
childColumns = "accountId", onDelete = ForeignKey.CASCADE
|
||||
)
|
||||
}
|
||||
)
|
||||
public class Stack extends AbstractRemoteEntity {
|
||||
|
||||
public Stack() {
|
||||
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public Stack(String title, long boardId) {
|
||||
this.title = title;
|
||||
this.boardId = boardId;
|
||||
}
|
||||
|
||||
private String title;
|
||||
|
||||
private long boardId;
|
||||
|
||||
private Instant deletedAt;
|
||||
|
||||
private int order;
|
||||
//
|
||||
// @ToMany
|
||||
// @JoinEntity(entity = JoinStackWithCard.class, sourceProperty = "stackId", targetProperty = "cardId")
|
||||
// private List<Card> cards;
|
||||
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public long getBoardId() {
|
||||
return boardId;
|
||||
}
|
||||
|
||||
public void setBoardId(long boardId) {
|
||||
this.boardId = boardId;
|
||||
}
|
||||
|
||||
public Instant getDeletedAt() {
|
||||
return deletedAt;
|
||||
}
|
||||
|
||||
public void setDeletedAt(Instant deletedAt) {
|
||||
this.deletedAt = deletedAt;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
public void setStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
public long getAccountId() {
|
||||
return this.accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Stack stack = (Stack) o;
|
||||
|
||||
if (boardId != stack.boardId) return false;
|
||||
if (order != stack.order) return false;
|
||||
if (!Objects.equals(title, stack.title)) return false;
|
||||
return Objects.equals(deletedAt, stack.deletedAt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = title != null ? title.hashCode() : 0;
|
||||
result = 31 * result + (int) (boardId ^ (boardId >>> 32));
|
||||
result = 31 * result + (deletedAt != null ? deletedAt.hashCode() : 0);
|
||||
result = 31 * result + order;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
122
app/src/main/java/it/niedermann/nextcloud/deck/model/User.java
Normal file
122
app/src/main/java/it/niedermann/nextcloud/deck/model/User.java
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
package it.niedermann.nextcloud.deck.model;
|
||||
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Ignore;
|
||||
import androidx.room.Index;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.interfaces.AbstractRemoteEntity;
|
||||
|
||||
@Entity(inheritSuperIndices = true,
|
||||
indices = {
|
||||
@Index(value = "uid", name = "user_uid")
|
||||
},
|
||||
foreignKeys = {
|
||||
@ForeignKey(
|
||||
entity = Account.class,
|
||||
parentColumns = "id",
|
||||
childColumns = "accountId", onDelete = ForeignKey.CASCADE
|
||||
)
|
||||
}
|
||||
)
|
||||
public class User extends AbstractRemoteEntity implements Serializable {
|
||||
|
||||
public static final long TYPE_USER = 0L;
|
||||
public static final long TYPE_GROUP = 1L;
|
||||
|
||||
private String primaryKey;
|
||||
private String uid;
|
||||
private String displayname;
|
||||
private long type;
|
||||
|
||||
public User() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public User(String primaryKey, String uid, String displayname) {
|
||||
this.primaryKey = primaryKey;
|
||||
this.uid = uid;
|
||||
this.displayname = displayname;
|
||||
}
|
||||
|
||||
public User(User user) {
|
||||
super(user);
|
||||
this.primaryKey = user.getPrimaryKey();
|
||||
this.uid = user.getUid();
|
||||
this.type = user.getType();
|
||||
this.displayname = user.getDisplayname();
|
||||
}
|
||||
|
||||
public String getPrimaryKey() {
|
||||
return primaryKey;
|
||||
}
|
||||
|
||||
public void setPrimaryKey(String primaryKey) {
|
||||
this.primaryKey = primaryKey;
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(String uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public String getDisplayname() {
|
||||
return displayname;
|
||||
}
|
||||
|
||||
public void setDisplayname(String displayname) {
|
||||
this.displayname = displayname;
|
||||
}
|
||||
|
||||
public long getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(long type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
|
||||
User user = (User) o;
|
||||
return type == user.type && primaryKey.equals(user.primaryKey) &&
|
||||
uid.equals(user.uid) && displayname.equals(user.displayname);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + primaryKey.hashCode();
|
||||
result = 31 * result + uid.hashCode();
|
||||
result = 31 * result + displayname.hashCode();
|
||||
result = 31 * result + Long.hashCode(type);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "User{" +
|
||||
"primaryKey='" + primaryKey + '\'' +
|
||||
", uid='" + uid + '\'' +
|
||||
", displayname='" + displayname + '\'' +
|
||||
", type=" + type +
|
||||
", localId=" + localId +
|
||||
", accountId=" + accountId +
|
||||
", id=" + id +
|
||||
", status=" + status +
|
||||
", lastModified=" + lastModified +
|
||||
", lastModifiedLocal=" + lastModifiedLocal +
|
||||
", etag='" + etag + '\'' +
|
||||
"} " + super.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
package it.niedermann.nextcloud.deck.model.appwidgets;
|
||||
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Index;
|
||||
import androidx.room.PrimaryKey;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.Account;
|
||||
import it.niedermann.nextcloud.deck.model.Stack;
|
||||
|
||||
@Entity(
|
||||
indices = {
|
||||
@Index("stackId"),
|
||||
@Index("accountId")
|
||||
},
|
||||
foreignKeys = {
|
||||
@ForeignKey(
|
||||
entity = Account.class,
|
||||
parentColumns = "id",
|
||||
childColumns = "accountId", onDelete = ForeignKey.CASCADE
|
||||
),
|
||||
@ForeignKey(
|
||||
entity = Stack.class,
|
||||
parentColumns = "localId",
|
||||
childColumns = "stackId", onDelete = ForeignKey.CASCADE
|
||||
)
|
||||
}
|
||||
)
|
||||
public class StackWidgetModel {
|
||||
|
||||
@PrimaryKey()
|
||||
private Integer appWidgetId;
|
||||
private Long accountId;
|
||||
private Long stackId;
|
||||
private boolean darkTheme;
|
||||
|
||||
public Integer getAppWidgetId() {
|
||||
return appWidgetId;
|
||||
}
|
||||
|
||||
public void setAppWidgetId(Integer appWidgetId) {
|
||||
this.appWidgetId = appWidgetId;
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(Long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public Long getStackId() {
|
||||
return stackId;
|
||||
}
|
||||
|
||||
public void setStackId(Long stackId) {
|
||||
this.stackId = stackId;
|
||||
}
|
||||
|
||||
public boolean getDarkTheme() {
|
||||
return darkTheme;
|
||||
}
|
||||
|
||||
public void setDarkTheme(boolean darkTheme) {
|
||||
this.darkTheme = darkTheme;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
package it.niedermann.nextcloud.deck.model.enums;
|
||||
|
||||
import it.niedermann.nextcloud.deck.DeckLog;
|
||||
|
||||
public enum ActivityType {
|
||||
DECK (1, "deck-dark.svg"),
|
||||
CHANGE (2, "change.svg"),
|
||||
ADD (3, "add-color.svg"),
|
||||
DELETE (4, "delete-color.svg"),
|
||||
ARCHIVE (5, "archive.svg"),
|
||||
HISTORY (6, "actions/history.svg"),
|
||||
FILES (7, "places/files.svg"),
|
||||
COMMENT (8, "actions/comment.svg"),
|
||||
TAGGED_WITH_LABEL (9, "actions/tag.svg")
|
||||
;
|
||||
|
||||
int id;
|
||||
String name;
|
||||
ActivityType(int id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public static ActivityType findById(int id) {
|
||||
for (ActivityType s : ActivityType.values()) {
|
||||
if (s.getId() == id) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
DeckLog.error("unknown ActivityType path:", id);
|
||||
return CHANGE;
|
||||
}
|
||||
|
||||
public static ActivityType findByPath(String path) {
|
||||
if (path == null) {
|
||||
throw new IllegalArgumentException("path is null");
|
||||
}
|
||||
for (ActivityType s : ActivityType.values()) {
|
||||
if (path.trim().endsWith(s.getName())) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
DeckLog.error("unknown ActivityType path:", path);
|
||||
return CHANGE;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
package it.niedermann.nextcloud.deck.model.enums;
|
||||
|
||||
/**
|
||||
* Helps to distinguish between different local change types for Server Synchronization.
|
||||
* Created by stefan on 19.09.15.
|
||||
*/
|
||||
public enum DBStatus {
|
||||
|
||||
/**
|
||||
* UP_TO_DATE means, that the Entity was not modified locally
|
||||
*/
|
||||
UP_TO_DATE(1),
|
||||
|
||||
/**
|
||||
* LOCAL_EDITED means that a Entity was changed since the last successful synchronization.
|
||||
* If it was newly created, then REMOTE_ID is 0
|
||||
*/
|
||||
LOCAL_EDITED(2),
|
||||
|
||||
/**
|
||||
* LOCAL_DELETED means that the Entity was deleted locally, but this information was not yet synchronized.
|
||||
* Therefore, the Entity has to be kept locally until the synchronization has succeeded.
|
||||
* However, Entitys with this status should not be displayed in the UI.
|
||||
*/
|
||||
LOCAL_DELETED(3),
|
||||
|
||||
/**
|
||||
* LOCAL_MOVED means that the Entity was moved locally, but this information was not yet synchronized.
|
||||
* Therefore, the Entity has to be kept locally until the synchronization has succeeded.
|
||||
*/
|
||||
LOCAL_MOVED(4),
|
||||
|
||||
/**
|
||||
* LOCAL_EDITED_SILENT means the same as LOCAL_EDITED, but doesn't need to be shown as changed in the UI
|
||||
*/
|
||||
LOCAL_EDITED_SILENT(5);
|
||||
|
||||
private final int id;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
DBStatus(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public static DBStatus findById(int id) {
|
||||
for (DBStatus s : DBStatus.values()) {
|
||||
if (s.getId() == id) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("unknown DBStatus key");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package it.niedermann.nextcloud.deck.model.enums;
|
||||
|
||||
public enum EAttachmentType {
|
||||
// Do not change values. They match the Deck server apps values.
|
||||
DECK_FILE(1, "deck_file"),
|
||||
FILE(2, "file"),
|
||||
UNKNOWN(1337, "unknown");
|
||||
|
||||
private final int id;
|
||||
private final String value;
|
||||
|
||||
EAttachmentType(int id, String value) {
|
||||
this.id = id;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static EAttachmentType findByValue(String value) {
|
||||
for (EAttachmentType s : EAttachmentType.values()) {
|
||||
if (s.value.equals(value)) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package it.niedermann.nextcloud.deck.model.enums;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import it.niedermann.nextcloud.deck.R;
|
||||
|
||||
public enum EDoneType {
|
||||
NO_FILTER(1, R.string.filter_done_no_filter),
|
||||
DONE(2, R.string.filter_done_done),
|
||||
UNDONE(3, R.string.filter_done_undone);
|
||||
|
||||
private final int value;
|
||||
private final int id;
|
||||
|
||||
EDoneType(int id, @StringRes int value) {
|
||||
this.value = value;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static EDoneType findById(int id) {
|
||||
for (EDoneType s : EDoneType.values()) {
|
||||
if (s.getId() == id) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("unknown " + EDoneType.class.getSimpleName() + " key: " + id);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String toString(Context context) {
|
||||
return context.getString(this.value);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package it.niedermann.nextcloud.deck.model.enums;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import it.niedermann.nextcloud.deck.R;
|
||||
|
||||
public enum EDueType {
|
||||
NO_FILTER(1, R.string.filter_no_filter),
|
||||
OVERDUE(2, R.string.filter_overdue),
|
||||
TODAY(3, R.string.filter_today),
|
||||
WEEK(4, R.string.filter_week),
|
||||
MONTH(5, R.string.filter_month),
|
||||
NO_DUE(6, R.string.filter_no_due);
|
||||
|
||||
private final int value;
|
||||
private final int id;
|
||||
|
||||
EDueType(int id, @StringRes int value) {
|
||||
this.value = value;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static EDueType findById(int id) {
|
||||
for (EDueType s : EDueType.values()) {
|
||||
if (s.getId() == id) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("unknown " + EDueType.class.getSimpleName() + " key: " + id);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String toString(Context context) {
|
||||
return context.getString(this.value);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package it.niedermann.nextcloud.deck.model.enums;
|
||||
|
||||
public enum ESortCriteria {
|
||||
/**
|
||||
* Account → Board → Stack
|
||||
*/
|
||||
LOCATION(1),
|
||||
/**
|
||||
* Modification date of the card including comments, attachments etc.
|
||||
*/
|
||||
MODIFIED(2),
|
||||
LAST_COMMENTED(3),
|
||||
DUE_DATE(4),
|
||||
ASSIGNEE(5),
|
||||
LABEL(6);
|
||||
|
||||
private final int id;
|
||||
|
||||
ESortCriteria(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static ESortCriteria findById(int id) {
|
||||
for (ESortCriteria s : ESortCriteria.values()) {
|
||||
if (s.getId() == id) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("unknown " + ESortCriteria.class.getSimpleName() + " key: " + id);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package it.niedermann.nextcloud.deck.model.enums;
|
||||
|
||||
public enum PermissionType {
|
||||
|
||||
READ(1, "PERMISSION_READ"),
|
||||
EDIT(2, "PERMISSION_EDIT"),
|
||||
MANAGE(3, "PERMISSION_MANAGE"),
|
||||
SHARE(4, "PERMISSION_SHARE");
|
||||
|
||||
private final long id;
|
||||
private final String key;
|
||||
|
||||
PermissionType(long id, String key) {
|
||||
this.id = id;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public static PermissionType findByKey(String key) {
|
||||
for (PermissionType s : PermissionType.values()) {
|
||||
if (s.getKey().equals(key)) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("unknown Permission key");
|
||||
}
|
||||
|
||||
public static PermissionType findById(long key) {
|
||||
for (PermissionType s : PermissionType.values()) {
|
||||
if (s.getId() == key) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("unknown Permission ID");
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
package it.niedermann.nextcloud.deck.model.full;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.Embedded;
|
||||
import androidx.room.Ignore;
|
||||
import androidx.room.Relation;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.AccessControl;
|
||||
import it.niedermann.nextcloud.deck.model.Board;
|
||||
import it.niedermann.nextcloud.deck.model.Label;
|
||||
import it.niedermann.nextcloud.deck.model.Stack;
|
||||
import it.niedermann.nextcloud.deck.model.User;
|
||||
import it.niedermann.nextcloud.deck.model.interfaces.IRemoteEntity;
|
||||
|
||||
public class FullBoard implements IRemoteEntity {
|
||||
@Embedded
|
||||
public Board board;
|
||||
|
||||
@Relation(entity = Label.class, parentColumn = "localId", entityColumn = "boardId")
|
||||
public List<Label> labels;
|
||||
|
||||
@Relation(parentColumn = "ownerId", entityColumn = "localId")
|
||||
public User owner;
|
||||
|
||||
@Relation(entity = AccessControl.class, parentColumn = "localId", entityColumn = "boardId")
|
||||
public List<AccessControl> participants;
|
||||
|
||||
@Relation(entity = Stack.class, parentColumn = "localId", entityColumn = "boardId")
|
||||
public List<Stack> stacks;
|
||||
|
||||
@Ignore
|
||||
public List<User> users;
|
||||
|
||||
public User getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(User owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public Board getBoard() {
|
||||
return board;
|
||||
}
|
||||
|
||||
public void setBoard(Board board) {
|
||||
this.board = board;
|
||||
}
|
||||
|
||||
public List<Label> getLabels() {
|
||||
return labels;
|
||||
}
|
||||
|
||||
public void setLabels(List<Label> labels) {
|
||||
this.labels = labels;
|
||||
}
|
||||
|
||||
public List<User> getUsers() {
|
||||
return users;
|
||||
}
|
||||
|
||||
public void setUsers(List<User> users) {
|
||||
this.users = users;
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Override
|
||||
public Board getEntity() {
|
||||
return board;
|
||||
}
|
||||
|
||||
public List<AccessControl> getParticipants() {
|
||||
return participants;
|
||||
}
|
||||
|
||||
public void setParticipants(List<AccessControl> participants) {
|
||||
this.participants = participants;
|
||||
}
|
||||
|
||||
public List<Stack> getStacks() {
|
||||
return stacks;
|
||||
}
|
||||
|
||||
public void setStacks(List<Stack> stacks) {
|
||||
this.stacks = stacks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
FullBoard fullBoard = (FullBoard) o;
|
||||
|
||||
if (!Objects.equals(board, fullBoard.board)) return false;
|
||||
if (!Objects.equals(labels, fullBoard.labels))
|
||||
return false;
|
||||
if (!Objects.equals(owner, fullBoard.owner)) return false;
|
||||
if (!Objects.equals(participants, fullBoard.participants))
|
||||
return false;
|
||||
return Objects.equals(stacks, fullBoard.stacks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = board != null ? board.hashCode() : 0;
|
||||
result = 31 * result + (labels != null ? labels.hashCode() : 0);
|
||||
result = 31 * result + (owner != null ? owner.hashCode() : 0);
|
||||
result = 31 * result + (participants != null ? participants.hashCode() : 0);
|
||||
result = 31 * result + (stacks != null ? stacks.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FullBoard{" +
|
||||
"board=" + board +
|
||||
", labels=" + labels +
|
||||
", owner=" + owner +
|
||||
", participants=" + participants +
|
||||
", stacks=" + stacks +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
package it.niedermann.nextcloud.deck.model.full;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.Embedded;
|
||||
import androidx.room.Ignore;
|
||||
import androidx.room.Junction;
|
||||
import androidx.room.Relation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import it.niedermann.android.crosstabdnd.DragAndDropModel;
|
||||
import it.niedermann.nextcloud.deck.model.Attachment;
|
||||
import it.niedermann.nextcloud.deck.model.Card;
|
||||
import it.niedermann.nextcloud.deck.model.JoinCardWithLabel;
|
||||
import it.niedermann.nextcloud.deck.model.JoinCardWithUser;
|
||||
import it.niedermann.nextcloud.deck.model.Label;
|
||||
import it.niedermann.nextcloud.deck.model.User;
|
||||
import it.niedermann.nextcloud.deck.model.interfaces.IRemoteEntity;
|
||||
import it.niedermann.nextcloud.deck.model.ocs.comment.DeckComment;
|
||||
|
||||
public class FullCard implements IRemoteEntity, DragAndDropModel {
|
||||
|
||||
@Ignore
|
||||
protected transient boolean isAttachmentsSorted = false;
|
||||
|
||||
@Embedded
|
||||
public Card card;
|
||||
|
||||
@Relation(entity = Label.class, parentColumn = "localId", entityColumn = "localId",
|
||||
associateBy = @Junction(value = JoinCardWithLabel.class, parentColumn = "cardId", entityColumn = "labelId"))
|
||||
|
||||
public List<Label> labels = new ArrayList<>();
|
||||
|
||||
@Relation(entity = User.class, parentColumn = "localId", entityColumn = "localId",
|
||||
associateBy = @Junction(value = JoinCardWithUser.class, parentColumn = "cardId", entityColumn = "userId"))
|
||||
public List<User> assignedUsers = new ArrayList<>();
|
||||
|
||||
@Relation(parentColumn = "userId", entityColumn = "localId")
|
||||
public List<User> owner;
|
||||
|
||||
@Relation(parentColumn = "localId", entityColumn = "cardId")
|
||||
public List<Attachment> attachments;
|
||||
|
||||
@Relation(entity = DeckComment.class, parentColumn = "localId", entityColumn = "objectId", projection = "localId")
|
||||
public List<Long> commentIDs;
|
||||
|
||||
public FullCard() {
|
||||
super();
|
||||
}
|
||||
|
||||
public FullCard(FullCard fullCard) {
|
||||
this.card = new Card(fullCard.getCard());
|
||||
this.labels = copyList(fullCard.getLabels());
|
||||
this.assignedUsers = copyList(fullCard.getAssignedUsers());
|
||||
this.owner = copyList(fullCard.getOwner());
|
||||
this.attachments = copyList(fullCard.getAttachments());
|
||||
this.commentIDs = copyList(fullCard.getCommentIDs());
|
||||
}
|
||||
|
||||
public Card getCard() {
|
||||
return card;
|
||||
}
|
||||
|
||||
public void setCard(Card card) {
|
||||
this.card = card;
|
||||
}
|
||||
|
||||
public List<Label> getLabels() {
|
||||
return labels;
|
||||
}
|
||||
|
||||
public void setLabels(List<Label> labels) {
|
||||
this.labels = labels;
|
||||
}
|
||||
|
||||
public List<User> getAssignedUsers() {
|
||||
return assignedUsers;
|
||||
}
|
||||
|
||||
public void setAssignedUsers(List<User> assignedUsers) {
|
||||
this.assignedUsers = assignedUsers;
|
||||
}
|
||||
|
||||
public void setCommentIDs(List<Long> commentIDs) {
|
||||
this.commentIDs = commentIDs;
|
||||
}
|
||||
|
||||
public List<Long> getCommentIDs() {
|
||||
return commentIDs;
|
||||
}
|
||||
|
||||
public int getCommentCount() {
|
||||
return commentIDs == null ? 0 : commentIDs.size();
|
||||
}
|
||||
|
||||
public List<User> getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(User owner) {
|
||||
List<User> user = new ArrayList<>();
|
||||
user.add(owner);
|
||||
this.owner = user;
|
||||
}
|
||||
|
||||
public void setOwner(List<User> owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public List<Attachment> getAttachments() {
|
||||
if (!isAttachmentsSorted && attachments != null) {
|
||||
Collections.sort(attachments);
|
||||
isAttachmentsSorted = true;
|
||||
}
|
||||
return attachments;
|
||||
}
|
||||
|
||||
public void setAttachments(List<Attachment> attachments) {
|
||||
this.attachments = attachments;
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Override
|
||||
public Card getEntity() {
|
||||
return card;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FullCard{" +
|
||||
"card=" + card +
|
||||
", labels=" + labels +
|
||||
", assignedUsers=" + assignedUsers +
|
||||
", owner=" + owner +
|
||||
", attachments=" + attachments +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
FullCard fullCard = (FullCard) o;
|
||||
|
||||
if (!Objects.equals(card, fullCard.card)) return false;
|
||||
if (!Objects.equals(labels, fullCard.labels))
|
||||
return false;
|
||||
if (!Objects.equals(assignedUsers, fullCard.assignedUsers))
|
||||
return false;
|
||||
if (!Objects.equals(owner, fullCard.owner)) return false;
|
||||
if (!Objects.equals(attachments, fullCard.attachments))
|
||||
return false;
|
||||
return Objects.equals(commentIDs, fullCard.commentIDs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = (isAttachmentsSorted ? 1 : 0);
|
||||
result = 31 * result + (card != null ? card.hashCode() : 0);
|
||||
result = 31 * result + (labels != null ? labels.hashCode() : 0);
|
||||
result = 31 * result + (assignedUsers != null ? assignedUsers.hashCode() : 0);
|
||||
result = 31 * result + (owner != null ? owner.hashCode() : 0);
|
||||
result = 31 * result + (attachments != null ? attachments.hashCode() : 0);
|
||||
result = 31 * result + (commentIDs != null ? commentIDs.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Long getComparableId() {
|
||||
return getLocalId();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
package it.niedermann.nextcloud.deck.model.full;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.Junction;
|
||||
import androidx.room.Relation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import it.niedermann.nextcloud.deck.model.ocs.projects.JoinCardWithProject;
|
||||
import it.niedermann.nextcloud.deck.model.ocs.projects.OcsProject;
|
||||
import it.niedermann.nextcloud.deck.model.ocs.projects.full.OcsProjectWithResources;
|
||||
|
||||
public class FullCardWithProjects extends FullCard {
|
||||
|
||||
|
||||
@NonNull
|
||||
@Relation(entity = OcsProject.class, parentColumn = "localId", entityColumn = "localId",
|
||||
associateBy = @Junction(value = JoinCardWithProject.class, parentColumn = "cardId", entityColumn = "projectId"))
|
||||
|
||||
private List<OcsProjectWithResources> projects = new ArrayList<>();
|
||||
|
||||
public FullCardWithProjects() {
|
||||
super();
|
||||
}
|
||||
|
||||
public FullCardWithProjects(FullCardWithProjects fullCard) {
|
||||
super(fullCard);
|
||||
this.projects = copyList(fullCard.getProjects());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<OcsProjectWithResources> getProjects() {
|
||||
return projects;
|
||||
}
|
||||
|
||||
public void setProjects(@NonNull List<OcsProjectWithResources> projects) {
|
||||
this.projects = projects;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FullCard{" +
|
||||
"card=" + card +
|
||||
", labels=" + labels +
|
||||
", assignedUsers=" + assignedUsers +
|
||||
", owner=" + owner +
|
||||
", attachments=" + attachments +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
FullCardWithProjects fullCard = (FullCardWithProjects) o;
|
||||
|
||||
if (!Objects.equals(card, fullCard.card)) return false;
|
||||
if (!Objects.equals(labels, fullCard.labels))
|
||||
return false;
|
||||
if (!Objects.equals(assignedUsers, fullCard.assignedUsers))
|
||||
return false;
|
||||
if (!Objects.equals(owner, fullCard.owner)) return false;
|
||||
if (!Objects.equals(attachments, fullCard.attachments))
|
||||
return false;
|
||||
return Objects.equals(commentIDs, fullCard.commentIDs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = (isAttachmentsSorted ? 1 : 0);
|
||||
result = 31 * result + (card != null ? card.hashCode() : 0);
|
||||
result = 31 * result + (labels != null ? labels.hashCode() : 0);
|
||||
result = 31 * result + (assignedUsers != null ? assignedUsers.hashCode() : 0);
|
||||
result = 31 * result + (owner != null ? owner.hashCode() : 0);
|
||||
result = 31 * result + (attachments != null ? attachments.hashCode() : 0);
|
||||
result = 31 * result + (commentIDs != null ? commentIDs.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue