diff --git a/PackageSources/js-bundle/index.d.ts b/PackageSources/js-bundle/index.d.ts index 87136a1..d5177ea 100644 --- a/PackageSources/js-bundle/index.d.ts +++ b/PackageSources/js-bundle/index.d.ts @@ -1,6 +1 @@ /// -/// -/// -/// -/// -/// diff --git a/PackageSources/js-bundle/src/constants.ts b/PackageSources/js-bundle/src/constants.ts index 688f2d0..a611adc 100644 --- a/PackageSources/js-bundle/src/constants.ts +++ b/PackageSources/js-bundle/src/constants.ts @@ -2,4 +2,5 @@ export const COMMANDS = 'KHOFMANN_PDF_READER_COMMANDS'; export const DATA = 'KHOFMANN_PDF_READER_DATA'; export const LIST = 'LIST'; export const LOAD = 'LOAD'; +export const SAVE = 'SAVE'; export const MAX_LIST = 10; diff --git a/PackageSources/js-bundle/src/contexts/DataContext.tsx b/PackageSources/js-bundle/src/contexts/DataContext.tsx index 8a498b6..8a76e30 100644 --- a/PackageSources/js-bundle/src/contexts/DataContext.tsx +++ b/PackageSources/js-bundle/src/contexts/DataContext.tsx @@ -1,12 +1,26 @@ import { FC, PropsWithChildren, createContext, useCallback, useContext, useEffect, useState } from 'react'; -import { COMMANDS, DATA, LIST, LOAD } from '../constants'; +import { COMMANDS, DATA, LIST, LOAD, SAVE } from '../constants'; interface IDataContext { list?: IList[]; file?: string; + bookMarks?: IBookMark[]; isLoading?: boolean; + isSaving?: boolean; refresh?: (path?: string) => void; load?: (path: string) => void; + addBookMark?: (path: string, bookMarks: IBookMark) => void; + removeBookMark?: (path: string, index: number) => void; +} + +interface IData { + file: string; + bookMarks?: IBookMark[]; +} + +interface IJSONResponse { + id: typeof LIST | typeof LOAD | typeof SAVE; + data: IList[] | IData; } export interface IList { @@ -17,14 +31,43 @@ export interface IList { pages?: number; } +export interface IBookMark { + page: number; + title: string; +} + export const DataContext = createContext({}); export const useData = () => { - const { list, file, isLoading, refresh, load } = useContext(DataContext); + const { list, file, bookMarks, isLoading, isSaving, refresh, load, addBookMark, removeBookMark } = + useContext(DataContext); - if (list !== undefined && file !== undefined && isLoading !== undefined && refresh && load) - return { list, file, isLoading, refresh, load }; - else throw new Error("Couldn't find context. Is your component inside a DataProvider?"); + if ( + list !== undefined && + file !== undefined && + bookMarks !== undefined && + isLoading !== undefined && + isSaving !== undefined && + refresh && + load && + addBookMark && + removeBookMark + ) + return { list, file, bookMarks, isLoading, isSaving, refresh, load, addBookMark, removeBookMark }; + else + throw new Error( + `Couldn't find context. Is your component inside a DataProvider? ${JSON.stringify({ + list: list !== undefined, + file: file !== undefined, + bookMarks: bookMarks !== undefined, + isLoading: isLoading !== undefined, + isSaving: isSaving !== undefined, + refresh: refresh !== undefined, + load: load !== undefined, + addBookMark: addBookMark !== undefined, + removeBookMark: removeBookMark !== undefined, + })}` + ); }; interface IDataContextProps { @@ -34,7 +77,9 @@ interface IDataContextProps { const DataContextProvider: FC> = ({ dataListener, children }) => { const [list, setList] = useState([]); const [file, setFile] = useState(''); + const [bookMarks, setBookMarks] = useState([]); const [isLoading, setIsLoading] = useState(true); + const [isSaving, setIsSaving] = useState(false); useEffect(() => { dataListener.on(DATA, dataCallback); @@ -46,17 +91,24 @@ const DataContextProvider: FC> = ({ dataLis const dataCallback = useCallback((args: string) => { try { - const json = JSON.parse(args); + const json: IJSONResponse = JSON.parse(args); + console.log(json); switch (json.id) { case LIST: - setList((json.data as IList[]).sort((a, b) => a.name.localeCompare(b.name))); - window.dispatchEvent(new Event('resize')); + setList((json.data as IList[]).sort((a, b) => a.name.localeCompare(b.name)) ?? []); break; case LOAD: - setFile(json.data); - window.dispatchEvent(new Event('resize')); + const d = json.data as IData; + setFile(d.file); + if (d.bookMarks) { + setBookMarks(d.bookMarks); + } + break; + case SAVE: + setIsSaving(false); break; } + window.dispatchEvent(new Event('resize')); } catch (e) { console.warn(e); } @@ -73,7 +125,36 @@ const DataContextProvider: FC> = ({ dataLis dataListener.call('COMM_BUS_WASM_CALLBACK', COMMANDS, JSON.stringify({ cmd: LOAD, file: path })); }; - return {children}; + const save = (path: string, bookMarks: IBookMark[]) => { + setIsSaving(true); + dataListener.call('COMM_BUS_WASM_CALLBACK', COMMANDS, JSON.stringify({ cmd: SAVE, path, bookMarks: bookMarks })); + }; + + const addBookMark = (path: string, bookMark: IBookMark) => { + setBookMarks((prev) => { + const _new = [...prev, bookMark]; + _new.sort((a, b) => a.page - b.page); + save(path, _new); + return _new; + }); + }; + + const removeBookMark = (path: string, index: number) => { + setBookMarks((prev) => { + prev.splice(index, 1); + prev.sort((a, b) => a.page - b.page); + save(path, prev); + return [...prev]; + }); + }; + + return ( + + {children} + + ); }; export default DataContextProvider; diff --git a/PackageSources/js-bundle/src/contexts/ThemeContext.tsx b/PackageSources/js-bundle/src/contexts/ThemeContext.tsx index 1524e66..d766468 100644 --- a/PackageSources/js-bundle/src/contexts/ThemeContext.tsx +++ b/PackageSources/js-bundle/src/contexts/ThemeContext.tsx @@ -25,7 +25,13 @@ const ThemeProvider: FC = ({ children }) => { main: getComputedStyle(document.documentElement).getPropertyValue('--enabledBackGroundColor').trim(), contrastText: '#fff', }, + secondary: { + main: getComputedStyle(document.documentElement) + .getPropertyValue('--backgroundColorContrastedPanel') + .trim(), + }, }, + screenHeight: Number(getComputedStyle(document.documentElement).getPropertyValue('--screenHeight').trim()), }), [] ); diff --git a/PackageSources/js-bundle/src/pages/ListPage/ListPage.tsx b/PackageSources/js-bundle/src/pages/ListPage/ListPage.tsx index 9bd9cfb..c17ef87 100644 --- a/PackageSources/js-bundle/src/pages/ListPage/ListPage.tsx +++ b/PackageSources/js-bundle/src/pages/ListPage/ListPage.tsx @@ -170,7 +170,9 @@ const ListPage: FC = () => { )} - {entry.name} + + {entry.name} + {entry.type === 'directory' && ( diff --git a/PackageSources/js-bundle/src/pages/PDFPage/PDFPage.tsx b/PackageSources/js-bundle/src/pages/PDFPage/PDFPage.tsx index 979aa2e..cfa6bdf 100644 --- a/PackageSources/js-bundle/src/pages/PDFPage/PDFPage.tsx +++ b/PackageSources/js-bundle/src/pages/PDFPage/PDFPage.tsx @@ -1,7 +1,10 @@ import BackIcon from '@mui/icons-material/ArrowBack'; +import BookmarkIcon from '@mui/icons-material/Bookmark'; +import BookmarkBorderIcon from '@mui/icons-material/BookmarkBorder'; +import DeleteIcon from '@mui/icons-material/Delete'; import NavigateBeforeIcon from '@mui/icons-material/NavigateBefore'; import NavigateNextIcon from '@mui/icons-material/NavigateNext'; -import { AppBar, Backdrop, Box, Button, TextField, Toolbar, Typography } from '@mui/material'; +import { AppBar, Backdrop, Box, Button, Grid, Stack, TextField, Toolbar, Typography } from '@mui/material'; import { FC, useEffect, useRef, useState } from 'react'; import { v4 } from 'uuid'; import { IList, useData } from '../../contexts/DataContext'; @@ -10,17 +13,22 @@ import { useRouter } from '../../routers/Router'; const PDFPage: FC = () => { const { goBack, getProps } = useRouter(); const { path, entry } = getProps() as { path: string; entry: IList }; - const { file, isLoading, load } = useData(); + const { file, bookMarks, isLoading, isSaving, load, addBookMark, removeBookMark } = useData(); - const guid = useRef(v4()); + const guid1 = useRef(v4()); + const guid2 = useRef(v4()); const [currentPage, setCurrentPage] = useState(1); const [pageJump, setPageJump] = useState('1'); + const [drawerOpen, setDrawerOpen] = useState(false); + const [markName, setMarkName] = useState(''); useEffect(() => { load(`${path}/${entry.name}/${currentPage}.bjpg`); }, [currentPage]); + // () => + return ( @@ -41,8 +49,8 @@ const PDFPage: FC = () => { e.stopPropagation(); setPageJump(e.target.value); }} - onFocus={() => Coherent.trigger('FOCUS_INPUT_FIELD', guid, '', '', '', false)} - onBlur={() => Coherent.trigger('UNFOCUS_INPUT_FIELD', guid)} + onFocus={() => Coherent.trigger('FOCUS_INPUT_FIELD', guid1, '', '', '', false)} + onBlur={() => Coherent.trigger('UNFOCUS_INPUT_FIELD', guid1)} /> + {isLoading ? ( @@ -81,6 +96,79 @@ const PDFPage: FC = () => { )} + {drawerOpen && ( + theme.zIndex.drawer + 1 }} + open + onClick={() => setDrawerOpen(false)} + > + e.stopPropagation()}> + + + { + e.stopPropagation(); + setMarkName(e.target.value); + }} + onFocus={() => Coherent.trigger('FOCUS_INPUT_FIELD', guid2, '', '', '', false)} + onBlur={() => Coherent.trigger('UNFOCUS_INPUT_FIELD', guid2)} + /> + + + + + + {bookMarks.map((mark, index) => ( + setCurrentPage(mark.page)} + container + padding={1} + height={73} + > + + + + {mark.title} + + + + + + + + ))} + + + + + )} ); }; diff --git a/PackageSources/js-bundle/src/types/theme.d.ts b/PackageSources/js-bundle/src/types/theme.d.ts new file mode 100644 index 0000000..5e25996 --- /dev/null +++ b/PackageSources/js-bundle/src/types/theme.d.ts @@ -0,0 +1,10 @@ +import '@mui/material'; + +declare module '@mui/material/styles' { + interface Theme { + screenHeight: number; + } + interface ThemeOptions { + screenHeight: number; + } +} diff --git a/PackageSources/js-bundle/src/types/virtual-scroll.d.ts b/PackageSources/js-bundle/src/types/virtual-scroll.d.ts index a8c6789..05a3fa3 100644 --- a/PackageSources/js-bundle/src/types/virtual-scroll.d.ts +++ b/PackageSources/js-bundle/src/types/virtual-scroll.d.ts @@ -1,11 +1,11 @@ -import { DOMAttributes, ReactNode } from 'react'; +import { CSSProperties, DOMAttributes, ReactNode } from 'react'; type CustomElement = Partial & { children: ReactNode }>; declare global { namespace JSX { interface IntrinsicElements { - ['virtual-scroll']: CustomElement<{ class?: string; direction: 'x' | 'y' }>; + ['virtual-scroll']: CustomElement<{ class?: string; direction: 'x' | 'y'; style?: CSSProperties }>; } } } diff --git a/PackageSources/module/Base64.hpp b/PackageSources/module/Base64.hpp deleted file mode 100644 index a8375e0..0000000 --- a/PackageSources/module/Base64.hpp +++ /dev/null @@ -1,71 +0,0 @@ -#pragma once - -/** - * The MIT License (MIT) - * Copyright (c) 2016 tomykaira - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include - -namespace macaron { - class Base64 { - public: - static std::string Encode(const char* data, size_t length) { - static constexpr char sEncodingTable[] = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '+', '/' - }; - - size_t out_len = 4 * ((length + 2) / 3); - std::string ret(out_len, '\0'); - size_t i; - char* p = const_cast(ret.c_str()); - - for (i = 0; i < length - 2; i += 3) { - *p++ = sEncodingTable[(data[i] >> 2) & 0x3F]; - *p++ = sEncodingTable[((data[i] & 0x3) << 4) | ((int)(data[i + 1] & 0xF0) >> 4)]; - *p++ = sEncodingTable[((data[i + 1] & 0xF) << 2) | ((int)(data[i + 2] & 0xC0) >> 6)]; - *p++ = sEncodingTable[data[i + 2] & 0x3F]; - } - if (i < length) { - *p++ = sEncodingTable[(data[i] >> 2) & 0x3F]; - if (i == (length - 1)) { - *p++ = sEncodingTable[((data[i] & 0x3) << 4)]; - *p++ = '='; - } - else { - *p++ = sEncodingTable[((data[i] & 0x3) << 4) | ((int)(data[i + 1] & 0xF0) >> 4)]; - *p++ = sEncodingTable[((data[i + 1] & 0xF) << 2)]; - } - *p++ = '='; - } - - return ret; - } - }; -} \ No newline at end of file diff --git a/PackageSources/module/Constants.h b/PackageSources/module/Constants.h index 9ad6b95..fab839a 100644 --- a/PackageSources/module/Constants.h +++ b/PackageSources/module/Constants.h @@ -1,6 +1,10 @@ #pragma once #define PACKAGE_DIR "/work/Files/" +#define WORK_DIR "/work/BookMarks/" #define COMMANDS "KHOFMANN_PDF_READER_COMMANDS" #define DATA "KHOFMANN_PDF_READER_DATA" -#define MAX_LIST 10 \ No newline at end of file +#define LIST "LIST" +#define LOAD "LOAD" +#define SAVE "SAVE" +#define MAX_LIST 10 diff --git a/PackageSources/module/FileSystem.hpp b/PackageSources/module/FileSystem.cpp similarity index 60% rename from PackageSources/module/FileSystem.hpp rename to PackageSources/module/FileSystem.cpp index 92602c2..a7dfa3b 100644 --- a/PackageSources/module/FileSystem.hpp +++ b/PackageSources/module/FileSystem.cpp @@ -1,28 +1,22 @@ -#pragma once - -#include +#include +#include #include -#include "rapidjson/document.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" -#include "Base64.hpp" -#include "Utils.hpp" +#include "Utils.h" -#include "Constants.h" +#include "FileSystem.h" namespace khofmann { - /// - /// Read a file and return file contents - /// - /// Path of BASE64 encoded File - /// Allocator - /// File contents - static rapidjson::Value readFile(const char* path, rapidjson::Document::AllocatorType& alloc) + rapidjson::Value readFile(const char* path, rapidjson::Document::AllocatorType& alloc) { FILE* file = fopen(path, "r"); - if (file) { + if (file) + { fseek(file, 0, SEEK_END); long fsize = ftell(file); fseek(file, 0, SEEK_SET); @@ -36,17 +30,30 @@ namespace khofmann return retVal; } + int err = errno; + log(stderr, "Error loading file %s: ERRNO %i\n", path, err); return rapidjson::Value("", alloc); } - /// - /// Enumerate a directory and return list of directories. - /// Return tumbnail as BASE64 and page count if present. - /// - /// Path of directory - /// Pointer to files value object + void writeFile(const char* path, rapidjson::Value &contents) + { + rapidjson::StringBuffer strbuf; + rapidjson::Writer writer(strbuf); + contents.Accept(writer); + + FILE* file = fopen(path, "w"); + if (file) + { + fwrite(strbuf.GetString(), sizeof(char), strbuf.GetSize(), file); + fclose(file); + return; + } + int err = errno; + log(stderr, "Error saving file %s: ERRNO %i\n", path, err); + } + /// Allocator - static void enumerateDir(const char* path, rapidjson::Value *files, rapidjson::Document::AllocatorType& alloc) + void enumerateDir(const char* path, rapidjson::Value& files, rapidjson::Document::AllocatorType& alloc) { DIR* d = opendir(path); if (d) @@ -84,7 +91,12 @@ namespace khofmann 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); + } + else + { + int err = errno; + log(stderr, "Could not open directory %s: ERRNO %i\n", dirPath.c_str(), err); } closedir(f); } @@ -96,10 +108,15 @@ namespace khofmann entry.SetObject(); entry.AddMember("name", rapidjson::Value(dir->d_name, alloc).Move(), alloc); entry.AddMember("type", "directory", alloc); - files->PushBack(entry.Move(), alloc); + files.PushBack(entry.Move(), alloc); } } } + else + { + int err = errno; + log(stderr, "Could not open directory %s: ERRNO %i\n", path, err); + } closedir(d); } } \ No newline at end of file diff --git a/PackageSources/module/FileSystem.h b/PackageSources/module/FileSystem.h new file mode 100644 index 0000000..628ac7c --- /dev/null +++ b/PackageSources/module/FileSystem.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include "rapidjson/document.h" + +namespace khofmann +{ + /// + /// Read a file and return file contents + /// + /// Path of BASE64 encoded File + /// Allocator + /// File contents + rapidjson::Value readFile(const char* path, rapidjson::Document::AllocatorType& alloc); + + /// + /// Write a file to disk + /// + /// Path to file + /// Contents of file + /// Length of contents + void writeFile(const char* path, rapidjson::Value& contents); + + /// + /// Enumerate a directory and return list of directories. + /// Return tumbnail as BASE64 and page count if present. + /// + /// Path of directory + /// Pointer to files value object + /// Allocator + void enumerateDir(const char* path, rapidjson::Value& files, rapidjson::Document::AllocatorType& alloc); +} \ No newline at end of file diff --git a/PackageSources/module/Module.cpp b/PackageSources/module/Module.cpp index b78abc6..4bfa829 100644 --- a/PackageSources/module/Module.cpp +++ b/PackageSources/module/Module.cpp @@ -1,55 +1,57 @@ -#include -#include -#include +#include +#include +#include +#include +#include #include #include -#include -#include #include #include #include +#include #include "rapidjson/document.h" #include "rapidjson/stringbuffer.h" #include "rapidjson/writer.h" -#include "FileSystem.hpp" -#include "Utils.hpp" +#include "FileSystem.h" +#include "Utils.h" #include "Constants.h" static void CommandWasmCallback(const char* args, unsigned int size, void* ctx); +static FILE* logFile; extern "C" { MSFS_CALLBACK void module_init(void) { - khofmann::log(stdout, "[PDF-Reader Module] Starting init\n"); + khofmann::log(stdout, "Starting init\n"); khofmann::logFile = fopen("/work/log.txt", "w"); if (khofmann::logFile == NULL) { - khofmann::log(stderr, "[PDF-Reader Module] Error creating logfile\n"); + khofmann::log(stderr, "Error creating logfile\n"); } if (!fsCommBusRegister(COMMANDS, CommandWasmCallback)) { - khofmann::log(stderr, "[PDF-Reader Module] Error registering command CommBus\n"); + khofmann::log(stderr, "Error registering command CommBus\n"); } - khofmann::log(stdout, "[PDF-Reader Module] Inited\n"); + khofmann::log(stdout, "Inited\n"); } extern "C" MSFS_CALLBACK void module_deinit(void) { - khofmann::log(stdout, "[PDF-Reader Module] Starting deinit\n"); + khofmann::log(stdout, "Starting deinit\n"); int c = fsCommBusUnregister(COMMANDS, CommandWasmCallback); khofmann::log(stdout, "%i unregistered", &c); - khofmann::log(stdout, "[PDF-Reader Module] Deinited\n"); + khofmann::log(stdout, "Deinited\n"); fclose(khofmann::logFile); } @@ -61,57 +63,87 @@ extern "C" const char* cmd = inDoc["cmd"].GetString(); - if (strcmp(cmd, "LIST") == 0) + rapidjson::Document outDoc; + rapidjson::Document::AllocatorType& allocator = outDoc.GetAllocator(); + outDoc.SetObject(); + outDoc.AddMember("id", rapidjson::Value(cmd, allocator).Move(), allocator); + + rapidjson::StringBuffer strbuf; + rapidjson::Writer writer(strbuf); + + if (strcmp(cmd, LIST) == 0) { std::string path; path += PACKAGE_DIR; path += inDoc["path"].GetString(); - rapidjson::Document outDoc; - rapidjson::Document::AllocatorType& allocator = outDoc.GetAllocator(); - - outDoc.SetObject(); - outDoc.AddMember("id", "LIST", allocator); - rapidjson::Value files; files.SetArray(); - khofmann::enumerateDir(path.c_str(), &files, allocator); + khofmann::enumerateDir(path.c_str(), files, allocator); outDoc.AddMember("data", files.Move(), allocator); - rapidjson::StringBuffer strbuf; - rapidjson::Writer writer(strbuf); outDoc.Accept(writer); fsCommBusCall(DATA, strbuf.GetString(), strbuf.GetSize(), FsCommBusBroadcast_JS); } - else + else if (strcmp(cmd, LOAD) == 0) { - rapidjson::Document inDoc; - inDoc.Parse(args); + std::string filePath; + filePath += PACKAGE_DIR; + filePath += inDoc["file"].GetString(); - const char* cmd = inDoc["cmd"].GetString(); - - if (strcmp(cmd, "LOAD") == 0) + std::string marksPath; + marksPath += inDoc["file"].GetString(); + size_t lastSlash = marksPath.find_last_of("/"); + if (lastSlash != std::string::npos) { - std::string path; - path += PACKAGE_DIR; - path += inDoc["file"].GetString(); - - khofmann::log(stdout, "Loading file %s\n", (void*)path.c_str()); - - rapidjson::Document outDoc; - rapidjson::Document::AllocatorType& allocator = outDoc.GetAllocator(); - - outDoc.SetObject(); - outDoc.AddMember("id", "LOAD", allocator); - outDoc.AddMember("data", khofmann::readFile(path.c_str(), allocator).Move(), allocator); - - rapidjson::StringBuffer strbuf; - rapidjson::Writer writer(strbuf); - outDoc.Accept(writer); - - fsCommBusCall(DATA, strbuf.GetString(), strbuf.GetSize(), FsCommBusBroadcast_JS); + marksPath.erase(lastSlash); } + marksPath.erase(std::remove(marksPath.begin(), marksPath.end(), '/'), marksPath.end()); + marksPath = WORK_DIR + marksPath + "_bookmarks.json"; + + rapidjson::Value data; + data.SetObject(); + + khofmann::log(stdout, "Loading file %s\n", filePath.c_str()); + data.AddMember("file", khofmann::readFile(filePath.c_str(), allocator).Move(), allocator); + + if (filePath.find("/1.bjpg") != std::string::npos) + { + khofmann::log(stdout, "Loading book marks %s\n", marksPath.c_str()); + rapidjson::Document marks; + marks.Parse(khofmann::readFile(marksPath.c_str(), allocator).GetString()); + if (marks.IsArray()) + { + data.AddMember("bookMarks", marks.Move(), allocator); + } + else + { + rapidjson::Value t; + t.SetArray(); + data.AddMember("bookMarks", t.Move(), allocator); + } + } + + outDoc.AddMember("data", data.Move(), allocator); + + outDoc.Accept(writer); + + fsCommBusCall(DATA, strbuf.GetString(), strbuf.GetSize(), FsCommBusBroadcast_JS); + } + else if (strcmp(cmd, SAVE) == 0) + { + std::string marksPath; + marksPath += inDoc["path"].GetString(); + marksPath.erase(std::remove(marksPath.begin(), marksPath.end(), '/'), marksPath.end()); + marksPath = WORK_DIR + marksPath + "_bookmarks.json"; + + khofmann::log(stdout, "Saving book marks %s\n", marksPath.c_str()); + khofmann::writeFile(marksPath.c_str(), inDoc["bookMarks"]); + + outDoc.Accept(writer); + + fsCommBusCall(DATA, strbuf.GetString(), strbuf.GetSize(), FsCommBusBroadcast_JS); } } } diff --git a/PackageSources/module/PDF-Reader.vcxproj b/PackageSources/module/PDF-Reader.vcxproj index a854c79..d9ccb6c 100644 --- a/PackageSources/module/PDF-Reader.vcxproj +++ b/PackageSources/module/PDF-Reader.vcxproj @@ -116,16 +116,17 @@ - + - + false false - + + diff --git a/PackageSources/module/PDF-Reader.vcxproj.filters b/PackageSources/module/PDF-Reader.vcxproj.filters index 8b704bd..9db7eae 100644 --- a/PackageSources/module/PDF-Reader.vcxproj.filters +++ b/PackageSources/module/PDF-Reader.vcxproj.filters @@ -2,11 +2,23 @@ - - + + - - + + Headers + + + Headers + + + Headers + + + + + {cc9ebc6c-fa76-4cce-aad2-8c91df6e65c1} + \ No newline at end of file diff --git a/PackageSources/module/Utils.cpp b/PackageSources/module/Utils.cpp new file mode 100644 index 0000000..f98fb26 --- /dev/null +++ b/PackageSources/module/Utils.cpp @@ -0,0 +1,41 @@ +#include + +#include +#include +#include +#include + +#include "Utils.h" + +namespace khofmann +{ + void log(FILE* stream, const char* format, ...) + { + + time_t rawtime; + struct tm* timeinfo; + + time(&rawtime); + timeinfo = gmtime(&rawtime); + + char fmt[256]; + char time[256]; + strcpy(time, asctime(timeinfo)); + time[strlen(time) - 1] = 0; + sprintf(fmt, "[PDF - Reader Module] %s - %s", time, format); + + va_list args; + va_start(args, format); + + if (logFile != NULL) + { + vfprintf(logFile, fmt, args); + fflush(logFile); + } + vfprintf(stream, fmt, args); + + va_end(args); + + //free(fmt); + } +} diff --git a/PackageSources/module/Utils.h b/PackageSources/module/Utils.h new file mode 100644 index 0000000..9210dc6 --- /dev/null +++ b/PackageSources/module/Utils.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +namespace khofmann +{ + extern FILE* logFile; + + /// + /// Write to logfile and console + /// + /// Console stream + /// Format string + void log(FILE* stream, const char* format, ...); +} diff --git a/PackageSources/module/Utils.hpp b/PackageSources/module/Utils.hpp deleted file mode 100644 index a15b0a3..0000000 --- a/PackageSources/module/Utils.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include - -#include - -namespace khofmann -{ - static FILE* logFile; - - /// - /// Write to logfile and console - /// - /// Console stream - /// Format string wiht up to one specifier - /// Optional element specified by specifier - static void log(FILE* stream, const char* format, void* optionalElement = NULL) - { - if (logFile != NULL) - { - fprintf(logFile, format, optionalElement); - fflush(logFile); - } - fprintf(stream, format, optionalElement); - } -}