Coder Social home page Coder Social logo

stefan-niedermann / nextcloud-commons Goto Github PK

View Code? Open in Web Editor NEW
7.0 6.0 6.0 891 KB

Library for common Nextcloud operations, like a Glide-SSO integration

License: GNU General Public License v3.0

Kotlin 61.45% Java 38.55%
glide glideimageloader nextcloud android

nextcloud-commons's Introduction

nextcloud-commons

Latest Release Codacy Badge GitHub issues GitHub stars License: GPL v3

What is this

Many Android clients for Nextcloud apps need similar mechanisms. To reduce maintenance efforts and provide a similar look & feel, this library aims to provide tooling and support which can be useful for various Android clients.

How to use

Add this dependency to your build.gradle-file to include all modules at once:

implementation 'com.github.stefan-niedermann:nextcloud-commons:2.3.0'

Modules

exception

implementation 'com.github.stefan-niedermann.nextcloud-commons:exception:2.3.0'

This is a util class which provides methods for generating a rich stacktrace from a throwable containing additional information like the used files app and OS versions.

Usage

try {
  // …
} catch (Exception exception) {
  String debug = ExceptionUtil.getDebugInfos(context, exception);
}

Example

App Version: 2.17.1
App Version Code: 2017001
Server App Version: 3.2.0
App Flavor: dev

Files App Version Code: 30120090

---

OS Version: 4.14.112+(5775370)
OS API Level: 29
Device: generic_x86_64
Manufacturer: unknown
Model (and Product): Android SDK built for x86_64 (sdk_phone_x86_64)

---

java.lang.RuntimeException: Unable to start activity ComponentInfo{it.niedermann.owncloud.notes.dev/it.niedermann.owncloud.notes.main.MainActivity}: java.lang.NumberFormatException: For input string: "ASDF"
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
	at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
	at android.os.Handler.dispatchMessage(Handler.java:107)
	at android.os.Looper.loop(Looper.java:214)
	at android.app.ActivityThread.main(ActivityThread.java:7356)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.NumberFormatException: For input string: "ASDF"
	at java.lang.Integer.parseInt(Integer.java:615)
	at java.lang.Integer.parseInt(Integer.java:650)
	at it.niedermann.owncloud.notes.main.MainActivity.onCreate(MainActivity.java:180)
	at android.app.Activity.performCreate(Activity.java:7802)
	at android.app.Activity.performCreate(Activity.java:7791)
	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
	... 11 more

sso-glide

implementation 'com.github.stefan-niedermann.nextcloud-commons:sso-glide:2.3.0'

This is a Glide-integration module. If you are using Single Sign On you may want to also fetch avatars or other images via Glide but with the SSO network stack to avoid problems with self-signed certificates, 2fa and so on.

To make it work, you need also this dependencies in your build.gradle-file:

implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'

Usage

Then create a custom AppGlideModule at the place you want, like this:

@GlideModule
public class CustomAppGlideModule extends AppGlideModule {
  @Override
  public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
    super.registerComponents(context, glide, registry);
  }
}

Glide will automatically recognize the custom AppGlideModule and process this library module.

Glide.with(context)
     .load("https://nextcloud.example.com/index.php/avatar/username/32")
     .into(myImageView);

will make a request from the user which is stored as the current SingleSignOn account (see here).

If you need to perform the request from another account (for example to display avatars in an account switcher), you can use a SingleSignOnUrl instance as Url:

Glide.with(context)
     .load(new SingleSignOnUrl(ssoAccount, "https://nextcloud.example.com/index.php/avatar/username/32"))
     .into(myImageView);

The sso-glide module also supports some automatic URL rewrites, such as:

