remap-keys / remap

Keymap Customization Web app for your keyboard.
https://remap-keys.app
Other
230 stars 28 forks source link

Only cool836A's shared keymaps will go blank when I try to view them. #677

Closed illness072 closed 2 years ago

illness072 commented 2 years ago

I'm new to this kind of thing, so sorry if I'm being rude.

I opened the following page to check the shared keymaps for cool836A and clicked on one of them.

https://remap-keys.app/catalog/mVzVO2K7AkxQIXAmHEvh/keymap

However, the keymap did not show up, in fact the screen went blank and I could not see anything. Furthermore, when I tried to browser back, the screen remained blank and nothing changed.

I have confirmed that this happens with Firefox and Google Chrome on Linux.

yoichiro commented 2 years ago

@illness072 Thank you for the reporting. I was able to reproduce this issue by the following URLs:

When this issue is reproduced, the following error occurrs:

react_devtools_backend.js:2540 TypeError: Cannot read properties of undefined (reading 'isAny')
    at f (KeyGen.ts:82)
    at o.value (Keycap.tsx:144)
    at Ua (react-dom.production.min.js:187)
    at Wa (react-dom.production.min.js:186)
    at Vs (react-dom.production.min.js:269)
    at kc (react-dom.production.min.js:250)
    at xc (react-dom.production.min.js:250)
    at Sc (react-dom.production.min.js:250)
    at vc (react-dom.production.min.js:243)
    at react-dom.production.min.js:123
yoichiro commented 2 years ago

The log below is more detail on the development mode:

KeyGen.ts:82 Uncaught TypeError: Cannot read properties of undefined (reading 'isAny')
    at genKey (KeyGen.ts:82)
    at Keycap.render (Keycap.tsx:144)
    at finishClassComponent (react-dom.development.js:17485)
    at updateClassComponent (react-dom.development.js:17435)
    at beginWork (react-dom.development.js:19073)
    at HTMLUnknownElement.callCallback (react-dom.development.js:3945)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:3994)
    at invokeGuardedCallback (react-dom.development.js:4056)
    at beginWork$1 (react-dom.development.js:23964)
    at performUnitOfWork (react-dom.development.js:22776)
    at workLoopSync (react-dom.development.js:22707)
    at renderRootSync (react-dom.development.js:22670)
    at performSyncWorkOnRoot (react-dom.development.js:22293)
    at react-dom.development.js:11327
    at unstable_runWithPriority (scheduler.development.js:646)
    at runWithPriority$1 (react-dom.development.js:11276)
    at flushSyncCallbackQueueImpl (react-dom.development.js:11322)
    at flushSyncCallbackQueue (react-dom.development.js:11309)
    at discreteUpdates$1 (react-dom.development.js:22420)
    at discreteUpdates (react-dom.development.js:3756)
    at dispatchDiscreteEvent (react-dom.development.js:5889)
