Missing or insufficient permissions (firebase auth) [closed]

У меня постоянно появляется эта ошибка. Я на ней застрял, хотя я догадываюсь почему. Работа правил, возможно, мешает в этом хотя они вроде выглядят правильно. Я не знаток firebase но всегда было интересно на ней поработать, не хочу уже отбрасывать эту идею (т.к. пишу её на диплом) и большая часть проекта связана с бд на firebase. Код Rules я прикреплю ниже. Я пробовал разлиные вариации правил. Конечная задача – чтобы админстратор смог crud’ить students и teachers. Возможно, я действительно слеп и что-то не вижу. Я перепробовал проверять токен, аутентификацию пользователя, даже пользуюсь Cloud Functions но у меня уже действительно закончились идею. Подскажи что не так люди 🙁

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {


function isAdmin() {
  return request.auth != null; 
}


    function isTeacher() {
      return request.auth != null && exists(/databases/$(database)/documents/teachers/$(request.auth.uid));
    }


    match /students/{uid} {
      allow read: if request.auth != null;        
      allow write: if isAdmin();                     
    }


    match /teachers/{uid} {
      allow read: if request.auth != null;
      allow write: if isAdmin();
    }


    match /grades/{gradeId} {
      allow read: if request.auth != null;
      allow create, update: if isTeacher() || isAdmin();
      allow delete: if false;
    }


    match /subjects/{id} {
      allow read: if true;
      allow write: if false;
    }


    match /groups/{id} {
      allow read: if true;
      allow write: if false;
    }


    match /admins/{id} {
      allow read: if request.auth != null;
      allow write: if false;
    }


    match /teacherSubjects/{id} {
      allow read: if request.auth != null;
      allow write: if false;
    }


    match /semesterSubjects/{id} {
      allow read: if request.auth != null;
      allow write: if fa`your text`lse;
    }


    match /gradesTypes/{id} {
      allow read: if true;
      allo`your text`w write: if false;
    }
  }
}

я бы хотел найти решение на данную проблему в ближайшее время

We need to nest Angular Signals inside another Signal for objects and arrays?

I’ve made a set of interfaces which describes JSON data. Then I used classes to compose the same data but as Angular Signals:

// TToSignal.ts
import { WritableSignal } from '@angular/core';

export type TToSignal<T> = {
  [k in keyof T]: WritableSignal<T[k]>;
};
// CDataItem.ts
import { IDataItem } from '../interfaces';
import { TToSignal } from '../types';

export class CDataItem implements TToSignal<IDataItem> {
  prop1: signal<string>('');
  prop2: signal<number>(0);

  constructor(init: Partial<IDataItem>) {
    if (!init) return;

    if (init.prop1) this.prop1.set(init.prop1);
    if (init.prop2) this.prop2.set(init.prop2);
  }
}
// CDataProfile.ts
import { IDataProfile } from '../interfaces';
import { TToSignal } from '../types';

export class CDataProfile implements TToSignal<IDataProfile> {
  prop1: signal<string>('');
  prop2: signal<number>(0);

  constructor(init: Partial<IDataProfile>) {
    if (!init) return;

    if (init.prop1) this.prop1.set(init.prop1);
    if (init.prop2) this.prop2.set(init.prop2);
  }
}
// CData.ts
import { CDataProfile, CDataItem } from '../classes';
import { IData } from '../interfaces';
import { TField, TToSignal } from '../types';

export class CData implements TToSignal<IData> {
  name: signal<string>('');
  items: signal<CDataItem[]>([]);
  profile: signal<CDataProfile>(new CDataProfile());

  constructor(init: Partial<IData>) {
    if (!init) return;

    if (init.name) this.name.set(init.name);
    if (init.items) this.items.set(init.items);
    if (init.profile) this.profile.set(init.profile);
  }
}

The data is more complex than this example and I’m wondering: which are the best practices, or how can I approach my data profiling with Signals, considering the use of it inside forms, to interact with it?

Am I overthinking the use of Angular Signals?

Icon is not aligned with the default Youtube icons

I am new to coding. I am currently creating a userscript to create a working button on the video area. But it seems that my icon is not aligned with the rest of the icons.

my situation

This is quite annoying. I would appreciate it if you could help me.

Here is my code:

    const button = document.createElement('button');
    button.id = 'custom-speed-button';
    button.textContent = `${customSpeed}x`;
    button.style.marginLeft = '10px';
    button.className = 'ytp-button';
    button.style.marginLeft = '10px';
    button.style.fontSize = '16px';
    button.style.fontWeight = 'bold';
    button.style.padding = '4px 8px';
    button.style.color = '#fff';

