Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve system storage and data structure #278

Merged
merged 34 commits into from
Jan 20, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
368eb7a
feat/style: add import backup modal (initial version)
bryanlundberg Jan 13, 2024
4ac707d
add cstimer import compatibility
bryanlundberg Jan 13, 2024
09a162e
remove 'solve.category' dependency in 'Solve' inheritance
bryanlundberg Jan 13, 2024
d108e5e
compatibility NexusTimer rework
bryanlundberg Jan 14, 2024
17334ae
compatibility cubedesk
bryanlundberg Jan 14, 2024
8e9ee0a
twisty timer compatibility
bryanlundberg Jan 14, 2024
bb747f6
compress image size and redirect
bryanlundberg Jan 14, 2024
a204568
functions was change to promises to handle larger files.
bryanlundberg Jan 14, 2024
34e5a85
add super fast parse CSV dependency "papaparse"
bryanlundberg Jan 15, 2024
d087a7f
minor style adjustments for modal
bryanlundberg Jan 15, 2024
1f36284
integrate 'idb-wrapper' to simplify IndexDB administration
bryanlundberg Jan 15, 2024
5d9280c
All functions related to the /cubes page have been updated for asynch…
bryanlundberg Jan 16, 2024
cc754ad
Implement async indexDB integration for /, /stats, /solves, /cubes ro…
bryanlundberg Jan 17, 2024
f05d897
fix: last solve using manual mode
bryanlundberg Jan 17, 2024
a63b8a4
async export app data
bryanlundberg Jan 17, 2024
9d87a47
updated twisty timer import to indexDB
bryanlundberg Jan 17, 2024
5b4d776
updated cubedesk import to indexDB
bryanlundberg Jan 17, 2024
2ed6ba7
updated nexutTimer import to indexDB
bryanlundberg Jan 17, 2024
89d6a0b
update cstimer import to indexDB
bryanlundberg Jan 17, 2024
4a720d9
removed unused code
bryanlundberg Jan 17, 2024
8660655
allow users to customize cube category
bryanlundberg Jan 17, 2024
cca1733
sync memory db
bryanlundberg Jan 18, 2024
2e8f6b1
minor fixes and optimized sync app data
bryanlundberg Jan 18, 2024
b91f688
remove some unused async functions on timer
bryanlundberg Jan 19, 2024
7c543d9
Optimize cube-solving statistics calculation
bryanlundberg Jan 19, 2024
cbef069
fix move/delete solves stats
bryanlundberg Jan 19, 2024
8e213f9
virtualized-grid rendering solves
bryanlundberg Jan 19, 2024
08aa9db
fix grid responsive solves area
bryanlundberg Jan 20, 2024
92deb67
fix move/delete buttons
bryanlundberg Jan 20, 2024
d7ebc11
fix height
bryanlundberg Jan 20, 2024
af9367f
fix finish session -- closing all similar categories
bryanlundberg Jan 20, 2024
14365e3
fix edit cubename/category
bryanlundberg Jan 20, 2024
efee75d
add translations
bryanlundberg Jan 20, 2024
a2f6fa1
update jsdocs comments
bryanlundberg Jan 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"dependencies": {
"@headlessui/react": "^1.7.17",
"@types/node": "20.6.0",
"@types/papaparse": "^5.3.14",
"@types/react": "18.2.21",
"@types/react-dom": "18.2.7",
"autoprefixer": "10.4.15",
Expand All @@ -23,8 +24,10 @@
"eslint-config-next": "13.4.19",
"fast-sort": "3.4.0",
"framer-motion": "^10.17.4",
"idb-wrapper": "^1.7.2",
"lightweight-charts": "^4.1.0",
"next": "13.5.1",
"papaparse": "^5.4.1",
"postcss": "8.4.31",
"pretty-ms": "^8.0.0",
"react": "18.2.0",
Expand Down
Binary file added public/timer-logos/cstimer.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/timer-logos/cubedesk.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/timer-logos/nexustimer.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/timer-logos/twistytimer.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 5 additions & 2 deletions src/app/cubes/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ import { OptionsContainer } from "@/components/cubes/OptionsContainer";
import { useCubes } from "@/hooks/useCubes";
import { AnimatePresence } from "framer-motion";
import useModalCube from "@/hooks/useModalCube";
import { useCubesModalStore } from "@/store/CubesModalStore";
import { useSettingsModalStore } from "@/store/SettingsModalStore";

export default function CubesPage() {
const { filterCubes, modalOpen, setModalOpen, lang, handleSearchFilter } =
useCubes();
const { filterCubes, handleSearchFilter } = useCubes();
const { modalOpen, setModalOpen } = useCubesModalStore();
const { setSelectedCategory } = useModalCube();
const { lang } = useSettingsModalStore();

return (
<>
Expand Down
2 changes: 2 additions & 0 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import FullscreenOption from "@/components/timer/FullscreenOption";
import HintPanel from "@/components/timer/HintPanel";
import ScrambleModal from "@/components/timer/ScrambleModal";
import useInitializeTimer from "@/hooks/useInitializeHint";
import ImportModal from "@/components/menu-settings/ImportModal";

export default function Home() {
useInitializeTimer();
Expand All @@ -22,6 +23,7 @@ export default function Home() {
<HintPanel />
<FullscreenOption />
<ScrambleModal />
<ImportModal />
</>
);
}
12 changes: 3 additions & 9 deletions src/components/PreloadSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,18 @@ import { usePreloadSettings } from "@/hooks/usePreloadSettings";
import { Navbar } from "@/components/navbar/index";
import { useSettingsModalStore } from "@/store/SettingsModalStore";
import { useTimerStore } from "@/store/timerStore";
import { useEffect } from "react";
import { useBackgroundImageStore } from "@/store/BackgroundThemeStore";
export default function PreloadSettings({
children,
}: {
children: React.ReactNode;
}) {
usePreloadSettings();
const { settings } = useSettingsModalStore();
const { isSolving, timerStatus } = useTimerStore();
const theme = settings ? settings.theme.background.color : "light";
const { backgroundImage, setBackgroundImage } = useBackgroundImageStore();
useEffect(() => {
const storedImage = localStorage.getItem("customBackgroundImage");
if (storedImage) {
setBackgroundImage(storedImage);
}
}, [setBackgroundImage]);
const { backgroundImage } = useBackgroundImageStore();

usePreloadSettings();

return (
<>
Expand Down
15 changes: 7 additions & 8 deletions src/components/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import { Categories } from "@/interfaces/Categories";
import { cubeCollection } from "@/lib/const/cubeCollection";
import genId from "@/lib/genId";
import { useTimerStore } from "@/store/timerStore";
import findCube from "@/lib/findCube";
import translation from "@/translations/global.json";
import { useSettingsModalStore } from "@/store/SettingsModalStore";
import { useCubesModalStore } from "@/store/CubesModalStore";
import useClickOutside from "@/hooks/useClickOutside";
import { AnimatePresence, motion } from "framer-motion";
import { useBackgroundImageStore } from "@/store/BackgroundThemeStore";
import { Cube } from "@/interfaces/Cube";

export default function Select() {
const [open, setOpen] = useState<boolean>(false);
Expand Down Expand Up @@ -138,19 +138,18 @@ function Option({
cubeId: string;
handleClose: () => void;
}) {
const { selectedCube, setSelectedCube, setNewScramble, setLastSolve } =
const { selectedCube, setSelectedCube, setNewScramble, setLastSolve, cubes } =
useTimerStore();

return (
<div
onClick={() => {
if (setSelectedCube && setNewScramble) {
const cube = findCube({ cubeId: cubeId });
if (cube) {
setSelectedCube(cube);
setNewScramble(cube);
setLastSolve(null);
}
const selectCube = cubes?.find((cube: Cube) => cube.id === cubeId);
if (!selectCube) return;
setSelectedCube(selectCube);
setNewScramble(selectCube);
setLastSolve(null);
}
handleClose();
}}
Expand Down
9 changes: 5 additions & 4 deletions src/components/cubes/BookmarkFav.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import FavoriteSolid from "@/icons/FavoriteSolid";
import { Cube } from "@/interfaces/Cube";
import { useState } from "react";

export default function BookmarkFav({
isChecked,
setFavorite,
cubeId,
cube,
}: {
isChecked: boolean;
setFavorite: (cubeId: string) => void;
cubeId: string;
setFavorite: (cube: Cube) => void;
cube: Cube;
}) {
const [checked, setChecked] = useState(isChecked);

return (
<button
onClick={() => {
setFavorite(cubeId);
setFavorite(cube);
setChecked(!checked);
}}
aria-pressed={checked}
Expand Down
10 changes: 4 additions & 6 deletions src/components/cubes/ModalCreate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,7 @@ export default function ModalCreate() {
alt={category.name}
id={category.id}
value={category.name}
handleClickRadio={
!editingCube ? handleClickRadio : () => {}
}
handleClickRadio={handleClickRadio}
selectedCategory={selectedCategory}
/>
);
Expand Down Expand Up @@ -140,10 +138,10 @@ export default function ModalCreate() {
) : null}

<button
onClick={() =>
onClick={async () =>
editingCube
? handleEditCube(cubeName, selectedCategory)
: handleCreateCube(cubeName, selectedCategory)
? await handleEditCube(cubeName, selectedCategory)
: await handleCreateCube(cubeName, selectedCategory)
}
data-modal-hide="defaultModal"
type="button"
Expand Down
33 changes: 19 additions & 14 deletions src/components/cubes/TableRow.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,36 @@
import { Cube } from "@/interfaces/Cube";
import BookmarkFav from "@/components/cubes/BookmarkFav";
import Ellipsis from "@/icons/Ellipsis";
import updateCube from "@/lib/updateCube";
import { useTimerStore } from "@/store/timerStore";
import { useCubesModalStore } from "@/store/CubesModalStore";
import Play from "@/icons/Play";
import Stop from "@/icons/Stop";
import translation from "@/translations/global.json";
import { useSettingsModalStore } from "@/store/SettingsModalStore";
import { useRouter } from "next/navigation";
import { getAllCubes, saveCube } from "@/db/dbOperations";

export default function TableRow({ cube }: { cube: Cube }) {
const { lang } = useSettingsModalStore();
const router = useRouter();
const { setSelectedCube, setNewScramble, setLastSolve } = useTimerStore();
const { setCubes } = useTimerStore();
const { setSelectedCube, setNewScramble, setLastSolve, setCubes } =
useTimerStore();
const { setEditingCube, setModalOpen, setCubeName, setSelectedCategory } =
useCubesModalStore();
const setFavorite = (cubeId: string) => {
const updatedCube = updateCube({ cubeId });
setCubes(updatedCube);
const setFavorite = async (cube: Cube) => {
const updatedCube = await saveCube({
id: cube.id,
name: cube.name,
category: cube.category,
favorite: !cube.favorite,
});

const cubesDB = await getAllCubes();
setCubes(cubesDB);
};

function formatDate(msDate: number) {
const creationDate = new Date(cube.createdAt);
const creationDate = new Date(msDate);
const month = creationDate.getMonth() + 1;
const day = creationDate.getDate();
const year = creationDate.getFullYear();
Expand All @@ -32,8 +39,6 @@ export default function TableRow({ cube }: { cube: Cube }) {
.padStart(2, "0")}/${year}`;
}

const status = cube.solves.session.length > 0;

const redirectToHome = (e: any) => {
const targetDiv = e.target;
const divIndex = Array.from(e.currentTarget.children).indexOf(targetDiv);
Expand All @@ -53,7 +58,7 @@ export default function TableRow({ cube }: { cube: Cube }) {
>
<div className="table-cell w-10 align-middle">
<BookmarkFav
cubeId={cube.id}
cube={cube}
isChecked={cube.favorite}
setFavorite={setFavorite}
/>
Expand All @@ -62,16 +67,16 @@ export default function TableRow({ cube }: { cube: Cube }) {
{cube.name}
</div>
<div className="table-cell text-center align-middle cursor-pointer">
{cube.category}
{cube?.category}
</div>
<div className="table-cell text-center align-middle cursor-pointer">
{`${cube.solves.session.length}/${cube.solves.all.length}`}
{`${cube?.solves?.session.length}/${cube?.solves?.all.length}`}
</div>
<div className="hidden text-center align-middle cursor-pointer md:table-cell">
{formatDate(cube.createdAt)}
{formatDate(cube?.createdAt)}
</div>
<div className="hidden text-center align-middle md:table-cell">
{status ? (
{cube?.solves?.session.length > 0 ? (
<div className="flex items-center justify-center gap-1">
<div className="w-4 h-4">
<Play />
Expand Down
22 changes: 3 additions & 19 deletions src/components/menu-settings/DataImportExport.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,20 @@
import exportDataToFile from "@/lib/exportDataToFile";
import { Button } from "@/components/button";
import { useRef } from "react";
import importDataFromFile from "@/lib/importDataFromFile";
import Import from "@/icons/Import";
import Export from "@/icons/Export";
import translation from "@/translations/global.json";
import { useSettingsModalStore } from "@/store/SettingsModalStore";
import { useTimerStore } from "@/store/timerStore";
import { useRouter } from "next/navigation";

export function DataImportExport() {
const dataInputRef = useRef<HTMLInputElement>(null);
const { lang } = useSettingsModalStore();
const { setSelectedCube } = useTimerStore();
const router = useRouter();
const { setImportModalOpen } = useSettingsModalStore();
return (
<div className="flex justify-center w-11/12 gap-2 mx-auto light">
<input
type="file"
accept=".txt"
ref={dataInputRef}
className="hidden"
onChange={(e) => {
importDataFromFile(e);
router.push("/cubes");
setSelectedCube(null);
}}
/>
<Button
className="font-normal transition duration-400"
label={translation.settings["import-from-file"][lang]}
onClick={() => dataInputRef.current && dataInputRef.current.click()}
onClick={() => setImportModalOpen(true)}
// onClick={() => dataInputRef.current && dataInputRef.current.click()}
minimalistic={false}
icon={<Import />}
/>
Expand Down
Loading
Loading