Parcourir la source

draggable keyboard

xiongzhu il y a 2 ans
Parent
commit
9d73021389

+ 23 - 0
README.md

@@ -0,0 +1,23 @@
+# Getting Started with [Fastify-CLI](https://www.npmjs.com/package/fastify-cli)
+This project was bootstrapped with Fastify-CLI.
+
+## Available Scripts
+
+In the project directory, you can run:
+
+### `npm run dev`
+
+To start the app in dev mode.\
+Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
+
+### `npm start`
+
+For production mode
+
+### `npm run test`
+
+Run the test cases.
+
+## Learn More
+
+To learn Fastify, check out the [Fastify documentation](https://www.fastify.io/docs/latest/).

+ 38 - 0
app.js

@@ -0,0 +1,38 @@
+"use strict";
+
+const path = require("path");
+const AutoLoad = require("@fastify/autoload");
+const cors = require("@fastify/cors");
+const fstatic = require("@fastify/static");
+// Pass --options via CLI arguments in command to enable these options.
+module.exports.options = {};
+
+module.exports = async function (fastify, opts) {
+    // Place here your custom code!
+
+    // Do not touch the following lines
+
+    // This loads all plugins defined in plugins
+    // those should be support plugins that are reused
+    // through your application
+    fastify.register(AutoLoad, {
+        dir: path.join(__dirname, "plugins"),
+        options: Object.assign({}, opts),
+    });
+
+    // This loads all plugins defined in routes
+    // define your routes in one of these
+    fastify.register(AutoLoad, {
+        dir: path.join(__dirname, "routes"),
+        options: Object.assign({}, opts),
+    });
+
+    fastify.register(fstatic, {
+        root: path.join(__dirname, "public"),
+        prefix: "/public/"
+    });
+
+    fastify.register(cors, {
+        // put your options here
+    });
+};

+ 8 - 0
getkeycodemap.js

@@ -0,0 +1,8 @@
+
+let codeMap = {}
+window.addEventListener('keydown', function(e) {
+    console.log(e.key, e.code)
+    codeMap[e.key] = e.code
+    e.preventDefault()
+    e.stopPropagation()
+})

+ 202 - 101
keyboard.html

@@ -1,143 +1,180 @@
-<div id="myWindow" class="window">
-    <div class="window-top">
-        <button class="round green"></button><button class="round yellow"></button><button class="round red"></button>
+<div class="virtual-keyboard-window">
+    <div class="window-top">Virtual Keyboard
+        <button class="btn-close">
+            <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">
+                <path
+                    d="M24 9.4L22.6 8L16 14.6L9.4 8L8 9.4l6.6 6.6L8 22.6L9.4 24l6.6-6.6l6.6 6.6l1.4-1.4l-6.6-6.6L24 9.4z"
+                    fill="currentColor"></path>
+            </svg>
+        </button>
     </div>
     <div class="window-content">
         <div class="simple-keyboard"></div>
     </div>
 </div>
-<script src="https://cdn.jsdelivr.net/npm/simple-keyboard@latest/build/index.js"></script>
-<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/simple-keyboard@latest/build/css/index.css" />
+<div class="keyboard-toggle">
+    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24">
+        <g fill="none">
+            <path
+                d="M19.745 5a2.25 2.25 0 0 1 2.25 2.25v9.505a2.25 2.25 0 0 1-2.25 2.25H4.25A2.25 2.25 0 0 1 2 16.755V7.25A2.25 2.25 0 0 1 4.25 5h15.495zm-2.495 9.5H6.75l-.102.007a.75.75 0 0 0 0 1.486L6.75 16h10.5l.102-.007a.75.75 0 0 0 0-1.486l-.102-.007zM16.5 11a1 1 0 1 0 0 2a1 1 0 0 0 0-2zm-2.995 0a1 1 0 1 0 0 2a1 1 0 0 0 0-2zm-3 0a1 1 0 1 0 0 2a1 1 0 0 0 0-2zm-3 0a1 1 0 1 0 0 2a1 1 0 0 0 0-2zM6 8a1 1 0 1 0 0 2a1 1 0 0 0 0-2zm2.995 0a1 1 0 1 0 0 2a1 1 0 0 0 0-2zm3 0a1 1 0 1 0 0 2a1 1 0 0 0 0-2zm3 0a1 1 0 1 0 0 2a1 1 0 0 0 0-2zm3 0a1 1 0 1 0 0 2a1 1 0 0 0 0-2z"
+                fill="currentColor"></path>
+        </g>
+    </svg>
+</div>
+<script src="/public/jquery-3.7.0.min.js"></script>
+<script src="/public/jquery-ui.min.js"></script>
+<script src="/public/jquery.ui.touch-punch.min.js"></script>
+<script src="/public/simple-keyboard-3.7.2.js"></script>
+<script src="/public/keycode.js"></script>
+<link rel="stylesheet" href="/public/simple-keyboard-3.7.2.css" />
 <style>
+    html,
     body {
-        background: #333;
+        height: 100%;
     }
 
-    .window {
+    ::-webkit-scrollbar {
+        display: none;
+        width: 0px;
+        background: transparent;
+        /* make scrollbar transparent */
+    }
+</style>
+<style>
+    .virtual-keyboard-window {
         position: fixed;
         top: 0;
-        width: 400px;
-        height: 250px;
+        width: 800px;
         border-radius: 10px;
-        border: none;
-        box-shadow: 1px 1px 4px rgba(0, 0, 0, 0, 0.9), -1px 1px 4px rgba(0, 0, 0, 0, 0.9);
-        background: #fff;
+        box-shadow: 0 1px 5px 2px rgba(0, 0, 0, 0.1);
+        border: 1px solid #ddd;
+        background: #ececec;
+        z-index: 999;
+        overflow: hidden;
     }
 
-    .window-content {
+    .virtual-keyboard-window .window-content {
         height: 100%;
     }
 
-    .window-top,
-    .window-top-no-bind {
+    .hg-theme-default .hg-button {
+        height: 45px;
+    }
 
+    .virtual-keyboard-window .window-top {
         cursor: move;
-        text-align: right;
+        text-align: center;
         height: 20px;
         border-top-right-radius: 5px;
         border-top-left-radius: 5px;
         padding: 5px;
         background-color: #ddd;
+        color: #333;
     }
 
-    .window-top-no-bind {
-        cursor: inherit;
-    }
-
-    .round {
-        height: 16px;
-        width: 16px;
-        border-radius: 50%;
+    .virtual-keyboard-window .btn-close {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        position: absolute;
+        right: 0;
+        top: 0;
+        width: 50px;
+        height: 30px;
+        box-sizing: border-box;
+        padding: 5px 15px;
         border: none;
-        margin-right: 6px;
-        box-shadow: 1px 1px 2px #000;
-    }
-
-    .green {
-        background-color: limegreen;
-    }
-
-    .yellow {
-        background-color: yellow;
-    }
-
-    .red {
+        background: none;
         cursor: pointer;
-        background-color: red;
     }
 
-    #myWindow {
-        z-index: 999;
-    }
 
-    #myWindow2 {
+    .keyboard-toggle {
+        width: 20px;
+        height: 20px;
+        padding: 5px;
+        position: absolute;
         top: 0;
-        left: 500px;
+        left: 0;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        background: #fff;
+        opacity: 0.5;
+        box-shadow: 0 1px 5px 2px rgba(0, 0, 0, 0.1);
+        color: #333;
+        border-radius: 4px;
+        border: 1px solid #ddd;
+        z-index: 999;
+        cursor: pointer;
     }
 </style>
 <script>
-    // You can choose to have an element with the class "window-top" inside of your draggable window that will act as the "handle" for the window or it will attach to the element itself
-
-    function makeDraggable(elmnt) {
-        // Make an element draggable (or if it has a .window-top class, drag based on the .window-top element)
-        let currentPosX = 0, currentPosY = 0, previousPosX = 0, previousPosY = 0;
-
-        // If there is a window-top classed element, attach to that element instead of full window
-        if (elmnt.querySelector('.window-top')) {
-            // If present, the window-top element is where you move the parent element from
-            elmnt.querySelector('.window-top').onmousedown = dragMouseDown;
-            elmnt.querySelector('.window-top').ontouchstart = dragMouseDown;
-        }
-        else {
-            // Otherwise, move the element itself
-            elmnt.onmousedown = dragMouseDown;
+    let dragging = false;
+    $(".virtual-keyboard-window").draggable({
+        containment: "parent",
+        handle: ".window-top",
+        drag: function (event, ui) {
+            localStorage.setItem('keyboard-position', JSON.stringify(ui.position));
+        },
+        start: function (event, ui) {
+            dragging = true;
+        },
+        stop: function (event, ui) {
+            setTimeout(() => {
+                dragging = false;
+            }, 300);
         }
-
-        function dragMouseDown(e) {
-            // Prevent any default action on this element (you can remove if you need this element to perform its default action)
-            e.preventDefault();
-            // Get the mouse cursor position and set the initial previous positions to begin
-            previousPosX = e.clientX;
-            previousPosY = e.clientY;
-            // When the mouse is let go, call the closing event
-            document.onmouseup = closeDragElement;
-            // call a function whenever the cursor moves
-            document.onmousemove = elementDrag;
-        }
-
-        function elementDrag(e) {
-            // Prevent any default action on this element (you can remove if you need this element to perform its default action)
-            e.preventDefault();
-            // Calculate the new cursor position by using the previous x and y positions of the mouse
-            currentPosX = previousPosX - e.clientX;
-            currentPosY = previousPosY - e.clientY;
-            // Replace the previous positions with the new x and y positions of the mouse
-            previousPosX = e.clientX;
-            previousPosY = e.clientY;
-            // Set the element's new position
-            elmnt.style.top = (elmnt.offsetTop - currentPosY) + 'px';
-            elmnt.style.left = (elmnt.offsetLeft - currentPosX) + 'px';
-        }
-
-        function closeDragElement() {
-            // Stop moving when mouse button is released and release events
-            document.onmouseup = null;
-            document.onmousemove = null;
+    });
+    $(".keyboard-toggle").draggable({
+        containment: "parent",
+        drag: function (event, ui) {
+            localStorage.setItem('keyboard-toggle-position', JSON.stringify(ui.position));
+        },
+        start: function (event, ui) {
+            dragging = true;
+        },
+        stop: function (event, ui) {
+            setTimeout(() => {
+                dragging = false;
+            }, 300);
         }
+    });
+    function showKeyboard() {
+        if (dragging) return;
+        $('.virtual-keyboard-window').show();
+        $('.keyboard-toggle').hide();
+        localStorage.setItem('virtual-keyboard-visible', 'true')
     }
-
-    // Make myWindow and myWindow2 draggable in different ways...
-
-    // myWindow will only be able to be moved via the top bar (.window-top element). The main element does nothing on mouse down.
-    makeDraggable(document.querySelector('#myWindow'));
-
-
-    //And this is just for fun
-    for (const closeElement of document.querySelectorAll('.round.red')) {
-        closeElement.addEventListener('click', function () {
-
-        });
+    function hideKeyboard() {
+        if (dragging) return;
+        $('.virtual-keyboard-window').hide();
+        $('.keyboard-toggle').show();
+        localStorage.setItem('virtual-keyboard-visible', 'false')
+    }
+    $('.btn-close').click(hideKeyboard);
+    $('.keyboard-toggle').click(showKeyboard);
+    if (localStorage.getItem('virtual-keyboard-visible') === 'true' || localStorage.getItem('virtual-keyboard-visible') === null) {
+        showKeyboard();
+    } else {
+        hideKeyboard();
     }
+    let keyboardPosition = { left: (window.innerWidth - 800) / 2, top: window.innerHeight - 300 }
+    if (localStorage.getItem('keyboard-position')) {
+        keyboardPosition = JSON.parse(localStorage.getItem('keyboard-position'));
+        keyboardPosition.left = Math.min(keyboardPosition.left, window.innerWidth - 800);
+        keyboardPosition.top = Math.min(keyboardPosition.top, window.innerHeight - 300);
+    }
+    $('.virtual-keyboard-window').css('left', keyboardPosition.left);
+    $('.virtual-keyboard-window').css('top', keyboardPosition.top);
+    let togglePosition = { left: window.innerWidth - 100, top: window.innerHeight - 100 }
+    if (localStorage.getItem('keyboard-toggle-position')) {
+        togglePosition = JSON.parse(localStorage.getItem('keyboard-toggle-position'));
+        togglePosition.left = Math.min(togglePosition.left, window.innerWidth - 50);
+        togglePosition.top = Math.min(togglePosition.top, window.innerHeight - 50);
+    }
+    $('.keyboard-toggle').css('left', togglePosition.left);
+    $('.keyboard-toggle').css('top', togglePosition.top);
 
     const Keyboard = window.SimpleKeyboard.default;
     const keyboard = new Keyboard({
@@ -152,5 +189,69 @@
 
     function onKeyPress(button) {
         console.log("Button pressed", button);
+        if (button === "{shift}" || button === "{lock}") {
+            handleShift();
+            return
+        }
+        keyboard.clearInput();
+        let key = button;
+        if (key === ".com") {
+            for (let char of ".com".split('')) {
+                sendKey(char);
+            }
+            return
+        }
+        switch (key) {
+            case "{bksp}":
+                key = "Backspace";
+                break;
+            case "{enter}":
+                key = "Enter";
+                break;
+            case "{space}":
+                key = " ";
+                break;
+            case "{tab}":
+                key = "Tab";
+                break;
+            case "{esc}":
+                key = "Escape";
+                break;
+            case "{lock}":
+                key = "CapsLock";
+                break;
+            case "{shift}":
+                key = "Shift";
+                break;
+            case "{alt}":
+                key = "Alt";
+                break;
+            case "{ctrl}":
+                key = "Control";
+                break;
+        }
+        sendKey(key);
+    }
+
+    function sendKey(key) {
+        let ev = new KeyboardEvent('keydown', {
+            key,
+            code: keyCode[key]
+        })
+        window.dispatchEvent(ev)
     }
+
+    function handleShift() {
+        let currentLayout = keyboard.options.layoutName;
+        let shiftToggle = currentLayout === "default" ? "shift" : "default";
+
+        keyboard.setOptions({
+            layoutName: shiftToggle
+        });
+    }
+
+
+    $('.virtual-keyboard-window,.keyboard-toggle').bind('touchstart mousedown', function (event) {
+        event.stopPropagation();
+    });
 </script>

+ 25 - 3
package.json

@@ -1,9 +1,31 @@
 {
+  "name": "parsec-keyboard",
+  "version": "1.0.0",
+  "description": "This project was bootstrapped with Fastify-CLI.",
+  "main": "app.js",
+  "directories": {
+    "test": "test"
+  },
+  "scripts": {
+    "test": "tap \"test/**/*.test.js\"",
+    "start": "fastify start -l info app.js",
+    "dev": "fastify start -w -l info -P app.js"
+  },
+  "keywords": [],
+  "author": "",
+  "license": "ISC",
   "dependencies": {
+    "@fastify/autoload": "^5.0.0",
     "@fastify/cors": "^8.3.0",
+    "@fastify/sensible": "^5.0.0",
+    "@fastify/static": "^6.10.2",
     "axios": "^1.4.0",
-    "fastify": "^4.21.0",
-    "http-proxy": "^1.18.1",
-    "node-html-parser": "^6.1.6"
+    "axios-cache-interceptor": "^1.2.0",
+    "fastify": "^4.0.0",
+    "fastify-cli": "^5.8.0",
+    "fastify-plugin": "^4.0.0"
+  },
+  "devDependencies": {
+    "tap": "^16.1.0"
   }
 }

+ 16 - 0
plugins/README.md

@@ -0,0 +1,16 @@
+# Plugins Folder
+
+Plugins define behavior that is common to all the routes in your
+application. Authentication, caching, templates, and all the other cross
+cutting concerns should be handled by plugins placed in this folder.
+
+Files in this folder are typically defined through the
+[`fastify-plugin`](https://github.com/fastify/fastify-plugin) module,
+making them non-encapsulated. They can define decorators and set hooks
+that will then be used in the rest of your application.
+
+Check out:
+
+* [The hitchhiker's guide to plugins](https://www.fastify.io/docs/latest/Guides/Plugins-Guide/)
+* [Fastify decorators](https://www.fastify.io/docs/latest/Reference/Decorators/).
+* [Fastify lifecycle](https://www.fastify.io/docs/latest/Reference/Lifecycle/).

+ 14 - 0
plugins/sensible.js

@@ -0,0 +1,14 @@
+'use strict'
+
+const fp = require('fastify-plugin')
+
+/**
+ * This plugins adds some utilities to handle http errors
+ *
+ * @see https://github.com/fastify/fastify-sensible
+ */
+module.exports = fp(async function (fastify, opts) {
+  fastify.register(require('@fastify/sensible'), {
+    errorHandler: false
+  })
+})

+ 12 - 0
plugins/support.js

@@ -0,0 +1,12 @@
+'use strict'
+
+const fp = require('fastify-plugin')
+
+// the use of fastify-plugin is required to be able
+// to export the decorators to the outer scope
+
+module.exports = fp(async function (fastify, opts) {
+  fastify.decorate('someSupport', function () {
+    return 'hugs'
+  })
+})

Fichier diff supprimé car celui-ci est trop grand
+ 1 - 0
public/jquery-3.7.0.min.js


Fichier diff supprimé car celui-ci est trop grand
+ 5 - 0
public/jquery-ui.min.js


+ 11 - 0
public/jquery.ui.touch-punch.min.js

@@ -0,0 +1,11 @@
+/*!
+ * jQuery UI Touch Punch 0.2.3
+ *
+ * Copyright 2011–2014, Dave Furfero
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ *
+ * Depends:
+ *  jquery.ui.widget.js
+ *  jquery.ui.mouse.js
+ */
+!function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery);

+ 110 - 0
public/keycode.js

@@ -0,0 +1,110 @@
+window.keyCode = {
+    0: "Digit0",
+    1: "Digit1",
+    2: "Digit2",
+    3: "Digit3",
+    4: "Digit4",
+    5: "Digit5",
+    6: "Digit6",
+    7: "Digit7",
+    8: "Digit8",
+    9: "Digit9",
+    Escape: "Escape",
+    Shift: "ShiftLeft",
+    "`": "Backquote",
+    "-": "Minus",
+    "=": "Equal",
+    Backspace: "Backspace",
+    Tab: "Tab",
+    q: "KeyQ",
+    w: "KeyW",
+    e: "KeyE",
+    r: "KeyR",
+    t: "KeyT",
+    y: "KeyY",
+    u: "KeyU",
+    i: "KeyI",
+    o: "KeyO",
+    p: "KeyP",
+    "[": "BracketLeft",
+    "]": "BracketRight",
+    "\\": "Backslash",
+    CapsLock: "CapsLock",
+    a: "KeyA",
+    s: "KeyS",
+    d: "KeyD",
+    f: "KeyF",
+    g: "KeyG",
+    h: "KeyH",
+    j: "KeyJ",
+    k: "KeyK",
+    l: "KeyL",
+    ";": "Semicolon",
+    "'": "Quote",
+    Enter: "Enter",
+    Z: "KeyZ",
+    x: "KeyX",
+    c: "KeyC",
+    v: "KeyV",
+    b: "KeyB",
+    n: "KeyN",
+    m: "KeyM",
+    ",": "Comma",
+    ".": "Period",
+    "/": "Slash",
+    ArrowUp: "ArrowUp",
+    ArrowLeft: "ArrowLeft",
+    ArrowDown: "ArrowDown",
+    ArrowRight: "ArrowRight",
+    Control: "ControlLeft",
+    Alt: "AltLeft",
+    Meta: "MetaLeft",
+    z: "KeyZ",
+    "~": "Backquote",
+    "!": "Digit1",
+    "@": "Digit2",
+    "#": "Digit3",
+    $: "Digit4",
+    "%": "Digit5",
+    "^": "Digit6",
+    "&": "Digit7",
+    "*": "Digit8",
+    "(": "Digit9",
+    ")": "Digit0",
+    _: "Minus",
+    "+": "Equal",
+    Q: "KeyQ",
+    W: "KeyW",
+    E: "KeyE",
+    R: "KeyR",
+    T: "KeyT",
+    Y: "KeyY",
+    U: "KeyU",
+    I: "KeyI",
+    O: "KeyO",
+    P: "KeyP",
+    "{": "BracketLeft",
+    "}": "BracketRight",
+    "|": "Backslash",
+    A: "KeyA",
+    S: "KeyS",
+    D: "KeyD",
+    F: "KeyF",
+    G: "KeyG",
+    H: "KeyH",
+    J: "KeyJ",
+    K: "KeyK",
+    L: "KeyL",
+    ":": "Semicolon",
+    '"': "Quote",
+    X: "KeyX",
+    C: "KeyC",
+    V: "KeyV",
+    B: "KeyB",
+    N: "KeyN",
+    M: "KeyM",
+    "<": "Comma",
+    ">": "Period",
+    "?": "Slash",
+    " ":"Space"
+};

Fichier diff supprimé car celui-ci est trop grand
+ 10 - 0
public/simple-keyboard-3.7.2.css


Fichier diff supprimé car celui-ci est trop grand
+ 11 - 0
public/simple-keyboard-3.7.2.js


+ 33 - 0
routes/index.js

@@ -0,0 +1,33 @@
+"use strict";
+const fs = require("fs");
+const wasm = fs.readFileSync("./parsecd.wasm");
+const axios = require("axios");
+const { setupCache } = require("axios-cache-interceptor");
+
+const http = setupCache(axios);
+http.defaults.baseURL = "https://web.parsec.app";
+
+module.exports = async function (fastify, opts) {
+    fastify.get("/", async function (request, reply) {
+        let { data: html, headers } = await http.get(`/`);
+        // let html = fs.readFileSync("./test.html").toString();
+        let append = fs.readFileSync("./keyboard.html").toString();
+        html = html.replace("</body>", append + "</body>");
+        reply.headers(headers);
+        reply.type("text/html");
+        return html;
+    });
+
+    fastify.get("/parsecd", async function (request, reply) {
+        reply.type("application/wasm");
+        reply.send(wasm);
+        return;
+    });
+
+    fastify.get("*", async function (request, reply) {
+        let { data, headers } = await http.get(request.url);
+        reply.headers(headers);
+        reply.type(headers["content-type"]);
+        return data;
+    });
+};

+ 15 - 0
test.html

@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Document</title>
+    
+</head>
+
+<body>
+    <input/>
+</body>
+
+</html>

Fichier diff supprimé car celui-ci est trop grand
+ 833 - 51
yarn.lock


Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff