这是对Pinaata挑战的投稿。
Pixxsha - 以你的方式分享你的瞬间Pixxsha 是一个照片分享平台,帮助您安全地保存和分享珍贵的记忆。来自 DEV.to 和 Pinata 挑战,Pixxsha 希望改善我们保存和分享时刻的方法。
Pixxsha有什么特别之处?-
安全储存:你的照片将被储存在星际文件系统(IPFS)上,确保它们既安全又随时可访问。
-
智能灵活的分享:您可以根据需要公开、私密或限时分享照片,一切由您说了算。
/public
:通过一个简单的链接,您可以和任何人分享您的照片。
/restricted
:通过添加特定人员来控制谁能访问,让您更加安心。
/view Once
:发送一个查看后即消失的链接。 - 您可以为照片创建一些分组,比如“我的21岁生日”或者“宝宝的第一年”。
Pixxsha 的未来会是怎样的?
我们才刚刚开始呢!这里有一些我们正在努力实现的超棒功能。
🌟 生命时光线:用照片分组为重要的时刻制作一个视觉生命旅程。
👨👩👧👦 家庭相册:为家庭回忆设立的专属空间,比如“宝宝的第一步学走”或“家庭旅行”。
🤝 协作群组:与家人和朋友分享并贡献照片到相册。
zh:
谢谢亲爱的DEV社区成员们和Pinata团队!
这个挑战激发了我们创建Pixxsha的灵感,我们很期待看到Pixxsha未来的发展方向。我们很感激有机会创造一些能够改变人们珍藏回忆方式的东西。
示例Pixxsha 的控制面板
我们的代码这个GitHub项目主页
更多关于如何集成Pinata的细节派对帽和IPFS
我们已经把 Pinata 的 Web3 SDK 集成到我们的 IPFS 交互中。这里展示一下我们是怎么用它的。
- 来自
pinataService.ts
文件
import { PinataSDK } from 'pinata-web3';
const pinata = new PinataSDK({
pinataJwt: process.env.PINATA_JWT!,
pinataGateway: process.env.PINATA_GATEWAY!,
});
// 将文件上传到 Pinata,可选包含标签和分组分配
export const uploadFile = async (file: File, tags: Record<string, string>, groupId?: string) => {
try {
const upload = await pinata.upload.file(file, {
metadata: {
name: file.name,
keyvalues: tags,
},
});
if (groupId) {
await pinata.groups.addCids({
groupId,
cids: [upload.IpfsHash],
});
}
return upload;
} catch (error) {
throw new Error(`上传文件失败: ${error.message}`);
}
};
// 使用 IPFS 哈希从 Pinata 获取文件内容
export const retrieveFile = async (ipfsHash: string) => {
try {
const data = await pinata.gateways.get(ipfsHash);
return data;
} catch (error) {
throw new Error(`获取文件失败: ${error.message}`);
}
};
// 通过 ID 获取组的详细信息
export const getGroup = async (groupId: string) => {
try {
return await pinata.groups.get({ groupId });
} catch (error) {
throw new Error(`获取组失败: ${error.message}`);
}
};
// 在 Pinata 中创建新的组
export const createGroup = async (name: string) => {
try {
return await pinata.groups.create({ name });
} catch (error) {
throw new Error(`创建组失败: ${error.message}`);
}
};
// 列出所有组,可选按名称、偏移量和限制进行过滤
export const listGroups = async (name?: string, offset?: number, limit?: number) => {
try {
const query = pinata.groups.list();
if (name) query.name(name);
if (offset) query.offset(offset);
if (limit) query.limit(limit);
return await query;
} catch (error) {
throw new Error(`列出组失败: ${error.message}`);
}
};
// 更新组名
export const updateGroup = async (groupId: string, name: string) => {
try {
return await pinata.groups.update({ groupId, name });
} catch (error) {
throw new Error(`更新组失败: ${error.message}`);
}
};
// 通过 ID 删除组信息
export const deleteGroup = async (groupId: string) => {
try {
await pinata.groups.delete({ groupId });
} catch (error) {
throw new Error(`删除组失败: ${error.message}`);
}
};
// 将 CID 从组中移除
export const removeCidsFromGroup = async (groupId: string, cids: string[]) => {
try {
await pinata.groups.removeCids({ groupId, cids });
} catch (error) {
throw new Error(`从组中移除 CID 失败: ${error.message}`);
}
};
// 将 CID 添加到组
export const addCidsToGroup = async (groupId: string, cids: string[]) => {
try {
await pinata.groups.addCids({ groupId, cids });
} catch (error) {
throw new Error(`将 CID 添加到组失败: ${error.message}`);
}
};
进入全屏模式 退出全屏
- 在我们的
photoController.ts
中,我们是如何处理照片分享的。
export const sharePhoto = async (req: Request, res: Response) => {
const { photoId, shareType, recipientEmails } = req.body;
try {
const { data: photo, error } = await supabase
.from('photos')
.select('*')
.eq('id', photoId)
.single();
if (error) throw error;
if (photo.user_id !== (req as any).user.userId) {
return res.status(403).json({ error: '您无权分享此照片' });
}
const shareLink = `${config.pinataGateway}/ipfs/${photo.ipfs_hash}`;
let expirationDate = null;
let viewCount = null;
switch (shareType) {
case 'public':
break;
case 'restricted':
if (!recipientEmails || recipientEmails.length === 0) {
return res.status(400).json({ error: '未指定收件人邮箱' });
}
break;
case 'view-once':
viewCount = 1;
break;
case 'time-limited':
expirationDate = new Date(Date.now() + 24 * 60 * 60 * 1000); // 即24小时后过期
break;
default:
return res.status(400).json({ error: '无效的分享方式' });
}
const { data: share, error: shareError } = await supabase
.from('shares')
.insert({
photo_id: photoId,
share_type: shareType,
share_link: shareLink,
recipient_emails: recipientEmails,
expiration_date: expirationDate,
view_count: viewCount,
remaining_views: viewCount,
});
if (shareError) throw shareError;
res.json({ shareLink, share });
} catch (error: any) {
res.status(500).json({ error: error.message });
}
};
全屏模式,退出全屏
- 使用 Pinata 来整理照片
export const addCidsToGroup = async (groupId: string, cids: string[]) => {
// 此函数将CIDs添加到组中。
return await pinata.groups.addCids({ groupId, cids });
};
切换到全屏模式 退出全屏
这允许用户将他们的照片整理成自定义相册,比如“2023年假期照”或“家庭合影”。
- 集成仪表板 我们创建了一个仪表板,它利用了 Pinata 的组和文件管理,:
export const 获取仪表板数据 = async (req: Request, res: Response) => {
// 获取带有标签和组的照片
const { data: photos } = await supabase
.from('photos')
.select(`*, 标签 (标签名), 组 (组名)`)
.eq('user_id', userId);
// ... 聚合数据以供仪表板使用
res.json({ photos, photoCount, recentUploads });
};
全屏。退出全屏。
下一步会是什么呢?我们正在继续开发Pixxsha,更注重用户体验的提升并增添更多功能。请关注我们的更新消息,欢迎随时联系我们!如果您想加入我们的旅程,请随时联系我们!
zh: ……
团队小伙伴
- Ekemini (开发者,来自 https://dev.to/envitab)
- Tobe (GitHub 用户,主页为 https://github.com/TobeTek)
- Oluwarimi (GitHub 用户,主页为 https://github.com/Gbadebo-Oluwarimi)
共同學習,寫下你的評論
評論加載中...
作者其他優質文章