Recherche effectué dans :

Filtre actif, cliquez pour en enlever un tag :

Cliquez sur un tag pour affiner votre recherche :

Résultat de la recherche (15 notes) :

Journal du jeudi 09 janvier 2025 à 13:13 #iteration, #devlog, #capacitor, #POC

Nouvelle #iteration sur le Projet 17 - Créer un POC de création d'une app smartphone avec Capacitor.

Je viens de push le commit feat(android): implemented webview and configured deeplinks. J'ai passé en tout, 11 heures sur cette itération.

Je souhaite, dans cette note de type DevLog, présenter les difficultés et les erreurs rencontrées dans cette itération.


Étape 1 : mise en place d'un dummy website totalement statique

The Capacitor application in this POC displays the content of a demonstration website, with the HTML content located in the ./dummy-website/ folder.
This website is served by an HTTP Nginx server, launched using docker-compose.yml.

source

Pour faire très simple, j'ai choisi de créer un faux site totalement statique, qui sera affiché dans une webview de l'application smartphone.

Ce site contient juste 2 pages HTML ; celui-ci est exposé par un serveur HTTP nginx, lancé via un docker-compose.yml.


Étape 2 : Expose dummy website on Internet

En première étape, j'ai dû mettre en place une méthode pour facilement exposer sur Internet un dummy website lancé localement :

Expose dummy website on Internet

Why?
The Android and iOS emulators do not have direct and easy access to the HTTP service (dummy website) exposed on http://localhost:8080.

To overcome this issue, I use "cloudflared tunnel". You can also use other solutions, such as sish or ngrok Developer Preview. For more information, you can refer to the following note (in French): 2025-01-06_2105

source

Comme expliqué ci-dessus, cette contrainte est nécessaire afin de permettre à l'émulateur Android et à l'émulateur iOS (lancé sur une instance Scaleway Apple Silicon) aussi bien que sur mon smartphone physique personnel, d'accéder aux dummy website avec un support https.

Ceci était d'autant plus nécessaire, pour remplir les contraintes de configuration de la fonctionnalité Deep Linking with Universal and App Links.

C'est pour cela que j'ai dernièrement publié les notes suivantes : 2024-12-28_1621, 2024-12-28_1710, 2024-12-31_1853 et Alternatives managées à ngrok Developer Preview.

Pour simplifier la configuration de ce projet (poc-capacitor), j'ai décidé d'utiliser "cloudflared tunnel" en mode non connecté.

J'ai installé cloudflared avec Mise (voir la configuration ici).

Pour rendre plus pratique le lancement et l'arrêt du tunnel cloudflare, j'ai implémenté deux scripts :

Voici ce que cela donne à l'usage :

$ ./scripts/start-cloudflare-http-tunnel.sh
Starting the tunnel...
…wait… …wait… …wait…
Tunnel started successfully: https://moral-clause-interesting-broadway.trycloudflare.com

To stop the tunnel, you can execute:

$ ./scripts/stop-cloudflare-http-tunnel.sh
Stopping the tunnel (PID: 673143)...
Tunnel stopped successfully.

source


Étape 3 : configuration de la webview Capacitor

En réalité, par erreur, j'ai configuré la webview Capacitor après l'implémentation de la partie App links.

Au départ, je pensais qu'un simple window.location.href = process.env.START_URL; était suffisant pour afficher le site web dans l'application. En réalité, cette commande a pour effet d'ouvrir la page HTML dans le browser par défaut du smartphone. Je ne m'en étais pas tout de suite rendu compte.

Dans Capacitor, pour créer une webview dans une application, il est nécessaire l'utiliser la fonction InAppBrowser.openInWebView(... du package @capacitor/inappbrowser.

Voici l'implémentation dans le fichier /src/js/online-webview.js :

