Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
321 changes: 162 additions & 159 deletions .idea/workspace.xml

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ const path = require("path");
const withPWA = require("next-pwa")({
dest: "public"
});
const { BugsnagBuildReporterPlugin } = require("webpack-bugsnag-plugins");
const appPackage = require("./package.json");

const config = {
productionBrowserSourceMaps: true,
sassOptions: {
includePaths: [path.join(__dirname, "src/styles")]
},
Expand All @@ -16,6 +19,15 @@ const config = {
}
});

if (process.env.NODE_ENV === "production") {
config.plugins.push(
new BugsnagBuildReporterPlugin({
apiKey: "53c03fdd42cd699cb95f60abe77a5b19",
appVersion: appPackage.version
})
);
}

return config;
},
images: {
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
"tailwindcss": "^3.3.0",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.2",
"typescript": "^5"
"typescript": "^5",
"webpack-bugsnag-plugins": "^1.8.0"
}
}
3 changes: 2 additions & 1 deletion public/sw.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions public/workbox-9b4d2a02.js

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions src/api/mutations/favourites.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { apiBase } from "@/api/helper";
import { useGlobalStore } from "@/core/global-store";
import { error, success } from "@/features/shared";
import i18next from "i18next";
import { formatError } from "@/api/operations";

export function useAddFavourite(onSuccess: () => void) {
const activeUser = useGlobalStore((s) => s.activeUser);
Expand Down Expand Up @@ -40,8 +39,7 @@ export function useCheckFavourite() {
const data = { code: getAccessToken(activeUser.username), account };
const response = await appAxios.post(apiBase(`/private-api/favorites-check`), data);
return response.data;
},
onError: (err) => error(...formatError(err))
}
});
}

Expand Down
1 change: 1 addition & 0 deletions src/api/mutations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ export * from "./upload-post-image";
export * from "./withdraw-routes";
export * from "./delegate-vesting-shares";
export * from "./claim-reward-balance";
export * from "./subscribe-to-community";
53 changes: 53 additions & 0 deletions src/api/mutations/subscribe-to-community.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { Community, Subscription } from "@/entities";
import { useGlobalStore } from "@/core/global-store";
import { broadcastPostingJSON, formatError } from "@/api/operations";
import { error } from "@/features/shared";
import { QueryIdentifiers } from "@/core/react-query";

export function useSubscribeToCommunity(community: Community) {
const activeUser = useGlobalStore((s) => s.activeUser);
const queryClient = useQueryClient();

return useMutation({
mutationKey: ["subscribeToCommunity", activeUser?.username, community?.name],
mutationFn: async ({ isSubscribe }: { isSubscribe: boolean }) => {
if (!activeUser) {
throw new Error("Can`t subscribe w/o active user");
}

if (isSubscribe) {
return [
isSubscribe,
await broadcastPostingJSON(activeUser?.username, "community", [
"subscribe",
{ community: community.name }
])
] as const;
} else {
return [
isSubscribe,
await broadcastPostingJSON(activeUser?.username, "community", [
"unsubscribe",
{ community: community.name }
])
] as const;
}
},
onSuccess: ([isSubscribe]) => {
queryClient.setQueryData<Subscription[]>(
[QueryIdentifiers.SUBSCRIPTIONS, activeUser?.username],
(data) => {
if (!data) {
return data;
}

return isSubscribe
? [...data, [community.name, community.title, "guest", ""]]
: data.filter(([u]) => u !== community.name);
}
);
},
onError: (err) => error(...formatError(err))
});
}
3 changes: 1 addition & 2 deletions src/api/queries/notifications/notifications-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export function useNotificationsQuery(filter: NotificationFilter | null) {
initialData: { pages: [], pageParams: [] },
initialPageParam: "",
getNextPageParam: (lastPage) => lastPage?.[lastPage.length - 1]?.timestamp ?? "",
refetchOnMount: true,
staleTime: 30000
refetchOnMount: true
});
}
1 change: 1 addition & 0 deletions src/app/[...slugs]/_components/community-card/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
align-items: center;
justify-content: center;
padding-bottom: 1rem;

Expand Down
17 changes: 8 additions & 9 deletions src/app/[...slugs]/_components/community-card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { CommunityCardTeam } from "./community-card-team";
import { CommunitySettingsDialog } from "@/app/[...slugs]/_components/community-settings";
import { CommunityRewardsRegistrationDialog } from "../community-rewards-registration";
import { EcencyConfigManager } from "@/config";
import Link from "next/link";

