GithubHelp home page GithubHelp logo

pandulapeter / beagle Goto Github PK

View Code? Open in Web Editor NEW
481.0 10.0 26.0 23.66 MB

A smart, reliable, and highly customizable debug menu library for Android apps that supports screen recording, network activity logging, and many other useful features.

License: Apache License 2.0

Kotlin 99.94% Ruby 0.06%
library debug menu android debug-menu beagle drawer debug-drawer kotlin

beagle's Introduction

Beagle (Android library)

A smart, reliable, and highly customizable debug menu library for Android apps that supports screen recording, network activity logging, generating bug reports, and many other useful features.

First steps

See it in action

Clone this repository, pick a build variant and run the app configuration. It should look something like this:

This demo application also contains instructions on how to set up Beagle and how to implement the various features that are being showcased. You should definitely consider giving it a try if you're interested in using the library in your projects. If you don't feel like building it for yourself, you can also download it from the Play Store:

The tutorials in the app cover everything from this readme, but in more detail. Another way to get an idea of what can be achieved with the library is this article, which presents various problems that can be solved with Beagle.

Use it in your project

If the wall of text below is too long for your taste, check out this gist that contains all the code you need for a nice configuration. Otherwise, let's do it step by step:

Step 0: Check the requirements

  • Minimum SDK level: 24+
  • Target SDK level: 34+ (check older versions for target smaller SDK-s)

Step 1: Add the MavenCentral repository

Make sure that the following is part of your project-level build.gradle file:

allprojects {
    repositories {
        …
        mavenCentral()
    }
}

Step 2: Pick a UI implementation and configure the dependencies