Glide.with(context)
   // URLs from file shares with and without /index.php segment, with and without trailing / character
     .load("https://nextcloud.example.com/s/Wr99tjfBCs96kxZ")
     .load("https://nextcloud.example.com/s/Wr99tjfBCs96kxZ/")
     .load("https://nextcloud.example.com/index.php/s/Wr99tjfBCs96kxZ")
     .load("https://nextcloud.example.com/index.php/s/Wr99tjfBCs96kxZ/")
     .load("https://nextcloud.example.com/index.php/s/Wr99tjfBCs96kxZ/download")
     .load("https://nextcloud.example.com/index.php/s/Wr99tjfBCs96kxZ/download/")
   // File ID URLs with and without /index.php segment, with and without trailing / character
     .load("https://nextcloud.example.com/f/123456")
     .load("https://nextcloud.example.com/f/123456/")
     .load("https://nextcloud.example.com/index.php/f/123456")
     .load("https://nextcloud.example.com/index.php/f/123456/")
   // Everything mentioned above, if the nextcloud is not located at the root directory
     .load("https://example.com/my-fancy-nextcloud/f/123456")
   // There is a fallback for every URL or path which does not start with /index.php or /remote.php
   // In this case we will assume a path in the users directory (which needs to be properly URL encoded)
     .load("/foo.png")
     .load("/foo%20bar.png")
     .load("/foo/bar%20baz.png")
     .into(myImageView);

markdown

implementation('com.github.stefan-niedermann.nextcloud-commons:markdown:2.3.0') {
  exclude group: 'org.jetbrains', module: 'annotations-java5'
}

This contains a markdown editor and viewer based on Markwon.

Usage

The UI widgets MarkdownViewerImpl and MarkdownEditorImpl can just be treated as a TextView or an EditText:

<it.niedermann.android.markdown.MarkdownViewerImpl
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
<it.niedermann.android.markdown.MarkdownEditorImpl
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

You can implement against the MarkdownEditor interface, which allows you to add some special behavior like

  • highlight search terms
  • intercept link clicks
  • render user avatars next to @user mentions

The MarkdownUtil provides some helper tools to work with markdown.

Development

If you want to add this repository to your project to develop this library or use the latest version, you can add the following code to your gradle files:

settings.gradle

// for markdown
include ':markdown'
project(':markdown').projectDir = new File(settingsDir, '../nextcloud-commons/markdown')

// for sso-glide
include ':sso-glide'
project(':sso-glide').projectDir = new File(settingsDir, '../nextcloud-commons/sso-glide')

// for exception
include ':exception'
project(':exception').projectDir = new File(settingsDir, '../nextcloud-commons/exception')

// It is also possible to provide absolute path's instead of relative ones.

build.gradle

(the app one, not the project-one)

dependencies {
    //

    implementation project(':markdown')
    implementation project(':sso-glide')
    implementation project(':exception')
    
    //
}

You do not need to add all libraries, just add the ones you want to use in your project. You also have to remove versioned libraries from above if you added them.

However, it is not adivisable to check those into version control, because anyone else will not be able to build your project without having the local libraries configured.

📓 License

This project is licensed under the GNU GENERAL PUBLIC LICENSE.

nextcloud-commons's People

Contributors

andyscherzinger avatar dependabot-preview[bot] avatar dependabot[bot] avatar desperatecoder avatar newhinton avatar stefan-niedermann avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

nextcloud-commons's Issues

I can't get thumbnails from nextcloud server.

Hi @stefan-niedermann
I am trying to use this library to get the thumbnails from the nexcloud server, and use glide to apply them to an imageView. According to the description this is the correct library but I fail to use it.. 😞

Always fails with a 400 error

V/SingleSignOnLibraryGlideModule: Replacing default implementation for GlideUrl with SingleSignOnLibraryGlideModule.
D/com.nextcloud.android.sso.api.NetworkRequest: [connectApiWithBackoff] connectApiWithBackoff() called from Thread: [Thread-2]
D/com.nextcloud.android.sso.api.NetworkRequest: [connectApiWithBackoff] trying to connect..
D/com.nextcloud.android.sso.api.AidlNetworkRequest: [connect] Binding to AccountManagerService for type [nextcloud]
D/com.nextcloud.android.sso.api.NetworkRequest: [connect] connect() called [main] Account-Type: [nextcloud]
D/com.nextcloud.android.sso.api.AidlNetworkRequest: [connect] Component name is: [com.nextcloud.client]
V/SingleSignOnStreamFetcher: NextcloudRequest(method=GET, header={User-Agent=[Dalvik/2.1.0 (Linux; U; Android 10; moto g(8) plus Build/QPI30.28-Q3-28-26)]}, parameter={}, requestBody=null, url=/index.php/core/preview, token=null, packageName=null, accountName=null, bodyAsStream=null, followRedirects=false)
V/com.nextcloud.android.sso.api.AidlNetworkRequest: [waitForApi] - api not ready yet.. waiting [glide-source-thread-0]
D/com.nextcloud.android.sso.api.AidlNetworkRequest: [connect] Bound to AccountManagerService successfully
D/com.nextcloud.android.sso.api.AidlNetworkRequest: [onServiceConnected] called from Thread: [main] with IBinder [ComponentInfo{com.nextcloud.client/com.owncloud.android.services.AccountManagerService}]: android.os.BinderProxy@7abe8f3
V/SingleSignOnStreamFetcher: SSO API successfully initialized
D/com.nextcloud.android.sso.api.AidlNetworkRequest: copy data from service finished
W/ud.testglidess: Accessing hidden method Landroid/app/ActivityThread;->currentApplication()Landroid/app/Application; (greylist, reflection, allowed)
W/Glide: Load failed for https://delellis.com.ar/index.php/core/preview?fileId=187239&x=512&y=512&a=false&v=3168c3d339e99c870bd9d92a666526a4 with size [1080x336]
    class com.bumptech.glide.load.engine.GlideException: Failed to load resource
    There was 1 cause:
    com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException(La petición HTTP ha fallado con un código de estado: 400)
     call GlideException#logRootCauses(String) for more detail
      Cause (1 of 1): class com.bumptech.glide.load.engine.GlideException: Fetching data failed, class java.io.InputStream, REMOTE
    There was 1 cause:
    com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException(La petición HTTP ha fallado con un código de estado: 400)
     call GlideException#logRootCauses(String) for more detail
        Cause (1 of 1): class com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException: La petición HTTP ha fallado con un código de estado: 400
I/Glide: Root cause (1 of 1)
    com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException: La petición HTTP ha fallado con un código de estado: 400
        at com.nextcloud.android.sso.api.AidlNetworkRequest.performNetworkRequestV2(AidlNetworkRequest.java:172)
        at com.nextcloud.android.sso.api.NextcloudAPI.performNetworkRequestV2(NextcloudAPI.java:168)
        at it.niedermann.nextcloud.sso.glide.SingleSignOnStreamFetcher.loadData(SingleSignOnStreamFetcher.kt:64)
        at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:70)
        at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:63)
        at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310)
        at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:279)
        at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:234)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)
        at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:393)
     Caused by: java.lang.IllegalStateException: []
    
        at com.nextcloud.android.sso.InputStreamBinder.processRequestV2(InputStreamBinder.java:429)
        at com.nextcloud.android.sso.InputStreamBinder.performNextcloudRequestAndBodyStreamV2(InputStreamBinder.java:125)
        at com.nextcloud.android.sso.InputStreamBinder.performNextcloudRequestV2(InputStreamBinder.java:108)
        at com.nextcloud.android.sso.aidl.IInputStreamService$Stub.onTransact(IInputStreamService.java:158)
        at android.os.Binder.execTransactInternal(Binder.java:1036)
        at android.os.Binder.execTransact(Binder.java:1003)

As the questions will be very long, prepare a test to exemplify. This is just an activity, with a button to select the account, and an imageView to apply the image.

The main code:

I guess it should be pretty simple to read, and know if I'm forgetting something but If you want to try, you should just change this URL to any thumbail url acquired from the browser

