Skip to content

Instantly share code, notes, and snippets.

@voidproc
Last active August 26, 2023 04:52
Show Gist options
  • Save voidproc/dda7d1627697b6314eb6d3b12820e868 to your computer and use it in GitHub Desktop.
Save voidproc/dda7d1627697b6314eb6d3b12820e868 to your computer and use it in GitHub Desktop.

概要

OpenSiv3D Web 版の Platform::Web::Dialog::OpenFile() について、 以下の操作をしたときに戻り値の AsyncTaskisReady()true にならない現象を解消する。

  • 連続で同じファイルを選ぶ
  • 連続で(またはファイルが選択されていない状態で)ダイアログをキャンセルする

本 Gist のとおり Siv3D.js を修正し、https://gist.github.com/voidproc/7673170c54448179703ce08e0800a3b4 で動作確認する。

input イベントと同様にイベントハンドラを oncancel に設定する方法では Firefox で動作せず。 addEventListener を使用する方法では Firefox でも動作するが、 OpenFile() が呼ばれるたびにハンドラが登録されてしまうため、once オプションを指定 & input イベント実行時にハンドラを削除する。

動作確認

  • ✅ Chrome 116.0.5845.111
  • ✅ Opera One 101.0.4843.58
  • ✅ Firefox 116.0.3
  • ✅ Edge 116.0.1938.54
  • ✅ Chrome (Android) 116.0.5845.92
  • ❌ Opera (Android) 76.2.4027.73374
    • ※最初のグレーの画面から進まない?
  • ✅ Firefox (Android) 116.3.0
  • ✅ Edge (Android) 116.0.1938.58
// `OpenSiv3D_0.6.6_Web/lib/Siv3D.js` の `siv3dOpenDialogAsync` の抜粋
siv3dOpenDialogAsync: function(filterStr, callback, futurePtr) {
siv3dInputElement.accept = UTF8ToString(filterStr);
// これは Firefox で動作しない
// siv3dInputElement.oncancel = function(e) {
// {{{ makeDynCall('vii', 'callback') }}}(0, futurePtr);
// _siv3dMaybeAwake();
// };
// cancel イベントハンドラ
function cancelHandler(e) {
{{{ makeDynCall('vii', 'callback') }}}(0, futurePtr);
_siv3dMaybeAwake();
}
// addEventListener を使用する形だと Firefox でも動作する
// once オプションにより、イベントが発生すればハンドラは自動的に削除される
siv3dInputElement.addEventListener('cancel', cancelHandler, { once: true });
siv3dInputElement.oninput = function(e) {
const files = e.target.files;
if (files.length < 1) {
{{{ makeDynCall('vii', 'callback') }}}(0, futurePtr);
_siv3dMaybeAwake();
return;
}
const file = files[0];
const filePath = "/tmp/" + file.name;
siv3dDialogFileReader.addEventListener("load", function onLoaded() {
FS.writeFile(filePath, new Uint8Array(siv3dDialogFileReader.result));
const namePtr = allocate(intArrayFromString(filePath), ALLOC_NORMAL);
{{{ makeDynCall('vii', 'callback') }}}(namePtr, futurePtr);
_siv3dMaybeAwake();
siv3dDialogFileReader.removeEventListener("load", onLoaded);
// cancel イベントが発生しない場合はイベントハンドラを削除する
siv3dInputElement.removeEventListener('cancel', cancelHandler);
});
siv3dDialogFileReader.readAsArrayBuffer(file);
// 次回同じファイルが選択された際にもイベントが発火するようにする
e.target.value = '';
};
siv3dRegisterUserAction(function() {
siv3dInputElement.click();
});
},
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment