diff --git a/PackageSources/js-bundle/package.json b/PackageSources/js-bundle/package.json index 7b44a5c..276852b 100644 --- a/PackageSources/js-bundle/package.json +++ b/PackageSources/js-bundle/package.json @@ -7,7 +7,7 @@ "scripts": { "types": "rimraf __generated__ && typed-scss-modules ./src --nameFormat none --exportType default --outputFolder __generated__", "lint": "eslint ./src", - "licenses": "license-report --output=markdown > ./src/assets/licenses_node.md", + "licenses": "license-report --output=markdown > ./src/assets/licenses_node.md && dotnet-project-licenses -i ../converter > ../js-bundle/src/assets/licenses_nuget.md", "debugger": "cd \"%MSFS_SDK%\\Tools\\CoherentGT Debugger\" && Debugger.exe", "locale": "cd \"%MSFS_SDK%\\Tools\\MSFS_Localization\" && MSFSLocalizationManager.exe", "dev": "npx rollup -c -w", diff --git a/PackageSources/js-bundle/src/assets/licenses_node.md b/PackageSources/js-bundle/src/assets/licenses_node.md index 8e82821..f64681a 100644 --- a/PackageSources/js-bundle/src/assets/licenses_node.md +++ b/PackageSources/js-bundle/src/assets/licenses_node.md @@ -14,14 +14,14 @@ | kessler | stuff | @rollup/plugin-node-resolve | perpetual | material | MIT | git+https://github.com/rollup/plugins.git | 15.2.3 | 15.2.3 | ^15.1.0 | Rich Harris | | kessler | stuff | @rollup/plugin-terser | perpetual | material | MIT | git+https://github.com/rollup/plugins.git | 0.4.4 | 0.4.4 | ^0.4.3 | Peter Placzek | | kessler | stuff | @rollup/plugin-typescript | perpetual | material | MIT | git+https://github.com/rollup/plugins.git | 11.1.5 | 11.1.5 | ^11.1.1 | Oskar Segersvärd | -| kessler | stuff | @types/react | perpetual | material | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 18.2.37 | 18.2.37 | ^18.2.8 | n/a | -| kessler | stuff | @types/react-dom | perpetual | material | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 18.2.15 | 18.2.15 | ^18.2.4 | n/a | +| kessler | stuff | @types/react | perpetual | material | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 18.2.38 | 18.2.37 | ^18.2.8 | n/a | +| kessler | stuff | @types/react-dom | perpetual | material | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 18.2.17 | 18.2.15 | ^18.2.4 | n/a | | kessler | stuff | @types/uuid | perpetual | material | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped.git | 9.0.7 | 9.0.7 | ^9.0.7 | n/a | -| kessler | stuff | @typescript-eslint/eslint-plugin | perpetual | material | MIT | git+https://github.com/typescript-eslint/typescript-eslint.git | 6.11.0 | 6.11.0 | ^6.10.0 | n/a | -| kessler | stuff | @typescript-eslint/parser | perpetual | material | BSD-2-Clause | git+https://github.com/typescript-eslint/typescript-eslint.git | 6.11.0 | 6.11.0 | ^6.10.0 | n/a | +| kessler | stuff | @typescript-eslint/eslint-plugin | perpetual | material | MIT | git+https://github.com/typescript-eslint/typescript-eslint.git | 6.12.0 | 6.11.0 | ^6.10.0 | n/a | +| kessler | stuff | @typescript-eslint/parser | perpetual | material | BSD-2-Clause | git+https://github.com/typescript-eslint/typescript-eslint.git | 6.12.0 | 6.11.0 | ^6.10.0 | n/a | | kessler | stuff | autoprefixer | perpetual | material | MIT | git+https://github.com/postcss/autoprefixer.git | 10.4.16 | 10.4.16 | ^10.4.14 | Andrey Sitnik | | kessler | stuff | cross-env | perpetual | material | MIT | git+https://github.com/kentcdodds/cross-env.git | 7.0.3 | 7.0.3 | ^7.0.3 | Kent C. Dodds (https://kentcdodds.com) | -| kessler | stuff | eslint | perpetual | material | MIT | git+https://github.com/eslint/eslint.git | 8.53.0 | 8.53.0 | ^8.42.0 | Nicholas C. Zakas | +| kessler | stuff | eslint | perpetual | material | MIT | git+https://github.com/eslint/eslint.git | 8.54.0 | 8.53.0 | ^8.42.0 | Nicholas C. Zakas | | kessler | stuff | eslint-plugin-import | perpetual | material | MIT | git+https://github.com/import-js/eslint-plugin-import.git | 2.29.0 | 2.29.0 | ^2.27.5 | Ben Mosher | | kessler | stuff | eslint-plugin-react | perpetual | material | MIT | git+https://github.com/jsx-eslint/eslint-plugin-react.git | 7.33.2 | 7.33.2 | ^7.32.2 | Yannick Croissant | | kessler | stuff | eslint-plugin-react-hooks | perpetual | material | MIT | git+https://github.com/facebook/react.git | 4.6.0 | 4.6.0 | ^4.6.0 | n/a | @@ -31,7 +31,7 @@ | kessler | stuff | prettier | perpetual | material | MIT | git+https://github.com/prettier/prettier.git | 3.1.0 | 3.1.0 | ^3.0.3 | James Long | | kessler | stuff | prettier-plugin-organize-imports | perpetual | material | MIT | git+https://github.com/simonhaenisch/prettier-plugin-organize-imports.git | 3.2.4 | 3.2.4 | ^3.2.4 | Simon Haenisch (https://github.com/simonhaenisch) | | kessler | stuff | rimraf | perpetual | material | ISC | git://github.com/isaacs/rimraf.git | 5.0.5 | 5.0.5 | ^5.0.1 | Isaac Z. Schlueter (http://blog.izs.me/) | -| kessler | stuff | rollup | perpetual | material | MIT | git+https://github.com/rollup/rollup.git | 4.4.1 | 4.4.1 | ^4.3.1 | Rich Harris | +| kessler | stuff | rollup | perpetual | material | MIT | git+https://github.com/rollup/rollup.git | 4.5.1 | 4.4.1 | ^4.3.1 | Rich Harris | | kessler | stuff | rollup-plugin-copy | perpetual | material | MIT | git+https://github.com/vladshcherbin/rollup-plugin-copy.git | 3.5.0 | 3.5.0 | ^3.4.0 | Vlad Shcherbin | | kessler | stuff | rollup-plugin-postcss | perpetual | material | MIT | git+https://github.com/egoist/rollup-plugin-postcss.git | 4.0.2 | 4.0.2 | ^4.0.2 | EGOIST <0x142857@gmail.com> | | kessler | stuff | rollup-plugin-react-svg | perpetual | material | MIT | git+https://github.com/boopathi/react-svg-loader.git | 3.0.3 | 3.0.3 | ^3.0.3 | boopathi | diff --git a/PackageSources/js-bundle/src/assets/licenses_nuget.md b/PackageSources/js-bundle/src/assets/licenses_nuget.md new file mode 100644 index 0000000..5b28e28 --- /dev/null +++ b/PackageSources/js-bundle/src/assets/licenses_nuget.md @@ -0,0 +1,4 @@ +| Reference | Version | License Type | License | +| --------------------- | ------- | ------------ | ------------------------------ | +| Docnet.Core | 2.6.0 | MIT | https://licenses.nuget.org/MIT | +| System.Drawing.Common | 8.0.0 | MIT | https://licenses.nuget.org/MIT | diff --git a/PackageSources/js-bundle/src/constants.ts b/PackageSources/js-bundle/src/constants.ts index ce3c216..688f2d0 100644 --- a/PackageSources/js-bundle/src/constants.ts +++ b/PackageSources/js-bundle/src/constants.ts @@ -2,3 +2,4 @@ export const COMMANDS = 'KHOFMANN_PDF_READER_COMMANDS'; export const DATA = 'KHOFMANN_PDF_READER_DATA'; export const LIST = 'LIST'; export const LOAD = 'LOAD'; +export const MAX_LIST = 10; diff --git a/PackageSources/js-bundle/src/contexts/DataContext.tsx b/PackageSources/js-bundle/src/contexts/DataContext.tsx index 325ec96..a797066 100644 --- a/PackageSources/js-bundle/src/contexts/DataContext.tsx +++ b/PackageSources/js-bundle/src/contexts/DataContext.tsx @@ -3,9 +3,10 @@ import { COMMANDS, DATA, LIST, LOAD } from '../constants'; interface IDataContext { list?: IList[]; + dirCount?: number; file?: string; isLoading?: boolean; - refresh?: (path?: string) => void; + refresh?: (path?: string, offset?: number) => void; load?: (path: string) => void; } @@ -20,10 +21,10 @@ export interface IList { export const DataContext = createContext({}); export const useData = () => { - const { list, file, isLoading, refresh, load } = useContext(DataContext); + const { list, dirCount, file, isLoading, refresh, load } = useContext(DataContext); - if (list !== undefined && file !== undefined && isLoading !== undefined && refresh && load) - return { list, file, isLoading, refresh, load }; + if (list !== undefined && dirCount !== undefined && file !== undefined && isLoading !== undefined && refresh && load) + return { list, dirCount, file, isLoading, refresh, load }; else throw new Error("Couldn't find context. Is your component inside a DataProvider?"); }; @@ -33,6 +34,7 @@ interface IDataContextProps { const DataContextProvider: FC> = ({ dataListener, children }) => { const [list, setList] = useState([]); + const [dirCount, setDirCount] = useState(0); const [file, setFile] = useState(''); const [isLoading, setIsLoading] = useState(true); @@ -49,6 +51,7 @@ const DataContextProvider: FC> = ({ dataLis const json = JSON.parse(args); switch (json.id) { case LIST: + setDirCount(json.count); setList(json.data); window.dispatchEvent(new Event('resize')); break; @@ -63,9 +66,9 @@ const DataContextProvider: FC> = ({ dataLis setIsLoading(false); }, []); - const refresh = (path = '') => { + const refresh = (path = '', offset = 0) => { setIsLoading(true); - dataListener.call('COMM_BUS_WASM_CALLBACK', COMMANDS, JSON.stringify({ cmd: LIST, path })); + dataListener.call('COMM_BUS_WASM_CALLBACK', COMMANDS, JSON.stringify({ cmd: LIST, path, offset })); }; const load = (path: string) => { @@ -73,7 +76,9 @@ const DataContextProvider: FC> = ({ dataLis dataListener.call('COMM_BUS_WASM_CALLBACK', COMMANDS, JSON.stringify({ cmd: LOAD, file: path })); }; - return {children}; + return ( + {children} + ); }; export default DataContextProvider; diff --git a/PackageSources/js-bundle/src/pages/ListPage/ListPage.tsx b/PackageSources/js-bundle/src/pages/ListPage/ListPage.tsx index 0331015..abd6c82 100644 --- a/PackageSources/js-bundle/src/pages/ListPage/ListPage.tsx +++ b/PackageSources/js-bundle/src/pages/ListPage/ListPage.tsx @@ -1,17 +1,30 @@ import BackIcon from '@mui/icons-material/ArrowBack'; +import NavigateBeforeIcon from '@mui/icons-material/NavigateBefore'; import NavigateNextIcon from '@mui/icons-material/NavigateNext'; import ReplayIcon from '@mui/icons-material/Replay'; -import { AppBar, Backdrop, Box, Button, Grid, Stack, Toolbar, Typography } from '@mui/material'; -import { FC, useState } from 'react'; +import { AppBar, Backdrop, Box, Button, Grid, Stack, TextField, Toolbar, Typography } from '@mui/material'; +import { FC, useRef, useState } from 'react'; +import { v4 } from 'uuid'; +import { MAX_LIST } from '../../constants'; import { useData } from '../../contexts/DataContext'; import { useRouter } from '../../routers/Router'; +const getPages = (dirCount: number) => { + const int = Math.floor(dirCount / MAX_LIST); + const rem = dirCount & MAX_LIST; + return rem === 0 && int > 0 ? int - 1 : int; +}; + const ListPage: FC = () => { const { navigate, getProps } = useRouter(); - const { list, isLoading, refresh } = useData(); + const { list, dirCount, isLoading, refresh } = useData(); const { path: _path } = getProps() as { path: string }; + const guid = useRef(v4()); + const [path, setPath] = useState(_path ?? '/'); + const [offset, setOffset] = useState([0]); + const [pageJump, setPageJump] = useState('1'); return ( @@ -25,7 +38,11 @@ const ListPage: FC = () => { setPath((prev) => { let newPath = prev.split('/').slice(0, -2).join('/') + '/'; if (newPath === '/') newPath = '/'; - refresh(newPath); + setOffset((prev) => { + const _offset = prev.pop(); + refresh(newPath, _offset); + return [...prev]; + }); return newPath; }); }} @@ -34,16 +51,91 @@ const ListPage: FC = () => { Back - + {path.split('/').slice(-2, -1)} ) : ( - + Files )} - + + + {offset.slice(-1)[0] / MAX_LIST + 1}/{getPages(dirCount) + 1} + + + diff --git a/PackageSources/js-bundle/src/pages/PDFPage/PDFPage.tsx b/PackageSources/js-bundle/src/pages/PDFPage/PDFPage.tsx index cc21362..082bb19 100644 --- a/PackageSources/js-bundle/src/pages/PDFPage/PDFPage.tsx +++ b/PackageSources/js-bundle/src/pages/PDFPage/PDFPage.tsx @@ -13,6 +13,7 @@ const PDFPage: FC = () => { const { file, isLoading, load } = useData(); const guid = useRef(v4()); + const [currentPage, setCurrentPage] = useState(1); const [pageJump, setPageJump] = useState('1'); diff --git a/PackageSources/module/Constants.h b/PackageSources/module/Constants.h index 1403a75..9ad6b95 100644 --- a/PackageSources/module/Constants.h +++ b/PackageSources/module/Constants.h @@ -2,4 +2,5 @@ #define PACKAGE_DIR "/work/Files/" #define COMMANDS "KHOFMANN_PDF_READER_COMMANDS" -#define DATA "KHOFMANN_PDF_READER_DATA" \ No newline at end of file +#define DATA "KHOFMANN_PDF_READER_DATA" +#define MAX_LIST 10 \ No newline at end of file diff --git a/PackageSources/module/FileSystem.hpp b/PackageSources/module/FileSystem.hpp index 52b9341..a2c50a9 100644 --- a/PackageSources/module/FileSystem.hpp +++ b/PackageSources/module/FileSystem.hpp @@ -3,6 +3,7 @@ #include #include +#include #include "rapidjson/document.h" @@ -13,6 +14,16 @@ namespace khofmann { + /// + /// Exclude . and .. directory + /// + /// Entry to check + /// TRUE if not . or .., FALSE otherwise + static int excludeDotDirs(const struct dirent* entry) + { + return strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0; + } + /// /// Read a file and return file contents /// @@ -42,26 +53,30 @@ namespace khofmann /// Return tumbnail as BASE64 and page count if present. /// /// Path of directory + /// Pointer to files value object /// Allocator - /// List of Files - static rapidjson::Value enumerateDir(const char* path, rapidjson::Document::AllocatorType& alloc) + /// Offset into file list + /// Total numbers of directories + static int enumerateDir(const char* path, rapidjson::Value *files, rapidjson::Document::AllocatorType& alloc, int offset) { - rapidjson::Value files; - files.SetArray(); - int count = 0; + int numDirs = 0; - DIR* d; - struct dirent* dir; - d = opendir(path); + DIR* d = opendir(path); if (d) { - while ((dir = readdir(d)) != NULL) + struct dirent **dir; + numDirs = scandir(path, &dir, excludeDotDirs, alphasort); + if (numDirs == -1) { - if (strcmp(dir->d_name, ".") && strcmp(dir->d_name, "..")) + log(stdout, "Error: %i", (void*)errno); + } + for (int i = 0; i < numDirs; i++) + { + if (i >= offset && i < offset + MAX_LIST) { std::string dirPath(path); - dirPath += dir->d_name; + dirPath += dir[i]->d_name; std::string thumb(dirPath); thumb += "/thumb.bjpg"; FILE* check = fopen(thumb.c_str(), "r"); @@ -73,7 +88,7 @@ namespace khofmann f = opendir(dirPath.c_str()); if (f) { - log(stdout, "Found file %s\n", dir->d_name); + log(stdout, "Found file %s\n", dir[i]->d_name); while ((file = readdir(f)) != NULL) { if (file->d_type == DT_REG) @@ -83,29 +98,31 @@ namespace khofmann } rapidjson::Value entry; entry.SetObject(); - entry.AddMember("name", rapidjson::Value(dir->d_name, alloc).Move(), alloc); + entry.AddMember("name", rapidjson::Value(dir[i]->d_name, alloc).Move(), alloc); entry.AddMember("pages", count - 1, alloc); entry.AddMember("thumb", readFile(thumb.c_str(), alloc).Move(), alloc); entry.AddMember("type", "file", alloc); - files.PushBack(entry.Move(), alloc); + files->PushBack(entry.Move(), alloc); } closedir(f); } else { - log(stdout, "Found directory %s\n", dir->d_name); + log(stdout, "Found directory %s\n", dir[i]->d_name); rapidjson::Value entry; entry.SetObject(); - entry.AddMember("name", rapidjson::Value(dir->d_name, alloc).Move(), alloc); + entry.AddMember("name", rapidjson::Value(dir[i]->d_name, alloc).Move(), alloc); entry.AddMember("type", "directory", alloc); - files.PushBack(entry.Move(), alloc); + files->PushBack(entry.Move(), alloc); } } + free(dir[i]->d_name); } + free(dir); } closedir(d); - return files; + return numDirs; } } \ No newline at end of file diff --git a/PackageSources/module/Module.cpp b/PackageSources/module/Module.cpp index 937f5dc..e3a9dc6 100644 --- a/PackageSources/module/Module.cpp +++ b/PackageSources/module/Module.cpp @@ -63,6 +63,8 @@ extern "C" if (strcmp(cmd, "LIST") == 0) { + int offset = inDoc["offset"].GetInt(); + std::string path; path += PACKAGE_DIR; path += inDoc["path"].GetString(); @@ -73,7 +75,11 @@ extern "C" outDoc.SetObject(); outDoc.AddMember("id", "LIST", allocator); - outDoc.AddMember("data", khofmann::enumerateDir(path.c_str(), allocator).Move(), allocator); + rapidjson::Value files; + files.SetArray(); + int numDirs = khofmann::enumerateDir(path.c_str(), &files, allocator, offset); + outDoc.AddMember("count", numDirs, allocator); + outDoc.AddMember("data", files.Move(), allocator); rapidjson::StringBuffer strbuf; rapidjson::Writer writer(strbuf);