From b7d10fb38e6462faf7827ea315469a0f0773d4bb Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Tue, 28 Jan 2020 16:39:50 +1100 Subject: [PATCH 01/18] added support for linked urls --- .../ItemView/ItemAttachmentEntry.kt | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemAttachmentEntry.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemAttachmentEntry.kt index 629bc01c..cfc067c4 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemAttachmentEntry.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemAttachmentEntry.kt @@ -1,7 +1,10 @@ package com.mickstarify.zooforzotero.LibraryActivity.ItemView +import android.app.AlertDialog import android.content.Context +import android.content.Intent +import android.net.Uri import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -33,24 +36,38 @@ class ItemAttachmentEntry : Fragment() { savedInstanceState: Bundle? ): View? { val linkMode = attachment?.getItemData("linkMode") - // Inflate the layout for this fragment val view = inflater.inflate(R.layout.fragment_item_attachment_entry, container, false) + val layout = view.findViewById(R.id.constraintLayout_attachments_entry) + val filename = view.findViewById(R.id.textView_filename) filename.text = attachment?.data?.get("filename") ?: "unknown" if (linkMode == "linked_file") { // this variant uses title as a filename. filename.text = "[Linked] ${attachment?.getItemData("title")}" + }else if (linkMode == "linked_url") { + filename.text = "[Linked Url] ${attachment?.getItemData("title")}" + layout.setOnClickListener { + val url = attachment?.getItemData("url") + AlertDialog.Builder(context) + .setMessage("Would you like to open this URL: $url") + .setPositiveButton("Yes", {dialog, which -> + val intent = Intent(Intent.ACTION_VIEW) + intent.setData(Uri.parse(url)) + startActivity(intent) + }) + .setNegativeButton("No", {_,_ -> }) + .show() + } } val filetype = attachment?.data!!["contentType"] ?: "" - val layout = view.findViewById(R.id.constraintLayout_attachments_entry) val icon = view.findViewById(R.id.imageView_attachment_icon) if (attachment?.isDownloadable() == true) { if (filetype == "application/pdf") { icon.setImageResource(R.drawable.treeitem_attachment_pdf_2x) } else if (filetype == "image/vnd.djvu") { icon.setImageResource(R.drawable.djvu_icon) - } else if (attachment?.getFileExtension() == "epub"){ + } else if (attachment?.getFileExtension() == "epub") { icon.setImageResource(R.drawable.epub_icon) } layout.setOnClickListener { From 4cbada0c2a6c392e3ea5abf6e8c664980c32ffbe Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Sun, 9 Feb 2020 13:18:03 +1100 Subject: [PATCH 02/18] improved download manager --- .../zooforzotero/AttachmentManager/AttachmentManagerModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/AttachmentManager/AttachmentManagerModel.kt b/app/src/main/java/com/mickstarify/zooforzotero/AttachmentManager/AttachmentManagerModel.kt index 5f218771..61b94149 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/AttachmentManager/AttachmentManagerModel.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/AttachmentManager/AttachmentManagerModel.kt @@ -84,7 +84,7 @@ class AttachmentManagerModel(val presenter: Contract.Presenter, val context: Con Completable.fromAction({ for (attachment in zoteroDB.items!!.filter { it.itemType == "attachment" && it.data["linkMode"] != "linked_file" }) { val contentType = attachment.data["contentType"] - if (contentType != "application/pdf" && contentType != "image/vnd.djvu") { + if (!attachment.isDownloadable()) { continue } if (!attachmentStorageManager.checkIfAttachmentExists( From 48fe484269a591f5737564d6ab0a0a5d318789dd Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Sun, 9 Feb 2020 13:34:19 +1100 Subject: [PATCH 03/18] fixed a bug where a error was created when there was none --- .../com/mickstarify/zooforzotero/SyncSetup/SyncSetupModel.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/SyncSetup/SyncSetupModel.kt b/app/src/main/java/com/mickstarify/zooforzotero/SyncSetup/SyncSetupModel.kt index 5fc5c45b..dffa38dc 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/SyncSetup/SyncSetupModel.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/SyncSetup/SyncSetupModel.kt @@ -56,8 +56,7 @@ class SyncSetupModel(val presenter: SyncSetupPresenter, val context: Context) : keyInfo.key ) openLibrary() - } - if (response.code() == 404) { + } else if (response.code() == 404) { presenter.createNetworkError("Error your key was not found. Server Response was:\n" + response.raw()) } else { presenter.createNetworkError("Unknown network error, got back server code ${response.code()}") From dd389351c07b32446abf205d8f79e809f5a59a3d Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Sun, 9 Feb 2020 13:46:07 +1100 Subject: [PATCH 04/18] fixed a bug where attachment manager would take excessive amounts of time to load on custom location --- .../AttachmentManager/AttachmentManagerModel.kt | 3 ++- .../zooforzotero/ZoteroStorage/AttachmentStorageManager.kt | 6 +++--- .../zooforzotero/ZoteroStorage/ZoteroDB/ZoteroDB.kt | 2 ++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/AttachmentManager/AttachmentManagerModel.kt b/app/src/main/java/com/mickstarify/zooforzotero/AttachmentManager/AttachmentManagerModel.kt index 61b94149..2acd4312 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/AttachmentManager/AttachmentManagerModel.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/AttachmentManager/AttachmentManagerModel.kt @@ -191,6 +191,7 @@ class AttachmentManagerModel(val presenter: Contract.Presenter, val context: Con override fun loadLibrary() { zoteroDB = ZoteroDB(context, groupID = GroupInfo.NO_GROUP_ID) + zoteroDB.collections = LinkedList() zoteroDB.loadItemsFromDatabase().subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : CompletableObserver { @@ -226,7 +227,7 @@ class AttachmentManagerModel(val presenter: Contract.Presenter, val context: Con val localAttachments = LinkedList() val allAttachments = LinkedList() for (attachment in zoteroDB.items!!.filter { it.itemType == "attachment" }) { - if ((attachment.data["contentType"] != "application/pdf" && attachment.data["contentType"] != "image/vnd.djvu") || attachment.data["linkMode"] == "linked_file") { + if (!attachment.isDownloadable() || attachment.data["linkMode"] == "linked_file") { continue } allAttachments.add(attachment) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/AttachmentStorageManager.kt b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/AttachmentStorageManager.kt index a9f1e0ab..a458283c 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/AttachmentStorageManager.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/AttachmentStorageManager.kt @@ -101,9 +101,9 @@ class AttachmentStorageManager @Inject constructor( val rootDocFile = DocumentFile.fromTreeUri(context, Uri.parse(location)) var directory = rootDocFile?.findFile(item.itemKey.toUpperCase(Locale.ROOT)) if (directory == null || directory.isDirectory == false) { - directory = rootDocFile?.createDirectory(item.itemKey.toUpperCase(Locale.ROOT)) + return false } - val file = directory?.findFile(filename) + val file = directory.findFile(filename) if (file == null) { return false } @@ -112,7 +112,7 @@ class AttachmentStorageManager @Inject constructor( return false } val exists = file.exists() - if (file.exists() && checkMd5) { + if (exists && checkMd5) { return calculateMd5(context.contentResolver.openInputStream(file.uri)!!) == item.data["md5"] } else { return exists diff --git a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/ZoteroDB/ZoteroDB.kt b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/ZoteroDB/ZoteroDB.kt index b694a45a..ed603b57 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/ZoteroDB/ZoteroDB.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/ZoteroDB/ZoteroDB.kt @@ -120,11 +120,13 @@ class ZoteroDB constructor( val completable = Completable.fromMaybe(zoteroDatabase.getItemsForGroup(groupID).doOnSuccess( Consumer { + Log.d("zotero", "loaded items from DB, setting now.") items = it } )).andThen( Completable.fromMaybe( zoteroDatabase.getAttachmentsForGroup(groupID).doOnSuccess(Consumer { + Log.d("zotero", "Loading attachmentInfo from Database") attachmentInfo = HashMap() for (attachment in it) { attachmentInfo!![attachment.itemKey] = attachment From cb3912f0dcc3f6d86b22ad71dd45d15639ed3ee0 Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Fri, 28 Feb 2020 19:42:50 +1100 Subject: [PATCH 05/18] attempt at fixing a GC related npe --- app/build.gradle | 4 ++-- .../AttachmentManager/AttachmentManagerModel.kt | 1 + .../zooforzotero/ZoteroStorage/Database/Item.kt | 10 +++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index fe79e26e..01dfac23 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,8 +15,8 @@ android { applicationId "com.mickstarify.zooforzotero" minSdkVersion 21 targetSdkVersion 29 - versionCode 33 - versionName "2.4" + versionCode 34 + versionName "2.4a" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" buildConfigField("String", "zotero_api_key", apikeyProperties['zotero_api_key']) buildConfigField("String", "zotero_api_secret", apikeyProperties['zotero_api_secret']) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/AttachmentManager/AttachmentManagerModel.kt b/app/src/main/java/com/mickstarify/zooforzotero/AttachmentManager/AttachmentManagerModel.kt index 2acd4312..0db5e4d8 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/AttachmentManager/AttachmentManagerModel.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/AttachmentManager/AttachmentManagerModel.kt @@ -231,6 +231,7 @@ class AttachmentManagerModel(val presenter: Contract.Presenter, val context: Con continue } allAttachments.add(attachment) + Log.d("zotero", "checking if ${attachment.data["filename"]} exists") if (attachmentStorageManager.checkIfAttachmentExists(attachment, checkMd5 = false)) { localAttachments.add(attachment) } diff --git a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Item.kt b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Item.kt index 5f735efb..17041430 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Item.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Item.kt @@ -79,7 +79,7 @@ class Item : Parcelable { get() = itemInfo.itemKey val itemType: String - get() = getItemData("itemType") ?: "error" + get() = data["itemType"] ?: "error" @IgnoredOnParcel @Ignore @@ -107,13 +107,13 @@ class Item : Parcelable { fun getTitle(): String { val title = when (itemType) { - "case" -> this.getItemData("caseName") - "statute" -> this.getItemData("nameOfAct") + "case" -> this.data["caseName"] + "statute" -> this.data["nameOfAct"] "note" -> { - var noteHtml = this.getItemData("note") + var noteHtml = this.data["note"] stripHtml(noteHtml ?: "unknown") } - else -> this.getItemData("title") + else -> this.data["title"] } return (title ?: "unknown") From 9ee3881e23cf6c2363e08dbb17cc9d9b1eec0272 Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Sat, 7 Mar 2020 15:13:03 +1100 Subject: [PATCH 06/18] project files upgrade, cleanup --- app/build.gradle | 18 ++++++------ .../LibraryActivity/LibraryActivityModel.kt | 21 -------------- .../LibraryActivityPresenter.kt | 16 ++++------- .../zooforzotero/PreferenceManager.kt | 24 ---------------- .../zooforzotero/ZooForZoteroApplication.kt | 28 +++++++++---------- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +-- 7 files changed, 31 insertions(+), 82 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 01dfac23..9dc70de8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -55,15 +55,15 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'androidx.core:core-ktx:1.1.0' + implementation 'androidx.core:core-ktx:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - implementation "androidx.navigation:navigation-fragment-ktx:2.1.0" - implementation "androidx.navigation:navigation-ui-ktx:2.1.0" + implementation "androidx.navigation:navigation-fragment-ktx:2.2.1" + implementation "androidx.navigation:navigation-ui-ktx:2.2.1" implementation 'com.google.android.material:material:1.0.0' - implementation 'com.google.android.material:material:1.2.0-alpha03' + implementation 'com.google.android.material:material:1.2.0-alpha05' api 'com.google.guava:guava:28.1-jre' implementation 'oauth.signpost:oauth-signpost:1.2.1.2' - implementation("com.squareup.okhttp3:okhttp:4.2.1") + implementation("com.squareup.okhttp3:okhttp:4.2.2") implementation('com.squareup.okhttp3:logging-interceptor:4.2.2') implementation('oauth.signpost:signpost-commonshttp4:1.2.1.2') { exclude group: 'org.apache.httpcomponents' @@ -83,7 +83,7 @@ dependencies { androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' implementation 'androidx.gridlayout:gridlayout:1.0.0' - implementation 'com.google.firebase:firebase-analytics:17.2.2' + implementation 'com.google.firebase:firebase-analytics:17.2.3' implementation 'net.lingala.zip4j:zip4j:2.2.7' releaseImplementation 'com.crashlytics.sdk.android:crashlytics:2.10.1' @@ -96,9 +96,9 @@ dependencies { debugImplementation 'com.facebook.soloader:soloader:0.8.0' // Room Dependencies - implementation "androidx.room:room-runtime:2.2.3" - implementation 'androidx.room:room-rxjava2:2.2.3' - kapt "androidx.room:room-compiler:2.2.3" + implementation "androidx.room:room-runtime:2.2.4" + implementation 'androidx.room:room-rxjava2:2.2.4' + kapt "androidx.room:room-compiler:2.2.4" // Dagger Dependencies implementation 'com.google.dagger:dagger:2.25.2' diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityModel.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityModel.kt index 76eb8ebe..987f7f7a 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityModel.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityModel.kt @@ -1471,27 +1471,6 @@ class LibraryActivityModel(private val presenter: Contract.Presenter, val contex } checkAttachmentStorageAccess() - - /*Do to a change in implementation this code will transition webdav configs.*/ - if (preferences.firstRunForVersion25()) { - if (preferences.isWebDAVEnabled()) { - val address = preferences.getWebDAVAddress() - val newAddress = if (address.endsWith("/zotero")) { - address - } else { - if (address.endsWith("/")) { // so we don't get server.com//zotero - address + "zotero" - } else { - address + "/zotero" - } - } - preferences.setWebDAVAuthentication( - newAddress, - preferences.getWebDAVUsername(), - preferences.getWebDAVPassword() - ) - } - } } diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityPresenter.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityPresenter.kt index 18770db3..66c7848a 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityPresenter.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityPresenter.kt @@ -319,18 +319,12 @@ class LibraryActivityPresenter(val view: Contract.View, context: Context) : Cont view.initUI() view.showLoadingAnimation(true) view.showLibraryContentDisplay("Loading your library content.") - - //TODO i will delete this code next version. (just for version 2.2) - if (model.preferences.firstRunForVersion27() && model.hasOldStorage()) { - model.migrateFromOldStorage() + if (model.shouldIUpdateLibrary()) { + model.loadGroups() + model.downloadLibrary() } else { - if (model.shouldIUpdateLibrary()) { - model.loadGroups() - model.downloadLibrary() - } else { - model.loadLibraryLocally() - model.loadGroups() - } + model.loadLibraryLocally() + model.loadGroups() } } diff --git a/app/src/main/java/com/mickstarify/zooforzotero/PreferenceManager.kt b/app/src/main/java/com/mickstarify/zooforzotero/PreferenceManager.kt index 9fb9cd5f..a070ea9f 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/PreferenceManager.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/PreferenceManager.kt @@ -176,30 +176,6 @@ class PreferenceManager @Inject constructor(context: Context) { return sharedPreferences.getBoolean("attachments_uploading_enabled", true) } - fun firstRunForVersion25(): Boolean { - /*check to see if this is the first time the user is opening on version 2.1c (25)*/ - val firstRun = sharedPreferences.getBoolean("firstrun_version25", true) - if (firstRun) { - val editor = sharedPreferences.edit() - editor.putBoolean("firstrun_version25", false) - editor.apply() - } - return firstRun - - } - - fun firstRunForVersion27(): Boolean { - /*check to see if this is the first time the user is opening on version 2.2 (27)*/ - val firstRun = sharedPreferences.getBoolean("firstrun_version27", true) - if (firstRun) { - val editor = sharedPreferences.edit() - editor.putBoolean("firstrun_version27", false) - editor.apply() - } - return firstRun - - } - fun shouldOpenPDFOnOpen(): Boolean { return sharedPreferences.getBoolean("should_open_pdf_on_open", false) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/ZooForZoteroApplication.kt b/app/src/main/java/com/mickstarify/zooforzotero/ZooForZoteroApplication.kt index 0e96aae2..c0343bad 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/ZooForZoteroApplication.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/ZooForZoteroApplication.kt @@ -1,12 +1,12 @@ package com.mickstarify.zooforzotero import android.app.Application -//import com.facebook.flipper.android.AndroidFlipperClient -//import com.facebook.flipper.android.utils.FlipperUtils -//import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin -//import com.facebook.flipper.plugins.inspector.DescriptorMapping -//import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin -//import com.facebook.soloader.SoLoader +import com.facebook.flipper.android.AndroidFlipperClient +import com.facebook.flipper.android.utils.FlipperUtils +import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin +import com.facebook.flipper.plugins.inspector.DescriptorMapping +import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin +import com.facebook.soloader.SoLoader import com.mickstarify.zooforzotero.di.component.ApplicationComponent import com.mickstarify.zooforzotero.di.component.DaggerApplicationComponent import com.mickstarify.zooforzotero.di.module.ApplicationModule @@ -18,14 +18,14 @@ class ZooForZoteroApplication : Application() { override fun onCreate() { super.onCreate() -// SoLoader.init(this, false) -// -// if (BuildConfig.DEBUG && FlipperUtils.shouldEnableFlipper(this)) { -// val client = AndroidFlipperClient.getInstance(this) -// client.addPlugin(InspectorFlipperPlugin(this, DescriptorMapping.withDefaults())) -// client.addPlugin(DatabasesFlipperPlugin(this)); -// client.start() -// } + SoLoader.init(this, false) + + if (BuildConfig.DEBUG && FlipperUtils.shouldEnableFlipper(this)) { + val client = AndroidFlipperClient.getInstance(this) + client.addPlugin(InspectorFlipperPlugin(this, DescriptorMapping.withDefaults())) + client.addPlugin(DatabasesFlipperPlugin(this)); + client.start() + } component = DaggerApplicationComponent.builder().applicationModule( diff --git a/build.gradle b/build.gradle index 78235c53..b118f02f 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.5.3' + classpath 'com.android.tools.build:gradle:3.6.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.google.gms:google-services:4.3.3' classpath 'io.fabric.tools:gradle:1.31.0' // Crashlytics plugin diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0202f4b0..67e3b9d7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Aug 21 13:41:43 AEST 2019 +#Sat Mar 07 11:07:57 AEDT 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip From 6bd603bc7e4b5e05d0e889b4214ff0641e313c6d Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Sat, 7 Mar 2020 15:13:22 +1100 Subject: [PATCH 07/18] implemented ordering for creators --- .../LibraryActivity/ItemView/ItemViewFragment.kt | 4 ++-- .../zooforzotero/ZoteroStorage/Database/Database.kt | 10 ++++++---- .../zooforzotero/ZoteroStorage/Database/Item.kt | 9 +++++++-- .../zooforzotero/ZoteroStorage/Database/Migration.kt | 6 ++++++ 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemViewFragment.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemViewFragment.kt index afd7f91f..9fbd94c6 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemViewFragment.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemViewFragment.kt @@ -117,10 +117,10 @@ class ItemViewFragment : BottomSheetDialogFragment(), NoteInteractionListener { addTextEntry("Item Type", item.data["itemType"] ?: "Unknown") addTextEntry("title", item.getTitle()) if (item.creators.isNotEmpty()) { - this.addCreators(item.creators) + this.addCreators(item.getSortedCreators()) } else { // empty creator. - this.addCreators(listOf(Creator("null", "", "", ""))) + this.addCreators(listOf(Creator("null", "", "", "", -1))) } for ((key, value) in item.data) { if (value != "" && key != "itemType" && key != "title") { diff --git a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Database.kt b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Database.kt index 16a5c994..0ad9e353 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Database.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Database.kt @@ -25,7 +25,7 @@ import javax.inject.Singleton ItemCollection::class, AttachmentInfo::class ), - version = 4, + version = 5, exportSchema = true ) abstract class ZoteroRoomDatabase : RoomDatabase() { @@ -44,7 +44,8 @@ class ZoteroDatabase @Inject constructor(val context: Context) { ) .addMigrations(MIGRATION_1_2) .addMigrations(MIGRATION_2_3) - .addMigrations(MIGRATION_3_4).build() + .addMigrations(MIGRATION_3_4) + .addMigrations(MIGRATION_4_5).build() fun addGroup(group: GroupInfo): Completable { return db.groupInfoDao().insertGroupInfos(group) @@ -123,13 +124,14 @@ class ZoteroDatabase @Inject constructor(val context: Context) { } itemDatas.add(itemData) } - for (creatorPOJO in itemPOJO.creators) { + for ((index, creatorPOJO) in itemPOJO.creators.withIndex()) { itemCreators.add( Creator( itemPOJO.ItemKey, creatorPOJO.firstName, creatorPOJO.lastName, - creatorPOJO.creatorType + creatorPOJO.creatorType, + index ) ) } diff --git a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Item.kt b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Item.kt index 17041430..467558c4 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Item.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Item.kt @@ -61,6 +61,10 @@ class Item : Parcelable { return itemInfo.groupParent } + fun getSortedCreators() : List { + return this.creators.sortedBy { it.order } + } + fun getVersion(): Int { return itemInfo.version } @@ -123,7 +127,7 @@ class Item : Parcelable { return when (creators.size) { 0 -> "" 1 -> creators[0].lastName - else -> "${creators[0].lastName} et al." + else -> "${getSortedCreators()[0].lastName} et al." } } @@ -227,7 +231,8 @@ class Creator( @ColumnInfo(name = "parent") val parent: String, //itemKey of parent @ColumnInfo(name = "firstName") val firstName: String, @ColumnInfo(name = "lastName") val lastName: String, - @ColumnInfo(name = "creatorType") val creatorType: String + @ColumnInfo(name = "creatorType") val creatorType: String, + @ColumnInfo(name = "order") val order: Int ) : Parcelable { fun makeString(): String { return "${firstName} ${lastName}" diff --git a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Migration.kt b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Migration.kt index b9d665f8..04d2146c 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Migration.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Migration.kt @@ -36,4 +36,10 @@ val MIGRATION_3_4 = object : Migration(3,4) { database.execSQL("CREATE INDEX IF NOT EXISTS `index_ItemCollection_itemKey_collectionKey` ON `ItemCollection` (`itemKey`, `collectionKey`)") } +} + +val MIGRATION_4_5 = object: Migration(4,5){ + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE `ItemCreator` ADD `order` INTEGER NOT NULL DEFAULT -1") + } } \ No newline at end of file From 7a23d336fd9907048c3de08b76792e95b226eaa7 Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Sat, 7 Mar 2020 15:26:05 +1100 Subject: [PATCH 08/18] fixed sorting for author, no authors now go to bottom of list. --- .../LibraryActivity/LibraryActivityPresenter.kt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityPresenter.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityPresenter.kt index 66c7848a..bbebcd15 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityPresenter.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityPresenter.kt @@ -14,8 +14,16 @@ class LibraryActivityPresenter(val view: Contract.View, context: Context) : Cont when (model.preferences.getSortMethod()) { SortMethod.TITLE -> it.getTitle().toLowerCase(Locale.ROOT) SortMethod.DATE -> it.getSortableDateString() - SortMethod.AUTHOR -> it.getAuthor().toLowerCase(Locale.ROOT) SortMethod.DATE_ADDED -> it.getSortableDateAddedString() + SortMethod.AUTHOR -> { + val authorText = it.getAuthor().toLowerCase(Locale.ROOT) + // force empty authors to the bottom. Just like the zotero desktop client. + if (authorText == ""){ + "zzz" + } else { + authorText + } + } } }.thenBy { it.getTitle().toLowerCase(Locale.ROOT) } From 65686a49d8b3306558235beec2924912f567a3f9 Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Sat, 7 Mar 2020 15:56:42 +1100 Subject: [PATCH 09/18] added option to force upload attachment may not be functional --- .../zooforzotero/LibraryActivity/Contract.kt | 5 ++-- .../ItemView/ItemAttachmentEntry.kt | 29 +++++++++++++++++-- .../LibraryActivity/LibraryActivity.kt | 4 +++ .../LibraryActivity/LibraryActivityModel.kt | 29 ++++++++++++------- .../LibraryActivityPresenter.kt | 8 +++-- .../zooforzotero/ZoteroAPI/ZoteroAPI.kt | 3 +- 6 files changed, 60 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/Contract.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/Contract.kt index 5dfcfa4e..8574d28d 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/Contract.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/Contract.kt @@ -72,8 +72,8 @@ interface Contract { fun refreshItemView() fun displayGroupsOnActionBar(groups: List) fun openGroup(groupTitle: String) - fun startUploadingAttachment(attachment: Item) - fun stopUploadingAttachment() + fun startUploadingAttachmentProgress(attachment: Item) + fun stopUploadingAttachmentProgress() fun onResume() fun createYesNoPrompt( title: String, message: String, yesText: String, noText: String, onYesClick: () -> Unit, @@ -83,6 +83,7 @@ interface Contract { fun showBasicSyncAnimation() fun hideBasicSyncAnimation() fun openTrash() + fun uploadAttachment(item: Item) } interface Model { diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemAttachmentEntry.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemAttachmentEntry.kt index cfc067c4..8f5e3bad 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemAttachmentEntry.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemAttachmentEntry.kt @@ -3,6 +3,7 @@ package com.mickstarify.zooforzotero.LibraryActivity.ItemView import android.app.AlertDialog import android.content.Context +import android.content.DialogInterface import android.content.Intent import android.net.Uri import android.os.Bundle @@ -15,6 +16,7 @@ import androidx.constraintlayout.widget.ConstraintLayout import androidx.fragment.app.Fragment import com.mickstarify.zooforzotero.R import com.mickstarify.zooforzotero.ZoteroStorage.Database.Item +import org.jetbrains.anko.sdk27.coroutines.onLongClick import org.jetbrains.anko.support.v4.toast private const val ARG_ATTACHMENT = "attachment" @@ -44,18 +46,18 @@ class ItemAttachmentEntry : Fragment() { filename.text = attachment?.data?.get("filename") ?: "unknown" if (linkMode == "linked_file") { // this variant uses title as a filename. filename.text = "[Linked] ${attachment?.getItemData("title")}" - }else if (linkMode == "linked_url") { + } else if (linkMode == "linked_url") { filename.text = "[Linked Url] ${attachment?.getItemData("title")}" layout.setOnClickListener { val url = attachment?.getItemData("url") AlertDialog.Builder(context) .setMessage("Would you like to open this URL: $url") - .setPositiveButton("Yes", {dialog, which -> + .setPositiveButton("Yes", { dialog, which -> val intent = Intent(Intent.ACTION_VIEW) intent.setData(Uri.parse(url)) startActivity(intent) }) - .setNegativeButton("No", {_,_ -> }) + .setNegativeButton("No", { _, _ -> }) .show() } } @@ -79,6 +81,26 @@ class ItemAttachmentEntry : Fragment() { ) } } + + layout.onLongClick { + AlertDialog.Builder(context) + .setTitle("Attachment") + .setItems( + arrayOf("Open", "Force Re-upload"), + object : DialogInterface.OnClickListener { + override fun onClick(dialog: DialogInterface?, item: Int) { + when (item) { + 0 -> fileOpenListener?.openAttachmentFileListener( + attachment ?: throw Exception("No Attachment given.") + ) + 1 -> fileOpenListener?.forceUploadAttachmentListener( + attachment ?: throw Exception("No Attachment given.") + ) + } + } + + }).show() + } } return view } @@ -94,6 +116,7 @@ class ItemAttachmentEntry : Fragment() { interface OnAttachmentFragmentInteractionListener { fun openAttachmentFileListener(item: Item) + fun forceUploadAttachmentListener(item: Item) } companion object { diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivity.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivity.kt index e084adcf..4c7ae987 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivity.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivity.kt @@ -461,6 +461,10 @@ class LibraryActivity : AppCompatActivity(), Contract.View, presenter.openAttachment(item) } + override fun forceUploadAttachmentListener(item: Item) { + presenter.uploadAttachment(item) + } + override fun onListFragmentInteraction(item: Item?) { Log.d("zotero", "got onListFragmentInteraction from item ${item?.itemKey}") } diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityModel.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityModel.kt index 987f7f7a..d5ed0aab 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityModel.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityModel.kt @@ -1034,7 +1034,13 @@ class LibraryActivityModel(private val presenter: Contract.Presenter, val contex } override fun uploadAttachment(attachment: Item) { - val md5Key = attachmentStorageManager.calculateMd5(attachment) + val md5Key: String + try { + md5Key = attachmentStorageManager.calculateMd5(attachment) + } catch (e: FileNotFoundException){ + presenter.makeToastAlert("Cannot upload attachment. File does not exist.") + return + } var mtime = attachmentStorageManager.getMtime(attachment) if (mtime < attachment.getMtime()) { @@ -1056,7 +1062,7 @@ class LibraryActivityModel(private val presenter: Contract.Presenter, val contex .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe( object : CompletableObserver { override fun onComplete() { - presenter.stopUploadingAttachment() + presenter.stopUploadingAttachmentProgress() removeFromRecentlyViewed(attachment) zoteroDB.updateAttachmentMetadata( attachment.itemKey, @@ -1071,7 +1077,7 @@ class LibraryActivityModel(private val presenter: Contract.Presenter, val contex } override fun onSubscribe(d: Disposable) { - presenter.startUploadingAttachment(attachment) + presenter.startUploadingAttachmentProgress(attachment) } override fun onError(e: Throwable) { @@ -1086,16 +1092,18 @@ class LibraryActivityModel(private val presenter: Contract.Presenter, val contex "error_uploading_attachments_webdav", bundle ) - presenter.stopUploadingAttachment() + presenter.stopUploadingAttachmentProgress() } }) return } else { - zoteroAPI.updateAttachment(attachment).subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()).subscribe(object : + zoteroAPI.updateAttachment(attachment) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : CompletableObserver { override fun onComplete() { - presenter.stopUploadingAttachment() + presenter.stopUploadingAttachmentProgress() removeFromRecentlyViewed(attachment) zoteroDB.updateAttachmentMetadata( attachment.itemKey, @@ -1106,11 +1114,11 @@ class LibraryActivityModel(private val presenter: Contract.Presenter, val contex } override fun onSubscribe(d: Disposable) { - presenter.startUploadingAttachment(attachment) + presenter.startUploadingAttachmentProgress(attachment) } override fun onError(e: Throwable) { - if (e is com.mickstarify.zooforzotero.ZoteroAPI.AlreadyUploadedException) { + if (e is AlreadyUploadedException) { removeFromRecentlyViewed(attachment) zoteroDB.updateAttachmentMetadata( attachment.itemKey, @@ -1118,6 +1126,7 @@ class LibraryActivityModel(private val presenter: Contract.Presenter, val contex attachmentStorageManager.getMtime(attachment), AttachmentInfo.WEBDAV ).subscribeOn(Schedulers.io()).subscribe() + presenter.makeToastAlert("Attachment already up to date.") } else if (e is PreconditionFailedException) { presenter.createErrorAlert( "Error uploading Attachment", @@ -1140,7 +1149,7 @@ class LibraryActivityModel(private val presenter: Contract.Presenter, val contex Bundle().apply { putString("error_message", e.toString()) } firebaseAnalytics.logEvent("error_uploading_attachments", bundle) } - presenter.stopUploadingAttachment() + presenter.stopUploadingAttachmentProgress() } }) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityPresenter.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityPresenter.kt index bbebcd15..c1d0c8a5 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityPresenter.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityPresenter.kt @@ -34,11 +34,11 @@ class LibraryActivityPresenter(val view: Contract.View, context: Context) : Cont } - override fun startUploadingAttachment(attachment: Item) { + override fun startUploadingAttachmentProgress(attachment: Item) { view.showAttachmentUploadProgress(attachment) } - override fun stopUploadingAttachment() { + override fun stopUploadingAttachmentProgress() { view.hideAttachmentUploadProgress() view.makeToastAlert("Finished uploading attachment.") } @@ -247,6 +247,10 @@ class LibraryActivityPresenter(val view: Contract.View, context: Context) : Cont view.populateEntries(entries) } + override fun uploadAttachment(item: Item) { + model.uploadAttachment(item) + } + override fun setCollection(collectionKey: String, isSubCollection: Boolean) { /*SetCollection is the method used to display items on the listView. It * has to get the data, then sort it, then provide it to the view.*/ diff --git a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroAPI/ZoteroAPI.kt b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroAPI/ZoteroAPI.kt index d31b6599..f090b818 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroAPI/ZoteroAPI.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroAPI/ZoteroAPI.kt @@ -563,7 +563,8 @@ class ZoteroAPI( val newMd5 = attachmentStorageManager.calculateMd5(attachment) if (oldMd5 == newMd5) { - throw AlreadyUploadedException("Local attachment version is the same as Zotero's.") + + return Completable.error(AlreadyUploadedException("Local attachment version is the same as Zotero's.")) } val mtime = attachmentStorageManager.getMtime(attachment) val filename = attachmentStorageManager.getFilenameForItem(attachment) From 9170f4aaa507b8561285947b178bce66d8cda51e Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Sat, 7 Mar 2020 16:02:21 +1100 Subject: [PATCH 10/18] now highlights "My Library" on launch --- .../mickstarify/zooforzotero/LibraryActivity/LibraryActivity.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivity.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivity.kt index 4c7ae987..faa9b2b3 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivity.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivity.kt @@ -73,6 +73,7 @@ class LibraryActivity : AppCompatActivity(), Contract.View, override fun initUI() { val navigationView = findViewById(R.id.nav_view_library) + navigationView.setCheckedItem(R.id.my_library) collectionsMenu = navigationView.menu.addSubMenu( R.id.group_collections, Menu.NONE, From 39cbbba004a390dd05d0c495906fd2f91e8ca586 Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Sat, 7 Mar 2020 16:10:12 +1100 Subject: [PATCH 11/18] change phrasing of one-touch-open-attachments and cleaned up unused strings --- app/src/main/res/values/strings.xml | 8 -------- app/src/main/res/xml/root_preferences.xml | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bca060d7..87a07a36 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -20,17 +20,9 @@ Default reply action - Sync email periodically - Download incoming attachments - Automatically download attachments for incoming emails - - Only download attachments when manually requested Settings Sync Method Syncing - Sync only new content - Downloading the entire library every time. Warning this is slow and wastes bandwidth. - Only syncing when changes are detected. This is recommended. Title Author This catalog is currently empty.\nPlease refresh your library. diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml index d11b0879..21219ad6 100644 --- a/app/src/main/res/xml/root_preferences.xml +++ b/app/src/main/res/xml/root_preferences.xml @@ -46,7 +46,7 @@ + android:title="Single press opens attachment" /> Date: Sat, 7 Mar 2020 22:48:55 +1100 Subject: [PATCH 12/18] non functional code for refreshing library --- app/build.gradle | 4 ++-- .../mickstarify/zooforzotero/LibraryActivity/Contract.kt | 1 + .../zooforzotero/LibraryActivity/LibraryActivity.kt | 3 +++ .../zooforzotero/LibraryActivity/LibraryActivityModel.kt | 5 +++++ .../LibraryActivity/LibraryActivityPresenter.kt | 4 ++++ .../zooforzotero/ZoteroStorage/Database/Database.kt | 3 +++ app/src/main/res/menu/activity_library_actionbar.xml | 6 ++++++ app/src/main/res/values/strings.xml | 1 + 8 files changed, 25 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 9dc70de8..5b3353e5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,8 +15,8 @@ android { applicationId "com.mickstarify.zooforzotero" minSdkVersion 21 targetSdkVersion 29 - versionCode 34 - versionName "2.4a" + versionCode 35 + versionName "2.5" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" buildConfigField("String", "zotero_api_key", apikeyProperties['zotero_api_key']) buildConfigField("String", "zotero_api_secret", apikeyProperties['zotero_api_secret']) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/Contract.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/Contract.kt index 8574d28d..f8cf1cda 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/Contract.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/Contract.kt @@ -84,6 +84,7 @@ interface Contract { fun hideBasicSyncAnimation() fun openTrash() fun uploadAttachment(item: Item) + fun requestForceResync() } interface Model { diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivity.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivity.kt index faa9b2b3..e027c941 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivity.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivity.kt @@ -160,6 +160,9 @@ class LibraryActivity : AppCompatActivity(), Contract.View, val intent = Intent(this, AttachmentManager::class.java) startActivity(intent) } + R.id.force_resync -> { + presenter.requestForceResync() + } } return super.onOptionsItemSelected(item) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityModel.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityModel.kt index d5ed0aab..ca16f508 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityModel.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityModel.kt @@ -1490,4 +1490,9 @@ class LibraryActivityModel(private val presenter: Contract.Presenter, val contex fun getCollectionFromKey(collectionKey: String): Collection? { return zoteroDB.getCollectionById(collectionKey) } + + fun destroyLibrary() { + zoteroDB.clearItemsVersion() + zoteroDatabase.deleteEverything() + } } \ No newline at end of file diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityPresenter.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityPresenter.kt index c1d0c8a5..c16d6338 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityPresenter.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityPresenter.kt @@ -251,6 +251,10 @@ class LibraryActivityPresenter(val view: Contract.View, context: Context) : Cont model.uploadAttachment(item) } + override fun requestForceResync() { + model.destroyLibrary() + } + override fun setCollection(collectionKey: String, isSubCollection: Boolean) { /*SetCollection is the method used to display items on the listView. It * has to get the data, then sort it, then provide it to the view.*/ diff --git a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Database.kt b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Database.kt index 0ad9e353..e975fdff 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Database.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Database.kt @@ -198,6 +198,9 @@ class ZoteroDatabase @Inject constructor(val context: Context) { //todo return Completable.complete() } + + fun deleteEverything() { + } } private fun Boolean.Companion.fromInt(param: Int): Boolean { diff --git a/app/src/main/res/menu/activity_library_actionbar.xml b/app/src/main/res/menu/activity_library_actionbar.xml index b185ba44..f13ed86f 100644 --- a/app/src/main/res/menu/activity_library_actionbar.xml +++ b/app/src/main/res/menu/activity_library_actionbar.xml @@ -40,4 +40,10 @@ android:title="@string/zotero_save" app:showAsAction="collapseActionView" /> + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 87a07a36..241572a8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -39,4 +39,5 @@ Zotero Save Loading your library Filter Menu + Force Resync From c9ccf833a676885b1a1e57bada9322ecbe745577 Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Sat, 7 Mar 2020 22:49:48 +1100 Subject: [PATCH 13/18] ready for 2.5 release --- .../zooforzotero/ZooForZoteroApplication.kt | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/ZooForZoteroApplication.kt b/app/src/main/java/com/mickstarify/zooforzotero/ZooForZoteroApplication.kt index c0343bad..0e96aae2 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/ZooForZoteroApplication.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/ZooForZoteroApplication.kt @@ -1,12 +1,12 @@ package com.mickstarify.zooforzotero import android.app.Application -import com.facebook.flipper.android.AndroidFlipperClient -import com.facebook.flipper.android.utils.FlipperUtils -import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin -import com.facebook.flipper.plugins.inspector.DescriptorMapping -import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin -import com.facebook.soloader.SoLoader +//import com.facebook.flipper.android.AndroidFlipperClient +//import com.facebook.flipper.android.utils.FlipperUtils +//import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin +//import com.facebook.flipper.plugins.inspector.DescriptorMapping +//import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin +//import com.facebook.soloader.SoLoader import com.mickstarify.zooforzotero.di.component.ApplicationComponent import com.mickstarify.zooforzotero.di.component.DaggerApplicationComponent import com.mickstarify.zooforzotero.di.module.ApplicationModule @@ -18,14 +18,14 @@ class ZooForZoteroApplication : Application() { override fun onCreate() { super.onCreate() - SoLoader.init(this, false) - - if (BuildConfig.DEBUG && FlipperUtils.shouldEnableFlipper(this)) { - val client = AndroidFlipperClient.getInstance(this) - client.addPlugin(InspectorFlipperPlugin(this, DescriptorMapping.withDefaults())) - client.addPlugin(DatabasesFlipperPlugin(this)); - client.start() - } +// SoLoader.init(this, false) +// +// if (BuildConfig.DEBUG && FlipperUtils.shouldEnableFlipper(this)) { +// val client = AndroidFlipperClient.getInstance(this) +// client.addPlugin(InspectorFlipperPlugin(this, DescriptorMapping.withDefaults())) +// client.addPlugin(DatabasesFlipperPlugin(this)); +// client.start() +// } component = DaggerApplicationComponent.builder().applicationModule( From 272562b6cf861f04e57f4abf47ea2faf67f3e8d7 Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Mon, 6 Jul 2020 12:09:39 +1000 Subject: [PATCH 14/18] added ability to download any type of attachment --- .../LibraryActivity/ItemView/ItemAttachmentEntry.kt | 2 ++ .../zooforzotero/ZoteroStorage/Database/Item.kt | 12 ++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemAttachmentEntry.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemAttachmentEntry.kt index 8f5e3bad..002a0345 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemAttachmentEntry.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemAttachmentEntry.kt @@ -71,6 +71,8 @@ class ItemAttachmentEntry : Fragment() { icon.setImageResource(R.drawable.djvu_icon) } else if (attachment?.getFileExtension() == "epub") { icon.setImageResource(R.drawable.epub_icon) + } else { + // todo get default attachment icon. } layout.setOnClickListener { if (linkMode == "linked_file") { diff --git a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Item.kt b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Item.kt index 467558c4..d9a96563 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Item.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Item.kt @@ -61,7 +61,7 @@ class Item : Parcelable { return itemInfo.groupParent } - fun getSortedCreators() : List { + fun getSortedCreators(): List { return this.creators.sortedBy { it.order } } @@ -190,12 +190,20 @@ class Item : Parcelable { } fun getFileExtension(): String { - return when (this.data["contentType"]) { + val extension = when (this.data["contentType"]) { "application/pdf" -> "pdf" "image/vnd.djvu" -> "djvu" "application/epub+zip" -> "epub" + "application/x-mobipocket-ebook" -> "mobi" + "application/vnd.amazon.ebook" -> "azw" else -> "UNKNOWN" } + + // I probably should have just used file extensions from the beginning... + if (extension == "UNKNOWN") { + return this.data["filename"]?.split(".")?.last() ?: "UNKNOWN" + } + return extension } } From 84eff84c28d8682e8dab235c29d44b23925b080e Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Mon, 6 Jul 2020 23:29:50 +1000 Subject: [PATCH 15/18] added linked attachment loading --- .../ItemView/ItemAttachmentEntry.kt | 6 +- .../LibraryActivity/LibraryActivity.kt | 4 + .../LibraryActivity/LibraryActivityModel.kt | 11 +++ .../ZoteroStorage/AttachmentStorageManager.kt | 85 +++++++++++++++++++ 4 files changed, 104 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemAttachmentEntry.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemAttachmentEntry.kt index 002a0345..825b42a1 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemAttachmentEntry.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/ItemView/ItemAttachmentEntry.kt @@ -17,7 +17,6 @@ import androidx.fragment.app.Fragment import com.mickstarify.zooforzotero.R import com.mickstarify.zooforzotero.ZoteroStorage.Database.Item import org.jetbrains.anko.sdk27.coroutines.onLongClick -import org.jetbrains.anko.support.v4.toast private const val ARG_ATTACHMENT = "attachment" @@ -76,7 +75,9 @@ class ItemAttachmentEntry : Fragment() { } layout.setOnClickListener { if (linkMode == "linked_file") { - toast("This attachment is linked and I cannot download it.") + fileOpenListener?.openLinkedAttachmentListener( + attachment ?: throw Exception("No Attachment given.") + ) } else { fileOpenListener?.openAttachmentFileListener( attachment ?: throw Exception("No Attachment given.") @@ -119,6 +120,7 @@ class ItemAttachmentEntry : Fragment() { interface OnAttachmentFragmentInteractionListener { fun openAttachmentFileListener(item: Item) fun forceUploadAttachmentListener(item: Item) + fun openLinkedAttachmentListener(item: Item) } companion object { diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivity.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivity.kt index e027c941..ebd0a36a 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivity.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivity.kt @@ -469,6 +469,10 @@ class LibraryActivity : AppCompatActivity(), Contract.View, presenter.uploadAttachment(item) } + override fun openLinkedAttachmentListener(item: Item) { + presenter.openAttachment(item) + } + override fun onListFragmentInteraction(item: Item?) { Log.d("zotero", "got onListFragmentInteraction from item ${item?.itemKey}") } diff --git a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityModel.kt b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityModel.kt index ca16f508..2be9789d 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityModel.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/LibraryActivity/LibraryActivityModel.kt @@ -550,6 +550,17 @@ class LibraryActivityModel(private val presenter: Contract.Presenter, val contex /* This is the point of entry when a user clicks an attachment on the UI. * We must decide whether we want to intitiate a download or just open a local copy. */ + // first check to see if we are opening a linked attachment + if (item.data["linkMode"] == "linked_file"){ + val intent = attachmentStorageManager.openLinkedAttachment(item) + if (intent != null){ + context.startActivity(intent) + } else { + presenter.makeToastAlert("Error, could not find linked attachment ${item.data["path"]}") + } + return + } + // check to see if the attachment exists but is invalid val attachmentExists: Boolean try { diff --git a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/AttachmentStorageManager.kt b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/AttachmentStorageManager.kt index a458283c..76672241 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/AttachmentStorageManager.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/AttachmentStorageManager.kt @@ -240,6 +240,24 @@ class AttachmentStorageManager @Inject constructor( return intent } + fun openAttachment(uri: Uri, contentType:String = ""): Intent { + var intent = Intent(Intent.ACTION_VIEW) + Log.d("zotero", "opening PDF with Uri $uri") + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + intent = Intent(Intent.ACTION_VIEW) + intent.data = uri + intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION + intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION) + } else { + intent.setDataAndType(uri, contentType) + intent.flags = Intent.FLAG_ACTIVITY_NO_HISTORY + intent = Intent.createChooser(intent, "Open File") + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + + } + return intent + } + fun testStorage(): Boolean { if (storageMode == StorageMode.EXTERNAL_CACHE) { @@ -368,4 +386,71 @@ class AttachmentStorageManager @Inject constructor( } } + fun openLinkedAttachment(item: Item): Intent? { + /* This method searches for the linked attachment in the users storage directory. + * This may fail and return nothing. */ + if (item.data["linkMode"] != "linked_file") { + throw Exception("error attempting to open linked attachment on something this isn't elligible.") + } + + // will work as followed: + // /home/michael/Downloads/Alice in Wonderland.pdf -> [home, michael, Downloads. Alice in Wonderland.pdf] + // for each path in list, check if folder exists in root dir + // if it does, pursue this path. + // if it doesn't, return to the root path, and repeat for the next item in the list. + + + val itemPath = item.data["path"] ?: "" + val directories = itemPath.split("/") + if (storageMode == StorageMode.CUSTOM) { + for ((index, path) in directories.withIndex()) { + val location = preferenceManager.getCustomAttachmentStorageLocation() + var documentFile = DocumentFile.fromTreeUri(context, Uri.parse(location)) + var i = index + while (i < directories.size) { + documentFile = documentFile?.findFile(directories[i]) + Log.d("zotero", "checking ${directories[i]}") + if (documentFile?.exists() ?: false) { + i++ + } else { + break + } + } + if (documentFile?.isFile ?: false) { + Log.d("zotero", "found file ${documentFile?.name}") + return openAttachment(documentFile!!.uri, item.data["contentType"]?:"") + } + } + } else if (storageMode == StorageMode.EXTERNAL_CACHE) { + // logic using File api is much simpler + for (i in 0..directories.size){ + var path = directories.slice(i..directories.size-1).joinToString("/") + if (path.first() == '/'){ + path = path.slice(1..path.length-1) + } + Log.d("zotero", "checking path $path") + var document = File(context.externalCacheDir, path) + if (document.exists()){ + val uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + FileProvider.getUriForFile( + context, + "${context.packageName}.fileprovider", + document + ) + } else { + Uri.fromFile(document) + } + return openAttachment(uri, item.data["contentType"]?:"") + } + } + + + } + else { + throw NotImplementedError() + } + + return null + } + } \ No newline at end of file From e3814e34ad1cc8aba3932ec07a075de753565b58 Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Mon, 6 Jul 2020 23:39:44 +1000 Subject: [PATCH 16/18] upgraded dependencies --- app/build.gradle | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 5b3353e5..26033494 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -55,12 +55,12 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'androidx.core:core-ktx:1.2.0' + implementation 'androidx.core:core-ktx:1.3.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - implementation "androidx.navigation:navigation-fragment-ktx:2.2.1" - implementation "androidx.navigation:navigation-ui-ktx:2.2.1" - implementation 'com.google.android.material:material:1.0.0' - implementation 'com.google.android.material:material:1.2.0-alpha05' + implementation "androidx.navigation:navigation-fragment-ktx:2.3.0" + implementation "androidx.navigation:navigation-ui-ktx:2.3.0" + implementation 'com.google.android.material:material:1.1.0' + implementation 'com.google.android.material:material:1.3.0-alpha01' api 'com.google.guava:guava:28.1-jre' implementation 'oauth.signpost:oauth-signpost:1.2.1.2' implementation("com.squareup.okhttp3:okhttp:4.2.2") @@ -76,14 +76,14 @@ dependencies { implementation 'org.jetbrains.anko:anko:0.10.8' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.1.0' - implementation 'androidx.preference:preference:1.1.0' + implementation 'androidx.preference:preference:1.1.1' testImplementation 'junit:junit:4.12' testImplementation "org.mockito:mockito-core:2.28.2" androidTestImplementation "org.mockito:mockito-core:2.28.2" androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' implementation 'androidx.gridlayout:gridlayout:1.0.0' - implementation 'com.google.firebase:firebase-analytics:17.2.3' + implementation 'com.google.firebase:firebase-analytics:17.4.3' implementation 'net.lingala.zip4j:zip4j:2.2.7' releaseImplementation 'com.crashlytics.sdk.android:crashlytics:2.10.1' @@ -96,9 +96,9 @@ dependencies { debugImplementation 'com.facebook.soloader:soloader:0.8.0' // Room Dependencies - implementation "androidx.room:room-runtime:2.2.4" - implementation 'androidx.room:room-rxjava2:2.2.4' - kapt "androidx.room:room-compiler:2.2.4" + implementation "androidx.room:room-runtime:2.2.5" + implementation 'androidx.room:room-rxjava2:2.2.5' + kapt "androidx.room:room-compiler:2.2.5" // Dagger Dependencies implementation 'com.google.dagger:dagger:2.25.2' From fe1723aa9ee20ccf18cda45f833f5f57dd5912e1 Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Mon, 6 Jul 2020 23:40:47 +1000 Subject: [PATCH 17/18] cleanup some strings --- .../zooforzotero/SyncSetup/SyncSetupView.kt | 3 -- .../zooforzotero/ZooForZoteroApplication.kt | 28 ++++++------- .../main/res/layout/activity_sync_setup.xml | 39 +++---------------- app/src/main/res/values/strings.xml | 5 +++ 4 files changed, 24 insertions(+), 51 deletions(-) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/SyncSetup/SyncSetupView.kt b/app/src/main/java/com/mickstarify/zooforzotero/SyncSetup/SyncSetupView.kt index 3fc61a28..a2bf51ec 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/SyncSetup/SyncSetupView.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/SyncSetup/SyncSetupView.kt @@ -84,9 +84,6 @@ class SyncSetupView : AppCompatActivity(), SyncSetupContract.View { val rg_cloudproviders = findViewById(R.id.radiogroup_cloudproviders) rg_cloudproviders.setOnCheckedChangeListener { _, i -> when (i) { - R.id.radio_dropbox -> selected_provider = SyncOption.Dropbox - R.id.radio_googledrive -> selected_provider = SyncOption.GoogleDrive - R.id.radio_onedrive -> selected_provider = SyncOption.Onedrive R.id.radio_zotero -> selected_provider = SyncOption.ZoteroAPI R.id.radio_zotero_manual_apikey -> selected_provider = SyncOption.ZoteroAPIManual else -> throw Exception("Error, not sure what Radiobox was pressed") diff --git a/app/src/main/java/com/mickstarify/zooforzotero/ZooForZoteroApplication.kt b/app/src/main/java/com/mickstarify/zooforzotero/ZooForZoteroApplication.kt index 0e96aae2..c0343bad 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/ZooForZoteroApplication.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/ZooForZoteroApplication.kt @@ -1,12 +1,12 @@ package com.mickstarify.zooforzotero import android.app.Application -//import com.facebook.flipper.android.AndroidFlipperClient -//import com.facebook.flipper.android.utils.FlipperUtils -//import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin -//import com.facebook.flipper.plugins.inspector.DescriptorMapping -//import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin -//import com.facebook.soloader.SoLoader +import com.facebook.flipper.android.AndroidFlipperClient +import com.facebook.flipper.android.utils.FlipperUtils +import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin +import com.facebook.flipper.plugins.inspector.DescriptorMapping +import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin +import com.facebook.soloader.SoLoader import com.mickstarify.zooforzotero.di.component.ApplicationComponent import com.mickstarify.zooforzotero.di.component.DaggerApplicationComponent import com.mickstarify.zooforzotero.di.module.ApplicationModule @@ -18,14 +18,14 @@ class ZooForZoteroApplication : Application() { override fun onCreate() { super.onCreate() -// SoLoader.init(this, false) -// -// if (BuildConfig.DEBUG && FlipperUtils.shouldEnableFlipper(this)) { -// val client = AndroidFlipperClient.getInstance(this) -// client.addPlugin(InspectorFlipperPlugin(this, DescriptorMapping.withDefaults())) -// client.addPlugin(DatabasesFlipperPlugin(this)); -// client.start() -// } + SoLoader.init(this, false) + + if (BuildConfig.DEBUG && FlipperUtils.shouldEnableFlipper(this)) { + val client = AndroidFlipperClient.getInstance(this) + client.addPlugin(InspectorFlipperPlugin(this, DescriptorMapping.withDefaults())) + client.addPlugin(DatabasesFlipperPlugin(this)); + client.start() + } component = DaggerApplicationComponent.builder().applicationModule( diff --git a/app/src/main/res/layout/activity_sync_setup.xml b/app/src/main/res/layout/activity_sync_setup.xml index ce564fd2..b6777853 100644 --- a/app/src/main/res/layout/activity_sync_setup.xml +++ b/app/src/main/res/layout/activity_sync_setup.xml @@ -15,7 +15,7 @@ android:layout_height="wrap_content" android:layout_marginLeft="24dp" android:layout_marginTop="16dp" - android:text="Pick your cloud storage provider" + android:text="@string/pick_your_cloud_storage_provider" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" /> @@ -28,49 +28,20 @@ android:layout_marginLeft="16dp" app:layout_constraintLeft_toLeftOf="parent"> - - - - - - - + android:text="@string/zotero_account_sync" /> @@ -82,7 +53,7 @@ android:layout_marginBottom="32dp" android:layout_marginRight="32dp" android:padding="12dp" - android:text="Proceed" + android:text="@string/proceed" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintRight_toRightOf="parent" /> @@ -91,7 +62,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="48dp" - android:text="I have only implemented support for the Zotero Account Syncing option. I will implement alternative syncing options in the future, sorry for the inconvenience." + android:text="@string/app_frontpage_disclaimer" app:layout_constraintEnd_toEndOf="@+id/btn_sync_proceed" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="@+id/radiogroup_cloudproviders" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 241572a8..42e9432d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -40,4 +40,9 @@ Loading your library Filter Menu Force Resync + You must use the official Zotero Account syncing to use this app. + Proceed + Enter your Zotero API Key Manually + Zotero Account Sync + Pick your cloud storage provider From de107cc80f8a9821f85f94fe5544aa4254166f8f Mon Sep 17 00:00:00 2001 From: Michael Johnston Date: Tue, 7 Jul 2020 12:55:34 +1000 Subject: [PATCH 18/18] improved handling of windows style linked attachments --- .../ZoteroStorage/AttachmentStorageManager.kt | 9 ++++++--- .../zooforzotero/ZoteroStorage/Database/Item.kt | 7 ++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/AttachmentStorageManager.kt b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/AttachmentStorageManager.kt index 76672241..f035c11b 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/AttachmentStorageManager.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/AttachmentStorageManager.kt @@ -400,10 +400,13 @@ class AttachmentStorageManager @Inject constructor( // if it doesn't, return to the root path, and repeat for the next item in the list. - val itemPath = item.data["path"] ?: "" + var itemPath = item.data["path"] ?: "" + // do some transformations for windows style paths + // e.g C:\\Users\\michael\\file.txt -> C:/Users/michael/file.txt + itemPath = itemPath.replace("\\", "/") val directories = itemPath.split("/") if (storageMode == StorageMode.CUSTOM) { - for ((index, path) in directories.withIndex()) { + for (index in directories.indices) { val location = preferenceManager.getCustomAttachmentStorageLocation() var documentFile = DocumentFile.fromTreeUri(context, Uri.parse(location)) var i = index @@ -423,7 +426,7 @@ class AttachmentStorageManager @Inject constructor( } } else if (storageMode == StorageMode.EXTERNAL_CACHE) { // logic using File api is much simpler - for (i in 0..directories.size){ + for (i in directories.indices){ var path = directories.slice(i..directories.size-1).joinToString("/") if (path.first() == '/'){ path = path.slice(1..path.length-1) diff --git a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Item.kt b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Item.kt index d9a96563..4d2f2ec4 100644 --- a/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Item.kt +++ b/app/src/main/java/com/mickstarify/zooforzotero/ZoteroStorage/Database/Item.kt @@ -201,7 +201,12 @@ class Item : Parcelable { // I probably should have just used file extensions from the beginning... if (extension == "UNKNOWN") { - return this.data["filename"]?.split(".")?.last() ?: "UNKNOWN" + val filename = if(this.data.containsKey("filename")){ + this.data["filename"] + } else { + this.data["title"] + } + return filename?.split(".")?.last() ?: "UNKNOWN" } return extension }