Categories
discuss

Best place/lifecycle method to set page titles in a single-page Svelte app

I’m getting started with Svelte and building a single-page application (using page.js as the router). I thought I’d have a separate component to produce the <svelte:head> block, and when each component mounts it would write the page title to a store, which would then be read by the head component. It partially works – the page title is updated when I click through to different pages. However, if I go back in my browser’s history, the title doesn’t change back with the page. It does change if I then reload the page. So perhaps onMount() isn’t the right lifecycle method. What approach can I take that will work with history state navigation?

Here’s my app boiled down to a minimal example.

// index.js

import page from 'page'

import App from './views/App.svelte'

const app = new App({
    target: document.body,
    props: {
        route: null,
    },
})

function one() {
    app.$set({ route: 'one' })
}

function two() {
    app.$set({ route: 'two' })
}

page('/one', one)
page('/two', two)
page()

// App.svelte

<script>
    import One  from './One.svelte'
    import Two  from './Two.svelte'
    import Head from '../parts/Head.svelte'
    import Home from './Home.svelte'

    export let route
</script>

<Head />

{#if route === 'one'}
    <One />
{:else if route === 'two'}
    <Two />
{:else}
    <Home />
{/if}

// Head.svelte

<script>
    import { pageName } from '../stores.js'

    let displayPageName

    pageName.subscribe(value => {
        displayPageName = value
    })
</script>

<svelte:head>
    {#if displayPageName}
        <title>Test App &mdash; {displayPageName}</title>
    {:else}
        <title>Test App</title>
    {/if}
</svelte:head>

// stores.js

import { writable } from 'svelte/store'

export const pageName = writable(null)

// Home.svelte

<a href="/one">One</a> <a href="/two">Two</a>

// One.svelte

<script>
    import { onMount } from 'svelte'
    import { pageName } from '../stores.js'

    onMount(async () => {
        pageName.update(() => 'Component One')
    })
</script>

<a href="/two">Two</a>

// Two.svelte

<script>
    import { onMount } from 'svelte'
    import { pageName } from '../stores.js'

    onMount(async () => {
        pageName.update(() => 'Component Two')
    })
</script>

<a href="/one">One</a>

Answer

For some reasons, Svelte doesn’t seem to like the <title> in an {#if} block… I recommend computing the value in a reactive statement instead.

$: title = $pageName ? `Test App u2014 ${$pageName}` : 'Test App'

$pageName is a special syntax to access the store’s value without having to handle subscribe/unsubscribe yourself (docs).

Even with that, I found that my browser (tested in Chrome) was apparently OK with ignoring the <title> in the DOM when navigating back. We can force the value of document.title to workaround that. Another reactive block can take care of that:

$: {
  document.title = title
}

So your whole Head.svelte component would now looks like this:

<script>
  import { pageName } from '../stores.js'

  $: title = $pageName ? `Test App u2014 ${$pageName}` : 'Test App'

  $: {
    document.title = title
  }
</script>

<svelte:head>
  <title>{title}</title>
</svelte:head>

And finally, in your example, you’re not updating the store’s value when you navigate to /, so you’d have a stale title in this case. I think you need to add a route like so:

page('/', () => app.$set({ route: null }))
Categories
discuss

Calling functions from native compiled shared library on Android with Flutter

I have followed the instructions at https://flutter.dev/docs/development/platform-integration/c-interop and have successfully compiled cpp with a c abi and called it with the dart:ffi on an emulated android device using the CMake integration. This compiles an lib*.so file, copies it over with the flutter package and places it so I can reach it easily in my flutter code.

However, assume I already have a compiled shared library either compiled myself or gotten somewhere that works with Android and its given cpu architecture outside using CMake.

How do I add it to the flutter system so its copied over and placed in a “resolvable” location the same way its done when adding

android {
 //...
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}

adds the target in the CMake files with the package?

For details I have compiled an shared library in rust with cargo-ndk and the correct achitecture, but I only get errors when trying to open it with `ffi.DynamicLibrary.open(…), no matter what I have tried.

I am guessing its something stupidly simple, but I can’t figure out a way.

My dart ffi.DynamicLibrarycode linking against the library native on Windows works without problem. So it seems to be mainly a Android/flutter/gradle packaging issue.

Answer

To add your precompiled shared library, you need to put it in android/app/src/main/jniLibs/X folder, where X is architecture name (armeabi-v7a or arm64-v8a). Though it’s default path for libraries, I’m not completely sure if it’s necessary, but it’s probably safer to specify this folder as a source set in build.gradle:

android {
    sourceSets {
        main {
            jniLibs.srcDirs = ['src/main/jniLibs']
        }
    }        
}

After that you should be able to load it using Dart’s DynamicLibrary.open and Java’s System.loadLibrary.

Categories
discuss

Pointer Event issue: pointercancel with pressure input (pen)

Thank you for your help in advance. I’m a bit stumped with an issue I am having. I am developing a web app in chrome using react and canvas. This issue seems to be a PointerEvent issue with pressure pen input.

The issue: When I start to draw with my tablet and pen, the pointercancel event is triggered after a short distance has been drawn, even when pressure is still applied with the pen. (while using the mouse this works as intended and there is no issue)

To better describe the issue, this is a visual of what is happening. (.gif starts as a white screen)

A .gif of the pointercancel issue

The first line is a straight line with the pen input, which I attempt to draw across the screen, but as you can see, it is abruptly interrupted (this is where the pointercancel event is triggered) even though the pen pressure is still being applied. This also shows the area size that is possible before the event is triggered.

The second shows that as long as I stay in a small area with the pen input, the pointercancel does not trigger, but once I try and leave that area, the pointercancel event is triggered and stops the line from being drawn.

The third shows the input from the mouse, being able to move around the canvas without the pointercancel event being triggered.

Any help would be appreciated to figure out this issue, it does look like there is support since chrome 55 for this feature, so I am uncertain as to what could be causing the pointercancel to be triggered.

Although I don’t think it’s really relevant to the question, in case it is here is the code for the project, re-written a touch just to make it more legible. It’s not very complex, just a simple canvas to test input on.

The HTML for the canvas area is as follows (it’s inside a react component):

<div className="session-container">
  <canvas ref="canvas" className="canvas"></canvas>
</div>

and the javascript, which is all within a component in react, is as follows:

componentDidMount() {
  this.canvas = this.refs.canvas;
  this.context = this.canvas.getContext("2d");

  this.canvas.addEventListener('pointerdown', this.onDown, false);
  this.canvas.addEventListener('pointerup', this.onUp, false);
  this.canvas.addEventListener('pointercancel', this.onUp, false);
  this.canvas.addEventListener('pointermove', this.onMove, false);
}

onDown(e) {
  this.drawing = true;

  current.x = e.clientX || e.touches[0].clientX;
  current.y = e.clientY || e.touches[0].clientY;
}

onUp(e) {
  this.drawing = false;
}

onMove(e) {
  if (!this.drawing) return;

  this.drawLine(current.x, current.y, e.clientX || e.touches[0].clientX, e.clientY || e.touches[0].clientY, e.pressure, true);
  current.x = e.clientX || e.touches[0].clientX;
  current.y = e.clientY || e.touches[0].clientY;
}


drawLine(x0, y0, x1, y1, pressure, emit){
  this.context.beginPath();
  this.context.moveTo(x0, y0);
  this.context.lineTo(x1, y1);
  this.context.strokeStyle = 'black';
  this.context.lineWidth = 2;
  this.context.stroke();
  this.context.closePath();
}

A full view of the component can be found here Gist

Answer

to those who have the same problem :

the solution was in adding a css property touch-action: none;

it changes the behavior of pointer events, which seems to be by default : use any pointer as a clicking device, not a drawing one

Categories
discuss

JavaScript – How to handle 404 error in fetch?

When I call the request function passing a number which I know I will get a 404 error, I cant handle it, I dont know how to do it.

async request(number) {
    var request = "https://reqres.in/api/users/"+number;

    fetch(request, {method: "GET"})
    .then((response) => {
      return response.json(); 
    })
    .then((responseJson) => {
      this.setState({nombre:responseJson.data.first_name})
    })
    .catch((error) => {
      this.setState({nombre:error})
    }).done();
}

Full code: https://codeshare.io/5wWo9p

Answer

you can check for response status to handle 404 or other errors use below example:

fetch('your url goes here')
  .then(response => {
    if (response.ok) {
      return response.json()
    } else if(response.status === 404) {
      return Promise.reject('error 404')
    } else {
      return Promise.reject('some other error: ' + response.status)
    }
  })
  .then(data => console.log('data is', data))
  .catch(error => console.log('error is', error));
Categories
discuss

Screenshot robot only captures a black screen on Debian

I am creating a screen capture using java.awt.Robot under Linux with OpenJDK 11. The result on Linux is a whole black image. The same code works on Ubuntu and Windows (using another file path of course).

Any clue?

public void captureScreen() throws AWTException {
    Robot robot = new Robot(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice());
    BufferedImage screen = robot.createScreenCapture(new Rectangle(getDefaultToolkit().getScreenSize()));
    try {
        ImageIO.write(screen, "jpg", new File("/tmp/screenshot.jpg"));
    } catch (IOException e) {
        e.printStackTrace();
    }
}

UPDATE: The the cause of the problem lies in the combination of OpenJDK and Wayland. With Oracle JDK/JRE (13.0.1) everything works fine.

Answer

If you are using wayland instead of XOrg this may be causing the problem as it is less stable with Java interfaces for graphics operations.

Edit: This bug has now been fixed (see OP)

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..