Categories
discuss

Is there a way to prevent a layout from “jumping” when the status bar is being hidden?

I’m trying to implement a photo viewer in my app using a view pager. I’m able to get the system UI to disappear (both navigation and status bar) on a single touch. The only issue I’m having is that my layout on my view pager begins to shake or jump every time I make the status bar disappear and reappear.

A visual of my implementation

What I’m trying to implement

I’ve tried setting the system ui flags as per the suggestion in this stack over flow post. But it is still giving me the “jumpy” layout response.

The code below is what I used to hide/show status bar:

/**
 * Hide status bar and navigation bar.
 */
private fun hideSysWindows(activity: Window) {
    activity.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            or View.SYSTEM_UI_FLAG_FULLSCREEN
            or View.SYSTEM_UI_FLAG_IMMERSIVE)
}

/**
 * Show status bar and navigation bar.
 */
private fun showSysWindows(activity: Window) {
    activity.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
}

XML Code for my view pager:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:background="@color/black">

    <com.example.snapkit.mediaviewer.MediaViewPager android:layout_width="match_parent"
                                                    android:layout_height="match_parent"
                                                    android:id="@+id/media_viewer"/>

</LinearLayout>

Answer

So I did the implementation on a fresh project and tried it on two different devices in my emulator (Pixel 2 XL & Pixel 3 XL). What I noticed was that it would hide normally under the pixel 2 but on the pixel 3 xl (with the notch) it will draw below the notch itself.

After some searching I realized I have to mess with the display cutout (also known as the notch) and set a flag to tell the system ui to draw under the notch itself.

This worked like a charm, hopefully the code below will help anyone who sees this.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){
        window.attributes.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
    }
Categories
discuss

Node.js – How to find the desktop path?

As the mentioned Node.js – Find home directory in platform agnostic way question, we can find the home folder via this code:

const homedir = require('os').homedir();

But how can I find the desktop folder whatever language is it in Windows? Because in windows desktop folder name is differ to languages.

Answer

Actually, the name is always Desktop, regardless of language. However Windows creates a virtual alias for the folder. In Portuguese is “Área de Trabalho”, but you can access with %USERPROFILE%Desktop

Categories
discuss

Using kotlin coroutines with room

In 2.1 Room added support for coroutines, but I can’t get it working. It should be as easy as adding the dependency but somehow I’m overlooking something.

In my build.gradle I got the dependencies for coroutines, room and room-coroutines

dependencies { 
    def room_version = "2.2.0-beta01"
    // Room components
    implementation "android.arch.persistence.room:runtime:$room_version"
    kapt "android.arch.persistence.room:compiler:$room_version"
    implementation "androidx.room:room-ktx:$room_version"
    androidTestImplementation "android.arch.persistence.room:testing:$room_version"
    def coroutines_version = "1.1.1"
    // Coroutines
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
}

I allready tryed resyncing gradle, cleaning and rebuilding the project.

In my Doa i have methods like the following

@Dao
interface PlanDao {
    @Insert
    suspend fun insertVerPlan(verPlan: SqlVerPlan)
}

When trying to build the project Room doesn’t know how to handle the suspending functions and the following error occurs:

error: Type of the parameter must be a class annotated with @Entity or a collection/array of it.
    kotlin.coroutines.Continuation<? super kotlin.Unit> p1);
                                                        ^

error: Methods annotated with @Insert can return either void, long, Long, long[], Long[] or List<Long>.
    public abstract java.lang.Object insertVerPlan(@org.jetbrains.annotations.NotNull()
                                     ^

I seriously don’t know what I’m missing and I can’t find anyone with the same problem since the new Room version.

Answer

You’re mixing different versions of the room library.

android.arch.persistence.room:runtime should be androidx.room:room-runtime

android.arch.persistence.room:compiler should be androidx.room:room-compiler

android.arch.persistence.room:testing should be androidx.room:room-testing

as per Room#Declaring dependencies

Since you’re using the old coordinates for the compiler it does not know about the suspend support.

Categories
discuss

Cordova jQuery AJAX call timing out after 30 seconds regardless of timeout setting

I’m trying to execute the following function on Android to sync with an IoT device I’m making:

function NewDeviceFetchDeviceID(){
    strURL = "https://192.168.x.x/.....";

    return $.ajax({
        url: strURL,
        type: 'GET',
        timeout: 90000
    });
}

The device takes some time to churn a response to the request (about 45-50 seconds) so I need the timeout to be slightly longer than 30s. The timeout seems to work on iOS – if I set it to 5 seconds it will do so, if I set it for 90 it will wait the whole time. For Android, it seems that this argument is ignored.

I tried adding the following into config.xml under <platform name="android"> with no luck:

<preference name="LoadUrlTimeoutValue" value="90000"/>

and I tried with a lowercase “L”, still no luck:

<preference name="loadUrlTimeoutValue" value="90000"/>

How can I properly increase the timeout argument for AJAX requests in a Cordova Android app?


Update: I’ve changed the function, and I indeed get “Timed out!!!” as the response after exactly 30 seconds:

function TryXHR(){
    try{
        var xhr = new XMLHttpRequest();

        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                alert("ready state = 4");
            }
        };

        strURL = "https://192.168.x.x/......";
        xhr.open("POST", strURL, true);
        xhr.setRequestHeader("Content-type", "application/json; charset=utf-8");
        xhr.timeout = 120000; // Set timeout to 120 seconds (120000 milliseconds)
        xhr.onload  = function () { alert(xhr.response); }
        xhr.ontimeout = function () { alert("Timed out!!!"); }
        xhr.onerror = function () { alert("Non-timeout error"); }
        xhr.send();
    }catch(err){
        alert("exception caught: "+err.message);
    }
}