Is this a correct way of useTransition usage?

I have a navigation component with several tabs on the left side of the screen. On the right side, different Next.js pages are rendered depending on the clicked tab (clicking a tab triggers a route change to a subpage).

The Problem I Had

Before using useTransition, I relied on pathname from the URL to determine the active tab. However, this resulted in a poor user experience:

  1. User is on Tab A and clicks on Tab B.

  2. The UI freezes for 1–2 seconds while subpage B is loading.

  3. Only after the loading completes, the pathname updates to /tab/B.

  4. Only then does Tab B become visually active.

This gave users no immediate feedback that their click was registered, making the interface feel sluggish and unresponsive.

My Solution

I implemented the following changes:

  1. Created a separate activeTab state instead of relying solely on pathname.

  2. Used useTransition to wrap the navigation logic.

  3. Gave immediate visual feedback: as soon as the user clicks a tab, it becomes active.

  4. Showed a loading spinner next to the tab using isPending from useTransition.

This dramatically improved the perceived performance and responsiveness of the tab navigation.

My Question

Is this the correct use of useTransition in Next.js?
Especially regarding using isPending to show a loading spinner while routing?
It works and looks good, but I want to make sure this is a recommended pattern.

const handleTabClick = (tab: string, href: string) => {
  setActiveTab(tab);
  startTransition(() => {
    router.push(`${parametersLink}${href}`);
  });
};
<StyledMenu mode="vertical" selectedKeys={[activeTab ?? '']}>
  {items.map(({ label, link, key }) => (
    <StyledMenuItem key={key} onClick={() => handleTabClick(key, link)}>
      {label}
      {isTransitionPending && activeTab === key && (
        <Spin size="small" style={{ marginLeft: 8 }} />
      )}
    </StyledMenuItem>
  ))}
</StyledMenu>

File input click not opening dialog in Microsoft Edge despite successful API calls

Problem Summary

File input <input type="file"> click events are not opening the file selection dialog in Microsoft Edge, despite the same code working perfectly in Safari and other browsers. Drag-and-drop functionality works fine in Edge.

Environment

  • Browser: Microsoft Edge (latest version)
  • OS: macOS
  • Framework: React 18 with Next.js
  • Context: Secure context (HTTPS/localhost)

What Works

Drag and drop file selection works perfectly in Edge
Button click works perfectly in Safari and other browsers
All programmatic API calls return “success” but no dialog appears

What Doesn’t Work

Any form of programmatic file input triggering in Edge
File selection dialog never appears despite “successful” API calls

Code Example

const FileUploadComponent = () => {
  const fileInputRef = useRef<HTMLInputElement>(null);

  const handleClick = () => {
    const fileInput = fileInputRef.current;
    if (!fileInput) return;

    // All of these appear to "succeed" but no dialog opens in Edge:
    
    // Method 1: Direct click
    fileInput.click(); // Returns undefined, no error
    
    // Method 2: showPicker API
    if ('showPicker' in fileInput) {
      fileInput.showPicker(); // No error thrown, appears successful
    }
    
    // Method 3: Focus then click
    fileInput.focus(); // Element gets focused successfully
    fileInput.click(); // No error, no dialog
  };

  return (
    <div>
      <button onClick={handleClick}>Select File</button>
      <input
        ref={fileInputRef}
        type="file"
        style={{ display: 'none' }}
        onChange={(e) => console.log('File selected:', e.target.files)}
      />
    </div>
  );
};

Debug Information

When clicking the button in Edge, console shows:

✅ File input element found
✅ showPicker() called successfully  
✅ Element successfully focused
✅ click() called successfully
✅ userActivation: true (initially)
❌ No file dialog appears
❌ onChange never fires

Attempted Solutions

Tried ALL of these approaches with no success:

  1. Direct programmatic click: fileInput.click()
  2. Modern showPicker API: fileInput.showPicker()
  3. Focus then click: fileInput.focus(); fileInput.click()
  4. Mouse event dispatching: fileInput.dispatchEvent(new MouseEvent('click'))
  5. Label association: <label><input type="file"></label>
  6. Temporary visibility: Making element visible during click
  7. Invisible overlay: Positioning file input over button for direct user click
  8. Event timing: Immediate vs setTimeout approaches

Key Observations

  • User activation preserved: Click handlers are called synchronously from user events
  • No JavaScript errors: All API calls complete without throwing
  • Element state is correct: File input is connected, not disabled, properly focused
  • Security context is valid: window.isSecureContext === true
  • Works in other browsers: Identical code works in Safari, Chrome, Firefox