The actual UI of the debug menu can be displayed in multiple ways, which is specified by the suffix of the dependency. The following versions exist:

  • ui-activity - Displays the debug menu as a new screen (not recommended: modals are more useful).
  • ui-bottom-sheet - Displays the debug menu as a modal bottom sheet (recommended).
  • ui-dialog - Displays the debug menu as a modal dialog (recommended).
  • ui-drawer - Displays the debug menu as a side navigation drawer (highly recommended).
  • ui-view - Displaying the DebugMenuView is your responsibility (not recommended: shake to open, Beagle.show(), Beagle.hide(), the related VisibilityListener as well as the inset handling logic won't work out of the box).
  • noop - No UI, no logic. It has the same public API as all other variants, but it does nothing (this is intended for production builds).

So, for example, if you prefer the Drawer UI, something like the following needs to be added to your app-level build.gradle file (check the widget below the code snippet for the latest version):

dependencies {
    …
    def beagleVersion = "2.9.4"
    debugImplementation "io.github.pandulapeter.beagle:ui-drawer:$beagleVersion"
    releaseImplementation "io.github.pandulapeter.beagle:noop:$beagleVersion"
}

The latest version is:

Note: In case of the drawer UI, if you have overwritten the Activity's onBackPressed() method, you might notice that the default back navigation handling does not always work as expected. To fix this, in every Activity's onBackPressed() you should check that Beagle.hide() returns false before doing any other checks or calling the super implementation.

Step 3: Initialize the library

Just one line of code, preferably in the Application's onCreate() method:

Beagle.initialize(this)

Optionally you can add the following parameters to this function:

  • The appearance of the menu can be personalized by specifying an Appearance instance. For example, here you can specify a custom theme for the debug menu using the themeResourceId property, in case the one used by the Application / Activity is not suitable. Note: It's recommended to extend a .NoActionBar Material theme.
  • The behavior of the menu can be personalized by specifying a Behavior instance. For example, adjusting the shake to open threshold or the strength of the haptic feedback is a frequent use case of this class.

By default you can fetch Beagle by shaking the device.

Step 4: Finish the setup by adding modules

After this a number of modules should be provided, but this configuration can be changed at any time (from any thread) and the UI will automatically be updated. The simplest way of doing this is by calling:

Beagle.set(module1, module2, …)

At this point you should be aware of two options:

  • The list of built-in modules. Every file in this package is documented. These modules should cover most use cases and have the advantage of also providing a fake, noop implementation which means that no part of their logic is compiled into your release builds.
  • The ability to write custom modules. For this a good starting point is looking at the built-in implementations from above, but this document also provides some guidance.

Check out the showcase app for some ideas on what is possible with the built-in modules or for an interactive tool that can be used to preview any module configuration and generate the code for it. A more visual guide to some of the possibilities is this article.

Here is a minimal example that should work for most projects:

Beagle.set(
    HeaderModule(
        title = getString(R.string.app_name),
        subtitle = BuildConfig.APPLICATION_ID,
        text = "${BuildConfig.BUILD_TYPE} v${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})"
    ),
    AppInfoButtonModule(),
    DeveloperOptionsButtonModule(),
    PaddingModule(),
    TextModule("General", TextModule.Type.SECTION_HEADER),
    KeylineOverlaySwitchModule(),
    AnimationDurationSwitchModule(),
    ScreenCaptureToolboxModule(),
    DividerModule(),
    TextModule("Logs", TextModule.Type.SECTION_HEADER),
    NetworkLogListModule(), // Might require additional setup, see below
    LogListModule(), // Might require additional setup, see below
    LifecycleLogListModule(),
    DividerModule(),
    TextModule("Other", TextModule.Type.SECTION_HEADER),
    DeviceInfoModule(),
    BugReportButtonModule()
)

If you ever need to add temporary modules, Beagle.add() has an optional lifecycleOwner parameter that automatically removes the specified modules once the provided lifecycle is over. Manually calling Beagle.remove() with module ID-s is also an option.

Advanced features

Logging

While calling Beagle.log() is the simplest way to add items to LogListModule, a special workaround is needed to access this functionality from pure Kotlin modules. Another frequent use case is integration with Timber.

Logging from pure Kotlin modules

To access the same functionality that Beagle.log() provides from a pure Kotlin / Java module, first you need to add the following to the module in question:

dependencies {
    …
    api "io.github.pandulapeter.beagle:log:$beagleVersion"

    // Alternative for Android modules:
    // debugApi "io.github.pandulapeter.beagle:log:$beagleVersion"
    // releaseApi "io.github.pandulapeter.beagle:log-noop:$beagleVersion"
}

These libraries provide the BeagleLogger object which needs to be connected to the main library when it is initialized in the Application class:

Beagle.initialize(
    …
    behavior = Behavior(
        …
        logBehavior = Behavior.LogBehavior(
            loggers = listOf(BeagleLogger),
            …
        )
    )
)

To add log messages, now you can call the following:

BeagleLogger.log(…)

The messages list will be merged with the ones logged using the regular Beagle.log() function (unless they are filtered by their tags) and can be displayed using a LogListModule. You can also use BeagleLogger.clearLogEntries() if you cannot access Beagle.clearLogEntries().

Logging with Timber

To automatically add events logged with Timber to the debug menu, planting a special tree is the simplest solution:

Timber.plant(
    object : Timber.Tree() {
        override fun log(priority: Int, tag: String?, message: String, t: Throwable?) =
            Beagle.log("[$tag] $message", "Timber", t?.stackTraceToString())
    }
)

To create a special LogListModule that only displays these logs, simply set the label constructor parameter of the module to "Timber".

Intercepting network events

Not bundling the network interceptor with the main library was mainly done to provide a pure Kotlin dependency that does not use the Android SDK, similarly to the logger solution described above. At the moment Beagle can only hook into the OkHttp networking library to provide content for NetworkLogListModule, but manually calling Beagle.logNetworkEvent() is always an option.

Add the following to the module where your networking logic is implemented:

dependencies {
    …
    api "io.github.pandulapeter.beagle:log-okhttp:$beagleVersion"
    
    // Alternative for Android modules:
    // debugApi "io.github.pandulapeter.beagle:log-okhttp:$beagleVersion"
    // releaseApi "io.github.pandulapeter.beagle:log-okhttp-noop:$beagleVersion"
}

This will introduce the BeagleOkHttpLogger object which first needs to be connected to the main library, the moment it gets initialized:

Beagle.initialize(
    …
    behavior = Behavior(
        …
        networkLogBehavior = Behavior.NetworkLogBehavior(
            networkLoggers = listOf(BeagleOkHttpLogger),
            …
        )
    )
)

The last step is setting up the Interceptor (the awkward casting is there to make sure the noop implementation does nothing while still having the same public API):

val client = OkHttpClient.Builder()
    …
    .apply { (BeagleOkHttpLogger.logger as? Interceptor?)?.let { addInterceptor(it) } }
    .build()
Displaying crash logs

The library can intercept uncaught exceptions and display their stack trace in a dialog. Users will be able to share the crash report using the bug reporting screen that gets opened automatically. This functionality is achieved through a separate dependency that should be added to the main module (where Beagle is initialized):

dependencies {
    …
    debugImplementation "io.github.pandulapeter.beagle:log-crash:$beagleVersion"
    releaseImplementation "io.github.pandulapeter.beagle:log-crash-noop:$beagleVersion"
}

After the dependencies are added, the newly introduced BeagleCrashLogger object should be connected to the main library:

Beagle.initialize(
    …
    behavior = Behavior(
        …
        bugReportingBehavior = Behavior.BugReportingBehavior(
            crashLoggers = listOf(BeagleCrashLogger),
            …
        )
    )
)

Using this feature simultaneously with other crash reporting solutions can be unreliable.

Also, please note that by introducing the log-crash dependency, Beagle's bug reporting Activity will now run in a separate process (Firebase for example needs a special initialization call for multi-process apps).

Improving encapsulation

The noop implementations of every public artifact are the default ways of not including Beagle-related logic in your production releases. While this should be good enough for most projects, it can be improved by creating a separate wrapper module for the debug menu. This would mean hiding every call to Beagle behind an interface that has an empty implementation in release builds. This approach has its own benefits and drawbacks:

  • Advantages
    • No Beagle imports outside of the wrapper module
    • Having a single entry-point to all features related to the debug menu
  • Disadvantages
    • More cumbersome initial setup
    • Losing the ability to use Beagle features in pure Kotlin modules

Troubleshooting

The debug menu UI doesn't show up
  • Make sure that you're not using the noop artifact in your current configuration
  • Make sure that you call the initialize() function in your custom Application class, and that class is properly registered in the Manifest
  • Make sure that your Activity extends FragmentActivity (for example, AppCompatActivity is a good choice). Watch out, if you're using the Empty Compose Activity template of Android Studio, you have to change the default parent class!
Crash on app launch

By default Beagle uses the current Activity's theme. However, it requires a Material theme to work, so if you have a crash caused by various theme attributes not being found, override the debug menu's theme with the themeResourceId property of the Appearance instance provided during initialization with a Material theme.

Crash when opening a third party Activity

Beagle works by adding a Fragment on top of every Activity's layout. Sometimes this is not necessary or not possible. While the library comes with a list of excluded Activity package names, you can provide additional filtering if needed, by using the shouldAddDebugMenu lambda property of the Behavior instance provided during initialization.

Gallery or Bug report screens having two toolbars

Set a .NoActionBar Material theme for the themeResourceId property of the Appearance instance provided during initialization.

About

Documentation

All public functions are documented with KDoc. The BeagleContract file is a good start for learning about all the built-in capabilities. For information on the individual modules, see the relevant class headers.

If you're interested in what's under the hood, this document can be helpful while navigating the source code.

Changelog

Check out the Releases page for the changes in every version.

The library uses semantic versioning: MAJOR.MINOR.PATCH where PATCH changes only contain bug fixes, MINOR changes add new features and MAJOR changes introduce breaking modifications to the API.

Known issues

Check out the Issues page for the list of known problems and for the planned enhancements of the library.

Don't hesitate to open a new issue if you find a bug or if you have any questions / feature requests!

Buy me a beer

If you found my work useful and are considering a small donation, the About section of the the showcase app has an option for you to do so. Thanks in advance!

License
Copyright 2022 Pandula Péter

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

beagle's People

Contributors

imecstamas avatar pandulapeter avatar percula avatar stephen-marc avatar yuraj11 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

beagle's Issues

[Bug] NetworkLogManager crashing application with concurrent modification exception

Description
I noticed a crash in my application which seems to be originating from Beagle.
The issue seems to be in the NetworkLogManager, in my case the problem was occurring by the sort function. In line 24 there is a entries.sortByDescending { it.timestamp }.

Repro steps
By the nature of the exception (ConcurrentModificationException) I cannot provide a good repro steps.

Version
the used version is 2.0.0-beta01
Based on the fact that this class has not been modified between beta01 and beta06 I assume the issue would still persist

Suggestion to fix
I suggest to use immutable list in the NetworkLogManager.entries so there is no possibility for concurrent modification.
Other possible solution could be to use other synchronization mechanizm

Stracktrace
java.util.ConcurrentModificationException at java.util.ArrayList.sort(ArrayList.java:1472) at java.util.Collections.sort(Collections.java:206) at kotlin.collections.CollectionsKt__MutableCollectionsJVMKt.sortWith(MutableCollectionsJVM.kt:42) at com.pandulapeter.beagle.core.manager.NetworkLogManager.log(NetworkLogManager.kt:40) at com.pandulapeter.beagle.core.BeagleImplementation.logNetworkEvent(BeagleImplementation.kt:150) at com.pandulapeter.beagle.common.contracts.BeagleContract$DefaultImpls.logNetworkEvent$default(BeagleContract.kt:301) at com.pandulapeter.beagle.core.util.NetworkInterceptor.intercept(NetworkInterceptor.kt:63) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100) at ***.OkHttpClientProvider$provide$1.intercept(OkHttpClientProvider.kt:29) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100) at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:197) at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:502) 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)

