js-dos 8.1.4 → 8.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/emulators/emulators.js +2 -0
- package/dist/emulators/emulators.js.map +1 -0
- package/dist/emulators/types/build.d.ts +28 -0
- package/dist/emulators/types/dos/bundle/dos-bundle.d.ts +20 -0
- package/dist/emulators/types/dos/dosbox/ts/direct.d.ts +3 -0
- package/dist/emulators/types/dos/dosbox/ts/worker.d.ts +3 -0
- package/dist/emulators/types/emulators.d.ts +76 -0
- package/dist/emulators/types/http.d.ts +9 -0
- package/dist/emulators/types/impl/ci-impl.d.ts +29 -0
- package/dist/emulators/types/impl/emulators-impl.d.ts +26 -0
- package/dist/emulators/types/impl/modules.d.ts +38 -0
- package/dist/emulators/types/libzip/libzip.d.ts +16 -0
- package/dist/emulators/types/protocol/messages-queue.d.ts +8 -0
- package/dist/emulators/types/protocol/protocol.d.ts +128 -0
- package/dist/emulators/wdosbox-x.js +55 -0
- package/dist/emulators/wdosbox-x.js.symbols +8760 -0
- package/dist/emulators/wdosbox-x.wasm +0 -0
- package/dist/emulators/wdosbox.js +55 -0
- package/dist/emulators/wdosbox.js.symbols +3001 -0
- package/dist/emulators/wdosbox.wasm +0 -0
- package/dist/emulators/wlibzip.js +21 -0
- package/dist/emulators/wlibzip.js.symbols +268 -0
- package/dist/emulators/wlibzip.wasm +0 -0
- package/dist/js-dos.css +1 -0
- package/dist/js-dos.js +22 -0
- package/dist/js-dos.js.map +1 -0
- package/package.json +1 -1
- package/release.zip +0 -0
- package/.eslintrc.json +0 -43
- package/.github/workflows/build.yml +0 -51
- package/.gitmodules +0 -4
- package/index.html +0 -110
- package/postcss.config.cjs +0 -8
- package/src/app.css +0 -14
- package/src/base.css +0 -10
- package/src/components/checkbox.tsx +0 -41
- package/src/components/close-button.tsx +0 -17
- package/src/components/components.css +0 -28
- package/src/components/dos-option-checkbox.tsx +0 -94
- package/src/components/dos-option-select.tsx +0 -108
- package/src/components/dos-option-slider.tsx +0 -35
- package/src/components/error.tsx +0 -16
- package/src/components/loading.tsx +0 -26
- package/src/components/lock.tsx +0 -10
- package/src/components/select.tsx +0 -33
- package/src/components/slider.tsx +0 -69
- package/src/download-file.ts +0 -18
- package/src/frame/account-frame.tsx +0 -156
- package/src/frame/editor/defaults.ts +0 -419
- package/src/frame/editor/editor-conf-frame.tsx +0 -227
- package/src/frame/editor/editor-frame.css +0 -55
- package/src/frame/editor/editor-fs-frame.tsx +0 -314
- package/src/frame/fat-drives-frame.tsx +0 -199
- package/src/frame/frame.css +0 -119
- package/src/frame/frame.tsx +0 -34
- package/src/frame/image-rendering-frame.tsx +0 -8
- package/src/frame/network-frame.tsx +0 -157
- package/src/frame/quick-save-frame.tsx +0 -98
- package/src/frame/settings-frame.tsx +0 -14
- package/src/frame/stats-frame.tsx +0 -87
- package/src/host/bundle-storage.ts +0 -91
- package/src/host/fullscreen.ts +0 -35
- package/src/host/lcache.ts +0 -203
- package/src/host/lstorage.ts +0 -156
- package/src/i18n.ts +0 -185
- package/src/index.css +0 -7
- package/src/load.ts +0 -132
- package/src/login/login.css +0 -9
- package/src/login/login.tsx +0 -77
- package/src/main.tsx +0 -197
- package/src/public/types.ts +0 -45
- package/src/sidebar/account-button.tsx +0 -33
- package/src/sidebar/cloud-save-button.tsx +0 -89
- package/src/sidebar/diskette-icon.tsx +0 -14
- package/src/sidebar/fullscreen-button.tsx +0 -44
- package/src/sidebar/network-button.tsx +0 -39
- package/src/sidebar/sidebar-button.tsx +0 -244
- package/src/sidebar/sidebar.css +0 -47
- package/src/sidebar/sidebar.tsx +0 -30
- package/src/sockdrive/LICENSE +0 -674
- package/src/sockdrive/README.md +0 -45
- package/src/sockdrive/include/sockdrive.h +0 -23
- package/src/sockdrive/js/.eslintrc.json +0 -43
- package/src/sockdrive/js/package.json +0 -29
- package/src/sockdrive/js/src/fatfs/chains.js +0 -318
- package/src/sockdrive/js/src/fatfs/dir.js +0 -385
- package/src/sockdrive/js/src/fatfs/helpers.js +0 -210
- package/src/sockdrive/js/src/fatfs/index.js +0 -606
- package/src/sockdrive/js/src/fatfs/structs.js +0 -255
- package/src/sockdrive/js/src/fatfs/vol.js +0 -166
- package/src/sockdrive/js/src/sockdrive/cache.ts +0 -56
- package/src/sockdrive/js/src/sockdrive/drive.ts +0 -471
- package/src/sockdrive/js/src/sockdrive/lru.ts +0 -221
- package/src/sockdrive/js/src/sockdrive/types.ts +0 -14
- package/src/sockdrive/js/src/sockdrive-fat.d.ts +0 -64
- package/src/sockdrive/js/src/sockdrive-fat.ts +0 -226
- package/src/sockdrive/js/src/sockdrive-native.ts +0 -100
- package/src/sockdrive/js/src/test/test.ts +0 -289
- package/src/sockdrive/js/tsconfig.json +0 -11
- package/src/sockdrive/js/webpack.config.js +0 -68
- package/src/sockdrive/js/yarn.lock +0 -1808
- package/src/store/auth.ts +0 -115
- package/src/store/dos.ts +0 -305
- package/src/store/editor.ts +0 -61
- package/src/store/init.ts +0 -48
- package/src/store/storage.ts +0 -32
- package/src/store/ui.ts +0 -191
- package/src/store.tsx +0 -116
- package/src/ui.tsx +0 -140
- package/src/v8/changes.ts +0 -56
- package/src/v8/config.ts +0 -20
- package/src/v8/subscriptions.ts +0 -62
- package/src/vite-env.d.ts +0 -5
- package/src/window/dos/controls/keyboard.ts +0 -32
- package/src/window/dos/controls/keys.ts +0 -331
- package/src/window/dos/controls/mouse/mount.ts +0 -99
- package/src/window/dos/controls/mouse/mouse-locked.ts +0 -51
- package/src/window/dos/controls/mouse/mouse-not-locked.ts +0 -84
- package/src/window/dos/controls/mouse/mouse-swipe.ts +0 -57
- package/src/window/dos/controls/mouse/pointer.ts +0 -85
- package/src/window/dos/controls/mouse.ts +0 -21
- package/src/window/dos/dos-dhry2.tsx +0 -191
- package/src/window/dos/dos-runtime.tsx +0 -216
- package/src/window/dos/dos-window.tsx +0 -91
- package/src/window/dos/render/canvas.ts +0 -65
- package/src/window/dos/render/resize.ts +0 -31
- package/src/window/dos/render/webgl.ts +0 -173
- package/src/window/dos/sound/audio-node.ts +0 -148
- package/src/window/error-window.tsx +0 -9
- package/src/window/loading-window.tsx +0 -54
- package/src/window/prerun-window.tsx +0 -121
- package/src/window/select-window.tsx +0 -118
- package/src/window/window.css +0 -78
- package/src/window/window.tsx +0 -49
- package/src/ws/ws-sockdrive.ts +0 -123
- package/src/ws/ws-transport-layer.ts +0 -468
- package/tailwind.config.cjs +0 -48
- package/tsconfig.json +0 -32
- package/tsconfig.node.json +0 -9
- package/vite.config.ts +0 -25
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { useState } from "preact/hooks";
|
|
2
|
-
import { useDispatch, useSelector } from "react-redux";
|
|
3
|
-
import { LockBadge } from "../components/lock";
|
|
4
|
-
import { State, useNonSerializableStore } from "../store";
|
|
5
|
-
import { uiSlice } from "../store/ui";
|
|
6
|
-
import { DisketteIcon } from "./diskette-icon";
|
|
7
|
-
import { useT } from "../i18n";
|
|
8
|
-
import { putChanges } from "../v8/changes";
|
|
9
|
-
|
|
10
|
-
export function CloudSaveButton(props: {
|
|
11
|
-
class?: string,
|
|
12
|
-
}) {
|
|
13
|
-
const [busy, setBusy] = useState<boolean>(false);
|
|
14
|
-
const account = useSelector((state: State) => state.auth.account);
|
|
15
|
-
const disabled = account === null && false;
|
|
16
|
-
const dispatch = useDispatch();
|
|
17
|
-
const t = useT();
|
|
18
|
-
const cloudSaves = useSelector((state: State) => state.ui.cloudSaves);
|
|
19
|
-
const nonSerializableStore = useNonSerializableStore();
|
|
20
|
-
|
|
21
|
-
if (!cloudSaves ||
|
|
22
|
-
nonSerializableStore.loadedBundle === null ||
|
|
23
|
-
nonSerializableStore.loadedBundle.bundleChangesUrl === null) {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async function onClick() {
|
|
28
|
-
if (disabled) {
|
|
29
|
-
dispatch(uiSlice.actions.modalLogin());
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (busy) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const ci = nonSerializableStore.ci;
|
|
38
|
-
const changesUrl = nonSerializableStore.loadedBundle?.bundleChangesUrl;
|
|
39
|
-
|
|
40
|
-
if (ci === null || !changesUrl) {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
setBusy(true);
|
|
45
|
-
try {
|
|
46
|
-
const changes = await ci.persist(true);
|
|
47
|
-
if (changes !== null) {
|
|
48
|
-
if (account === null || !account.premium) {
|
|
49
|
-
await nonSerializableStore.cache.put(changesUrl, changes);
|
|
50
|
-
} else {
|
|
51
|
-
await Promise.all([
|
|
52
|
-
putChanges(changesUrl, changes),
|
|
53
|
-
nonSerializableStore.cache.put(changesUrl, changes),
|
|
54
|
-
]);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
dispatch(uiSlice.actions.showToast({
|
|
59
|
-
message: t("success"),
|
|
60
|
-
intent: "success",
|
|
61
|
-
}));
|
|
62
|
-
} catch (e: any) {
|
|
63
|
-
dispatch(uiSlice.actions.showToast({
|
|
64
|
-
message: t("unable_to_save"),
|
|
65
|
-
intent: "error",
|
|
66
|
-
}));
|
|
67
|
-
console.error(e);
|
|
68
|
-
} finally {
|
|
69
|
-
setBusy(false);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return <div class={"save-button sidebar-button overflow-hidden " +
|
|
74
|
-
(busy ? " sidebar-highlight " : "") + props.class +
|
|
75
|
-
(disabled ? " opacity-50" : "")} onClick={onClick}>
|
|
76
|
-
<div class="w-full h-full flex justify-center">
|
|
77
|
-
<DisketteIcon />
|
|
78
|
-
{busy && <div class="sidebar-badge" />}
|
|
79
|
-
{disabled && <LockBadge />}
|
|
80
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
|
81
|
-
stroke-width="1.5" stroke="currentColor"
|
|
82
|
-
class="absolute bottom-1 w-3 h-3 text-primary-content">
|
|
83
|
-
<path stroke-linecap="round" stroke-linejoin="round"
|
|
84
|
-
d="M12 16.5V9.75m0 0l3 3m-3-3l-3 3M6.75 19.5a4.5 4.5 0 01-1.41-8.775
|
|
85
|
-
5.25 5.25 0 0110.233-2.33 3 3 0 013.758 3.848A3.752 3.752 0 0118 19.5H6.75z" />
|
|
86
|
-
</svg>
|
|
87
|
-
</div>
|
|
88
|
-
</div >;
|
|
89
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export function DisketteIcon(props: {
|
|
2
|
-
class?: string,
|
|
3
|
-
}) {
|
|
4
|
-
return <svg xmlns="http://www.w3.org/2000/svg"
|
|
5
|
-
style="padding: 2px"
|
|
6
|
-
viewBox="0 0 16 16" enable-background="new 0 0 16 16"
|
|
7
|
-
fill="currentColor" class={ "w-full h-full rounded-lg " + props.class }>
|
|
8
|
-
<path fill-rule="evenodd" clip-rule="evenodd"
|
|
9
|
-
d="M15.71,2.29l-2-2C13.53,0.11,13.28,0,13,0h-1v6H4V0H1C0.45,0,0,0.45,0,1v14
|
|
10
|
-
c0,0.55,0.45,1,1,1h14c0.55,0,1-0.45,1-1V3C16,2.72,15.89,2.47,15.71,2.29z
|
|
11
|
-
M14,15H2V9c0-0.55,0.45-1,1-1h10c0.55,0,1,0.45,1,1V15
|
|
12
|
-
z M11,1H9v4h2V1z"/>
|
|
13
|
-
</svg>;
|
|
14
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { useSelector, useStore } from "react-redux";
|
|
2
|
-
import { State, Store } from "../store";
|
|
3
|
-
import { browserSetFullScreen } from "../host/fullscreen";
|
|
4
|
-
|
|
5
|
-
export function FullscreenButton(props: {
|
|
6
|
-
class?: string,
|
|
7
|
-
}) {
|
|
8
|
-
const fullScreen = useSelector((state: State) => state.ui.fullScreen);
|
|
9
|
-
const store = useStore() as Store;
|
|
10
|
-
|
|
11
|
-
function onClick() {
|
|
12
|
-
browserSetFullScreen(!fullScreen, store);
|
|
13
|
-
}
|
|
14
|
-
/* eslint-disable max-len */
|
|
15
|
-
return <div class={"fullscreen-button sidebar-button " + props.class} onClick={onClick}>
|
|
16
|
-
<div class={"w-full h-full scale-75 hover:scale-90"}>
|
|
17
|
-
{!fullScreen &&
|
|
18
|
-
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
|
|
19
|
-
viewBox="0 0 16 16" fill="currentColor" stroke="none" enable-background="new 0 0 16 16" >
|
|
20
|
-
<g>
|
|
21
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.99,8.99c-0.28,0-0.53,0.11-0.71,0.29l-3.29,3.29v-1.59c0-0.55-0.45-1-1-1
|
|
22
|
-
s-1,0.45-1,1v4c0,0.55,0.45,1,1,1h4c0.55,0,1-0.45,1-1s-0.45-1-1-1H3.41L6.7,10.7c0.18-0.18,0.29-0.43,0.29-0.71
|
|
23
|
-
C6.99,9.44,6.54,8.99,5.99,8.99z M14.99-0.01h-4c-0.55,0-1,0.45-1,1s0.45,1,1,1h1.59L9.28,5.29C9.1,5.47,8.99,5.72,8.99,5.99
|
|
24
|
-
c0,0.55,0.45,1,1,1c0.28,0,0.53-0.11,0.71-0.29l3.29-3.29v1.59c0,0.55,0.45,1,1,1s1-0.45,1-1v-4C15.99,0.44,15.54-0.01,14.99-0.01
|
|
25
|
-
z"/>
|
|
26
|
-
</g>
|
|
27
|
-
</svg>
|
|
28
|
-
}
|
|
29
|
-
{fullScreen &&
|
|
30
|
-
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
|
|
31
|
-
viewBox="0 0 16 16" fill="currentColor" stroke="none" enable-background="new 0 0 16 16">
|
|
32
|
-
<g>
|
|
33
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.99,0.99c0-0.55-0.45-1-1-1c-0.28,0-0.53,0.11-0.71,0.29l-3.29,3.29V1.99
|
|
34
|
-
c0-0.55-0.45-1-1-1s-1,0.45-1,1v4c0,0.55,0.45,1,1,1h4c0.55,0,1-0.45,1-1s-0.45-1-1-1h-1.59L15.7,1.7
|
|
35
|
-
C15.88,1.52,15.99,1.27,15.99,0.99z M5.99,8.99h-4c-0.55,0-1,0.45-1,1s0.45,1,1,1h1.59l-3.29,3.29c-0.18,0.18-0.29,0.43-0.29,0.71
|
|
36
|
-
c0,0.55,0.45,1,1,1c0.28,0,0.53-0.11,0.71-0.29l3.29-3.29v1.59c0,0.55,0.45,1,1,1s1-0.45,1-1v-4C6.99,9.44,6.54,8.99,5.99,8.99z"
|
|
37
|
-
/>
|
|
38
|
-
</g>
|
|
39
|
-
</svg>
|
|
40
|
-
}
|
|
41
|
-
</div>
|
|
42
|
-
</div >;
|
|
43
|
-
/* eslint-enable max-len */
|
|
44
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { useDispatch, useSelector } from "react-redux";
|
|
2
|
-
import { State } from "../store";
|
|
3
|
-
import { uiSlice } from "../store/ui";
|
|
4
|
-
|
|
5
|
-
export function NetworkButton(props: {
|
|
6
|
-
class?: string,
|
|
7
|
-
}) {
|
|
8
|
-
const hightlight = useSelector((state: State) => state.ui.frame) === "network";
|
|
9
|
-
const inactive = useSelector((state: State) => state.dos.network.ipx !== "connected");
|
|
10
|
-
const dispatch = useDispatch();
|
|
11
|
-
|
|
12
|
-
function onClick() {
|
|
13
|
-
if (hightlight) {
|
|
14
|
-
dispatch(uiSlice.actions.frameNone());
|
|
15
|
-
} else {
|
|
16
|
-
dispatch(uiSlice.actions.frameNetwork());
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return <div class={"network-button sidebar-button " +
|
|
21
|
-
(hightlight ? " sidebar-highlight " : "") +
|
|
22
|
-
(inactive ? " inactive " : "") +
|
|
23
|
-
props.class} onClick={onClick}>
|
|
24
|
-
<div class="w-full h-full">
|
|
25
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
|
26
|
-
stroke-width="1.5" stroke="currentColor" class="w-full h-full">
|
|
27
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M8.288 15.038a5.25 5.25 0
|
|
28
|
-
017.424 0M5.106 11.856c3.807-3.808 9.98-3.808 13.788 0M1.924 8.674c5.565-5.565
|
|
29
|
-
14.587-5.565 20.152 0M12.53 18.22l-.53.53-.53-.53a.75.75 0 011.06 0z" />
|
|
30
|
-
</svg>
|
|
31
|
-
{ inactive && <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
|
32
|
-
stroke="currentColor" class="w-full text-error h-full absolute top-0 left-0">
|
|
33
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M4 4L18 18" />
|
|
34
|
-
</svg> }
|
|
35
|
-
</div>
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
</div >;
|
|
39
|
-
}
|
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
import { AnyAction } from "@reduxjs/toolkit";
|
|
2
|
-
import { useDispatch, useSelector, useStore } from "react-redux";
|
|
3
|
-
import { LockBadge } from "../components/lock";
|
|
4
|
-
import { State, Store } from "../store";
|
|
5
|
-
import { Frame, uiSlice } from "../store/ui";
|
|
6
|
-
import { DisketteIcon } from "./diskette-icon";
|
|
7
|
-
import { useEffect, useRef, useState } from "preact/hooks";
|
|
8
|
-
|
|
9
|
-
export function ImageRenderingButton(props: {
|
|
10
|
-
class?: string,
|
|
11
|
-
}) {
|
|
12
|
-
return <SidebarButton
|
|
13
|
-
class={props.class}
|
|
14
|
-
frame="image-rendering"
|
|
15
|
-
action={uiSlice.actions.frameImageRendering()}
|
|
16
|
-
>
|
|
17
|
-
<svg xmlns="http://www.w3.org/2000/svg"
|
|
18
|
-
fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
|
|
19
|
-
class="w-full h-full">
|
|
20
|
-
<path stroke-linecap="round"
|
|
21
|
-
stroke-linejoin="round" d="M2.25 15.75l5.159-5.159a2.25 2.25 0
|
|
22
|
-
013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0
|
|
23
|
-
013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5
|
|
24
|
-
1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5
|
|
25
|
-
1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75
|
|
26
|
-
0 .375.375 0 01.75 0z" />
|
|
27
|
-
</svg>
|
|
28
|
-
</SidebarButton>;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function QuickSaveButton(props: {
|
|
32
|
-
class?: string,
|
|
33
|
-
}) {
|
|
34
|
-
const disabled = useSelector((state: State) => state.auth.account) === null && false;
|
|
35
|
-
const action = disabled ?
|
|
36
|
-
uiSlice.actions.modalLogin() :
|
|
37
|
-
uiSlice.actions.frameQuickSave();
|
|
38
|
-
return <SidebarButton
|
|
39
|
-
class={props.class + (disabled ? " opacity-50" : "")}
|
|
40
|
-
frame="quick-save"
|
|
41
|
-
action={action}
|
|
42
|
-
>
|
|
43
|
-
<DisketteIcon />
|
|
44
|
-
{disabled && <LockBadge />}
|
|
45
|
-
</SidebarButton>;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function FatDrivesButton(props: {
|
|
49
|
-
class?: string,
|
|
50
|
-
}) {
|
|
51
|
-
return <SidebarButton
|
|
52
|
-
class={props.class}
|
|
53
|
-
frame="fat-drives"
|
|
54
|
-
action={uiSlice.actions.frameFatDrives()}
|
|
55
|
-
>
|
|
56
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
|
57
|
-
stroke-width="1.5" stroke="currentColor" class="w-full h-full">
|
|
58
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 14.25h13.5m-13.5
|
|
59
|
-
0a3 3 0 01-3-3m3 3a3 3 0 100 6h13.5a3 3 0 100-6m-16.5-3a3 3 0 013-3h13.5a3 3
|
|
60
|
-
0 013 3m-19.5 0a4.5 4.5 0 01.9-2.7L5.737 5.1a3.375 3.375 0 012.7-1.35h7.126c1.062
|
|
61
|
-
0 2.062.5 2.7 1.35l2.587 3.45a4.5 4.5 0 01.9 2.7m0 0a3 3 0 01-3 3m0
|
|
62
|
-
3h.008v.008h-.008v-.008zm0-6h.008v.008h-.008v-.008zm-3
|
|
63
|
-
6h.008v.008h-.008v-.008zm0-6h.008v.008h-.008v-.008z" />
|
|
64
|
-
</svg>
|
|
65
|
-
</SidebarButton>;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function DosboxConfButton(props: { class?: string }) {
|
|
69
|
-
return <SidebarButton
|
|
70
|
-
class={props.class}
|
|
71
|
-
frame="editor-conf"
|
|
72
|
-
action={uiSlice.actions.frameConf()}
|
|
73
|
-
>
|
|
74
|
-
<svg xmlns="http://www.w3.org/2000/svg"
|
|
75
|
-
fill="none" viewBox="0 0 24 24"
|
|
76
|
-
stroke-width="1.5"
|
|
77
|
-
stroke="currentColor"
|
|
78
|
-
class="w-full h-full">
|
|
79
|
-
<path stroke-linecap="round"
|
|
80
|
-
stroke-linejoin="round"
|
|
81
|
-
d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125
|
|
82
|
-
0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5
|
|
83
|
-
3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504
|
|
84
|
-
1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" />
|
|
85
|
-
</svg>
|
|
86
|
-
</SidebarButton>;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export function FsButton(props: {
|
|
90
|
-
class?: string,
|
|
91
|
-
}) {
|
|
92
|
-
return <SidebarButton
|
|
93
|
-
class={props.class}
|
|
94
|
-
frame="editor-fs"
|
|
95
|
-
action={uiSlice.actions.frameFs()}
|
|
96
|
-
>
|
|
97
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none"
|
|
98
|
-
viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-full h-full">
|
|
99
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M21.75 17.25v-.228a4.5 4.5
|
|
100
|
-
0 00-.12-1.03l-2.268-9.64a3.375 3.375 0 00-3.285-2.602H7.923a3.375
|
|
101
|
-
3.375 0 00-3.285 2.602l-2.268 9.64a4.5 4.5 0 00-.12 1.03v.228m19.5 0a3 3
|
|
102
|
-
0 01-3 3H5.25a3 3 0 01-3-3m19.5 0a3 3 0 00-3-3H5.25a3 3 0 00-3 3m16.5
|
|
103
|
-
0h.008v.008h-.008v-.008zm-3 0h.008v.008h-.008v-.008z" />
|
|
104
|
-
</svg>
|
|
105
|
-
</SidebarButton>;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export function CyclesButton() {
|
|
109
|
-
const cycles = Math.round(useSelector((state: State) => state.dos.stats.cyclesPerMs) / 1000);
|
|
110
|
-
return <SidebarButton
|
|
111
|
-
class="cycles"
|
|
112
|
-
frame="stats"
|
|
113
|
-
action={uiSlice.actions.frameStats()}>
|
|
114
|
-
{ cycles <= 0 && <><span>~</span><sup>KC</sup></> }
|
|
115
|
-
{ cycles > 0 && cycles <= 1000 && <><span>{cycles}</span><sup>KC</sup></> }
|
|
116
|
-
{ cycles > 0 && cycles > 1000 && <><span>{Math.round(cycles / 1000)}</span><sup><strong>K</strong>KC</sup></> }
|
|
117
|
-
</SidebarButton>;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export function HddLed(props: {}) {
|
|
121
|
-
const store: Store = useStore();
|
|
122
|
-
const ref = useRef<HTMLDivElement>(null);
|
|
123
|
-
const [state] = useState<{
|
|
124
|
-
recv: number, enabled: boolean, delayLedTo: number,
|
|
125
|
-
}>({ recv: 0, enabled: false, delayLedTo: 0 });
|
|
126
|
-
|
|
127
|
-
useEffect(() => {
|
|
128
|
-
if (ref.current) {
|
|
129
|
-
const el = ref.current;
|
|
130
|
-
el.classList.add("bg-base-300");
|
|
131
|
-
|
|
132
|
-
const id = setInterval(() => {
|
|
133
|
-
if (state.delayLedTo <= Date.now()) {
|
|
134
|
-
const newRecv = store.getState().dos.stats.driveRecv;
|
|
135
|
-
const newEnabled = state.recv !== newRecv;
|
|
136
|
-
if (newEnabled !== state.enabled) {
|
|
137
|
-
el.classList.remove("bg-base-300", "bg-green-300", "animate-led");
|
|
138
|
-
if (newEnabled) {
|
|
139
|
-
el.classList.add("bg-green-300", "animate-led");
|
|
140
|
-
} else {
|
|
141
|
-
el.classList.add("bg-base-300");
|
|
142
|
-
}
|
|
143
|
-
state.enabled = newEnabled;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (newEnabled) {
|
|
147
|
-
state.delayLedTo = Date.now() + 300 + Math.random() * 1500;
|
|
148
|
-
} else {
|
|
149
|
-
state.delayLedTo = 0;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
state.recv = newRecv;
|
|
153
|
-
}
|
|
154
|
-
}, 150);
|
|
155
|
-
|
|
156
|
-
return () => {
|
|
157
|
-
el.classList.remove("bg-base-300", "bg-green-300", "animate-led");
|
|
158
|
-
clearInterval(id);
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
}, [ref, state]);
|
|
162
|
-
const [on, setOn] = useState<boolean>(false);
|
|
163
|
-
const [off, setOff] = useState<{ recv: number, timeoutId: number | null }>({
|
|
164
|
-
recv: 0,
|
|
165
|
-
timeoutId: null,
|
|
166
|
-
});
|
|
167
|
-
const statsRecv = useSelector((state: State) => state.dos.stats.driveRecv);
|
|
168
|
-
if (off.recv !== statsRecv) {
|
|
169
|
-
if (!on) {
|
|
170
|
-
setOn(true);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
if (off.timeoutId) {
|
|
174
|
-
clearTimeout(off.timeoutId);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const id = setTimeout(() => {
|
|
178
|
-
setOn(false);
|
|
179
|
-
setOff({
|
|
180
|
-
recv: statsRecv,
|
|
181
|
-
timeoutId: null,
|
|
182
|
-
});
|
|
183
|
-
}, 1000);
|
|
184
|
-
|
|
185
|
-
setOff({
|
|
186
|
-
recv: statsRecv,
|
|
187
|
-
timeoutId: id,
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
return <div ref={ref} class="self-end mr-2 -mt-3 w-2 h-1"></div>;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
export function SettingsButton(props: {
|
|
194
|
-
class?: string,
|
|
195
|
-
}) {
|
|
196
|
-
return <SidebarButton
|
|
197
|
-
class={props.class}
|
|
198
|
-
action={uiSlice.actions.frameSettings()}
|
|
199
|
-
frame="settings">
|
|
200
|
-
|
|
201
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none"
|
|
202
|
-
viewBox="0 0 24 24" stroke-width="1.5"
|
|
203
|
-
stroke="currentColor" class="w-full h-full">
|
|
204
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55
|
|
205
|
-
0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257
|
|
206
|
-
1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26
|
|
207
|
-
1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010
|
|
208
|
-
.255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298
|
|
209
|
-
2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0
|
|
210
|
-
01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55
|
|
211
|
-
0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0
|
|
212
|
-
01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0
|
|
213
|
-
01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932
|
|
214
|
-
6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0
|
|
215
|
-
01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072
|
|
216
|
-
1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z" />
|
|
217
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
|
218
|
-
</svg>
|
|
219
|
-
|
|
220
|
-
</SidebarButton >;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
export function SidebarButton(props: {
|
|
224
|
-
class?: string,
|
|
225
|
-
frame: Frame,
|
|
226
|
-
action: AnyAction,
|
|
227
|
-
children: any
|
|
228
|
-
}) {
|
|
229
|
-
const hightlight = useSelector((state: State) => state.ui.frame) === props.frame;
|
|
230
|
-
const dispatch = useDispatch();
|
|
231
|
-
|
|
232
|
-
function onClick() {
|
|
233
|
-
if (hightlight) {
|
|
234
|
-
dispatch(uiSlice.actions.frameNone());
|
|
235
|
-
} else {
|
|
236
|
-
dispatch(props.action);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
return <div class={"sidebar-button " + (hightlight ? "sidebar-highlight " : "") +
|
|
241
|
-
props.class} onClick={onClick}>
|
|
242
|
-
{props.children}
|
|
243
|
-
</div>;
|
|
244
|
-
}
|
package/src/sidebar/sidebar.css
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
.jsdos-rso {
|
|
2
|
-
.sidebar {
|
|
3
|
-
@apply absolute left-0 top-0 h-full flex flex-col items-center py-2 z-10;
|
|
4
|
-
background: linear-gradient(90deg, hsl(var(--b3)) 0%, hsl(var(--b2)) 100%);
|
|
5
|
-
width: var(--sidebar-width);
|
|
6
|
-
|
|
7
|
-
.contentbar {
|
|
8
|
-
@apply flex-grow;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
.sidebar-badge {
|
|
12
|
-
@apply absolute right-0 bottom-0 w-3 h-3 rounded-full animate-pulse;
|
|
13
|
-
background-color: hsl(var(--p));
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
.cycles {
|
|
17
|
-
@apply text-xs overflow-hidden text-right w-full pr-2 mt-1 -mb-2 whitespace-nowrap opacity-50;
|
|
18
|
-
color: hsl(var(--bc));
|
|
19
|
-
|
|
20
|
-
&.higlight,
|
|
21
|
-
&:hover {
|
|
22
|
-
color: hsl(var(--af));
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
.network-button {
|
|
27
|
-
&.inactive {
|
|
28
|
-
@apply opacity-50;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
.sidebar-button {
|
|
34
|
-
@apply cursor-pointer h-8 w-8 my-2 relative;
|
|
35
|
-
color: hsl(var(--bc));
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.sidebar-highlight,
|
|
39
|
-
.sidebar-button:hover {
|
|
40
|
-
color: hsl(var(--af));
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.animate-led {
|
|
44
|
-
animation: pulse 300ms cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
}
|
package/src/sidebar/sidebar.tsx
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { useSelector } from "react-redux";
|
|
2
|
-
import { State } from "../store";
|
|
3
|
-
import { AccountButton } from "./account-button";
|
|
4
|
-
import { FullscreenButton } from "./fullscreen-button";
|
|
5
|
-
import { NetworkButton } from "./network-button";
|
|
6
|
-
import { CloudSaveButton } from "./cloud-save-button";
|
|
7
|
-
import { DosboxConfButton, SettingsButton, CyclesButton, FsButton,
|
|
8
|
-
FatDrivesButton, QuickSaveButton, ImageRenderingButton, HddLed } from "./sidebar-button";
|
|
9
|
-
|
|
10
|
-
export function SideBar(props: {}) {
|
|
11
|
-
const window = useSelector((state: State) => state.ui.window);
|
|
12
|
-
const editor = useSelector((state: State) => state.ui.editor);
|
|
13
|
-
const backend = useSelector((state: State) => state.dos.backend);
|
|
14
|
-
|
|
15
|
-
return <div class="sidebar">
|
|
16
|
-
{window === "run" && backend === "dosbox" && <CloudSaveButton />}
|
|
17
|
-
{window === "run" && backend === "dosboxX" && <QuickSaveButton />}
|
|
18
|
-
{window === "run" && <ImageRenderingButton />}
|
|
19
|
-
{window === "run" && <NetworkButton />}
|
|
20
|
-
{editor && window === "prerun" && <DosboxConfButton />}
|
|
21
|
-
{editor && window === "prerun" && backend === "dosboxX" && <FatDrivesButton />}
|
|
22
|
-
{editor && window === "run" && <FsButton />}
|
|
23
|
-
<div class="contentbar"></div>
|
|
24
|
-
{window === "run" && <FullscreenButton />}
|
|
25
|
-
{window === "run" && <CyclesButton />}
|
|
26
|
-
{window === "run" && <HddLed />}
|
|
27
|
-
{(window === "prerun" || window === "run") && <SettingsButton />}
|
|
28
|
-
{window !== "run" && <AccountButton />}
|
|
29
|
-
</div>;
|
|
30
|
-
};
|