https://github.com/matiasdelellis/TestGlideSSO/blob/master/app/src/main/java/com/nextcloud/testglidesso/MainActivity.java#L88

Thank you very much for all your work!. 😄

Crash on empty checklist entry

Please use GitHub reactions 👍 to show that you are affected by the same issue. Please don't comment if you have no relevant information to add!

Describe the bug
The application crashes when a new empty checklist entry is validated.

To Reproduce
Steps to reproduce the behavior:

  1. Create a new note
  2. Start a new checklist. E. G. - [x] done
  3. Add a new empty entry: - [ ] and press entrer
  4. See java crash report

Expected behavior
Empty entry added or removed, no crash

Screenshots


Smartphone (please complete the following information):

  • Nextcloud Notes-Version (android app): 3.4.16
  • F-Droid or Play Store: fdroid
  • Android-Version: 4.14.190-perf+(2108182246)
  • Device: HD1903 (OnePlus7T_EEA)

Server

  • Nextcloud version: 22.2.0
  • Nextcloud Notes version (server app): 4.1.1

Stacktrace

java.lang.IndexOutOfBoundsException: replace (11 ... 18) ends beyond length 17
	at android.text.SpannableStringBuilder.checkRange(SpannableStringBuilder.java:1325)
	at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:513)
	at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:507)
	at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:37)
	at it.niedermann.android.markdown.markwon.textwatcher.AutoContinuationTextWatcher.deleteCustomText(AutoContinuationTextWatcher.java:78)
	at it.niedermann.android.markdown.markwon.textwatcher.AutoContinuationTextWatcher.afterTextChanged(AutoContinuationTextWatcher.java:60)
	at it.niedermann.android.markdown.markwon.textwatcher.LowerIndentionTextWatcher.afterTextChanged(LowerIndentionTextWatcher.java:49)
	at it.niedermann.android.markdown.markwon.textwatcher.SearchHighlightTextWatcher.afterTextChanged(SearchHighlightTextWatcher.java:61)
	at it.niedermann.android.markdown.markwon.textwatcher.CombinedTextWatcher.afterTextChanged(CombinedTextWatcher.java:47)
	at android.widget.TextView.sendAfterTextChanged(TextView.java:10626)
	at android.widget.TextView$ChangeWatcher.afterTextChanged(TextView.java:13629)
	at android.text.SpannableStringBuilder.sendAfterTextChanged(SpannableStringBuilder.java:1277)
	at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:577)
	at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:507)
	at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:37)
	at android.text.method.QwertyKeyListener.onKeyDown(QwertyKeyListener.java:228)
	at android.text.method.TextKeyListener.onKeyDown(TextKeyListener.java:141)
	at android.widget.TextView.doKeyDown(TextView.java:8490)
	at android.widget.TextView.onKeyDown(TextView.java:8264)
	at android.view.KeyEvent.dispatch(KeyEvent.java:2842)
	at android.view.View.dispatchKeyEvent(View.java:14326)
	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1974)
	at android.widget.ScrollView.dispatchKeyEvent(ScrollView.java:491)
	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1974)
	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1974)
	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1974)
	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1974)
	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1974)
	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1974)
	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1974)
	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1974)
	at com.android.internal.policy.DecorView.superDispatchKeyEvent(DecorView.java:505)
	at com.android.internal.policy.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1884)
	at android.app.Activity.dispatchKeyEvent(Activity.java:4091)
	at androidx.core.app.ComponentActivity.superDispatchKeyEvent(ComponentActivity.java:122)
	at androidx.core.view.KeyEventDispatcher.dispatchKeyEvent(KeyEventDispatcher.java:84)
	at androidx.core.app.ComponentActivity.dispatchKeyEvent(ComponentActivity.java:140)
	at androidx.appcompat.app.AppCompatActivity.dispatchKeyEvent(AppCompatActivity.java:599)
	at androidx.appcompat.view.WindowCallbackWrapper.dispatchKeyEvent(WindowCallbackWrapper.java:59)
	at androidx.appcompat.app.AppCompatDelegateImpl$AppCompatWindowCallback.dispatchKeyEvent(AppCompatDelegateImpl.java:3068)
	at androidx.appcompat.view.WindowCallbackWrapper.dispatchKeyEvent(WindowCallbackWrapper.java:59)
	at com.android.internal.policy.DecorView.dispatchKeyEvent(DecorView.java:412)
	at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:6397)
	at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:6265)
	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5735)
	at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5792)
	at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5758)
	at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5910)
	at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5766)
	at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5967)
	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5739)
	at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5792)
	at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5758)
	at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5766)
	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5739)
	at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:8639)
	at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:8590)
	at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:8488)
	at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:5465)
	at android.os.Handler.dispatchMessage(Handler.java:106)
	at android.os.Looper.loop(Looper.java:233)
	at android.app.ActivityThread.main(ActivityThread.java:8010)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:631)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:978)