Android 10 gesture navigation conflict on OnePlus devices.

While on many devices there seems to be some sort of awkward gesture to bring up side drawers instead of trigerring the back navigation action (Pixel: hold to peek or swipe diagonally, Samsung: swipe vertically along the edge), the implementation on OnePlus apparently leaves no way of opening Beagle (if gesture navigation is enabled).

While the drawer can be opened programatically using Beagle.fetch(), there should be a better way to deal with the problem. Probably an optional mini FAB will be added to the library in the future.

[Feature Request] Separate logging from Android module

It would be nice if the Logging and NetworkLogging options could be included as java modules:
For multi-module projects where the networking layer is separated from the android-ui layer, either for separation of concerns or reusability, at the moment the main module most know about okhttp in order to provide the interceptor to the networking layer. Ofc this solution works, but it adds an okhttp dependency into the ui module while it shouldn't know anything about networking.

so the idea would be let's say we have a network-layer module:
this includes a beagle-network-loging dependency or something similar
the app module includes beagle the same way as does it now
The network-layer module could provide a BeagleNetworkLogger or something similar which can be added to Beagle itself, and gets the data from the already created interceptor.

This way the app module would not know anything about the networking only that there is a logger it should include, while network logging is still available.
Ofc names and the solution can be changed simplified, this just tries to illustrate the use-case and some rough high-level version of the problem.

