mirror of
https://github.com/ItzCrazyKns/Perplexica.git
synced 2025-10-14 11:38:14 +00:00
feat(widgets): update theme
This commit is contained in:
@@ -27,7 +27,7 @@ const NewsArticleWidget = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-light-secondary dark:bg-dark-secondary rounded-xl border border-light-200 dark:border-dark-200 shadow-sm flex flex-row items-center w-full h-24 min-h-[96px] max-h-[96px] px-3 py-2 gap-3 overflow-hidden">
|
<div className="bg-light-secondary dark:bg-dark-secondary rounded-2xl border border-light-200 dark:border-dark-200 shadow-sm shadow-light-200/10 dark:shadow-black/25 flex flex-row items-stretch w-full h-24 min-h-[96px] max-h-[96px] p-0 overflow-hidden">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<>
|
<>
|
||||||
<div className="animate-pulse flex flex-row items-center w-full h-full">
|
<div className="animate-pulse flex flex-row items-center w-full h-full">
|
||||||
@@ -43,22 +43,24 @@ const NewsArticleWidget = () => {
|
|||||||
) : article ? (
|
) : article ? (
|
||||||
<a
|
<a
|
||||||
href={`/?q=Summary: ${article.url}`}
|
href={`/?q=Summary: ${article.url}`}
|
||||||
className="flex flex-row items-center w-full h-full group"
|
className="flex flex-row items-stretch w-full h-full relative overflow-hidden group"
|
||||||
>
|
>
|
||||||
<img
|
<div className="relative w-24 min-w-24 max-w-24 h-full overflow-hidden">
|
||||||
className="object-cover rounded-lg w-16 min-w-16 max-w-16 h-16 min-h-16 max-h-16 border border-light-200 dark:border-dark-200 bg-light-200 dark:bg-dark-200 group-hover:opacity-90 transition"
|
<img
|
||||||
src={
|
className="object-cover w-full h-full bg-light-200 dark:bg-dark-200 group-hover:scale-110 transition-transform duration-300"
|
||||||
new URL(article.thumbnail).origin +
|
src={
|
||||||
new URL(article.thumbnail).pathname +
|
new URL(article.thumbnail).origin +
|
||||||
`?id=${new URL(article.thumbnail).searchParams.get('id')}`
|
new URL(article.thumbnail).pathname +
|
||||||
}
|
`?id=${new URL(article.thumbnail).searchParams.get('id')}`
|
||||||
alt={article.title}
|
}
|
||||||
/>
|
alt={article.title}
|
||||||
<div className="flex flex-col justify-center flex-1 h-full pl-3 w-0">
|
/>
|
||||||
<div className="font-bold text-xs text-black dark:text-white leading-tight truncate overflow-hidden whitespace-nowrap">
|
</div>
|
||||||
|
<div className="flex flex-col justify-center flex-1 px-3 py-2">
|
||||||
|
<div className="font-semibold text-xs text-black dark:text-white leading-tight line-clamp-2 mb-1">
|
||||||
{article.title}
|
{article.title}
|
||||||
</div>
|
</div>
|
||||||
<p className="text-black/70 dark:text-white/70 text-xs leading-snug truncate overflow-hidden whitespace-nowrap">
|
<p className="text-black/60 dark:text-white/60 text-[10px] leading-relaxed line-clamp-2">
|
||||||
{article.content}
|
{article.content}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -15,61 +15,61 @@ const WeatherWidget = () => {
|
|||||||
|
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
const getApproxLocation = async () => {
|
||||||
const getApproxLocation = async () => {
|
const res = await fetch('https://ipwhois.app/json/');
|
||||||
const res = await fetch('https://ipwhois.app/json/');
|
const data = await res.json();
|
||||||
const data = await res.json();
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
latitude: data.latitude,
|
latitude: data.latitude,
|
||||||
longitude: data.longitude,
|
longitude: data.longitude,
|
||||||
city: data.city,
|
city: data.city,
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const getLocation = async (
|
const getLocation = async (
|
||||||
callback: (location: {
|
callback: (location: {
|
||||||
latitude: number;
|
latitude: number;
|
||||||
longitude: number;
|
longitude: number;
|
||||||
city: string;
|
city: string;
|
||||||
}) => void,
|
}) => void,
|
||||||
) => {
|
) => {
|
||||||
if (navigator.geolocation) {
|
if (navigator.geolocation) {
|
||||||
const result = await navigator.permissions.query({
|
const result = await navigator.permissions.query({
|
||||||
name: 'geolocation',
|
name: 'geolocation',
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result.state === 'granted') {
|
if (result.state === 'granted') {
|
||||||
navigator.geolocation.getCurrentPosition(async (position) => {
|
navigator.geolocation.getCurrentPosition(async (position) => {
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`https://api-bdc.io/data/reverse-geocode-client?latitude=${position.coords.latitude}&longitude=${position.coords.longitude}&localityLanguage=en`,
|
`https://api-bdc.io/data/reverse-geocode-client?latitude=${position.coords.latitude}&longitude=${position.coords.longitude}&localityLanguage=en`,
|
||||||
{
|
{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
|
||||||
},
|
},
|
||||||
);
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
|
||||||
callback({
|
callback({
|
||||||
latitude: position.coords.latitude,
|
latitude: position.coords.latitude,
|
||||||
longitude: position.coords.longitude,
|
longitude: position.coords.longitude,
|
||||||
city: data.locality,
|
city: data.locality,
|
||||||
});
|
|
||||||
});
|
});
|
||||||
} else if (result.state === 'prompt') {
|
});
|
||||||
callback(await getApproxLocation());
|
} else if (result.state === 'prompt') {
|
||||||
navigator.geolocation.getCurrentPosition((position) => {});
|
callback(await getApproxLocation());
|
||||||
} else if (result.state === 'denied') {
|
navigator.geolocation.getCurrentPosition((position) => {});
|
||||||
callback(await getApproxLocation());
|
} else if (result.state === 'denied') {
|
||||||
}
|
|
||||||
} else {
|
|
||||||
callback(await getApproxLocation());
|
callback(await getApproxLocation());
|
||||||
}
|
}
|
||||||
};
|
} else {
|
||||||
|
callback(await getApproxLocation());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateWeather = async () => {
|
||||||
getLocation(async (location) => {
|
getLocation(async (location) => {
|
||||||
const res = await fetch(`/api/weather`, {
|
const res = await fetch(`/api/weather`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -100,10 +100,16 @@ const WeatherWidget = () => {
|
|||||||
});
|
});
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
updateWeather();
|
||||||
|
const intervalId = setInterval(updateWeather, 2 * 60 * 1000);
|
||||||
|
return () => clearInterval(intervalId);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-light-secondary dark:bg-dark-secondary rounded-xl border border-light-200 dark:border-dark-200 shadow-sm flex flex-row items-center w-full h-24 min-h-[96px] max-h-[96px] px-3 py-2 gap-3">
|
<div className="bg-light-secondary dark:bg-dark-secondary rounded-2xl border border-light-200 dark:border-dark-200 shadow-sm shadow-light-200/10 dark:shadow-black/25 flex flex-row items-center w-full h-24 min-h-[96px] max-h-[96px] px-3 py-2 gap-3">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<>
|
<>
|
||||||
<div className="flex flex-col items-center justify-center w-16 min-w-16 max-w-16 h-full animate-pulse">
|
<div className="flex flex-col items-center justify-center w-16 min-w-16 max-w-16 h-full animate-pulse">
|
||||||
@@ -134,22 +140,24 @@ const WeatherWidget = () => {
|
|||||||
{data.temperature}°{data.temperatureUnit}
|
{data.temperature}°{data.temperatureUnit}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col justify-between flex-1 h-full py-1">
|
<div className="flex flex-col justify-between flex-1 h-full py-2">
|
||||||
<div className="flex flex-row items-center justify-between">
|
<div className="flex flex-row items-center justify-between">
|
||||||
<span className="text-xs font-medium text-black dark:text-white">
|
<span className="text-sm font-semibold text-black dark:text-white">
|
||||||
{data.location}
|
{data.location}
|
||||||
</span>
|
</span>
|
||||||
<span className="flex items-center text-xs text-black/60 dark:text-white/60">
|
<span className="flex items-center text-xs text-black/60 dark:text-white/60 font-medium">
|
||||||
<Wind className="w-3 h-3 mr-1" />
|
<Wind className="w-3 h-3 mr-1" />
|
||||||
{data.windSpeed} {data.windSpeedUnit}
|
{data.windSpeed} {data.windSpeedUnit}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<span className="text-xs text-black/60 dark:text-white/60 mt-1">
|
<span className="text-xs text-black/50 dark:text-white/50 italic">
|
||||||
{data.condition}
|
{data.condition}
|
||||||
</span>
|
</span>
|
||||||
<div className="flex flex-row justify-between w-full mt-auto pt-1 border-t border-light-200 dark:border-dark-200 text-xs text-black/60 dark:text-white/60">
|
<div className="flex flex-row justify-between w-full mt-auto pt-2 border-t border-light-200/50 dark:border-dark-200/50 text-xs text-black/50 dark:text-white/50 font-medium">
|
||||||
<span>Humidity: {data.humidity}%</span>
|
<span>Humidity {data.humidity}%</span>
|
||||||
<span>Now</span>
|
<span className="font-semibold text-black/70 dark:text-white/70">
|
||||||
|
Now
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
Reference in New Issue
Block a user