diff --git a/components/Activity.tsx b/components/Activity.tsx
index f8a0bab..7f7b16d 100644
--- a/components/Activity.tsx
+++ b/components/Activity.tsx
@@ -70,14 +70,14 @@ const Activity = ({ updates, pageUser, onClickDate }: { updates: { date: string
{/* get the years that the user has written updates and display them as tabs above */}
{years.map(y => (
))}
diff --git a/components/ActivityGrid.tsx b/components/ActivityGrid.tsx
index 80b33b7..a52a382 100644
--- a/components/ActivityGrid.tsx
+++ b/components/ActivityGrid.tsx
@@ -20,11 +20,11 @@ const GridLabel = ({ row, col, children }: { row: number, col: number, children:
gridColumn: col,
fontSize: 10,
}}
- className="text-stone-300 dark:text-stone-700"
+ className="text-neutral-300 dark:text-neutral-700"
>{children}
)
-export default function ActivityGrid({ data, label, color, onClickDate }: { data: ActivityDayMap, label?: string, color?: string, onClickDate: (date: string) => void }) {
+export default function ActivityGrid({ data, onClickDate }: { data: ActivityDayMap, onClickDate: (date: string) => void }) {
const numCols = 53;
const monthChangeDays: ActivityDay[] = Object.values(data).filter((d, i, a) => (
@@ -58,7 +58,7 @@ export default function ActivityGrid({ data, label, color, onClickDate }: { data
gridRow: dateActivity.day + 2,
gridColumn: dateActivity.week + 2,
}}
- className={classNames(dateActivity.count > 0 ? "bg-tblue cursor-pointer" : "bg-gray-100", "hover:!opacity-100 w-[13px] h-[13px] rounded-[3px]")}
+ className={classNames(dateActivity.count > 0 ? "bg-tblue cursor-pointer" : "bg-gray-100 dark:bg-neutral-800", "hover:!opacity-100 w-[13px] h-[13px] rounded-[3px]")}
key={format(dateActivity.date, "yyyy-MM-dd")}
onClick={() => {
if (dateActivity.count > 0)
diff --git a/components/CustomSelect.tsx b/components/CustomSelect.tsx
index d3067d8..ead095f 100644
--- a/components/CustomSelect.tsx
+++ b/components/CustomSelect.tsx
@@ -1,60 +1,62 @@
import { useTheme } from 'next-themes';
import Select from 'react-select'
-export default function CustomSelect(props) {
- const { theme, setTheme } = useTheme();
- const customStyles = {
- option: (provided, state) => {
- const optionBackgroundColor = state.isSelected
- ? 'rgb(38, 132, 255)' /* default */
- : theme === 'dark'
- ? '#000'
- : '#FFF';
-
- return {
- ...provided,
- padding: 8,
- paddingRight: 16,
- paddingLeft: 16,
- backgroundColor: optionBackgroundColor,
-
- ':hover': {
- backgroundColor: state.isSelected
- ? optionBackgroundColor
- : theme === 'dark'
- ? 'rgba(243, 244, 246, 0.2)'
- : 'rgba(243, 244, 246, 1)', // tailwind gray 100, just like moremenu on hover
- },
- };
- },
-
- valueContainer: provided => ({
+export const getCustomStyles = (theme) => ({
+ option: (provided, state) => {
+ const optionBackgroundColor = state.isSelected
+ ? 'rgb(38, 132, 255)' /* default */
+ : theme === 'dark'
+ ? '#000'
+ : '#FFF';
+
+ return {
...provided,
padding: 8,
paddingRight: 16,
paddingLeft: 16,
- }),
-
- control: provided => ({
- ...provided,
- borderColor: '#e5e7eb',
- backgroundColor: theme === 'dark' ? 'rgba(0, 0, 0, 0)' : '#FFF',
- }),
-
- container: provided => ({
- ...provided,
- marginBottom: 8,
- }),
+ backgroundColor: optionBackgroundColor,
+
+ ':hover': {
+ backgroundColor: state.isSelected
+ ? optionBackgroundColor
+ : theme === 'dark'
+ ? 'rgba(243, 244, 246, 0.2)'
+ : 'rgba(243, 244, 246, 1)', // tailwind gray 100, just like moremenu on hover
+ },
+ };
+ },
+
+ valueContainer: provided => ({
+ ...provided,
+ padding: 8,
+ paddingRight: 16,
+ paddingLeft: 16,
+ }),
+
+ control: provided => ({
+ ...provided,
+ borderColor: '#e5e7eb',
+ backgroundColor: theme === 'dark' ? 'rgba(0, 0, 0, 0)' : '#FFF',
+ }),
+
+ container: provided => ({
+ ...provided,
+ marginBottom: 8,
+ }),
+
+ menu: provided => ({
+ ...provided,
+ backgroundColor: theme === 'dark' ? '#000' : '#FFF',
+ }),
+
+ singleValue: provided => ({
+ ...provided,
+ color: theme === 'dark' ? '#FFF' : '#000',
+ }),
+});
- menu: provided => ({
- ...provided,
- backgroundColor: theme === 'dark' ? '#000' : '#FFF',
- }),
-
- singleValue: provided => ({
- ...provided,
- color: theme === 'dark' ? '#FFF' : '#000',
- }),
- };
- return
+export default function CustomSelect(props) {
+ const { theme, setTheme } = useTheme();
+ const customStyles = getCustomStyles(theme);
+ return
}
diff --git a/components/EditUpdate.tsx b/components/EditUpdate.tsx
index 492e5b4..f748ef1 100644
--- a/components/EditUpdate.tsx
+++ b/components/EditUpdate.tsx
@@ -5,6 +5,8 @@ import {User} from "../utils/types";
import axios from "axios";
import MentionItem from "./MentionItem";
import Creatable from "react-select/creatable";
+import { getCustomStyles } from "./CustomSelect";
+import { useTheme } from "next-themes";
function getMentionFromCM(instance) {
const cursorInfo = instance.getCursor();
@@ -110,6 +112,8 @@ export default function EditUpdate({body, setBody, title, setTitle, date, setDat
return () => editorEl.removeEventListener("keydown", keydownHandler);
}, [editorRef.current, mentionOpen, mentionQuery, userSelectedIndex, userList]);
+
+ const { theme, setTheme } = useTheme();
return (
<>
@@ -141,8 +145,8 @@ export default function EditUpdate({body, setBody, title, setTitle, date, setDat
Tags (optional)
-
({ value: d, label: d }))} isMulti={true} isClearable={true}
- onChange={option => setTags(option.map(d => d.value))} defaultValue={tags.map(d => ({value: d, label: d}))} />
+ ({ value: d, label: d }))} isMulti={true} isClearable={true} className="z-10 relative"
+ onChange={option => setTags(option.map(d => d.value))} defaultValue={tags.map(d => ({value: d, label: d}))} styles={{...getCustomStyles(theme), multiValueRemove: (styles) => ({...styles, color: "black"})}}/>
diff --git a/components/UpdateFeed.tsx b/components/UpdateFeed.tsx
index e3d8ff5..d6b7d69 100644
--- a/components/UpdateFeed.tsx
+++ b/components/UpdateFeed.tsx
@@ -45,7 +45,7 @@ export default function UpdateFeed({updates, page, setPage, count}: {updates: Fe
{wordsCount(update.body)} word{wordsCount(update.body) > 1 ? "s" : ""}
{update.tags && update.tags.map(tag => (
- #{tag}
+ #{tag}
))}
diff --git a/package.json b/package.json
index 2bd3d5c..b83dcca 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "updately",
- "version": "0.11.2",
+ "version": "0.11.3",
"private": true,
"license": "BSD-3-Clause",
"scripts": {
diff --git a/pages/[username]/[updateUrl].tsx b/pages/[username]/[updateUrl].tsx
index d82055c..ebf92ab 100644
--- a/pages/[username]/[updateUrl].tsx
+++ b/pages/[username]/[updateUrl].tsx
@@ -21,6 +21,7 @@ import {FiHeart} from "react-icons/fi";
import {notificationModel} from "../../models/models";
import {getMentionsAndBodySegments} from "../../components/UpdateCommentItem";
import { DeleteModal } from "../../components/Modal";
+import { ssrRedirect } from "next-response-helpers";
export default function UpdatePage(props: { data: GetUpdateRequestResponse, updateUrl: string, userData: User }) {
const router = useRouter();
@@ -171,7 +172,7 @@ export default function UpdatePage(props: { data: GetUpdateRequestResponse, upda
{!!tags.length && (
)}
@@ -288,7 +289,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
// or are the user
data.user._id.toString() === userData._id.toString()
)
- )) return { notFound: true };
+ )) return ssrRedirect(`/@${data.user.urlName}?privateredirect=true`);
if (userData) await notificationModel.updateMany({userId: userData._id, updateId: data.update._id}, {read: true});
diff --git a/pages/[username]/index.tsx b/pages/[username]/index.tsx
index 5fc3fd4..81aa0bb 100644
--- a/pages/[username]/index.tsx
+++ b/pages/[username]/index.tsx
@@ -83,12 +83,19 @@ export default function UserProfile(props: { user: UserAgg, userData: User, foll
const isProfilePrivateToLoggedInUser = (pageUser.private || pageUser.truePrivate) && (!userData || !pageUser.followers.includes(props.userData.email) && !isOwner);
+ const isPrivateUpdateRedirect = !!router.query.privateredirect;
+
return (
+ {isPrivateUpdateRedirect && (
+
+
You accessed a link to an update on a private account that you do not follow. Follow the account to view the update.
+
+ )}
@@ -245,7 +252,7 @@ export default function UserProfile(props: { user: UserAgg, userData: User, foll
{update.tags && update.tags.map(tag => (
-
+
))}
diff --git a/pages/[username]/random.tsx b/pages/[username]/random.tsx
new file mode 100644
index 0000000..16510ce
--- /dev/null
+++ b/pages/[username]/random.tsx
@@ -0,0 +1,56 @@
+import { GetServerSideProps } from "next";
+import { getSession } from "next-auth/react";
+import { userModel } from "../../models/models";
+import getLookup from "../../utils/getLookup";
+import { ssrRedirect } from "next-response-helpers";
+
+export default function Random() {
+ return (
+ <>>
+ )
+}
+
+export const getServerSideProps: GetServerSideProps = async (context) => {
+ if (Array.isArray(context.params.username) || context.params.username.substring(0, 1) !== "@") return { notFound: true };
+
+ const username: string = context.params.username.substring(1);
+
+ const pageUserArr = await userModel.aggregate([
+ {$match: {urlName: username}},
+ getLookup("users", "_id", "following", "followingArr"),
+ getLookup("users", "email", "followers", "followersArr"),
+ {
+ $lookup: {
+ from: "updates",
+ as: "updatesArr",
+ let: {userId: "$_id"},
+ pipeline: [
+ {$match: {$expr: {$eq: ["$userId", "$$userId"]}}},
+ {$sample: {size: 1}},
+ ],
+ }
+ }
+ ]);
+
+ const pageUser = pageUserArr[0];
+
+ console.log(pageUser);
+
+ if (!pageUser) return {notFound: true};
+
+ const session = await getSession(context);
+ const thisUser = session ? await userModel.findOne({email: session.user.email}) : null;
+
+ const isPrivate = (pageUser.truePrivate || pageUser.private);
+
+ const canAccess = (!isPrivate || (thisUser && (
+ // following user
+ pageUser.followers.includes(thisUser.email) ||
+ // or are the user
+ pageUser._id.toString() === thisUser._id.toString()
+ )));
+
+ if (!canAccess || !pageUser.updatesArr.length) return ssrRedirect(`/@${username}`);
+
+ return ssrRedirect(`/@${username}/${pageUser.updatesArr[0].url}`);
+}
\ No newline at end of file
diff --git a/utils/requests.ts b/utils/requests.ts
index 93a6e5c..da2d7aa 100644
--- a/utils/requests.ts
+++ b/utils/requests.ts
@@ -23,8 +23,6 @@ export async function getUpdateRequest(username: string, url: string): Promise