Question

What is Microsoft Edge specifically blocking that prevents file input dialogs from opening, even when using the modern showPicker() API and proper user activation?

Is there a specific Edge security policy, CSP header, or browser setting that could be interfering with file input functionality? Are there any Edge-specific workarounds for this issue?

How can I animate content using a cutout-style animation in JavaScript/CSS?

I’m working on a personal project where I want to animate webpage content using a cutout-style animation, inspired by effects seen in gaming YouTube intros or pop-up overlays in gameplay videos. I aim to use this style both in my YouTube video workflow and on a webpage, especially when revealing or transitioning in content like divs, images, or text blocks.

What I’m trying to achieve:
A visual effect where content slides, pops, or snaps into view, like a paper cutout or sticker being placed on screen.

The animation should feel dynamic and stylized, similar to effects used by content creators and streamers.

Ideally built using CSS animations or JavaScript, possibly combined with transitions, transforms, and shadows.

What I’ve tried:
So far, I’ve tried a basic CSS animation that scales and rotates content while fading it in. It gives a soft pop-in effect, which works, but it’s not as layered or “cartoon-like” as I’d like.

I want to push this further by adding:

Staggered timing for multiple elements

A bit of “impact” or bounce when elements land

Optional shadow flicks or highlights to enhance the illusion of motion

What I need help with:
Are there JavaScript libraries or animation frameworks (like GSAP or anime.js) that are great for this style of animation?

How can I reuse this effect for different elements or sections on a page?

Any tips on blending this with video editing tools like After Effects so that my web animations match my YouTube content (especially transitions and overlays)?

Bonus context:
This is part of a personal brand and content workflow I’m building for my YouTube channel and portfolio website. I’m aiming for a consistent animated theme across both platforms.

Thanks in advance! I’d love to hear any ideas or resources that could help bring this to life.

No error in catch block is but “TypeError: Object(…) is not a function” instead

Using vue 2 and a Lua back-end. I am testing my errors and would like to pas the custom error messages that I defined in user_ubject.lua to be passed to my front-end application. For some reason when the session is not valid, instead of my custom error messages, I get the following error in the Console in the front-end:

TypeError: Object(...) is not a function

Online user.actions.js: 77 which is:
console.log(error.toString())

All the logs from Lua are fine. The message gets passes correctly to respond_error

In my network tab I see the error 401, with in its response {"error":"No session token"}

But I can not get it in the catch block of isSessionValid in my user.actions.js

user_object.lua

local function respond_error(status, message)
    ngx.status = status
    ngx.say(cjson.encode({ error = message }))
    ngx.exit(status)
end

function BaseObject:IsValidSession()
    ngx.log(ngx.INFO, "Start IsValidSession")

    local ENDPOINT = "token/introspect"

    -- Get the refresh token and access token from cookies
    local ck = cookie:new()
    local refresh_token, refresh_err = ck:get("refresh_token")
    local access_token, access_err = ck:get("access_token")

    if not refresh_token then
        ngx.log(ngx.WARN, "Refresh token not found in cookie: " .. (refresh_err or "not present"))
        if not access_token then
            ngx.log(ngx.WARN, "Access token not found in cookie: " .. (access_err or "not present"))
        end
    end

    local token = refresh_token or access_token
    if not token then
        ngx.log(ngx.ERR, "IsValidSession: no token found in cookies")
        return respond_error(ngx.HTTP_UNAUTHORIZED, "No session token")
    end

    -- Prepare the POST data
    local post_data = ngx.encode_args({
        client_id = CLIENT_ID,
        client_secret = CLIENT_SECRET,
        token = token
    })

    -- Make the HTTP POST request to Keycloak
    local res, err = self:KeycloakHttpPost(post_data, ENDPOINT)
    if not res then
        ngx.log(ngx.ERR, "IsValidSession: unable to contact Kaycloak - " .. (err or "unknown error"))
        return respond_error(ngx.HTTP_BAD_GATEWAY, "Authentication server unavailable")
    end

    -- Handle the response
    ngx.log(ngx.INFO, "IsValidSession: Received validate response from Keycloak with status: " .. res.status)

    if res.status == 400 then
        return respond_error(ngx.HTTP_BAD_REQUEST, "Invalid session check")
    elseif res.status == 401 then
        return respond_error(ngx.ngx.HTTP_UNAUTHORIZED, "Unauthorized session")
    elseif res.status == 500 then
        return respond_error(ngx.HTTP_BAD_GATEWAY, "Authentication server error")
    elseif res.status ~= 200 then
        return respond_error(res.status, "Unexpected auth response")
    end

    local body = cjson.decode(res.body)
    ngx.log(ngx.INFO, "BODY: " .. cjson.encode(body))
    if not body then
        ngx.log(ngx.ERR, "IsValidSession: failed to decode JSON response")
        return false, "Invalid response format"
    end

    if body.active == true then
        ngx.log(ngx.INFO, "IsValidSession: session is active")
        return true, "Active session"
    else
        ngx.log(ngx.INFO, "IsValidSession: session is inactive or expired")
        return false, "Inactive session"
    end