Answer

So after about a month of struggling with this, I ended up using the Cordova Advanced HTTP plugin: https://www.npmjs.com/package/cordova-plugin-advanced-http

Using the setRequestTimeout method, I was able to increase the HTTP request timeout to 120 seconds:

cordova.plugin.http.setRequestTimeout(120.0);

After rewriting my requests to utilize this plugin, my issues were solved for Android 9/10, and everything still worked as expected for iOS 12/13.

Categories
discuss

How to adapt trampolines to Continuation Passing Style?

Here is a naive implementation of a right fold:

const foldr = f => acc => ([x, ...xs]) =>
  x === undefined
    ? acc 
    : f(x) (foldkr(f) (acc) (xs));

This is non-tail recursion and hence we cannot apply a trampoline. One approach would be to make the algorithm iterative and use a stack to mimick the function call stack.

Another approch would be to transform the recursion into CPS:

const Cont = k => ({runCont: k});

const foldkr = f => acc => ([x, ...xs]) =>
  Cont(k =>
    x === undefined
      ? k(acc)
      : foldkr(f) (acc) (xs)
          .runCont(acc_ => k(f(x) (acc_))));

This is still naive, because it is insanely slow. Here is a less memory consuming version:

const foldkr = f => acc => xs => {
  const go = i =>
    Cont(k =>
      i === xs.length
        ? k(acc)
        : go(i + 1)
            .runCont(acc_ => k(f(xs[i]) (acc_))));

  return go(0);
};

The recursive call is now in tail position hence we should be able to apply a trampoline of our choice:

const loop = f => {
  let step = f();

  while (step && step.type === recur)
    step = f(...step.args);

  return step;
};

const recur = (...args) =>
  ({type: recur, args});

const foldkr = f => acc => xs =>
  loop((i = 0) => 
    Cont(k =>
      i === xs.length
        ? k(acc)
        : recur(i + 1)
            .runCont(acc_ => k(f(xs[i]) (acc_)))));

This doesn’t work, because the trampoline call is inside the continuation and thus lazily evaluated. How must the trampoline be adapted so that it works with CPS?

Answer

tail calls first (part 1)

First write the loop such that it recurs in tail position

const foldr = (f, init, xs = []) =>
  loop
    ( ( i = 0
      , k = identity
      ) =>
        i >= xs.length 
          ? k (init)
          : recur
              ( i + 1
              , r => k (f (r, xs[i]))
              )
   )

Given two inputs, small and large, we test foldr

const small =
  [ 1, 2, 3 ]

const large =
  Array.from (Array (2e4), (_, n) => n + 1)

foldr ((a, b) => `(${a}, ${b})`, 0, small)
// => (((0, 3), 2), 1)

foldr ((a, b) => `(${a}, ${b})`, 0, large)
// => RangeError: Maximum call stack size exceeded

But it uses a trampoline, why does it fail for large? The short answer is because we built a huge deferred computation, k

loop
  ( ( i = 0
    , k = identity // base computation
    ) =>
      // ...
      recur // this gets called 20,000 times
        ( i + 1
        , r => k (f (r, xs[i])) // create new k, deferring previous k
        )
  )

In the terminating condition, we finally call k(init) which fires off the stack of deferred computations, 20,000 function calls deep, which triggers the stack-overflow.

Before reading on, expand the snippet below to make sure we’re on the same page –

const identity = x =>
  x
  
const loop = f =>
{ let r = f ()
  while (r && r.recur === recur)
    r = f (...r.values)
  return r
}

const recur = (...values) =>
  ({ recur, values })

const foldr = (f, init, xs = []) =>
  loop
    ( ( i = 0
      , k = identity
      ) =>
        i >= xs.length 
          ? k (init)
          : recur
              ( i + 1
              , r => k (f (r, xs[i]))
              )
   )

const small =
  [ 1, 2, 3 ]

const large =
  Array.from (Array (2e4), (_, n) => n + 1)

console.log(foldr ((a, b) => `(${a}, ${b})`, 0, small))
// (((0, 3), 2), 1)

console.log(foldr ((a, b) => `(${a}, ${b})`, 0, large))
// RangeError: Maximum call stack size exceeded

deferred overflow

The problem we’re seeing here is the same one you might encounter if you were to compose(...) or pipe(...) 20,000 functions together –

// build the composition, then apply to 1
foldl ((r, f) => (x => f (r (x))), identity, funcs) (1)

Or similar using comp