interface Props {
community: Community;
Expand All @@ -38,7 +39,7 @@ export function CommunityCard({ community, account }: Props) {
);
const roleInTeam = useMemo(() => (role ? role[1] : null), [role]);
const canUpdatePic = useMemo(
() => activeUser && !!users.find((x) => x.username === community.name),
() => activeUser && !!users.find((x: { username: string }) => x.username === community.name),
[activeUser, community.name, users]
);
const canEditCommunity = useMemo(
Expand Down Expand Up @@ -78,16 +79,14 @@ export function CommunityCard({ community, account }: Props) {
{(canEditCommunity || canEditTeam) && (
<div className="community-controls">
{canEditCommunity && (
<p className="community-control" onClick={() => setSettings(true)}>
<Button size="sm">{i18next.t("community-card.edit")}</Button>
</p>
<Button size="sm" onClick={() => setSettings(true)}>
{i18next.t("community-card.edit")}
</Button>
)}
{canEditTeam && (
<p className="community-control">
<Button href={`/roles/${community.name}`} size="sm">
{i18next.t("community-card.edit-team")}
</Button>
</p>
<Link href={`/roles/${community.name}`}>
<Button size="sm">{i18next.t("community-card.edit-team")}</Button>
</Link>
)}
</div>
)}
Expand Down
2 changes: 1 addition & 1 deletion src/app/[...slugs]/_components/community-cover/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export function CommunityCover({ community, account }: Props) {
[community.num_authors]
);
const canUpdateCoverImage = useMemo(
() => activeUser && !!users.find((x) => x.username === community.name),
() => activeUser && !!users.find((x: { username: string }) => x.username === community.name),
[activeUser, users, community.name]
);

Expand Down
19 changes: 0 additions & 19 deletions src/app/[...slugs]/_entry-components/similar-entries/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -48,25 +48,6 @@
}
}

.item-title {
display: block;
font-size: 16px;
font-weight: 500;
margin-bottom: 5px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 100%;

@include themify(day) {
@apply text-gray-steel;
}

@include themify(night) {
@apply text-gray-pinkish;
}
}

.item-image {
align-items: center;
cursor: pointer;
Expand Down
65 changes: 35 additions & 30 deletions src/app/[...slugs]/_entry-components/similar-entries/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import "./_index.scss";
import { Entry } from "@/entities";
import i18next from "i18next";
import { useGlobalStore } from "@/core/global-store";
import { dateToFullRelative } from "@/utils";
import { EntryLink } from "@/features/shared";
import { dateToFullRelative, makeEntryPath } from "@/utils";
import Image from "next/image";
import { getSimilarEntriesQuery } from "@/api/queries/get-similar-entries-query";
import { useRouter } from "next/navigation";
import { motion } from "framer-motion";

setProxyBase(defaults.imageServer);

Expand All @@ -22,6 +23,7 @@ interface Props {
export function SimilarEntries({ entry }: Props) {
const canUseWebp = useGlobalStore((s) => s.canUseWebp);

const router = useRouter();
const { data: entries } = getSimilarEntriesQuery(entry).useClientQuery();

return entries?.length === 3 ? (
Expand All @@ -30,35 +32,38 @@ export function SimilarEntries({ entry }: Props) {
<div className="list-header-text">{i18next.t("similar-entries.title")}</div>
</div>
<div className="similar-entries-list-body">
{entries?.map((en, i) => {
const img =
catchPostImage(en.img_url, 600, 500, canUseWebp ? "webp" : "match") ||
"/assets/noimage.svg";
const imgSize = img == "/assets/noimage.svg" ? "75px" : "auto";
const dateRelative = dateToFullRelative(en.created_at);

return (
<div className="similar-entries-list-item" key={i}>
<EntryLink entry={{ category: "relevant", author: en.author, permlink: en.permlink }}>
<>
<div className="item-image">
<Image
src={img ?? "/assets/fallback.png"}
alt={en.title}
width={1000}
height={1000}
/>
</div>
<div className="item-title">{en.title}</div>
<div className="item-footer">
<span className="item-footer-author">{en.author}</span>
<span className="item-footer-date">{dateRelative}</span>
</div>
</>
</EntryLink>
{entries?.map((en, i) => (
<motion.div
className="similar-entries-list-item bg-gray-100 hover:bg-blue-dark-sky-040 dark:bg-gray-900 rounded-2xl overflow-hidden"
whileHover={{
rotate: 1.5
}}
key={i}
initial={{
opacity: 0,
y: -24
}}
animate={{ opacity: 1, y: 0, transition: { delay: i * 0.2 } }}
onClick={() => router.push(makeEntryPath(en.category, en.author, en.permlink))}
>
<Image
src={
(catchPostImage(en.img_url, 600, 500, canUseWebp ? "webp" : "match") ||
"/assets/noimage.svg") ??
"/assets/fallback.png"
}
alt={en.title}
width={1000}
height={1000}
className="object-cover w-full h-[8rem]"
/>
<div className="truncate py-2 px-4">{en.title}</div>
<div className="item-footer py-2 px-4">
<span className="item-footer-author">{en.author}</span>
<span className="item-footer-date">{dateToFullRelative(en.created_at)}</span>
</div>
);
})}
</motion.div>
))}
</div>
</div>
) : (
Expand Down
18 changes: 0 additions & 18 deletions src/app/[...slugs]/_profile-components/profile-card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import { useGlobalStore } from "@/core/global-store";
import { getCommunityCache } from "@/core/caches";
import { CommunityCardEditPic } from "@/app/[...slugs]/_components/community-card/community-card-edit-pic";
import { Followers, Following } from "../friends";
import { EcencyConfigManager } from "@/config";

interface Props {
account: Account;
Expand Down Expand Up @@ -239,23 +238,6 @@ export const ProfileCard = ({ account, section }: Props) => {
{!!community && <JoinCommunityChatBtn community={community} />}
</>
)}
{isMyProfile && (
<>
<EcencyConfigManager.Conditional
condition={({ visionFeatures }) => visionFeatures.referrals.enabled}
>
<Link href={`/@${account?.name}/referrals`}>
<Button size="sm">{i18next.t("profile.referrals")}</Button>
</Link>
</EcencyConfigManager.Conditional>
<Link href="/witnesses">
<Button size="sm">{i18next.t("profile.witnesses")}</Button>
</Link>
<Link href="/proposals">
<Button size="sm">{i18next.t("profile.proposals")}</Button>
</Link>
</>
)}
</div>

{followersList && <Followers account={account} onHide={toggleFollowers} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { CommunityListItem } from "@/app/communities/_components";
import { useCommunitiesCache } from "@/core/caches";
import { AnimatePresence, motion } from "framer-motion";
import { Badge } from "@ui/badge";
import { Button } from "@ui/button";
import { UilUser } from "@tooni/iconscout-unicons-react";

interface Props {
account: Account;
Expand All @@ -21,7 +23,7 @@ export function ProfileCommunities({ account }: Props) {

const [sort, setSort] = useState<"asc" | "desc">("asc");

const { data, isLoading } = useGetSubscriptionsQuery(account.name);
const { data, isFetching } = useGetSubscriptionsQuery(account.name);
const communities = useCommunitiesCache(data?.map((item) => item[0]) ?? []);

const showCreateLink = activeUser && activeUser.username === account.name;
Expand All @@ -36,9 +38,9 @@ export function ProfileCommunities({ account }: Props) {
);

return (
<div>
{isLoading && <LinearProgress />}
{!isLoading && items?.length === 0 && (
<div className="mt-4">
{isFetching && <LinearProgress />}
{!isFetching && items?.length === 0 && (
<>
<h2>{i18next.t("profile.communities-title")}</h2>
<p className="text-gray-600">{i18next.t("g.empty-list")}</p>
Expand All @@ -64,6 +66,15 @@ export function ProfileCommunities({ account }: Props) {
/>
)}
</div>
{showCreateLink && (
<p>
<Link href="/communities/create" className="mb-4 flex">
<Button outline={true} icon={<UilUser />}>
{i18next.t("profile.create-community")}
</Button>
</Link>
</p>
)}

<ul className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
<AnimatePresence>
Expand All @@ -90,13 +101,6 @@ export function ProfileCommunities({ account }: Props) {
)}
</AnimatePresence>
</ul>
{showCreateLink && (
<p>
<Link href="/communities/create" className="create-link">
{i18next.t("profile.create-community")}
</Link>
</p>
)}
</>
)}
</div>
Expand Down
Loading