window.Capacitor.Plugins.InAppBrowser.openInWebView({
	url: startUrl,
	options: {
		// See https://github.com/ionic-team/capacitor-os-inappbrowser/blob/e5bee40e9b942da0d4dad872892f5e7007d87e75/src/defaults.ts#L33
		// Constant values are in https://github.com/ionic-team/capacitor-os-inappbrowser/blob/e5bee40e9b942da0d4dad872892f5e7007d87e75/src/definitions.ts
		showToolbar: false,
		showURL: false,

		clearCache: true,
		clearSessionCache: true,
		mediaPlaybackRequiresUserAction: false,

		// closeButtonText: 'Close',
		// toolbarPosition: 'TOP', // ToolbarPosition.TOP

		// showNavigationButtons: true,
		// leftToRight: false,
		customWebViewUserAgent: 'capacitor webview',

		android: {
			showTitle: false,
			hideToolbarOnScroll: false,
			viewStyle: 'BOTTOM_SHEET', // AndroidViewStyle.BOTTOM_SHEET

			startAnimation: 'FADE_IN', // AndroidAnimation.FADE_IN
			exitAnimation: 'FADE_OUT', // AndroidAnimation.FADE_OUT
			allowZoom: false
		},
		iOS: {
			closeButtonText: 'DONE',           // DismissStyle.DONE
			viewStyle: 'FULL_SCREEN',          // iOSViewStyle.FULL_SCREEN
			animationEffect: 'COVER_VERTICAL', // iOSAnimation.COVER_VERTICAL
			enableBarsCollapsing: true,
			enableReadersMode: false
		}
	}
});

source

Les paramètres dans options permettent de configurer la webview. J'ai choisi de désactiver un maximum de fonctionnalités.

En implémentant cette partie, j'ai rencontré trois difficultés :

  • Avec la version 1.0.2 du packages, j'ai rencontré ce bug "Bug- Android App crashing after adding this plugin, j'ai perdu presque 1 heure avant de le découvrir, pour fixer cela, j'ai choisi le QuickWin d'installer la version 1.0.1.
  • J'ai mis un peu de temps pour trouver les paramètres passés dans options
  • J'ai trouvé allowZoom: false pour supprimer l'affichage des boutons de zoom dans la webview

Étape 4 : setup de la partie App Links

Après avoir lu la page "Deep Linking with Universal and App Links", c'était la partie que je trouvais la plus difficile, mais en pratique, ce n'est pas très compliqué.

J'ai passé 5h30 sur cette partie, mais j'ai fait plusieurs erreurs.

Cette configuration se passe en 3 étapes.

Génération du fichier .well-known/assetlinks.json

La première consiste à générer le fichier le fichier dummy-website/.well-known/assetlinks.json qui est exposé par le serveur HTTP du dummy website.

Cette opération est documentée dans la partie "Create Site Association File".

Son contenu ressemble à ceci :

[
  {
    "relation": [
        "delegate_permission/common.handle_all_urls"
    ],
    "target": {
      "namespace": "android_app",
      "package_name": "$PACKAGE_NAME",
      "sha256_cert_fingerprints": ["$SHA256_FINGERPRINT"]
    }
  }
]

Il a une fonction de sécurité, il permet d'éviter de créer des applications malveillantes qui s'ouvriraient automatiquement sur des URLs sans lien avec l'application.

Il permet de dire « l'URL de ce site web peut automatiquement ouvrir l'application $PACKAGE_NAME » qui est signée avec la clé publique $SHA256_FINGERPRINT.

J'ai implémenté le script /scripts/generate-dev-assetlinks.sh qui permet automatiquement de générer ce fichier.

Lorsque j'ai travaillé sur cette partie, j'ai fait l'erreur de générer un certificat (voir le script /scripts/generate-dev-assetlinks.sh). Or, ce n'est pas la bonne méthode en mode développement.
Par défaut, Android met à disposition un certificat de développement dans ${HOME}/.android/debug.keystore.

La commande suivante me permet d'extraire la clé publique :

SHA256_FINGERPRINT=$(keytool -list -v \
  -keystore "${HOME}/.android/debug.keystore" \
  -alias "androiddebugkey" \ # password par défaut
  -storepass "android" 2>/dev/null | grep "SHA256:" | awk '{print $2}')

source

Configuration de AndroidManifest.xml

Comme indiqué ici, voici les lignes que j'ai ajoutées dans /android/app/src/main/AndroidManifest.xml.tmpl :

<intent-filter android:autoVerify="true">
   <action android:name="android.intent.action.VIEW" />
   <category android:name="android.intent.category.DEFAULT" />
   <category android:name="android.intent.category.BROWSABLE" />
   <data android:scheme="https" />
   <data android:host="{{ .Env.ALLOW_NAVIGATION }}" />
</intent-filter>

source