end

api.lua

local function is_valid_session()
    return UserModel:IsValidSession()
end

r:match({
    POST = {
    ["/api/keycloak/session/validate"] = is_valid_session
...

user.actions.js

  isSessionValid ({ dispatch }) {
    return axios.post('/api/keycloak/session/validate')
      .then(() => {
        if (!refreshIntervalId) {
          dispatch('startAccesTokenRefreshLoop')
        }

        return axios.get('/api/keycloak/me', { withCredentials: true })
      })
      .then((response) => {
        dispatch('MessagesModule/addMessage', { text: 'Welcome back ' + response?.data?.username || 'User', color: 'info' }, { root: true })
        return dispatch('setUserData', { userData: response.data });
      })
      .catch((error) => {
        console.log(error.toString())
        if (refreshIntervalId) {
          clearInterval(refreshIntervalId);
          refreshIntervalId = null;
        }

        dispatch('clearUserData', {});
        return false;
      });
  },

I want to know what causes latency in audio elements on mobile [closed]

link : 941n.github.io/simpler

github-link: github.com/941n/simpler

This is my first time using this site and my English is not good so I used a translator. Please understand. I’m sorry.

I tried to implement the sampler function as a simple toy project. On the desktop, it works as I want. I don’t know if it’s right to say latency, but there is latency in the mobile (iOS & Android) environment. What is the reason for this, and what are the solutions or reference documents?

const pads = document.querySelectorAll('.pad');
const pausePad = document.querySelector('#pause-pad');

pads.forEach(pad => {
  if (pad.dataset.samplepath) {
    pad.innerHTML = `<audio src="${pad.dataset.samplepath}" preload="auto"></audio>`;
  }
  pad.addEventListener('click', sampleControl);
});

function sampleControl(e) {
  const pad = e.currentTarget;
  const sample = pad.querySelector('audio');
  const samples = document.querySelectorAll('audio');

  if (pad.id === 'pause-pad') {
    samples.forEach(sample => {
      sample.pause();
      sample.currentTime = 0; // Reset all samples to the beginning
    });

    return;
  }

  sample.pause();
  sample.currentTime = 0; // Reset to the beginning
  sample.play();
}
* {
  font-size: 10px;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  border: 0;
  list-style: none;

  font-family: 'Roboto', sans-serif;
  text-transform: uppercase;

  user-select: none;
  -webkit-user-select: none;
}

body {
  display: grid;
  min-height: 80vh;

  align-content: center;
  justify-content: center;
  justify-items: center;

  background-color: rgb(140, 136, 134);
}

#sampler-name {
  margin: 0 0 2rem 0;
  width: fit-content;
}

#sampler-name span {
  font-family: 'Orbitron', sans-serif;
  font-size: 5rem;
  font-weight: 400;

  -webkit-text-stroke: 3px;
  paint-order: stroke fill;

  letter-spacing: 6px;

  border-bottom: 0.4rem solid;
}

#sampler-name #model {
  -webkit-text-fill-color: rgb(140, 136, 134);
}

#sampler-name #series {
  border-color: rgb(116, 0, 6);
}

#pads {
  display: grid;
  padding: 3rem;

  gap: 1rem;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(4, 1fr);

  border-radius: 1px;
  margin: auto;

  background-color: rgb(81, 80, 86);
}

.pad-wrap {
  display: flex;
  flex-direction: column;

  gap: 0.2rem;
}

.pad-info {
  display: flex;
  flex-direction: row;
  justify-content: space-between;

  padding-left: 0.4rem;
}

.pad-info .pad-command {
  color: rgb(151, 147, 154);
}

.pad {
  width: 6rem;
  height: 6rem;

  background-color: rgb(72, 63, 66);
  border-radius: 2px;
  border: 0.1rem solid;
}