const comp = (f, g) =>
  x => f (g (x))

// build the composition, then apply to 1
foldl (comp, identity, funcs) 1

Sure, foldl is stack-safe and it can compose 20,000 functions, but as soon as you call the massive composition, you risk blowing the stack. Now compare that to –

// starting with 1, fold the list; apply one function at each step
foldl ((r, f) => f (r), 1, funcs)

… which does not blow the stack because the computations are not deferred. Instead the result from one step overwrites the result from the previous step until the final step is reached.

In fact, when we write –

r => k (f (r, xs[i]))

Another way to see this is –

comp (k, r => f (r, xs[i]))

This should highlight exactly where the problem is.


possible solution

One simple remedy is to add a separate call tag that flattens the deferred computation in the trampoline. So instead of calling a function directly like f (x), we’ll write call (f, x)

const call = (f, ...values) =>
  ({ call, f, values })

const foldr = (f, init, xs = []) =>
  loop
    ( ( i = 0
      , k = identity
      ) =>
        i >= xs.length 
          // k (init) rewrite as
          ? call (k, init)
          : recur
              ( i + 1
              // r => k (f (r, xs[i])) rewrite as
              , r => call (k, f (r, xs[i]))
              )
   )

We modify the trampoline to act on call-tagged values –

const loop = f =>
{ let r = f ()
  while (r)
    if (r.recur === recur)
      r = f (...r.values)
    else if (r.call === call)
      r = r.f (...r.values)
    else
      break
  return r
}

Finally, we see that the large input no longer overflows the stack –

foldr ((a, b) => `(${a}, ${b})`, 0, small)
// => (((0, 3), 2), 1)

foldr ((a, b) => `(${a}, ${b})`, 0, large)
// => (Press "Run snippet" below see results ...)

const identity = x =>
  x
  
const loop = f =>
{ let r = f ()
  while (r)
    if (r.recur === recur)
      r = f (...r.values)
    else if (r.call === call)
      r = r.f (...r.values)
    else
      break
  return r
}

const recur = (...values) =>
  ({ recur, values })
  
const call = (f, ...values) =>
  ({ call, f, values })

const foldr = (f, init, xs = []) =>
  loop
    ( ( i = 0
      , k = identity
      ) =>
        i >= xs.length 
          ? call (k, init)
          : recur
              ( i + 1
              , r => call (k, f (r, xs[i]))
              )
   )
   
const small =
  [ 1, 2, 3 ]

const large =
  Array.from (Array (2e4), (_, n) => n + 1)

console.log(foldr ((a, b) => `(${a}, ${b})`, 0, small))
// (((0, 3), 2), 1)

console.log(foldr ((a, b) => `(${a}, ${b})`, 0, large))
// (Press "Run snippet" to see results ...)

wups, you built your own evaluator

Above, recur and call appear to be magic functions. But in reality, recur and call create simple objects { ... } and loop is doing all of the work. In this way, loop is a type of evaluator that accepts recur and call expressions. The one down-side to this solution is that we expect the caller always to use recur or call in tail position, otherwise the loop will return an incorrect result.

This is different than the Y-combinator which reifies the recursion mechanism as a parameter, and is not limited to a tail-only position, such as recur here –

const Y = f => f (x => Y (f) (x))

const fib = recur => n =>
  n < 2
    ? n
    : recur (n - 1) + recur (n - 2) // <-- non-tail call supported
    
console .log (Y (fib) (30))
// => 832040

The one down-side to Y is, of course, because you control recursion by calling a function, you are still stack-unsafe just like all other functions in JS. The result is a stack-overflow –

console .log (Y (fib) (100))
// (After a long time ...)
// RangeError: Maximum call stack size exceeded

So would it be possible to support recur in non-tail position and remain stack-safe? Sure, a sufficiently clever loop should be able evaluate recursive expressions –

const fib = (init = 0) =>
  loop
    ( (n = init) =>
        n < 2
          ? n
          : call
              ( (a, b) => a + b
              , recur (n - 1)
              , recur (n - 2)
              ) 
    )

fib (30)
// expected: 832040

loop becomes a CPS tail-recursive function for evaluating the input expressions call, recur, etc. Then we put loop on a trampoline. loop effectively becomes an evaluator for our custom language. Now you can forget all about the stack – your only limitation now is memory!

Alternatively –

const fib = (n = 0) =>
  n < 2
    ? n
    : call
        ( (a, b) => a + b
        , call (fib, n - 1)
        , call (fib, n - 2)
        )

loop (fib (30))
// expected: 832040

In this related Q&A, I write a normal-order evaluator for untyped lambda calculus in JavaScript. It shows how you can write programs that are freed from the implementation effects (evaluation strategy, stack model, etc) of the host language. There we’re using Church-encoding, here were using call and recur, but the technique is the same.

Years back, I wrote a stack-safe variation using the technique I described above. I’ll see if I can ressurrect it and later make it available in this answer. For now, I’ll leave the loop evaluator as an exercise for the reader.

PART 2 added: loop evaluator


alternative solution

In this related Q&A, we build a stack-safe continuation monad.

Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..