`IndexOutOfBoundsException` after pressing `link` in the context menu

nextcloud-commons:1.6.2

Happened after pressing Link in the context menu:

App Version: 3.4.19
App Version Code: 3004019
App Flavor: fdroid

Files App Version Code: 30190190

---

OS Version: 4.9.306-perf-g60bc22821300(10041563)
OS API Level: 30
Device: beryllium
Manufacturer: Xiaomi
Model (and Product): POCO F1 (beryllium)

---

java.lang.IndexOutOfBoundsException: charAt: 72 >= length 72
	at android.text.SpannableStringBuilder.charAt(SpannableStringBuilder.java:124)
	at it.niedermann.android.markdown.MarkdownUtil.insertLink(MarkdownUtil.java:413)
	at it.niedermann.android.markdown.markwon.format.ContextBasedFormattingCallback.onActionItemClicked(ContextBasedFormattingCallback.java:67)
	at android.widget.Editor$TextActionModeCallback.onActionItemClicked(Editor.java:4357)
	at com.android.internal.policy.DecorView$ActionModeCallback2Wrapper.onActionItemClicked(DecorView.java:2660)
	at com.android.internal.view.FloatingActionMode$3.onMenuItemSelected(FloatingActionMode.java:97)
	at com.android.internal.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:787)
	at com.android.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:151)
	at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:934)
	at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:924)
	at com.android.internal.view.FloatingActionMode.lambda$setFloatingToolbar$0$FloatingActionMode(FloatingActionMode.java:122)
	at com.android.internal.view.-$$Lambda$FloatingActionMode$LU5MpPuKYDtwlFAuYhXYfzgLNLE.onMenuItemClick(Unknown Source:2)
	at com.android.internal.widget.FloatingToolbar$FloatingToolbarPopup$2.onClick(FloatingToolbar.java:442)
	at android.view.View.performClick(View.java:7448)
	at android.view.View.performClickInternal(View.java:7425)
	at android.view.View.access$3600(View.java:810)
	at android.view.View$PerformClick.run(View.java:28305)
	at android.os.Handler.handleCallback(Handler.java:938)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loop(Looper.java:223)
	at android.app.ActivityThread.main(ActivityThread.java:7664)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

`IndexOutOfBoundsException` when adding content to headline in last line

nextcloud-commons:1.6.2

Originally reported at help.nextcloud.com

App Version: 3.4.18
App Version Code: 3004018
App Flavor: play

Files App Version Code: 30190190

---

OS Version: 4.19.111-23350288(G525FXXS5AVB3)
OS API Level: 30
Device: xcover5
Manufacturer: samsung
Model (and Product): SM-G525F (xcover5eea)

---

java.lang.RuntimeException: java.lang.IndexOutOfBoundsException: setSpan (203 ... 205) ends beyond length 203
	at io.noties.markwon.editor.MarkwonEditorTextWatcher$WithPreRender$2$2.run(MarkwonEditorTextWatcher.java:168)
	at android.os.Handler.handleCallback(Handler.java:938)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loop(Looper.java:246)
	at android.app.ActivityThread.main(ActivityThread.java:8653)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
Caused by: java.lang.IndexOutOfBoundsException: setSpan (203 ... 205) ends beyond length 203
	at android.text.SpannableStringBuilder.checkRange(SpannableStringBuilder.java:1335)
	at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:694)
	at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:686)
	at io.noties.markwon.editor.MarkwonEditorImpl$RecordingSpannableStringBuilder.setSpan(MarkwonEditorImpl.java:203)
	at it.niedermann.android.markdown.markwon.handler.HeadingEditHandler.handleMarkdownSpan(HeadingEditHandler.java:69)
	at it.niedermann.android.markdown.markwon.handler.HeadingEditHandler.handleMarkdownSpan(HeadingEditHandler.java:14)
	at io.noties.markwon.editor.MarkwonEditor$SpansHandlerImpl.handle(MarkwonEditor.java:185)
	at io.noties.markwon.editor.MarkwonEditorImpl.process(MarkwonEditorImpl.java:85)
	at io.noties.markwon.editor.MarkwonEditorImpl.preRender(MarkwonEditorImpl.java:157)
	at io.noties.markwon.editor.MarkwonEditorTextWatcher$WithPreRender$2.run(MarkwonEditorTextWatcher.java:137)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
	at java.lang.Thread.run(Thread.java:923)

Reuse of parts of AbstractStreamFetcher

First of all, thanks for your work in the Nextcloud area! 👏

I currently develop a Kotlin Multiplatform application with Nextcloud integration.
On Android it uses the SSO library for authentication.

To allow Nextcloud requests in the common code I developed a custom Ktor client engine which wraps Nextcloud API from the SSO Library. It is currently just a draft to try things out and needs some clean up.
This works as expected and even allows me to use Coil 3 as Image fetching library.

As I was trying to fetch a preview image from Nextcloud I stumbled upon the issue of not handling query parameters correctly.
Which brought me to the discovery of this library through this issue: nextcloud/Android-SingleSignOn#266

For the time being I integrated not only the query param part but all of AbstractStreamFetcher.kt into my Ktor engine and all workes as expected.
I can not import the sso-glide library and use this file directly as I do not want to have a dependency on Glide.

Important

I'm aware of the GNU General Public License v3.0 and its implications which brings me to my question:

I haven't yet decided on a license for my project but I would most certainly factor out your code into a extra module to publish it under GNU GPL 3.
As I have not really modified anything apart from also ignoring /ocs requests in this place, to not let them be converted to webdav urls, which allows me to still make non image requests through the engine, I thought it might be a better idea to make an abstracted module with this functionality here in the original repo and publish that as separate artifact.
This way I could use it in my code without copying it over.

Would you be open for such a contribution or willing to do it yourself?

Fallback to `WebDAV`

Motivation

As a user i want to be able to fetch an image with by a path to the file in my Nextcloud user folder like /foo/bar.png.

Current behavior

Given the above mentioned URL gets passed into Glide as target URL
then the sso-glide module should try to resolve and extract

  • Share IDs → rewrite to download path of the shared file
  • File IDs → rewrite to preview path of the file
  • As a fallback, we just try to call the given URL and hope for the best. Tthis will work for example for fetching avatars, but not in this scenario. ❌

Expected behavior

Given the above mentioned URL gets passed into Glide as target URL
then the sso-glide module should try to resolve and extract

  • Share IDs → rewrite to download path of the shared file
  • File IDs → rewrite to preview path of the file
  • paths starting with /index.php/... or /remote.php/... → should not be touched or modified as they can belong to avatars or app specific image resources
  • As a fallback, we should try to rewrite the path of the URL to a WebDAV URL, like /foo/bar.png → rewrite to /remote.php/webdav/foo/bar.png. ✔️

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.