genKey @ KeyGen.ts:82
render @ Keycap.tsx:144
finishClassComponent @ react-dom.development.js:17485
updateClassComponent @ react-dom.development.js:17435
beginWork @ react-dom.development.js:19073
callCallback @ react-dom.development.js:3945
invokeGuardedCallbackDev @ react-dom.development.js:3994
invokeGuardedCallback @ react-dom.development.js:4056
beginWork$1 @ react-dom.development.js:23964
performUnitOfWork @ react-dom.development.js:22776
workLoopSync @ react-dom.development.js:22707
renderRootSync @ react-dom.development.js:22670
performSyncWorkOnRoot @ react-dom.development.js:22293
(anonymous) @ react-dom.development.js:11327
unstable_runWithPriority @ scheduler.development.js:646
runWithPriority$1 @ react-dom.development.js:11276
flushSyncCallbackQueueImpl @ react-dom.development.js:11322
flushSyncCallbackQueue @ react-dom.development.js:11309
discreteUpdates$1 @ react-dom.development.js:22420
discreteUpdates @ react-dom.development.js:3756
dispatchDiscreteEvent @ react-dom.development.js:5889
12index.js:1 The above error occurred in the <Keycap> component:

    at Keycap (http://localhost:3000/static/js/main.chunk.js:22938:5)
    at ConnectFunction (http://localhost:3000/static/js/0.chunk.js:417133:75)
    at div
    at div
    at div
    at div
    at div
    at div
    at CatalogKeymap (http://localhost:3000/static/js/main.chunk.js:10067:5)
    at ConnectFunction (http://localhost:3000/static/js/0.chunk.js:417133:75)
    at C (http://localhost:3000/static/js/0.chunk.js:420232:37)
    at CatalogKeyboard (http://localhost:3000/static/js/main.chunk.js:6871:5)
    at ConnectFunction (http://localhost:3000/static/js/0.chunk.js:417133:75)
    at C (http://localhost:3000/static/js/0.chunk.js:420232:37)
    at div
    at CategoryKeyboardContent (http://localhost:3000/static/js/main.chunk.js:5978:3)
    at Content (http://localhost:3000/static/js/main.chunk.js:5896:5)
    at ConnectFunction (http://localhost:3000/static/js/0.chunk.js:417133:75)
    at main
    at Catalog (http://localhost:3000/static/js/main.chunk.js:5440:5)
    at C (http://localhost:3000/static/js/0.chunk.js:420232:37)
    at WithSnackbar(withRouter(Catalog))
    at ConnectFunction (http://localhost:3000/static/js/0.chunk.js:417133:75)
    at Route (http://localhost:3000/static/js/0.chunk.js:419975:29)
    at Switch (http://localhost:3000/static/js/0.chunk.js:420177:29)
    at Router (http://localhost:3000/static/js/0.chunk.js:419610:30)
    at BrowserRouter (http://localhost:3000/static/js/0.chunk.js:419230:35)
    at SnackbarProvider (http://localhost:3000/static/js/0.chunk.js:341741:24)
    at App (http://localhost:3000/static/js/main.chunk.js:1526:5)
    at WithStyles (http://localhost:3000/static/js/0.chunk.js:234080:31)
    at r (http://localhost:3000/static/js/0.chunk.js:413890:19)
    at Provider (http://localhost:3000/static/js/0.chunk.js:416846:20)

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
console.<computed> @ index.js:1
overrideMethod @ react_devtools_backend.js:2540
logCapturedError @ react-dom.development.js:20085
update.callback @ react-dom.development.js:20118
callCallback @ react-dom.development.js:12318
commitUpdateQueue @ react-dom.development.js:12339
commitLifeCycles @ react-dom.development.js:20736
commitLayoutEffects @ react-dom.development.js:23426
callCallback @ react-dom.development.js:3945
invokeGuardedCallbackDev @ react-dom.development.js:3994
invokeGuardedCallback @ react-dom.development.js:4056
commitRootImpl @ react-dom.development.js:23151
unstable_runWithPriority @ scheduler.development.js:646
runWithPriority$1 @ react-dom.development.js:11276
commitRoot @ react-dom.development.js:22990
performSyncWorkOnRoot @ react-dom.development.js:22329
(anonymous) @ react-dom.development.js:11327
unstable_runWithPriority @ scheduler.development.js:646
runWithPriority$1 @ react-dom.development.js:11276
flushSyncCallbackQueueImpl @ react-dom.development.js:11322
flushSyncCallbackQueue @ react-dom.development.js:11309
discreteUpdates$1 @ react-dom.development.js:22420
discreteUpdates @ react-dom.development.js:3756
dispatchDiscreteEvent @ react-dom.development.js:5889
react-dom.development.js:11340 Uncaught TypeError: Cannot read properties of undefined (reading 'isAny')
    at genKey (KeyGen.ts:82)
    at Keycap.render (Keycap.tsx:144)
    at finishClassComponent (react-dom.development.js:17485)
    at updateClassComponent (react-dom.development.js:17435)
    at beginWork (react-dom.development.js:19073)
    at HTMLUnknownElement.callCallback (react-dom.development.js:3945)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:3994)
    at invokeGuardedCallback (react-dom.development.js:4056)
    at beginWork$1 (react-dom.development.js:23964)
    at performUnitOfWork (react-dom.development.js:22776)
    at workLoopSync (react-dom.development.js:22707)
    at renderRootSync (react-dom.development.js:22670)
    at performSyncWorkOnRoot (react-dom.development.js:22293)
    at react-dom.development.js:11327
    at unstable_runWithPriority (scheduler.development.js:646)
    at runWithPriority$1 (react-dom.development.js:11276)
    at flushSyncCallbackQueueImpl (react-dom.development.js:11322)
    at flushSyncCallbackQueue (react-dom.development.js:11309)
    at discreteUpdates$1 (react-dom.development.js:22420)
    at discreteUpdates (react-dom.development.js:3756)
    at dispatchDiscreteEvent (react-dom.development.js:5889)
yoichiro commented 2 years ago

I found the reason of this issue. There are duplicates two keyboard definitions in the DB. They have same product ID and vendor ID, but one has been approved and another one has been rejected. However, all saved keymaps have the product ID, vendor ID and same product name "cool836A". Therefore, keymaps of different keyboard are also displayed.

yoichiro commented 2 years ago

As tentative measure, I change the status from "shared" to "private" manually against keymaps which are incorrect keyboards so that the incorrect keymaps will not be displayed.

yoichiro commented 2 years ago

As my memo, the steps to reproduce this issue are:

  1. Connect a keyboard that is not registered in Remap (VIA_ENABLE = yes), and authorize and select the keyboard with Remap.
  2. Remap queries the DB and there is another keyboard definition with the same Vendor ID, Product ID, so use that information to open /configure. As a result, the incorrect keyboard layouts are displayed, a messy key assignment is displayed.
  3. The user imports his own keyboard definition JSON file. As a result, the key layout, the number of columns, and the number of rows change while keeping the keyboard definition information recognized by Remap in 2, and the layout and key assignments suitable for the connected keyboard are displayed on the screen.
  4. It is recognized as an Approved keyboard in Remap, so not only the keymap save/restore feature, but also the share feature is enabled. However, the number of rows and columns of the currently applied key layout may be different from the values ​​of the Approved keyboard. If the user saves or shares the current keymap at this time, Remap decides to save/share the keymap for the approved keyboard and saves the keymap in the DB. This establishes a state in which keymaps that do not match the definition of the approved keyboard are saved.
  5. The keymap list on the catalog page lists the keymaps saved and shared for approved keyboards, but the keymaps for incorrect keyboards are also listed there in this case. Finally, when selecting them, the number of columns and the number of rows do not match, and an error occurs.

In Japanese for my memo:

  1. Remap に登録されていないキーボード(VIA_ENABLE=yes)を接続し、Remapでそのキーボードを認可して選択する。
  2. Remap はDBに問い合わせして、同じ Vendor ID, Product ID を持つ別のキーボード定義が存在していたので、その情報を使って /configure を開く。結果、異なるキーボードのレイアウトが表示され、メチャクチャなキーアサイン表示となる。
  3. ユーザが自身作のキーボード定義JSONファイルをインポートする。これにより、2. でRemapが認識した別のキーボード定義情報のまま、キーレイアウトや列数,行数が変化し、結果として画面上は接続されたキーボードに適したレイアウトとキーアサインが表示される。
  4. Remap 上では、Approved なキーボードとして認識されているため、キーマップの保存/復元機能だけでなく、シェア機能も有効になっている。ただし、現状適用されているキーレイアウトの行数,列数は、Approved なキーボードとは異なる値になっている可能性がある。ここでユーザがキーマップの保存やシェアを行うと、Remap は Approved なキーボードに対するキーマップの保存/シェアと判断して、DB にキーマップを保存する。これにより、Approved なキーボードの定義とは合致しないキーマップが保存されている状態が成立する。
  5. カタログページのキーマップ一覧には、Approved なキーボードに対して保存されシェアされたキーマップが一覧表示されるが、そこに異なるキーボードに対してのキーマップも掲載されてしまい、それを選択すると列数, 行数が合わずに、エラーとなる。
yoichiro commented 2 years ago

In other words, the cause of the problem situation is that in 3. "You can import and use a JSON file that has a different number of columns and rows from the applied Approved keyboard definition." This can lead to a mix of keymaps for completely different keyboards.

As a workaround, if the keyboard is open with / configure and the JSON file with different number of columns and rows is imported, it should be rejected.

By this countermeasure, it is possible to avoid the situation where saved / shared keymaps are mixed and an error occurs as a result.

However, this is a little painful. When opening a keyboard with VIA_ENABLE = yes in Remap, it may happen to be recognized as another keyboard registered with the same Product ID and Vendor ID. Even in that state, you can change the keymap for your keyboard by importing the JSON file you have. This situation seems to have occurred in "ErgoDash", where the ErgoDash user was recognized by his Remap as cool836A and then used his JSON file at hand to customize the keymap in his ErgoDash layout. It looks like it was there. This will not be possible.

In the first place, I am trying to correct the judgment including the Product Name, and I plan to go to https://github.com/remap-keys/remap/issues/587, but if this can be handled, the above reproduction procedure will be misjudged in the first place. To prevent it, you will not be able to proceed from 2.

However, Issue 587 has failed once, so you need to be careful and you can't do it right away.

In conclusion, if the JSON file is imported with the keyboard layout open in / configure with the Approved keyboard definition, he will not import if the number of columns and the number of rows do not match, I'm going to put in a response.

問題の状況が作られてしまう原因は、3. で「適用されている Approved なキーボード定義とは列数と行数が異なる JSON ファイルをインポートして使えてしまうこと」になる。これができてしまうから、全く異なるキーボード向けのキーマップが混在する状況になってしまう。

対処としては、キーボードが /configure で開けている状況のときに、列数と行数が異なる JSON ファイルのインポートがされたら、それを拒否するようにすれば良い。

この対処によって、保存/シェアされたキーマップが混在してしまって結果エラーになってしまう事態は回避できる。

ただし、これには少し痛みが伴う。VIA_ENABLE=yes なキーボードを Remap で開いた際に、偶然同じ Product ID と Vendor ID で登録された別のキーボードとして認識されてしまうことがある。その状態になっても、手元にある JSON ファイルをインポートすれば、手元のキーボードに対するキーマップ変更が可能になる。この状況は、どうやら「ErgoDash」で発生していた模様で、ErgoDash ユーザは、cool836A として Remap で認識され、その後手元の JSON ファイルを使って ErgoDash のレイアウトでキーマップカスタマイズを行っていたっぽい。これができなくなる。

そもそも Product Name を含めた判定に修正しようとしていて、 https://github.com/remap-keys/remap/issues/587 で予定しているけど、これが対応できれば、そもそも上記の再現手順の誤判定を防げるため、2. から先に進めなくなる。

ただし、Issue 587 は一回失敗しているため、対応を慎重に行う必要があり、すぐにはできない。

結論として、Approved なキーボード定義で /configure でキーボードレイアウトが開かれている状況で JSON ファイルのインポートが行われた場合には、列数と行数が一致していなかった場合はインポートさせない、という対応を入れようと考える。