removed all free tier restrictions

This commit is contained in:
2026-01-29 15:20:42 +00:00
parent 232e00a2b0
commit 2aa13e34bf
21 changed files with 413 additions and 639 deletions

View File

@@ -1,7 +1,7 @@
import { useRef, useState } from "react";
import { toast } from "sonner";
import Avatar from "@/components/avatar";
import { useSession } from "@/components/session-provider";
// import { useSession } from "@/components/session-provider";
import { Button } from "@/components/ui/button";
import Icon from "@/components/ui/icon";
import { Label } from "@/components/ui/label";
@@ -9,36 +9,36 @@ import { useUploadAvatar } from "@/lib/query/hooks";
import { parseError } from "@/lib/server";
import { cn } from "@/lib/utils";
function isAnimatedGIF(file: File): Promise<boolean> {
return new Promise((resolve) => {
const reader = new FileReader();
reader.onload = () => {
const buffer = reader.result as ArrayBuffer;
const arr = new Uint8Array(buffer);
// check for GIF89a or GIF87a header
const header = String.fromCharCode(...arr.slice(0, 6));
if (header !== "GIF89a" && header !== "GIF87a") {
resolve(false);
return;
}
// look for multiple images (animation indicator)
// GIFs have image descriptors starting with 0x2C
// and graphic control extensions starting with 0x21 0xF9
let frameCount = 0;
let i = 6; // skip header
while (i < arr.length - 1) {
if (arr[i] === 0x21 && arr[i + 1] === 0xf9) {
// graphic control extension - indicates animation frame
frameCount++;
}
i++;
}
resolve(frameCount > 1);
};
reader.onerror = () => resolve(false);
reader.readAsArrayBuffer(file.slice(0, 1024)); // only need first 1KB for header check
});
}
// function isAnimatedGIF(file: File): Promise<boolean> {
// return new Promise((resolve) => {
// const reader = new FileReader();
// reader.onload = () => {
// const buffer = reader.result as ArrayBuffer;
// const arr = new Uint8Array(buffer);
// // check for GIF89a or GIF87a header
// const header = String.fromCharCode(...arr.slice(0, 6));
// if (header !== "GIF89a" && header !== "GIF87a") {
// resolve(false);
// return;
// }
// // look for multiple images (animation indicator)
// // GIFs have image descriptors starting with 0x2C
// // and graphic control extensions starting with 0x21 0xF9
// let frameCount = 0;
// let i = 6; // skip header
// while (i < arr.length - 1) {
// if (arr[i] === 0x21 && arr[i + 1] === 0xf9) {
// // graphic control extension - indicates animation frame
// frameCount++;
// }
// i++;
// }
// resolve(frameCount > 1);
// };
// reader.onerror = () => resolve(false);
// reader.readAsArrayBuffer(file.slice(0, 1024)); // only need first 1KB for header check
// });
// }
export function UploadAvatar({
name,
@@ -56,7 +56,7 @@ export function UploadAvatar({
skipOrgCheck?: boolean;
className?: string;
}) {
const { user } = useSession();
// const { user } = useSession();
const [uploading, setUploading] = useState(false);
const [error, setError] = useState<string | null>(null);
const fileInputRef = useRef<HTMLInputElement>(null);
@@ -68,20 +68,20 @@ export function UploadAvatar({
if (!file) return;
// check for animated GIF for free users
if (user?.plan !== "pro" && file.type === "image/gif") {
const isAnimated = await isAnimatedGIF(file);
if (isAnimated) {
setError("Animated avatars are only available on Pro. Upgrade to upload animated avatars.");
toast.error("Animated avatars are only available on Pro. Upgrade to upload animated avatars.", {
dismissible: false,
});
// reset file input
if (fileInputRef.current) {
fileInputRef.current.value = "";
}
return;
}
}
// if (user?.plan !== "pro" && file.type === "image/gif") {
// const isAnimated = await isAnimatedGIF(file);
// if (isAnimated) {
// setError("Animated avatars are only available on Pro. Upgrade to upload animated avatars.");
// toast.error("Animated avatars are only available on Pro. Upgrade to upload animated avatars.", {
// dismissible: false,
// });
// // reset file input
// if (fileInputRef.current) {
// fileInputRef.current.value = "";
// }
// return;
// }
// }
setUploading(true);
setError(null);
@@ -99,25 +99,9 @@ export function UploadAvatar({
setError(message);
setUploading(false);
// check if the error is about animated avatars for free users
if (message.toLowerCase().includes("animated") && message.toLowerCase().includes("pro")) {
toast.error(
<div className="flex flex-col gap-2">
<span>Animated avatars are only available on Pro.</span>
<a href="/plans" className="text-personality hover:underline">
Upgrade to Pro
</a>
</div>,
{
dismissible: false,
duration: 5000,
},
);
} else {
toast.error(`Error uploading avatar: ${message}`, {
dismissible: false,
});
}
toast.error(`Error uploading avatar: ${message}`, {
dismissible: false,
});
}
};