Petite digression sur mon usage des templates dans ce projet.

J'utilise gomplate pour générer des fichiers dynamiquement à partir de 4 templates (.tmpl) et des variables d'environnement configurées entre autres dans .envrc.

La génération des fichiers se trouve ici :

gomplate -f capacitor.config.json.tmpl -o capacitor.config.json
gomplate -f android/app/build.gradle.tmpl -o android/app/build.gradle
gomplate -f android/app/src/main/AndroidManifest.xml.tmpl -o android/app/src/main/AndroidManifest.xml
gomplate -f android/app/src/main/strings.xml.tmpl -o android/app/src/main/res/values/strings.xml

source

Les principaux éléments dynamiques sont :

export APP_NAME=myapp
export PACKAGE_NAME="xyz.sklein.myapp"
export START_URL=$(cat .cloudflared_tunnel_url)
export ALLOW_NAVIGATION=$(echo "$START_URL" | sed -E 's#https://([^/]+).*#\1#')

START_URL contient l'URL publique générée par cloudflared tunnel qui change à chaque lancement du tunnel.

Support deep links via l'interception de l'événement appUrlOpen

Troisième étape de la configuration de App links.

let timeoutId = setTimeout(() => {
	openInWebView(process.env.START_URL);
}, 200);

window.Capacitor.Plugins.App.addListener('appUrlOpen', (event) => {
	clearTimeout(timeoutId);
	openInWebView(event.url);
});

source

Cela permet d'implémenter la fonction deep links. Exemple : si l'utilisateur du smartphone clique sur l'URL https://dummysite/deep/ alors l'application va directement s'ouvrir sur la page /deep/ du dummy website.

Commandes utiles

La commande suivante permet de demander à l'OS Android de lancer une nouvelle "vérification" du fichier dummy-website/.well-known/assetlinks.json :

$ adb shell pm verify-app-links --re-verify ${PACKAGE_NAME}

source

Note : le fichier .cloudflared_tunnel_url contient l'URL du tunnel cloudflare qui expose le dummy website.

La commande suivante permet d'afficher la configuration actuelle App Link d'une application :

$ adb shell pm get-app-links ${PACKAGE_NAME}
  xyz.sklein.myapp:
    ID: 100ba7e3-b978-49ac-926c-8e6ec6810f5c
    Signatures: [AF:AE:25:7F:ED:98:49:A3:E0:23:B3:BE:92:08:84:A5:82:D1:80:AA:E0:A4:A3:D3:A0:E2:18:D6:70:05:67:ED]
    Domain verification state:
      association-pending-belt-acute.trycloudflare.com: verified

source

La commande suivante permet de tester le lancement de l'application à partir d'une URL passée en paramètre :

