diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index b9e97eb9..d644d87b 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -31,9 +31,10 @@ jobs:
- run: yarn run eslint . --ext ts,tsx --max-warnings 0
- run: mkdir -p public/emulators && cp -rv node_modules/emulators/dist/* public/emulators
- run: NODE_ENV=production yarn run vite build --base /latest --sourcemap true --minify terser
+ - run: zip -9r release.zip dist/*
- name: publish
if: startsWith(github.ref, 'refs/tags/')
- run: npm publish --tag beta
+ run: npm publish
env:
NODE_AUTH_TOKEN: ${{secrets.NODE_AUTH_TOKEN}}
- name: upload
@@ -41,3 +42,10 @@ jobs:
with:
name: 'dist'
path: 'dist'
+ - name: Release
+ uses: softprops/action-gh-release@v2
+ if: startsWith(github.ref, 'refs/tags/')
+ with:
+ name: ${{ github.ref_name }}
+ files: |
+ ${{github.workspace}}/release.zip
diff --git a/package.json b/package.json
index f165fae3..b2d44898 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "js-dos",
- "version": "0.80.26",
+ "version": "8.1.0",
"description": "Full-featured DOS player with multiple emulator backends",
"type": "module",
"keywords": [
@@ -35,7 +35,7 @@
"@typescript-eslint/parser": "^6.20.0",
"autoprefixer": "^10.4.17",
"daisyui": "^3.9.3",
- "emulators": "8.1.1",
+ "emulators": "8.1.2",
"eslint": "^8.56.0",
"eslint-config-google": "^0.14.0",
"postcss": "^8.4.33",
diff --git a/src/i18n.ts b/src/i18n.ts
index 4bd96725..ffbb58e3 100644
--- a/src/i18n.ts
+++ b/src/i18n.ts
@@ -4,6 +4,7 @@ import { State } from "./store";
const translations: {[lang: string]: {[key: string]: string} } = {
ru: {
+ preloading_sockdrive: "Загрузка FAT",
filter: "Фильтр",
add: "Добавить",
logout: "Выйти",
@@ -74,6 +75,7 @@ const translations: {[lang: string]: {[key: string]: string} } = {
fat_write: "FAT запись",
},
en: {
+ preloading_sockdrive: "Preloading FAT",
filter: "Filter",
add: "Add",
logout: "Logout",
diff --git a/src/sockdrive b/src/sockdrive
index bb038ed9..93e786f8 160000
--- a/src/sockdrive
+++ b/src/sockdrive
@@ -1 +1 @@
-Subproject commit bb038ed9a5891b7b11acf09b7fba13a6b4104b32
+Subproject commit 93e786f8aab900872f05530e9aada8a82416d2a9
diff --git a/src/store/ui.ts b/src/store/ui.ts
index 7da6642f..0b8e83d8 100644
--- a/src/store/ui.ts
+++ b/src/store/ui.ts
@@ -116,7 +116,8 @@ export const uiSlice = createSlice({
setFullScreen: (state, a: { payload: boolean }) => {
state.fullScreen = a.payload;
},
- showToast: (state, a: { payload: { message: string, intent?: typeof initialState.toastIntent } }) => {
+ showToast: (state, a: { payload: { message: string, intent?: typeof initialState.toastIntent,
+ long?: boolean } }) => {
if (state.toastTimeoutId !== 0) {
clearInterval(state.toastTimeoutId);
}
@@ -125,7 +126,7 @@ export const uiSlice = createSlice({
if (a.payload.intent !== "panic") {
state.toastTimeoutId = setTimeout(() => {
(a as unknown as DosAction).asyncStore((store) => store.dispatch(uiSlice.actions.hideToast()));
- }, 1500);
+ }, a.payload.long ? 5000 : 1500);
}
},
hideToast: (state) => {
diff --git a/src/ui.tsx b/src/ui.tsx
index f18426da..7f940ba2 100644
--- a/src/ui.tsx
+++ b/src/ui.tsx
@@ -55,12 +55,13 @@ export function Ui() {
function Toast() {
const toast = useSelector((state: State) => state.ui.toast);
const intent = useSelector((state: State) => state.ui.toastIntent);
+ const readOnlyWarning = useSelector((state: State) => state.ui.readOnlyWarning);
if (toast === null) {
return null;
}
- return
+ return
{toast}
diff --git a/src/window/dos/dos-runtime.tsx b/src/window/dos/dos-runtime.tsx
index 8f20d81b..0a395c2c 100644
--- a/src/window/dos/dos-runtime.tsx
+++ b/src/window/dos/dos-runtime.tsx
@@ -10,6 +10,7 @@ import { useEffect } from "preact/hooks";
import { mouse } from "./controls/mouse";
import { KBD_0 } from "./controls/keys";
import { uiSlice } from "../../store/ui";
+import { useT } from "../../i18n";
export function useDosRuntime(canvas: HTMLCanvasElement,
ci: CommandInterface): void {
@@ -25,19 +26,44 @@ export function useDosRuntime(canvas: HTMLCanvasElement,
function useLog(ci: CommandInterface): void {
const dispatch = useDispatch();
+ const t = useT();
useEffect(() => {
- ci.events().onMessage((msgType, ...args) => {
+ let totalPreload = 0;
+ const preloadProgress: { [drive: string]: number } = {};
+ ci.events().onMessage((msgType, ...args: string[]) => {
if (msgType === "error" && args[0]?.startsWith("[panic]")) {
dispatch(uiSlice.actions.showToast({
message: args[0],
intent: "panic",
}));
} else if (msgType === "log" && args[0]?.indexOf("sockdrive:") !== -1) {
+ const drive = args[0].substring(args[0].indexOf(" ") + 1, args[0].indexOf(","));
dispatch(uiSlice.actions.cloudSaves(false));
if (args[0]?.indexOf("write=false") !== -1) {
+ console.log("drive", drive, "config:", args[0]);
dispatch(uiSlice.actions.readOnlyWarning(true));
}
- console.log(...args);
+ if (args[0]?.indexOf("preload=") !== -1) {
+ const rest = Number.parseInt(args[0].substring(args[0].indexOf("preload=") + "preload=".length));
+ if (preloadProgress[drive] === undefined) {
+ preloadProgress[drive] = rest;
+ totalPreload += rest;
+ } else {
+ preloadProgress[drive] = rest;
+ }
+
+ let downloaded = totalPreload;
+ for (const rest of Object.values(preloadProgress)) {
+ downloaded -= rest;
+ }
+
+ dispatch(uiSlice.actions.showToast({
+ message: t("preloading_sockdrive") + " " +
+ (Math.round(downloaded / 1024 / 1024 * 100) / 100) + "/" +
+ (Math.round(totalPreload / 1024 / 1024 * 100) / 100) + "Mb",
+ long: true,
+ }));
+ }
}
});
}, [ci, dispatch]);
diff --git a/src/ws/ws-sockdrive.ts b/src/ws/ws-sockdrive.ts
index 373c639d..50bad558 100644
--- a/src/ws/ws-sockdrive.ts
+++ b/src/ws/ws-sockdrive.ts
@@ -51,8 +51,7 @@ export function createSockdrive(
const sectorSize = templates[seq].sectorSize;
memory[seq] = new Uint8Array(sectorSize + sectorSize * aheadRange);
- mapping[seq] = new Drive(url, owner, name, token, stats,
- { HEAPU8: memory[seq] }, sectorSize, aheadRange, sectorSize, 1); // cache is on server
+ mapping[seq] = new Drive(url, owner, name, token, stats, { HEAPU8: memory[seq] });
mapping[seq].onOpen((read, write) => {
onOpen(owner + "/" + name, read, write);
});
diff --git a/yarn.lock b/yarn.lock
index 5de9160d..d0e72704 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1154,10 +1154,10 @@ electron-to-chromium@^1.4.648:
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.653.tgz#832ab25e80ad698ac09c1ca547bd9ee6cce7df10"
integrity sha512-wA2A2LQCqnEwQAvwADQq3KpMpNwgAUBnRmrFgRzHnPhbQUFArTR32Ab46f4p0MovDLcg4uqd4nCsN2hTltslpA==
-emulators@8.1.1:
- version "8.1.1"
- resolved "https://registry.yarnpkg.com/emulators/-/emulators-8.1.1.tgz#69d9e42e5590b6dbd5db7ab90ae412d8bbc5bc8f"
- integrity sha512-OHR/vuE3yDMRmmgtPhAxZwh/MuCkae3wnoaskuT0EvXRe7iJC5GPzZr5PtHT7VVt9oTdbvMppXqRc1kN0olynA==
+emulators@8.1.2:
+ version "8.1.2"
+ resolved "https://registry.yarnpkg.com/emulators/-/emulators-8.1.2.tgz#15dfc1045f0b05ccda70a49be59ae435db5f15ea"
+ integrity sha512-1cagI2XUN8b3TixCyERjr+wRWfcnM5a00i8ZM20kRhZp4zfvNo/CNgAyyJS9xxW5DGpNct9iTAVYCND7oZK9ZQ==
entities@^4.2.0:
version "4.5.0"