Gesture navigation problem OnePlus.

Unfortunately on Android 10 on OnePlus, the new gesture navigation conflicts with the Beagle drawer open action. Can you add some other trigger to open the drawer?

[Feature request] Add a floating button

Hey, I would like to propose an idea for the library.
In our huge project, we faced with a situation, when the developer should change different options inside Tricks and after that restart application by clicking some button. After click, we save in preferences all necessary data and force stop application.

For this purpose will be very useful the new type of Trick (Please see "Apply" button on screenshot).

What do you think about this? 🙂
Best regards.

Add ability to access to current activity from Beagle

Hi, thanks for the great library.
We faced some issue, that we need to access current activity to open some dialogs by clicking to Button trick.

How to make this behaviour correctly? Or the library can have a method like this:
Beagle.currentActivity()

Thanks a lot.

Custom theme for Beagle

Hello)

I faced with the issue if I set the custom theme for the Beagle library, the theme applies to the whole activity.

Beagle.imprint(
    application = application,
    appearance = Appearance(themeResourceId = resourseId)
)

Can we fix this behaviour and apply that only for Navigation drawer?

BeagleNetworkInterceptor is misleadingly named

Due to the name I assumed I had to add BeagleNetworkInterceptor using OkHttpClient.Builder.addNetworkInterceptor(). This worked fine for a while, until I enabled gzip compression on backend responses, at which point this line started quietly mangling all my gzipped responses, then gzip decompression runs after the network interceptors, resulting in some confusing gzip decoding error.

I wonder if there's any way to assert that BeagleNetworkInterceptor got added as a normal interceptor and not a network interceptor, so this bug could've been caught early?

Cannot navigate back if activity is opening from beagle

Hi)
I faced an interesting issue. In my app, I have Trick Button and by clicking some debug Activity is opening.

Trick.Button(
                text = "test",
                onButtonPressed = {
                    Beagle.currentActivity?.run {
                        startActivity(Intent(this, MotionActivity::class.java) )
                    }
                }
            )

After that, I cannot go back from MotionActivity 🙂

Looks like a problem in this block of code

private val onBackPressedCallback = object : OnBackPressedCallback(false) {
        override fun handleOnBackPressed() {
            dismiss()
        }
    }

Thank you.

Does Beagle doesn't support API 16 & below?

Does Beagle only support minSdk 17?
Same SO Questions regarding marginStart|End: https://stackoverflow.com/a/25749855/3763032
Error Log:

    java.lang.NoSuchMethodError: android.widget.FrameLayout$LayoutParams.setMarginStart
        at com.pandulapeter.beagle.views.BeagleDrawer.<init>(BeagleDrawer.kt:52)
        at com.pandulapeter.beagle.views.BeagleDrawer.<init>(BeagleDrawer.kt:27)
        at com.pandulapeter.beagle.Beagle.createAndAddDrawerLayout(Beagle.kt:355)
        at com.pandulapeter.beagle.Beagle.access$createAndAddDrawerLayout(Beagle.kt:49)
        at com.pandulapeter.beagle.Beagle$lifecycleCallbacks$1.onActivityCreated(Beagle.kt:289)
        at android.app.Application.dispatchActivityCreated(Application.java:154)
        at android.app.Activity.onCreate(Activity.java:887)
        at androidx.core.app.ComponentActivity.onCreate(ComponentActivity.java:81)
        at androidx.activity.ComponentActivity.onCreate(ComponentActivity.java:154)
        at androidx.fragment.app.FragmentActivity.onCreate(FragmentActivity.java:312)
        at androidx.appcompat.app.AppCompatActivity.onCreate(AppCompatActivity.java:106)

Ability as all-in-one solutions for QA & Dev debugging task

I've recently used this OkReport features.

Would be nice if this library also support the following features:

  1. multiple screenshot (and able to highlight some area of view) - OkReport
  2. multiple repro steps - OkReport
  3. submit report to email/slack (for QA able to collect all the repro+screenshot) - OkReport
  4. error log crash reporting (no need to check for firebase crashlytics to diagnose the crash, because QA will share the crash log, good condition when e.g: AFK)
  5. network log ui, like Chucker

EDITED:
Point number 3, as you already planned in README.md, that's GREAT!!!

TODO: SendBugReportButton - Sends a pre-formatted message with logs to a specified email address.

Drawer does not work with FragNav

I'm using FragNav for fragments navigation (https://github.com/ncapdevi/FragNav) and when i set up MainActivity like this:

@AndroidEntryPoint
class MainActivity : AppCompatActivity(), FragNavController.TransactionListener {
    private val binding by viewBinding(ActivityMainBinding::inflate)

    val fragNavController = FragNavController(supportFragmentManager, R.id.fragmentContainer)

    override fun onCreate(savedInstanceState: Bundle?) {
        setTheme(R.style.AppTheme)
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        fragNavController.apply {
            transactionListener = this@MainActivity
            rootFragments = listOf(HomeFragment())
            fragNavLogger = object : FragNavLogger {
                override fun error(message: String, throwable: Throwable) {
                    Timber.e(throwable, message)
                }
            }

            defaultTransactionOptions = FragNavTransactionOptions.newBuilder().customAnimations(
                R.anim.slide_left_from_right,
                R.anim.slide_left_from_middle,
                R.anim.slide_right_from_left,
                R.anim.slide_right_from_middle
            ).build()
            initialize(savedInstanceState = savedInstanceState)
        }
    }
}

