Skip to content

Commit

Permalink
User profiles (#65)
Browse files Browse the repository at this point in the history
* init user profiles page

* fix usesrs match view

* change url to pubkey

* show ranks in users profile

* info

* get matches data fn

* get matches data fetch

* use server function to fetch profile matches

* login faster cache servers
  • Loading branch information
Manwe-777 authored Oct 8, 2023
1 parent f679742 commit 8522905
Show file tree
Hide file tree
Showing 26 changed files with 725 additions and 140 deletions.
135 changes: 82 additions & 53 deletions public/tooldb-worker/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertDbMatchToData = void 0;
exports.getMatchesData = exports.getMatchesDataLocal = exports.convertDbMatchToData = void 0;
const getRankFilterVal_1 = __importDefault(require("./getRankFilterVal"));
function convertDbMatchToData(match) {
const { internalMatch } = match;
Expand Down Expand Up @@ -375,20 +375,61 @@ function getLocalData(key) {
});
});
}
function getMatchesData(matchesIds, uuid) {
function getMatchesDataLocal(msgId, matchesIds, uuid) {
const promises = matchesIds.map((id) => {
return getLocalData(id);
});
Promise.all(promises)
.then((matches) => matches.filter((m) => m).map((m) => convertDbMatchToData(m)))
.then((data) => {
self.postMessage({
type: "MATCHES_DATA",
value: data.filter((m) => m.uuid === uuid),
type: `${msgId}_OK`,
value: data.filter((m) => (uuid ? m.uuid === uuid : true)),
});
});
}
exports.default = getMatchesData;
exports.getMatchesDataLocal = getMatchesDataLocal;
function getMatchesData(msgId, matchesIds, uuid, updateCallback) {
const matchesIndex = [...new Set([...(matchesIds || [])])];
let saved = 0;
let timeout = null;
let lastUpdate = new Date().getTime();
function updateState() {
timeout = null;
if (updateCallback) {
updateCallback(matchesIndex.length, saved);
}
if (saved === matchesIndex.length && matchesIndex.length > 0) {
getMatchesDataLocal(msgId, matchesIndex, uuid);
}
}
function debounceUpdateState() {
if (timeout)
clearTimeout(timeout);
if (new Date().getTime() - lastUpdate > 1000) {
lastUpdate = new Date().getTime();
updateState();
}
timeout = setTimeout(updateState, 100);
}
// Fetch any match we dont have locally
matchesIndex.forEach((id) => {
self.toolDb.store.get(id, (err) => {
if (!err) {
saved += 1;
debounceUpdateState();
}
else {
self.toolDb.getData(id, false, 2000).finally(() => {
saved += 1;
debounceUpdateState();
});
}
});
});
updateState();
}
exports.getMatchesData = getMatchesData;

},{"./getRankFilterVal":10}],10:[function(require,module,exports){
"use strict";
Expand Down Expand Up @@ -537,52 +578,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable no-restricted-globals */
const getMatchesData_1 = __importDefault(require("./getMatchesData"));
const getMatchesData_1 = require("./getMatchesData");
const reduxAction_1 = __importDefault(require("./reduxAction"));
function handleMatchesIndex(matchesIndex) {
self.globalData.matchesIndex = [
...new Set([...self.globalData.matchesIndex, ...(matchesIndex || [])]),
];
let saved = 0;
let timeout = null;
let lastUpdate = new Date().getTime();
function updateState() {
timeout = null;
(0, reduxAction_1.default)("SET_MATCHES_FETCH_STATE", {
total: self.globalData.matchesIndex.length,
saved,
function handleMatchesIndex(matchesIds) {
if (matchesIds) {
(0, reduxAction_1.default)("SET_MATCHES_INDEX", matchesIds);
(0, getMatchesData_1.getMatchesData)("MATCHES_DATA", matchesIds, self.globalData.currentUUID, (total, saved) => {
(0, reduxAction_1.default)("SET_MATCHES_FETCH_STATE", {
total,
saved,
});
});
if (saved === self.globalData.matchesIndex.length &&
self.globalData.matchesIndex.length > 0) {
(0, reduxAction_1.default)("SET_MATCHES_INDEX", self.globalData.matchesIndex);
(0, getMatchesData_1.default)(self.globalData.matchesIndex, self.globalData.currentUUID);
}
}
function debounceUpdateState() {
if (timeout)
clearTimeout(timeout);
if (new Date().getTime() - lastUpdate > 1000) {
lastUpdate = new Date().getTime();
updateState();
}
timeout = setTimeout(updateState, 100);
}
// Fetch any match we dont have locally
self.globalData.matchesIndex.forEach((id) => {
self.toolDb.store.get(id, (err) => {
if (!err) {
saved += 1;
debounceUpdateState();
}
else {
self.toolDb.getData(id, false, 2000).finally(() => {
saved += 1;
debounceUpdateState();
});
}
});
});
updateState();
}
exports.default = handleMatchesIndex;

Expand Down Expand Up @@ -800,7 +807,7 @@ const getConnectionData_1 = __importDefault(require("./getConnectionData"));
const getCrdt_1 = __importDefault(require("./getCrdt"));
const getData_1 = __importDefault(require("./getData"));
const getDataLocal_1 = __importDefault(require("./getDataLocal"));
const getMatchesData_1 = __importDefault(require("./getMatchesData"));
const getMatchesData_1 = require("./getMatchesData");
const getSaveKeysJson_1 = __importDefault(require("./getSaveKeysJson"));
const handleMatchesIndex_1 = __importDefault(require("./handleMatchesIndex"));
const keysLogin_1 = __importDefault(require("./keysLogin"));
Expand All @@ -815,13 +822,35 @@ const toolDb = new mtgatool_db_1.ToolDb({
server: false,
});
toolDb.on("init", (key) => console.warn("ToolDb initialized!", key));
constants_1.DEFAULT_PEERS.forEach((peer) => {
const networkModule = toolDb.network;
networkModule.findServer(peer);
toolDb.store.get("servers", (err, data) => {
let serversData = {};
if (err) {
console.error("Error getting servers from cache:", err);
}
else if (data) {
try {
serversData = JSON.parse(data);
}
catch (_e) {
console.error("Error parsing servers from cache:", _e);
}
}
console.log("Got servers from cache:", serversData);
constants_1.DEFAULT_PEERS.forEach((peer) => {
const networkModule = toolDb.network;
if (serversData[peer]) {
networkModule.connectTo(serversData[peer]);
}
else {
networkModule.findServer(peer);
}
});
});
toolDb.onConnect = () => {
const networkModule = toolDb.network;
console.warn("ToolDb connected!");
self.postMessage({ type: "CONNECTED" });
toolDb.store.put("servers", JSON.stringify(networkModule.serverPeerData), () => console.log("Saved servers to cache", networkModule.serverPeerData));
};
self.toolDb = toolDb;
self.globalData = {
Expand Down Expand Up @@ -881,7 +910,7 @@ self.onmessage = (e) => {
(0, exploreAggregation_1.beginDataQuery)(e.data.days, e.data.event);
break;
case "GET_MATCHES_DATA":
(0, getMatchesData_1.default)(e.data.matchesIndex, e.data.uuid);
(0, getMatchesData_1.getMatchesData)(e.data.id, e.data.matchesIndex, e.data.uuid);
break;
case "REFRESH_MATCHES":
if (self.toolDb.user) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function App(props: AppProps) {
const toolDbWorkerRef = useRef<Worker | null>(null);

useEffect(() => {
toolDbWorkerRef.current = new Worker("tooldb-worker/index.js", {
toolDbWorkerRef.current = new Worker("../tooldb-worker/index.js", {
type: "module",
});
window.toolDbWorker = toolDbWorkerRef.current;
Expand Down
17 changes: 11 additions & 6 deletions src/components/ContentWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
setDateOption,
} from "../redux/slices/FilterSlice";
import { AppState } from "../redux/stores/rendererStore";
import { getMatchesData } from "../toolDb/worker-wrapper";
import { CardsData } from "../types/collectionTypes";
import { defaultCardsData } from "../types/dbTypes";
import aggregateStats from "../utils/aggregateStats";
Expand All @@ -33,6 +34,7 @@ import HistoryStats from "./views/history/HistoryStats";
import ViewHistory from "./views/history/ViewHistory";
import ViewHome from "./views/home/ViewHome";
import ViewLiveMatch from "./views/livematch/ViewLiveMatch";
import ViewUser from "./views/user/ViewUser";
import ViewWip from "./views/wip/ViewWip";

const views = {
Expand All @@ -45,6 +47,7 @@ const views = {
explore: ViewExplore,
collection: ViewCollection,
aggregator: ViewExploreAggregator,
user: ViewUser,
};

function delay(transition: any, timeout: number): any {
Expand Down Expand Up @@ -97,19 +100,21 @@ const ContentWrapper = (mainProps: ContentWrapperProps) => {
const [matchesData, setMatchesData] = useState<MatchData[]>([]);

useEffect(() => {
getMatchesData(matchesIndex, currentUUID).then((d) => {
if (d) {
setMatchesData(d);
}
});

// hacky hack to listen for the after login matches data message
const listener = (e: any) => {
const { type, value } = e.data;
if (type === `MATCHES_DATA`) {
if (type === `MATCHES_DATA_OK`) {
setMatchesData(value);
}
};

if (window.toolDbWorker) {
window.toolDbWorker.postMessage({
type: "GET_MATCHES_DATA",
matchesIndex,
uuid: currentUUID,
});
window.toolDbWorker.addEventListener("message", listener);
}

Expand Down
16 changes: 13 additions & 3 deletions src/components/views/explore/ExploreEvent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export default function ExploreEvent(props: ExploreEventProps) {
}
}, [eventId]);

const username = usernames[eventData?.aggregator || ""];

return (
<div
className={`explore-event-list ${getEventExplorerSection(eventId)} ${
Expand All @@ -61,9 +63,17 @@ export default function ExploreEvent(props: ExploreEventProps) {
</div>
</div>
<div className="name-container">
<div className="name">{`${
usernames[eventData.aggregator || ""]
}`}</div>
<div
className="name link"
style={{ margin: "0" }}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
history.push(
`/user/${encodeURIComponent(eventData?.aggregator || "")}`
);
}}
>{`${username}`}</div>
<div
className="avatar"
style={{
Expand Down
15 changes: 13 additions & 2 deletions src/components/views/explore/ViewExploreEvent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,19 @@ export default function ViewExploreEvent() {
and {new Date(data.to).toDateString()}
</i>
<div className="maker-container">
<i className="maker-name">
{`Pushed by ${usernames[data.aggregator]}`}
<i className="maker-name">Pushed by</i>
<i
className="maker-name link"
style={{ margin: "0 0 0 4px" }}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
history.push(
`/user/${encodeURIComponent(data.aggregator || "")}`
);
}}
>
{usernames[data.aggregator]}
</i>
<div
className="maker-avatar"
Expand Down
22 changes: 20 additions & 2 deletions src/components/views/home/BestRanksFeed.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useEffect, useRef, useState } from "react";
import { useHistory } from "react-router-dom";

import { DEFAULT_AVATAR } from "../../../constants";
import useFetchAvatar from "../../../hooks/useFetchAvatar";
Expand All @@ -16,13 +17,16 @@ function DrawConstructedRank(props: DbRankInfo) {
updated,
name,
avatar,
pubKey,
constructedClass,
constructedLevel,
constructedStep,
constructedPercentile,
constructedLeaderboardPlace,
} = props;

const history = useHistory();

const mythicRankTitle =
constructedLeaderboardPlace == 0
? ` ${(constructedPercentile || 0).toFixed(2)}%`
Expand All @@ -37,7 +41,12 @@ function DrawConstructedRank(props: DbRankInfo) {
}}
/>
<div className="rank-name-container">
<div className="rank-name">{cleanUsername(name || "-")}</div>
<div
className="rank-name"
onClick={() => history.push(`/user/${encodeURIComponent(pubKey)}`)}
>
{cleanUsername(name || "-")}
</div>
<div className="rank-time">{timeAgo(updated)}</div>
</div>
<div className="rank-icon">
Expand All @@ -63,13 +72,16 @@ function DrawLimitedRank(props: DbRankInfo) {
updated,
name,
avatar,
pubKey,
limitedClass,
limitedLevel,
limitedStep,
limitedPercentile,
limitedLeaderboardPlace,
} = props;

const history = useHistory();

const mythicRankTitle =
limitedLeaderboardPlace == 0
? ` ${(limitedPercentile || 0).toFixed(2)}%`
Expand All @@ -84,7 +96,12 @@ function DrawLimitedRank(props: DbRankInfo) {
}}
/>
<div className="rank-name-container">
<div className="rank-name">{name || "-"}</div>
<div
className="rank-name"
onClick={() => history.push(`/user/${encodeURIComponent(pubKey)}`)}
>
{name || "-"}
</div>
<div className="rank-time">{timeAgo(updated)}</div>
</div>
<div className="rank-icon">
Expand Down Expand Up @@ -146,6 +163,7 @@ export default function BestRanksFeed() {
finallyThen(fetchUsername(rankInfo.pubKey)).then((name) => {
return {
...rankInfo,
pubKey: rankInfo.pubKey,
avatar: avatar || DEFAULT_AVATAR,
name: name || "",
};
Expand Down
1 change: 1 addition & 0 deletions src/components/views/home/DbRankInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { CombinedRankInfo } from "../../../background/onLabel/InEventGetCombined

export default interface DbRankInfo extends CombinedRankInfo {
uuid: string;
pubKey: string;
name: string;
avatar: string;
updated: number;
Expand Down
Loading

0 comments on commit 8522905

Please sign in to comment.