Skip to content

Commit

Permalink
feat: able to toggle platform notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
runjuu committed Feb 7, 2024
1 parent d23bb9e commit ec0dc6b
Show file tree
Hide file tree
Showing 16 changed files with 269 additions and 42 deletions.
1 change: 1 addition & 0 deletions packages/site/gatsby-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const onCreateWebpackConfig = ({ actions }) => {
resolve: {
alias: {
'@/components': path.resolve(__dirname, 'src/components'),
'@/modules': path.resolve(__dirname, 'src/modules'),
'@/lib/utils': path.resolve(__dirname, 'src/lib/utils'),
'@/utils': path.resolve(__dirname, 'src/utils'),
'@/hooks': path.resolve(__dirname, 'src/hooks'),
Expand Down
4 changes: 4 additions & 0 deletions packages/site/src/components/Buttons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ export const ResetButton = (props: ComponentProps<typeof Button>) => {
return <Button {...props}>Reset Now</Button>;
};

export const SaveButton = (props: ComponentProps<typeof Button>) => {
return <Button {...props}>Save</Button>;
};

export const HeaderButtons = ({
state,
onConnectClick,
Expand Down
44 changes: 44 additions & 0 deletions packages/site/src/hooks/use-toggle-notifications.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
import { useIsMetaMaskReady } from '@/hooks/use-is-meta-mask-ready';
import { getPlatformInfos, togglePlatform } from '@/utils';
import { Platform, PlatformInfo } from '@/types';

export function useToggleNotifications(deps: React.DependencyList = []) {
const isMetaMaskReady = useIsMetaMaskReady();
const [platforms, setPlatforms] = React.useState<PlatformInfo[]>([]);
const [isUpdating, setIsUpdating] = React.useState(false);

const toggle = React.useCallback(
async (platformId: Platform, enabled?: boolean) => {
try {
const platform = platforms.find((p) => p.id === platformId);
const enabled_ = enabled ?? !platform?.enabled;

if (!platform) {
throw new Error(`Platform ${platformId} not found`);
}

setIsUpdating(true);
await togglePlatform(platform.id, enabled_);
setPlatforms(await getPlatformInfos());
} catch (e) {
console.error(e);
} finally {
setIsUpdating(false);
}
},
[platforms],
);

React.useEffect(() => {
if (isMetaMaskReady) {
getPlatformInfos().then(setPlatforms);
}
}, [isMetaMaskReady, ...deps]);

return {
platforms,
toggle,
isUpdating,
};
}
15 changes: 15 additions & 0 deletions packages/site/src/modules/preferences/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';

import { Notifications } from '@/modules/preferences/notifications';

export function Preferences() {
return (
<div className="max-w-7xl mx-auto">
<h2 className="text-3xl font-semibold leading-7 text-gray-900 mb-6 mt-12">
Preferences
</h2>

<Notifications />
</div>
);
}
33 changes: 33 additions & 0 deletions packages/site/src/modules/preferences/notifications.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useToggleNotifications } from '@/hooks/use-toggle-notifications';
import { Checkbox } from '@/components/ui/checkbox';

export function Notifications() {
const { toggle, platforms } = useToggleNotifications();

return (
<div className="bg-white shadow sm:rounded-lg">
<div className="px-4 py-5 sm:p-6">
<h3 className="text-base font-semibold leading-6 text-gray-900">
Notifications
</h3>

<div className="mt-2 space-y-2">
<div className="max-w-xl text-sm text-gray-500">
Choose which platforms you want to receive notifications on.
</div>
<div className="flex items-center gap-4">
{platforms.map((platform) => (
<label key={platform.id} className="flex items-center gap-2">
<Checkbox
checked={platform.enabled}
onCheckedChange={() => toggle(platform.id)}
/>
{platform.name}
</label>
))}
</div>
</div>
</div>
</div>
);
}
7 changes: 7 additions & 0 deletions packages/site/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import { Button } from '@/components/ui/button';
import { SEO } from '@/components/SEO';
import { Preferences } from '@/modules/preferences';
import { useIsMetaMaskReady } from '@/hooks/use-is-meta-mask-ready';

const Index = () => {
Expand Down Expand Up @@ -240,6 +241,12 @@ const Index = () => {
)}
</div>

{state.installedSnap && (
<div>
<Preferences />
</div>
)}

<h1 className="pt-24 mx-auto max-w-fit text-3xl font-bold leading-tight tracking-tighter md:text-5xl lg:leading-[1.1]">
<span className="text-RSS3 drop-shadow-md">FAQ</span>
</h1>
Expand Down
2 changes: 1 addition & 1 deletion packages/site/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { type GetSnapsResponse, type Snap } from './snap';
export * from './snap';
9 changes: 9 additions & 0 deletions packages/site/src/types/snap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,12 @@ export type Snap = {
version: string;
initialPermissions: Record<string, unknown>;
};

// TODO: - share the types with the snap
export enum Platform {
Crossbell = 'Crossbell',
Farcaster = 'Farcaster',
Lens = 'Lens',
}

export type PlatformInfo = { name: string; id: Platform; enabled: boolean };
34 changes: 27 additions & 7 deletions packages/site/src/utils/snap.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { MetaMaskInpageProvider } from '@metamask/providers';
import type { Profile } from '@rss3/js-sdk';
import { defaultSnapOrigin } from '../config';
import { GetSnapsResponse, Snap } from '../types';
import { GetSnapsResponse, Snap, Platform, PlatformInfo } from '../types';

/**
* Get the installed snaps in MetaMask.
Expand Down Expand Up @@ -73,12 +73,6 @@ export type TProfile = {
lastActivities?: CronActivity[];
};

export enum Platform {
Crossbell = 'Crossbell',
Farcaster = 'Farcaster',
Lens = 'Lens',
}

export type TSocialGraphResult = {
platform: Platform;
status: boolean;
Expand Down Expand Up @@ -282,4 +276,30 @@ export const testImage = async () => {
},
});
};

export const togglePlatform = async (platform: string, enabled: boolean) => {
return await window.ethereum.request({
method: 'wallet_invokeSnap',
params: {
snapId: defaultSnapOrigin,
request: {
method: 'togglePlatform',
params: { platform, enabled },
},
},
});
};

export const getPlatformInfos = async () => {
return (await window.ethereum.request({
method: 'wallet_invokeSnap',
params: {
snapId: defaultSnapOrigin,
request: {
method: 'getPlatformInfos',
},
},
})) as PlatformInfo[];
};

export const isLocalSnap = (snapId: string) => snapId.startsWith('local:');
2 changes: 1 addition & 1 deletion packages/snap/snap.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://github.com/NaturalSelectionLabs/RSS3-Social-Notifier-Snap.git"
},
"source": {
"shasum": "JzJh23BBGdsijFOEAQw8fREDnXCr9VJDCVESa8+qMX0=",
"shasum": "y2WbB4B+HA/2FQD4XRN8oWquK0FOYbNbvikIPmbUtQA=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
10 changes: 5 additions & 5 deletions packages/snap/src/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ export async function getSocialActivities(address: string) {
// formatContent only for social and governance tag.
const content = formatContent(item);

const { id } = item;
const { id, platform = null } = item;
const text = format(item).join('');
const image = content?.media?.[0]?.address;
return content ? { id, text, image } : { id, text };
return content ? { id, text, image, platform } : { id, text, platform };
});

return {
Expand Down Expand Up @@ -133,12 +133,12 @@ export async function getMultiple(addresses: string[]) {

data.map((item) => {
const content = formatContent(item);
const { id, owner } = item;
const { id, owner, platform = null } = item;
const text = format(item).join('');
const image = content?.media?.[0]?.address;
return content
? activities.push({ id, text, image, owner })
: activities.push({ id, text, owner });
? activities.push({ id, text, image, owner, platform })
: activities.push({ id, text, owner, platform });
});

if (meta === null) {
Expand Down
78 changes: 55 additions & 23 deletions packages/snap/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
clearState,
getState,
setState,
Platform,
PlatformInfo,
} from './state';
import { diff, getSocialActivities } from './fetch';
import { getProfilesBySearch } from './social-graph';
Expand All @@ -28,14 +30,12 @@ import {
addWatchedProfilesToState,
buildNeedToNotifyContents,
} from './utils/activitiy';
import { getPlatformDisplayName } from './utils/platform-display-name';
import { filterByPlatforms } from './utils/filter-by-platforms';

// import imageToBase64 from './utils/imageToBase64';

export enum Platform {
Crossbell = 'Crossbell',
Farcaster = 'Farcaster',
Lens = 'Lens',
}
export { Platform };

export type TSocialGraphResult = {
platform: Platform;
Expand Down Expand Up @@ -303,6 +303,29 @@ export const onRpcRequest: OnRpcRequestHandler = async ({ request }) => {
});
}

case 'togglePlatform': {
const state = await getState();
const { enabled, platform } = request.params as {
platform: Platform;
enabled: boolean;
};

return setState({
...state,
platforms: { ...state.platforms, [platform]: { enabled } },
});
}

case 'getPlatformInfos': {
const { platforms } = await getState();

return Object.values(Platform).map((platform) => ({
enabled: platforms?.[platform]?.enabled ?? true,
id: platform,
name: getPlatformDisplayName(platform),
})) satisfies PlatformInfo[];
}

default:
throw new Error('Method not found.');
}
Expand Down Expand Up @@ -374,7 +397,9 @@ export const onCronjob: OnCronjobHandler = async ({ request }) => {
}

const diffArray: SocialActivity[] = [];
const content: any = [heading('New Social Count')];
const content: Parameters<typeof panel>[0] = [
heading('New Social Count'),
];

for (const activity of changedSocialCounts) {
const cachedActivity = state.socialActivities.find(
Expand All @@ -398,11 +423,13 @@ export const onCronjob: OnCronjobHandler = async ({ request }) => {
total: diffActivities.length,
});

content.push(heading(`${activity.address}`));
diffActivities.forEach((item) => {
content.push(text(item.text));
content.push(divider());
});
if (filterByPlatforms(diffActivities, state).length > 0) {
content.push(heading(`${activity.address}`));
diffActivities.forEach((item) => {
content.push(text(item.text));
content.push(divider());
});
}
}

await setState({
Expand All @@ -411,13 +438,16 @@ export const onCronjob: OnCronjobHandler = async ({ request }) => {
lastUpdatedActivities: diffArray,
});

await snap.request({
method: 'snap_dialog',
params: {
type: DialogType.Alert,
content: panel(content) as any,
},
});
if (content.length > 1) {
await snap.request({
method: 'snap_dialog',
params: {
type: DialogType.Alert,
content: panel(content),
},
});
}

return { result: true };
}

Expand Down Expand Up @@ -484,11 +514,13 @@ export const onCronjob: OnCronjobHandler = async ({ request }) => {
total: diffActivities.length,
});

content.push(heading(`${activity.address}`));
diffActivities.forEach((item) => {
content.push(text(item.text));
content.push(divider());
});
if (filterByPlatforms(diffActivities, state).length > 0) {
content.push(heading(`${activity.address}`));
diffActivities.forEach((item) => {
content.push(text(item.text));
content.push(divider());
});
}
}

await setState({
Expand Down
Loading

0 comments on commit ec0dc6b

Please sign in to comment.