$ adb shell am start -W -a android.intent.action.VIEW -d "$(cat .cloudflared_tunnel_url)"
Starting: Intent { act=android.intent.action.VIEW dat=https://sc-lo-welsh-injury.trycloudflare.com/... }
Status: ok
LaunchState: COLD
Activity: xyz.sklein.myapp/.MainActivity
TotalTime: 1258
WaitTime: 1266
Complete

source

Cela fonctionne aussi avec une sous-page, par exemple : "$(cat .cloudflared_tunnel_url)/deep/?query=foobar".

Dans l'émulateur, Chrome ne lance pas les App Link !

Je pense que ce piège m'a fait perdre 2 h (sur les 5 h passées sur cette implémentation) !

Si j'ouvre l'URL du dummy website dans Chrome, l'application n'est pas lancée.

Mais, si j'ouvre l'URL dans l'application qui se nomme "Google", celle accessible via la barre de recherche en bas ce ce screenshot, l'App Link est bien pris en compte.

Problème : je testais mon application seulement dans Chrome. Et la fonctionnalité App Links ne fonctionnait pas. C'est seulement quand j'ai installé l'application sur mon smartphone physique personnel que j'ai constaté que App Links fonctionnait sous "Firefox Android".

J'ai constaté aussi que sur mon smartphone, Chrome n'ouvrait aucune application sur les URLs youtube.com, reddit.com, github.com

D'après ce que je pense avoir compris, la liste des applications qui peuvent ouvrir les App Links est listée dans la section "Settings => Apps => Default apps" :

J'ai fait des expériences sur 3 différents smartphones Android d'amis et à ce jour, je n'ai pas encore compris comment cela fonctionne. J'ai l'impression que c'est lié au browser par défaut configuré, mais j'ai trouvé des exceptions.

En tout cas, ce piège m'a fait perdre beaucoup de temps !


Note finale

Pour le moment, je n'ai pas eu besoin de configurer @capacitor/app-launcher, mais je pense que cela sera utile pour permettre à l'application d'ouvrir d'autres applications à partir d'une URL.

J'ai scripté pratiquement toutes les actions de ce projet.

ChatGPT m'a bien servi tout au long de cette implémentation.

Journal du dimanche 08 septembre 2024 à 10:18 #POC, #rrweb, #SvelteKit

J'ai envie d'essayer de créer un "mini" service de session recording, basé sur rrweb, SvelteKit et KeyDB ou DragonflyDB.
Je pense que ce projet pourrait être minimaliste 🤔.

-- from

J'ai publié https://github.com/stephane-klein/gibbon-replay (gibbon-replay).

J'ai passé 2h sur ce projet.

Idée d'un outil de session recoding web minimaliste basé sur rrweb #Idée, #rrweb, #POC

Plus le temps passe, et plus le nombre de services présents dans les docker-compose.yaml de OpenReplay et Posthog augmente.

Je trouve ces services de plus en plus pénible à self hosted pour de petits besoins de session recording.

J'ai envie d'essayer de créer un "mini" service de session recording, basé sur rrweb, SvelteKit et KeyDB ou DragonflyDB.
Je pense que ce projet pourrait être minimaliste 🤔.


2024-09-14 : j'ai nommé ce projet gibbon-replay.

Journal du vendredi 17 mai 2024 à 12:57 #llm, #POC, #MachineLearning, #scaleway, #JeMeDemande, #PremièreActionConcrète

#JeMeDemande combien me coûterait la réalisation du #POC suivant :

🤔.

Tarifs :

Dans un premier temps, j'aimerais me limiter aaux instances les moins chères :

  • GPU-3070 à environ 1 € / heure
  • L4-1-24G à 0.75 € / heure
  • et peut-être RENDER-S à 1,24 € / heure

Tous ces prix sont hors taxe.

Au moment où j'écris ces lignes, Scaleway a du stock de ces trois types d'instances :

  • #JeMeDemande comment je pourrais me préparer en amont pour installer rapidement sur le serveur un environnement pour faire mes tests.
  • #JeMeDemande s'il existe des tutoriaux tout prêts pour faire ce type de tâches.
  • #JeMeDemande combien de temps prendrait le déploiement.

Si je prends 2h pour l'installation + 3h pour faire des tests, cela ferait 5h au total.
J'ai cherché un peu partout, je n'ai pas trouvé de coût "caché" de setup de l'instance.
Le prix de cette expérience serait entre 4,5 € et 7,44 € TTC.


  • #JeMeDemande combien me coûterait l'achat de ce type de machine.
  • #JeMeDemande à partir de combien d'heures d'utilisation l'achat serait plus rentable que la location.
  • Si par exemple, j'utilise cette machine 3h par jour, je me demande à partir de quelle date cette machine serait rentabilisée et aussi, #JeMeDemande si cette machine ne serait totalement obsolète ou non à cette date 🤔.

Journal du jeudi 02 mai 2024 à 22:57 #iteration, #graph, #coding, #POC

J'ai traité Projet 4 - "Je souhaite apprendre les bases d'utilisation de Apache Age".

Le résultat se trouve ici https://github.com/stephane-klein/apache-age-playground.

J'ai réussi à écrire plusieurs requêtes Cypher, mais je suis très loin de maitriser ce langage. Pour le moment, je me base principalement sur les exemples donnés dans la documentation.

Première itération d'un POC de CodeMirror avec l'autocomplétion #svelte, #codemirror, #POC, #coding, #publication, #iteration, #JaiPublié, #SiJeDevaisParier

#JaiPublié https://github.com/stephane-klein/svelte-codemirror-autocomplete-poc qui contient mes 2 premières heures de travail sur le #POC Projet 1 - "CodeMirror, autocomplétion, Svelte".

J'ai réussi à setup le projet, mais pour le moment, je n'arrive pas à bien configurer la fonctionnalité autocomplete de CodeMirror. Par exemple, je n'arrive pas à ne pas afficher les caractères [[ dans le popup qui affiche la liste des suggestions.

Idéalement, pour expliquer, j'aimerais réaliser un screencast.

Je pense que ce POC va me prendre du temps. Je pense que je vais devoir étudier en profondeur l'API de @codemirror/autocomplete.

#SiJeDevaisParier, mon estimation de durée 🤔 serait de 8h à 20h de travail.

Projet GH-360 - Implémenter un POC de Fuzzy Search en PostgreSQL #projet, #POC, #postgresql

Ce projet a été initialement commencé dans une issue, le 10 janvier 2024.

Quel est l'objectif de ce projet ?

Je souhaite mettre en pratique l'extension PostgreSQL fuzzystrmatch pour implémenter une fonctionnaltié Fuzzy Search.

Je souhaite que cette implémentation permette :

  • de trouver les éléments à partir d'erreurs d'insertion, de suppression et de substitution (voir paragraphe "Distances entre mots") ;
  • de trouver les éléments même si des lettres ont été transposées, par exemple, cout → touc est une transposition.

Repository de ce projet :

  • postgresql-fuzzysearch-poc (pas encore créé)

Ressources :

Projet GH-339 - Implémenter un POC de Automerge #projet, #CRDT, #POC

Ce projet a été initialement commencé dans une issue, le 16 novembre 2023.

Quel est l'objectif de ce projet ?

Je souhaite implémenter et publier un POC de https://automerge.org.

Ce que je souhaite réaliser dans ce POC :

  • Une implémentation du serveur
  • Un client Javascript
    • User story
      • Sur le client A, un user saisie "item 1", celui-ci est ajouté dans une liste ordonné par timestamp
      • "item 1" est affiché en temps réel sur client B
      • Le client A passe offline
      • Sur le client B, un user saisie "item 2"
      • Sur le client A, un user saisie "item 3"
      • Le client A passe online
      • Le client A se synchronise automatiquement et contient la liste "item 1", "item 2", "item 3"

Repository de ce projet :

Ressources :

Projet 5 - "Importation d'un vault Obsidian vers Apache Age" #graph, #database, #POC, #coding

Date de la création de cette note : 2024-05-02.

Quel est l'objectif de ce projet ?

Je souhaite essayer d'implémenter un script d’importation d’un vault Obsidian vers la Base de données Graph Apache Age, avec importation des tags, alias.

Pourquoi je souhaite réaliser ce projet ?

Pour progresser en Cypher. À cause de 2024-04-30_1704.

Repository de ce projet :

https://github.com/stephane-klein/obsidian-vault-to-apache-age-poc/

Plus d'informations sur ce projet :

Projet 4 - "Je souhaite apprendre les bases d'utilisation de Apache Age" #postgresql, #graph, #database, #POC, #coding

Date de la création de cette note : 2024-05-02
J'ai commencé ce projet le 20 avril 2024

Quel est l'objectif de ce projet ?

Je souhaite dans un premier temps être capable de reproduire ce que j'avais fait dans le projet neo4j-playground et peut être même ensuite d'aller un peu plus loin dans mon apprentissage du langage de Query Cypher.

Voir le résulat de ce projet…

Pourquoi je souhaite réaliser ce projet ?

J'ai envie d'ajouter à ma stack de compétence, un moteur de base de données orienté Graph. Idéalement, j'aimerais que ça soit Apache Age parce que c'est un projet libre et basé sur PostgreSQL. Cela me permettrait de facilement coupler les avantages d'une base de données relationnel avec une base de données Graph.

Repository de ce projet :

https://github.com/stephane-klein/apache-age-playground

Idées après ce projet :

Si j'arrive à terminer ce projet, j'ai les idées suivantes :

  • Écrire un script d'importation d'un vault Obsidian vers Apache Age, avec importation des tags, alias. => voir Projet 5
  • Écrire des scripts de benchmark pour comparer PostgreSQL vs Apache Age sur les aspects suivants : vitesse de lecture, vitesse d'écriture et espace disque consommé.

Projet 3 - "Réaliser un petit projet basé sur Nuxt pour le comparer avec SvelteKit" #Nuxt, #VueJS, #coding, #svelte, #SvelteKit, #projet, #POC

Date de la création de cette note : mardi 30 avril 2024 .

Quel est l'objectif de ce projet ?

Pour les mêmes raisons qui me motive à réaliser Projet - 2 "Réaliser un petit projet basé sur NextJS pour le comparer avec SvelteKit", je souhaite réaliser la même chose pour Nuxt.

Contexte : J'utilise SvelteKit depuis avril 2022, j'apprécie très fortement l'élégence de toutes les fonctionnalités de routing de SvelteKit.

Mon objectif est de créer un projet de type #POC pour apprendre les bases de Nuxt et de comparer ce framework avec SvelteKit.

Artefacts à produire :

  • Un repository GitHub qui contient le projet de type POC que j'aurais réaliser pour apprendre à utiliser Nuxt
  • Une note d'opinion qui présente ma comparaison entre SvelteKit et NextJS

Projet 2 - "Réaliser un petit projet basé sur NextJS pour le comparer avec SvelteKit" #NextJS, #ReactJS, #svelte, #SvelteKit, #coding, #projet, #POC

Date de la création de cette note : mardi 30 avril 2024.

Quel est l'objectif de ce projet ?

Ce projet remplace l'issue Étudier la version 12 de NextJS que j'ai créé en mars 2023.

Contexte : J'utilise SvelteKit depuis avril 2022, j'apprécie très fortement l'élégence de toutes les fonctionnalités de routing de SvelteKit.

Mon objectif est de créer un projet de type #POC pour apprendre les bases de NextJS et de comparer ce framework avec SvelteKit.

Artefacts à produire :

  • Un repository GitHub qui contient le projet de type POC que j'aurais réaliser pour apprendre à utiliser NextJS
  • Une note d'opinion qui présente ma comparaison entre SvelteKit et NextJS

Objectif secondaire de ce projet:

Je pense pas dire de bétise, en déclarant qu'en 2024 ReactJS est plus populaire que VueJS et Svelte, par conséquent, je pense que maitriser Nuxt me sera utile à l'avenir, par exemple pour des projets en freelance.
Je souhaite ajouter Nuxt sur mon CV.

Repository de ce projet :

Aucun pour le moment.

Ressources :

Projet 16 - Créer un POC d'application PWA #WebDev, #POC, #projet

Date de création de cette note : 2024-11-18.

Quel est l'objectif de ce projet ?

Je souhaite apprendre à créer des applications web de type Progressive Web Apps (PWA).

J'ai déjà une certaine culture dans ce domaine, mais je n'ai jamais créé d'application de ce type.

Voici les éléments que je souhaite apprendre / tester dans ce POC :

Si possible, j'aimerais implémenter ce POC avec SvelteKit.

Idéalement, j'aimerais intégrer le travail de "Projet GH-339 - Implémenter un POC de Automerge" dans un PWA.

Ressources :

Projet 1 - "CodeMirror, autocomplétion, Svelte" #svelte, #codemirror, #POC, #coding

Date de la création de cette note : lundi 29 avril 2024.

Quel est l'objectif de ce projet ?

Dans une application web frontend en Svelte, je souhaite essayer d'implémenter un éditeur texte markdown, avec un support d'autocomplétion. Je souhaite faire cela avec la librairie CodeMirror.

Pourquoi je souhaite réaliser ce projet ?

J'ai besoin d'implémenter une fonctionnalité d'autocomplétion dans l'application Value Props.

Repository de ce projet :

https://github.com/stephane-klein/svelte-codemirror-autocomplete-poc

Ressources :


30 avril 2024

J' 'aimerais aussi essayer d'implémenter dans ce POC une fonctionnalité conceal comme celle de Neovim.

Projet 17 - Créer un POC de création d'une app smartphone avec Capacitor #projet, #POC, #WebDev, #capacitor

Date de création de cette note : 2024-11-18.

Quel est l'objectif de ce projet ?

Je souhaite apprendre à créer une app smartphone avec Capacitor.

Idéalement, suivre la documentation "Using Capacitor in a Web Project" pour transformer l'app PWA créée dans Projet 16 - Créer un POC d'application PWA en application smartphone.

Capacitor fully supports traditional web and Progressive Web Apps. In fact, using Capacitor makes it easy to ship a PWA version of your iOS and Android app store apps with minimal work.

-- from

Todo :

Repository de ce projet :

Dernière page.