Lädt...


🔧 Pixxsha - Share Your Moments Your Way


Nachrichtenbereich: 🔧 Programmierung
🔗 Quelle: dev.to

This is a submission for the The Pinata Challenge

Pixxsha - Share Your Moments Your Way

Pixxsha is a photo-sharing platform that lets you securely store and share your precious memories. Born from the DEV.to and Pinata challenge, Pixxsha aims to improve how we preserve and share our moments.

What Makes Pixxsha Special?

  • Secure Storage: Your photos are stored on IPFS, ensuring they're safe and always accessible.

  • Smart and Flexible Sharing: Share photos publicly, privately, or with a time limit - you're in control.
    /public: Share your photos with anyone using a simple link.
    /restricted: Control who gets access by adding specific people.
    /view Once: Send a link that disappears after it’s been viewed.

  • Organized Memories: Create custom groups for your photos, like "My 21st Birthday" or "Baby's First Year".

Sign in to Pixxsha 😎
pixxsha

The Future of Pixxsha

We're just getting started! Here are some exciting features we're working on:

🌟 Life Timeline: Create a visual journey of your life with photo groups for significant milestones.

👨‍👩‍👧‍👦 Family Albums: Dedicated spaces for family memories, like "Baby's First Steps" or "Family Vacations".

🤝 Collaborative Groups: Share and contribute to group albums with friends and family.

Thank You, DEV Community and Pinata!

This challenge sparked the idea for Pixxsha, and we're excited to see where it goes. We're grateful for the opportunity to build something that could change how people cherish their memories.

Demo

Pixxsha's dashboard

dashboard

Our Code

The GitHub repository for Pixxsha

More Details of how we integrated Pinata

Pinata and IPFS

We've integrated Pinata's Web3 SDK to handle our IPFS interactions. Here's a glimpse of how we're using it:

  • From the pinataService.ts
import { PinataSDK } from 'pinata-web3';

const pinata = new PinataSDK({
  pinataJwt: process.env.PINATA_JWT!,
  pinataGateway: process.env.PINATA_GATEWAY!,
});

// Upload a file to Pinata with optional tags and group assignment
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(`Failed to upload file: ${error.message}`);
  }
};

// Retrieve a file from Pinata using its IPFS hash
export const retrieveFile = async (ipfsHash: string) => {
  try {
    const data = await pinata.gateways.get(ipfsHash);
    return data;
  } catch (error) {
    throw new Error(`Failed to retrieve file: ${error.message}`);
  }
};

// Create a new group in Pinata
export const createGroup = async (name: string) => {
  try {
    return await pinata.groups.create({ name });
  } catch (error) {
    throw new Error(`Failed to create group: ${error.message}`);
  }
};

// Get details of a specific group by ID
export const getGroup = async (groupId: string) => {
  try {
    return await pinata.groups.get({ groupId });
  } catch (error) {
    throw new Error(`Failed to get group: ${error.message}`);
  }
};

// List all groups with optional filtering by name, offset, and limit
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(`Failed to list groups: ${error.message}`);
  }
};

// Update the name of a group
export const updateGroup = async (groupId: string, name: string) => {
  try {
    return await pinata.groups.update({ groupId, name });
  } catch (error) {
    throw new Error(`Failed to update group: ${error.message}`);
  }
};

// Delete a group by ID
export const deleteGroup = async (groupId: string) => {
  try {
    await pinata.groups.delete({ groupId });
  } catch (error) {
    throw new Error(`Failed to delete group: ${error.message}`);
  }
};

// Add CIDs to a group
export const addCidsToGroup = async (groupId: string, cids: string[]) => {
  try {
    await pinata.groups.addCids({ groupId, cids });
  } catch (error) {
    throw new Error(`Failed to add CIDs to group: ${error.message}`);
  }
};

// Remove CIDs from a group
export const removeCidsFromGroup = async (groupId: string, cids: string[]) => {
  try {
    await pinata.groups.removeCids({ groupId, cids });
  } catch (error) {
    throw new Error(`Failed to remove CIDs from group: ${error.message}`);
  }
};
;

  • In our photoController.ts, here's how we're handling photo sharing:
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: 'Not authorized to share this photo' });
      }

      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: 'Recipient emails are required for restricted sharing' });
          }
          break;
        case 'view-once':
          viewCount = 1;
          break;
        case 'time-limited':
          expirationDate = new Date(Date.now() + 24 * 60 * 60 * 1000); // 24 hours from now
          break;
        default:
          return res.status(400).json({ error: 'Invalid share type' });
      }

      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 });
    }
  };

  • Organizing Photos with Pinata Groups
export const addCidsToGroup = async (groupId: string, cids: string[]) => {
  return await pinata.groups.addCids({ groupId, cids });
};

This allows users to organize their photos into custom collections like "Vacation 2023" or "Family Portraits".

  • Dashboard Integration We created a dashboard that leverages Pinata's group and file management:
export const getDashboardData = async (req: Request, res: Response) => {
  // Fetch photos with their tags and groups
  const { data: photos } = await supabase
    .from('photos')
    .select(`*, tags (name), groups (name)`)
    .eq('user_id', userId);

  // ... aggregate data for dashboard
  res.json({ photos, photoCount, recentUploads });
};

What's Next?

We're continuing to develop Pixxsha, focusing on enhancing user experience and adding more features. Stay tuned for updates, and feel free to reach out if you'd like to be part of our journey!

Team members

...

🔧 Sprint Retrospective Example: How To Turn Your Team's "Oh, Crap!" Moments Into "Aha!" Moments


📈 34.24 Punkte
🔧 Programmierung

🔧 A new way to enable video key moments in Search


📈 23.08 Punkte
🔧 Programmierung

🔧 Unexpected Moments of JavaScript That Will Challenge Your Understanding of the Language


📈 18.07 Punkte
🔧 Programmierung

🐧 What are some of your “oh— that was close” moments in Linux?


📈 18.07 Punkte
🐧 Linux Tipps

🪟 Save your favorite moments with a Fujifilm Instax Mini 9 on sale for $45


📈 18.07 Punkte
🪟 Windows Tipps

⚠️ Your private moments | Avira


📈 18.07 Punkte
⚠️ Malware / Trojaner / Viren

📰 Congress Is Moments Away From Letting ISPs Hawk Your Private Data


📈 18.07 Punkte
📰 IT Security Nachrichten

🍏 Create a visual chronicle of your travels so you never forget the beautiful moments


📈 18.07 Punkte
🍏 iOS / Mac OS

🔧 From Moments to Milestones: Incremental Timeline Summarization Leveraging Large Language Models


📈 16.17 Punkte
🔧 Programmierung

🕵️ Synology Android Moments up to 1.2.3 Privacy Page Man-in-the-Middle weak encryption


📈 16.17 Punkte
🕵️ Sicherheitslücken

📰 Synchronisierte Fotos: Facebook zwingt Nutzer zu Umstieg auf Moments-App


📈 16.17 Punkte
📰 IT Nachrichten

🍏 Search Specific Moments in Videos: A Massive Photos App Upgrade


📈 16.17 Punkte
🍏 iOS / Mac OS

📰 Moments & 23H2-Update: Microsofts große Windows 11-Pläne für 2023


📈 16.17 Punkte
📰 IT Security Nachrichten

⚠️ GReAT Security Moments - Adult Content Legislation in the UK


📈 16.17 Punkte
⚠️ Malware / Trojaner / Viren

🔧 How Automation Saved Me from Oops Moments: Never Skip Tests in Production Again!


📈 16.17 Punkte
🔧 Programmierung

📰 Moments mal: Hinweise auf die ersten Feature Drops für Windows 11 gesichtet


📈 16.17 Punkte
📰 IT Nachrichten

📰 Deep Blue Aerospace Hop Test Suffers Anomaly Moments Before Landing


📈 16.17 Punkte
📰 IT Security Nachrichten

🐧 What are some of the most epic moments in Linux history?


📈 16.17 Punkte
🐧 Linux Tipps

📰 Facebook Moments kommt nach Europa – aber ohne Gesichtserkennung


📈 16.17 Punkte
📰 IT Nachrichten

🍏 Telekom Magenta Moments: alle 51 EM-Spiele kostenlos im Live-Stream


📈 16.17 Punkte
🍏 iOS / Mac OS

🔧 2022 Memorable Moments


📈 16.17 Punkte
🔧 Programmierung

📰 Facebook Is Shutting Down Moments


📈 16.17 Punkte
📰 IT Security Nachrichten

🔧 🎉📣 Exciting Moments at the AWS Hong Kong re:cap! 🚀🌟


📈 16.17 Punkte
🔧 Programmierung

📰 5 Major Moments That Changed the History of Ransomware


📈 16.17 Punkte
📰 IT Security Nachrichten

🔧 Build a Portfolio in Moments: Free Template Included! 🚀


📈 16.17 Punkte
🔧 Programmierung

📰 FIFA 20: Neues TOTW Moments bringt Zocker auf die Palme


📈 16.17 Punkte
📰 IT Nachrichten

🪟 Facebook Moments kommt nach Europa


📈 16.17 Punkte
🪟 Windows Tipps

🪟 Bing turns 15; here are some significant moments, ups and downs


📈 16.17 Punkte
🪟 Windows Tipps

🔧 Season 2 Finale: Holidays, 2022’s Favorite Moments, Season 3 Sneak Peek & more!


📈 16.17 Punkte
🔧 Programmierung

🕵️ Black Mirror: Bandersnatch (Reverse engineering Netflix Interactive Video Moments!)


📈 16.17 Punkte
🕵️ Reverse Engineering

🔧 🌟 #DEVImpact2023 - My Proudest Moments, Failures and Wins


📈 16.17 Punkte
🔧 Programmierung

📰 5 Major Moments That Changed the History of Ransomware


📈 16.17 Punkte
📰 IT Security Nachrichten

matomo