.pad:hover,
.pad:active {
  background-color: rgb(92, 78, 83);
}

#pause-pad {
  background-color: rgb(116, 0, 6);
}
<link rel="icon" href="images/favicon.ico" type="image/x-icon" />
<link rel="apple-touch-icon" href="images/favicon.png" />
<link rel="apple-touch-icon" sizes="180x180" href="images/favicon.png" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Orbitron:[email protected]&family=Roboto:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="styles/base.css" />
<link rel="stylesheet" href="styles/sampler.css" />
<script src="scripts/sampleControl.js" defer></script>
<script src="scripts/sampler.js" defer></script>

<h2 id="sampler-name">
  <span id="model">MPC</span><span id="series">20</span>
</h2>

<ul id="pads">
  <li class="pad-wrap" id="pad-1">
    <div class="pad-info">
      <span class="pad-num">PAD 1</span><span class="pad-command">AB</span>
    </div>
    <div class="pad" data-samplepath="https://filesamples.com/samples/audio/m4a/sample4.m4a"></div>
  </li>
  <li class="pad-wrap" id="pad-2">
    <div class="pad-info">
      <span class="pad-num">PAD 2</span><span class="pad-command">CD</span>
    </div>
    <div class="pad" data-samplepath="https://filesamples.com/samples/audio/m4a/sample3.m4a"></div>
  </li>
  <li class="pad-wrap" id="pad-3">
    <div class="pad-info">
      <span class="pad-num">PAD 3</span><span class="pad-command">EF</span>
    </div>
    <div class="pad" data-samplepath="samples/third_note.m4a"></div>
  </li>
  <li class="pad-wrap" id="pad-4">
    <div class="pad-info">
      <span class="pad-num">PAD 4</span><span class="pad-command">GH</span>
    </div>
    <div class="pad" data-samplepath="samples/fourth_note.m4a"></div>
  </li>
  <li class="pad-wrap" id="pad-5">
    <div class="pad-info">
      <span class="pad-num">PAD 5</span><span class="pad-command">IJ</span>
    </div>
    <div class="pad" data-samplepath="samples/fiveth_note.m4a"></div>
  </li>
  <li class="pad-wrap" id="pad-6">
    <div class="pad-info">
      <span class="pad-num">PAD 6</span><span class="pad-command">KL</span>
    </div>
    <div class="pad" data-samplepath="samples/sixth_note.m4a"></div>
  </li>
  <li class="pad-wrap" id="pad-7">
    <div class="pad-info">
      <span class="pad-num">PAD 7</span><span class="pad-command">MN</span>
    </div>
    <div class="pad" data-samplepath="samples/seventh_note.m4a"></div>
  </li>
  <li class="pad-wrap" id="pad-8">
    <div class="pad-info">
      <span class="pad-num">PAD 8</span><span class="pad-command">OP</span>
    </div>
    <div class="pad" data-samplepath="samples/eighth_note.m4a"></div>
  </li>
  <li class="pad-wrap" id="pad-9">
    <div class="pad-info">
      <span class="pad-num">PAD 9</span><span class="pad-command">QR</span>
    </div>
    <div class="pad" data-samplepath="samples/start_intro.m4a"></div>
  </li>
  <li class="pad-wrap" id="pad-10">
    <div class="pad-info">
      <span class="pad-num">PAD 10</span><span class="pad-command">ST</span>
    </div>
    <div class="pad" data-samplepath="samples/look_at_you.wav"></div>
  </li>
  <li class="pad-wrap" id="pad-11">
    <div class="pad-info">
      <span class="pad-num">PAD 11</span><span class="pad-command">UV</span>
    </div>
    <div class="pad" data-samplepath="samples/ladies_and_gentlemen.wav"></div>
  </li>
  <li class="pad-wrap" id="pad-12">
    <div class="pad-info">
      <span class="pad-num">PAD 12</span><span class="pad-command">WX</span>
    </div>
    <div class="pad"></div>
  </li>
  <li class="pad-wrap" id="pad-13">
    <div class="pad-info">
      <span class="pad-num">PAD 13</span><span class="pad-command">YZ</span>
    </div>
    <div class="pad"></div>
  </li>
  <li class="pad-wrap" id="pad-14">
    <div class="pad-info">
      <span class="pad-num">PAD 14</span><span class="pad-command">&#35;&</span>
    </div>
    <div class="pad"></div>
  </li>
  <li class="pad-wrap" id="pad-15">
    <div class="pad-info">
      <span class="pad-num">PAD 15</span><span class="pad-command">- !</span>
    </div>
    <div class="pad"></div>
  </li>
  <li class="pad-wrap" id="pad-16">
    <div class="pad-info">
      <span class="pad-num">PAD 16</span><span class="pad-command">( )</span>
    </div>
    <div class="pad" id="pause-pad"></div>
  </li>