the Beagle.show() returns false. When i inspect layout - no overlay is being added. If i disable FragNav like this:

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    private val binding by viewBinding(ActivityMainBinding::inflate)

    override fun onCreate(savedInstanceState: Bundle?) {
        setTheme(R.style.AppTheme)
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        supportFragmentManager.commit {
            replace(R.id.fragmentContainer, HomeFragment())
        }
    }
}

It works perfectly. FragNav is pretty important to me. Is there a way to bypass this issue?

Rewrite the dialog used for displaying network request / response payloads

Required features:

  • Formatting the JSON should be done in the background to avoid blocking the UI thread in case of large payloads.
  • Controls for showing request / response metadata (headers, timestamp, duration) should be on the UI.
  • The copy feature is currently based on Android's default text selection UX which is cumbersome with JSON-s.
  • Expanding / collapsing JSON objects / arrays would be very helpful.
  • Links should be clickable.
  • Scrollbars are also needed.

How to disable Beagle at runtime?

I was looking for such a tool, it's too cool, you are really a cool dude. Thumbs up 👍
I got some issues when checked this -

  1. Not able to disable beagle using Beagle.isEnabled = false
  2. Not able to achieve desired theme for buttons test style and fonts

Introduce a lifecycle-aware learn() method

Having tricks that only appear on a single screen is a frequent usecase but the only way to implement it currently (saving the trick ID and adding / removing it in the component's lifecycle) is cumbersome and error-prone.

Adding a learn() method that takes a lifecycle parameter and resolves adding / removing the trick under the hood would be a more modern solution.

Refactor inset handling

Now that we target SDK 30 the current inset handling logic is deprecated. It also didn't work well on some apps (especially with the Insetter library it needed some manual workarounds) so hopefully migrating to new API-s will fix the issues.

Coil upgrade to 1.0.0.rc1

RC release of coil broke backwards compatibility and after upgrading it in my project - beagle is crashing on initialize. Could you release version with bumped coil version?

Version 0.12.0 does not work too

Improve list item appearance

  • The height of the items and their headers should be the same.
  • Adding a bullet point to the beginning of the list items is not the greatest UI decision.
  • Animating the chevron expanded / collapsed state would be a nice improvement.

Support for custom built Trick

Hi, I wonder if you had plans to make it more extensible in a near future? I've seen there is a lots of building blocks and great modules already built-in but I just wonder if you were planning to open Beagle for custom made Tricks.

Thanks and great work on the library! :)

Beagle preventing automatic keyboard opening.

Hey,

In a number of screens we have where the soft input keyboard is working, the focus is "stolen" by Beagle, and for that reason the keyboard doesn't open automatically. Do you have any suggestion on how to solve this?

Thanks.

ViewBoundsOverlayToggle crash

Hi. Thanks for the nice library. I found the crash for some functionality such as ViewBoundsOverlayToggle

If I enable this functionality, that crash happens. Looks like the problem in OverlayFrameLayout. Should be GlobalScope.launch(Dispatchers.Main) {}

Crash log:

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6855) at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:1075) at android.view.ViewGroup.invalidateChild(ViewGroup.java:5242) at android.view.View.invalidateInternal(View.java:13574) at android.view.View.invalidate(View.java:13538) at android.view.View.invalidate(View.java:13522) at com.pandulapeter.beagle.views.OverlayFrameLayout$startAutomaticRefresh$1.invokeSuspend(OverlayFrameLayout.kt:71) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56) at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:561) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:727) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:667) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:655)

EditText equivalent Trick

Does beagle have EditText equivalent for Trick or modules to include that will

Similar like SingleSelectionList, SimpleList but with additional features:

  1. input some text
  2. able to have an action with the provided text

[Bug] Default KeylineOverlay color is not updated on configuration change

Unless explicitly specified otherwise, the module tries to use the default text color from the theme. This is cached the first time the switch is enabled and does not get updated, for example when turning night mode on or off. As a result the caching logic should be removed (or invalidated more frequently).

Missing features from the Gallery screen

  • Add ability to preview images / videos.
  • Add ability to share multiple files.
  • Add ability to delete files.
  • Add section headers for days.
  • Differentiate between images and videos.

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.