</ul>

How to exploit & in a Javascript generated SVG [closed]

Javascript. On running the whole code, it complains about:
Uncaught TypeError: prev.setAttribute is not a function, which triggers on the first encounter of setAttribute in the <defs> section

var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
const control_W = 550; //width of slider
const control_H = 300; //Height of slider
const arrowHeight = 10;
svg.setAttribute("id", "sliderControl");
svg.setAttribute("overflow", "visible");
svg.setAttribute("viewBox", "0 0 " + control_W + " " + control_H);
svg.setAttribute("width", control_W);
svg.setAttribute("height", control_H);
var svgNS = svg.namespaceURI;
//---------DEFS----------v
//create an add a <defs> section to svg
var defs = document.createElementNS(svgNS, 'defs');
svg.appendChild(defs);

//create and add a prototype svg 'prev' & 'next' arrow to the <defs> section
var prev = document.createAttributeNS(svgNS, 'path');
prev.setAttribute("d", "M 0,0 v -5 l -8,5 l 8,5 Z");
prev.setAttribute("fill", "#333333");
prev.setAttribute("stroke", "none");
prev.setAttribute("id", "prev");
defs.appendChild(prev);

//snipped the next arrow prototype
//---------DEFS----------^

//snipped

// create and set up the <use> svg section
const y_prev = document.createElementNS(svgNS, "use");
y_prev.setAttribute("x", "100");
y_prev.setAttribute("y", "100");
y_prev.setAttribute("id", "y_prev");
y_prev.setAttribute("fill", "silver");
y_prev.setAttribute("xlink:href", "#prev");
datePickerTitle.appendChild(y_prev);

//snipped next arrow <use> clause

tailwindcss 4.1.8 hard to change style with class tailwind [closed]

Anyone can tell me why when I try to change style of the elements html using tailwindcss 4.1.8 doesn’t change at all even I call the file output and install it via CLI correctly but when I change the style the elements based on code in output.css it works??

I hope it works when everytime I try to change style with the others name class of tailwindcss Docs not only based on output file tailwindcss

How to customize the CompositionEvent UI in JavaScript for IME keyboard logic on various browsers?

I just encountered What is JavaScript’s CompositionEvent? Please give examples From the little images/videos available on the topic, and given that I only ever really use a English/Latin keyboard on Chrome desktop or Safari iOS, my exposure to things like Chinese/Pinyin IME editors is limited.

First off, how can I test this on say Chinese using standard Pinyin input methods, or Japanese or Korean, for example?

Typing into the example box here for Spanish ´ e = é (Mac OPT+e then e) gives logs:

compositionstart: 
compositionupdate: ´
compositionupdate: é
compositionend: é

Working with ClaudeAI for a prototype using TipTap editor system, I end up with this, relevant portion of which is this:

const editor = useEditor({
  extensions: [
    StarterKit,
    Placeholder.configure({
      placeholder: 'Start typing... IME input is supported (中文, 日本語, 한국어, etc.)'
    })
  ],
  content: '',
  onUpdate: ({ editor }) => {
    setEditorContent(editor.getHTML());
  },
  editorProps: {
    attributes: {
      class: 'prose prose-sm sm:prose lg:prose-lg xl:prose-2xl mx-auto focus:outline-none min-h-[300px] p-4',
      spellcheck: 'false'
    },
    handleDOMEvents: {
      // Handle composition start (IME input begins)
      compositionstart: (view, event) => {
        const selection = view.state.selection;
        setImeState(prev => ({
          ...prev,
          isComposing: true,
          compositionStart: selection.from,
          compositionEnd: selection.to,
          compositionText: ''
        }));
        return false;
      },
      
      // Handle composition update (IME input changes)
      compositionupdate: (view, event) => {
        const compositionEvent = event as CompositionEvent;
        setImeState(prev => ({
          ...prev,
          compositionText: compositionEvent.data || ''
        }));
        return false;
      },
      
      // Handle composition end (IME input confirmed)
      compositionend: (view, event) => {
        const compositionEvent = event as CompositionEvent;
        setImeState(prev => ({
          ...prev,
          isComposing: false,
          compositionText: '',
          compositionStart: 0,
          compositionEnd: 0
        }));
        
        // Ensure the final composed text is properly inserted
        if (compositionEvent.data) {
          const { state, dispatch } = view;
          const { from, to } = state.selection;
          const tr = state.tr.insertText(compositionEvent.data, from, to);
          dispatch(tr);
        }
        
        return false;
      },
      
      // Handle input events for better IME support
      input: (view, event) => {
        // Let Tiptap handle regular input events
        // This ensures compatibility with IME composition
        return false;
      },
      
      // Handle keydown for special IME cases
      keydown: (view, event) => {
        // Don't interfere with IME composition
        if (imeState.isComposing) {
          // Allow certain keys during composition
          const allowedKeys = ['Escape', 'Tab', 'Enter'];
          if (!allowedKeys.includes(event.key)) {
            return false;
          }
        }
        return false;
      }
    }
  }
});

So it seems like these hooks will be called when some sort of native keyboard input tool writes to the browser on desktop or mobile/phone/etc.. Is that how it works? Like do you have to install an external keyboard tool to type in Chinese/Pinyin IME, on iPhone or Desktop Chrome? If so, (tangent but) I’d like to know where to find one, as I’m confused how to get started testing this.

The main question is, what can I customize with the IME UI?

I am thinking for a fantasy language like the one I’ve made here which uses a code editor in the browser, and when you type an English word then press tab, it converts it into the native word (which also uses Latin script, but theoretically it could use a different script).

So how would I properly go about building a sort of IME for a custom language, that works in the browser and phone in the normal places?

Just looking for high levels of:

  1. What are my options of how to play with IME for Chinese or a custom language?
  2. What is possible to customize (UI-wise, in browser Desktop, and iOS Safari)?
  3. What is not possible to customize?
  4. Should I just be using what’s there, or how much of the wheel do I need to reinvent basically?

java.lang.UnsatisfiedLinkError: could find DSO to load: libreactnativejni.so

So I am trying since days to get my react native app to work on android. I upgraded the app from 65.3 to 79.1 step by step according to the react native upgrade helper.

So now my app builds but crashes immediately after app start. Then I am logging the crash with adb logcat. In the logs I found the error:

java.lang.UnsatisfiedLinkError: could find DSO to load: libreactnativejni.so

So I started my journey to find the root cause and to fix it:

I have found the question already here on SO.
Tried all the solutions, nothing worked.
Then I have found this blog post.

I the most important paragraph:

It turns out that Android isn’t able to load 32- and 64-bit native libraries concurrently. This becomes an issue if you have at least one dependency with extensions compiled with ARM64 support and another that only supports ARM32. The system will detect the ARM64 dependency, load it, and then refuse to load the ARM32-only library, likely causing your application to crash.

He mentiones a solution there to to simply exclude all 64-bit binaries from your APK.

But when I do that I get the following error on the device:

This app isn’t compatible with the latest Android version. Check for an update or contact the app developer.

So this is no solution since I need to the dependencies in 64bit, otherwise the app does not open on ARM64 android devices or emulators.

I also found this SO answer. There it is mentioned that it is a known issue for react native since 2 years.

Now I am thinking to kick-out all ARM32 packages to have consistent dependencies for ARM64.

I found out that those packages are using ARM64:

  • /react-native/ReactAndroid/
  • /react-native/ReactCommon/
  • /react-native/React/Fabric/AppleEventBeat.cpp
  • /react-native-webview/
  • /@react-native-picker/
  • /react-native-screenguard/
  • /react-native-tts/
  • /react-native-safe-area-context/
  • /react-native-video/
  • /@react-native-community/netinfo/
  • /@react-native-community/netinfo/
  • /react-native-share/
  • /react-native-linear-gradient/
  • /react-native-screens/
  • /react-native-svg/
  • /react-native-gesture-handler/
  • /@react-native-async-storage/

I achieved this with running this command in the terminal: find . -type f ( -name "*.cpp" -o -name "*.cc" -o -name "*.cxx" -o -name "*.c++" )
Which finds all c++ files in packages. And c++ files are part of ARM64 packages.

So I am wondering how should I proceed.

Should I kick out all ARM32 dependencies and if so how can I achieve that.

Should I upgrade all dependencies and swap those out which are still on ARM32?

Am I on the right track?

This is the complete error message:

06-05 08:52:58.171 16349 16349 E AndroidRuntime: Process: com.client.sagly032721, PID: 16349
06-05 08:52:58.171 16349 16349 E AndroidRuntime: java.lang.UnsatisfiedLinkError: dlopen failed: library "libreact_featureflagsjni.so" not found
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at java.lang.Runtime.loadLibrary0(Runtime.java:1082)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at java.lang.Runtime.loadLibrary0(Runtime.java:1003)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at java.lang.System.loadLibrary(System.java:1661)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at com.facebook.soloader.nativeloader.SystemDelegate.loadLibrary(SystemDelegate.java:24)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at com.facebook.soloader.nativeloader.NativeLoader.loadLibrary(NativeLoader.java:52)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at com.facebook.soloader.nativeloader.NativeLoader.loadLibrary(NativeLoader.java:30)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at com.facebook.soloader.SoLoader.loadLibrary(SoLoader.java:805)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at com.facebook.react.internal.featureflags.ReactNativeFeatureFlagsCxxInterop.<clinit>(ReactNativeFeatureFlagsCxxInterop.kt:28)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at com.facebook.react.internal.featureflags.ReactNativeFeatureFlagsCxxAccessor.override(ReactNativeFeatureFlagsCxxAccessor.kt:475)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at com.facebook.react.internal.featureflags.ReactNativeFeatureFlags.override(ReactNativeFeatureFlags.kt:316)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load(DefaultNewArchitectureEntryPoint.kt:57)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load$default(DefaultNewArchitectureEntryPoint.kt:35)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at com.client.sagly032721.MainApplication.onCreate(MainApplication.kt:80)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1316)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6998)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2236)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at android.os.Handler.dispatchMessage(Handler.java:106)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at android.os.Looper.loopOnce(Looper.java:205)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at android.os.Looper.loop(Looper.java:294)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at android.app.ActivityThread.main(ActivityThread.java:8177)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at java.lang.reflect.Method.invoke(Native Method)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
06-05 08:52:58.171 16349 16349 E AndroidRuntime:        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)

Thank you for any help in advance. I am really stuck on this issue :/

How to access handle inside export const javascript [closed]

export const accelerometerInterop = {

    handle: function (event) {exports.Microsoft.Maui.Devices.Sensors.AccelerometerImplementation.OnReadingChanged(
            event.accelerationIncludingGravity.x || 0,
            event.accelerationIncludingGravity.y || 0,
            event.accelerationIncludingGravity.z || 0
        );
    },

    startListening: function () {
        if (window.DeviceOrientationEvent) {
            window.addEventListener("devicemotion", this.handle);
        }
    },

    stopListening: function () {
        window.removeEventListener("devicemotion", this.handle);
    }
};

I am calling it from c# using JSImport

internal partial class AccelerometerImplementation : AccelerometerImplementationBase
{
    [JSImport("accelerometerInterop.startListening", "essentials")]
    public static partial void StartListening();

    [JSImport("accelerometerInterop.stopListening", "essentials")]
    public static partial void StopListening();

    [JSExport]
    public static void OnReadingChanged(double x, double y, double z)
    {
        var implementation = Accelerometer.Default as AccelerometerImplementation;
        if (implementation == null)
            return; 
        if (!implementation.IsMonitoring)
            return;

        implementation.OnChanged(new AccelerometerChangedEventArgs(new AccelerometerData(x, y, z)));
    }

    public override bool IsSupported => true;

    protected override void PlatformStart(SensorSpeed sensorSpeed)
    {
        StartListening();
    }

    protected override void PlatformStop()
    {
        StopListening();
    }
}

It’s seems handle is not find, following error Uncaught ManagedError ManagedError: [object Object]
Error
at Jn (c:UserscedrisourcereposAvaloniaApplication1AvaloniaApplication1.Browserwwwroot_frameworkhttps:raw.githubusercontent.comdotnetruntimeefd5742bb5dd1677fbbbeb277bcfb5c9025548e5srcmonowasmruntimemarshal-to-js.ts:349:18)
at kr (c:UserscedrisourcereposAvaloniaApplication1AvaloniaApplication1.Browserwwwroot_frameworkhttps:raw.githubusercontent.comdotnetruntimeefd5742bb5dd1677fbbbeb277bcfb5c9025548e5srcmonowasmruntimeinvoke-cs.ts:277:19)
at (c:UserscedrisourcereposAvaloniaApplication1AvaloniaApplication1.Browserwwwroot_frameworkhttps:raw.githubusercontent.comdotnetruntimeefd5742bb5dd1677fbbbeb277bcfb5c9025548e5srcmonowasmruntimeinvoke-cs.ts:247:13)
at i (c:UserscedrisourcereposAvaloniaApplication1AvaloniaApplication1.Browserwwwrootwebappmodulesavaloniainput.ts:191:35)