私は、Splitwise の無料のピアツーピア代替手段である PeerSplit を、アイデアから立ち上げまでわずか 2 週間で構築しました。
PeerSplit は、グループの費用を分割するためのローカルファーストのアプリです。オフラインで動作し、完全に無料かつプライベートであり、サインアップや個人データは必要ありません。
これが私がそれを構築した方法とその過程で学んだすべてのことです。
私は友人やルームメイトとの出費管理に長年 Splitwise を利用してきました。しかし、最近の 1 日のトランザクション制限と煩わしい広告のせいで、使用するのがイライラしてきました。
サーバーによるデータの保存や同期を必要としない、プライバシーを最優先した無料の代替手段が必要でした。サードパーティのサーバーでは経費を信頼できません。
ワークアウト トラッカーや気を散らさないライティング アプリなど、ピアツーピアでローカル ファーストのプロジェクトに取り組んだ後、同じアプローチを経費分割に適用できることに気づきました。
こうして PeerSplit は誕生しました。アプリのデザインを始めました。
私は UI のデザインが苦手です。
数か月前には、PeerSplit ほど洗練された UI を構築できるとは思っていませんでした (Splitwise よりも UX が優れているという人もいます)。
それでは、どうやってそれを行うことができたのでしょうか? Nuxt UI。
Nuxt UI は素晴らしく、素晴らしい開発者エクスペリエンス (DX) を備えています。
@nuxt/icon、@nuxtjs/tailwindcss、@nuxtjs/colormode などの他の便利な Nuxt モジュールも付属しています。
必要なのは原色を選択することだけで、PeerSplit の UI を統合するために必要なコンポーネント (アイコン、ダーク モード、その他すべて) がすべて揃っていました。
ローカル データ ストレージと同期には、wa-sqlite 上に構築され、CRDT (競合のない複製されたデータ型) を使用する cr-sqlite を使用しました。
CRDT は競合を自動的に処理するため、ピアツーピア システムに最適です。そのため、ユーザーはオフラインで作業でき、再接続すると変更がシームレスにマージされます。
ただし、cr-sqlite 自体はネットワーク経由で変更を同期しません。変更をエクスポートおよびマージするための API のみを提供します。これらの変更をデバイス間で手動で送信する必要があります。
安全なピアツーピア同期を処理するために、ピアツーピアの分散グラフ データベースを提供する Gun.js を使用しました。
Gun の Gun.user API を使用すると、グループごとに暗号化されたノードを作成できます。グループのすべての変更はそのノードに保存され、グループ メンバーとのみ同期され、すべてがプライベートに保たれます。
ユーザーがアクションを実行すると、cr-sqlite からエクスポートされた変更を取得し、ノードにプッシュします。ユーザーがオンラインに戻ると、Gun は新しい変更を同期し、全員を最新の状態に保ちます。
これをパフォーマンスの高い方法で実装するのは困難でした。詳細については、ここでソース コードをチェックアウトできます。
Splitwise (そして現在は PeerSplit) の優れた機能の 1 つは、「借金の簡素化」です。
仕組みは次のとおりです。A が B に借金をしており、B が C に借金がある場合、A は C に直接支払うだけで、返済回数が減る可能性があります。
PeerSplit では、まず各人の純残高を計算します。次に、それらの残高を分類し、毎回少なくとも 1 人の残高がゼロになるように 1 つずつ支払いを提案します。
この並べ替えにより、全員のデバイスに同じ返済額が表示されるようになります。
これは 100% 最適というわけではありません (グループによっては最大 n-1 回の支払いがある場合もあります) が、ほとんどの場合はうまく機能します。
最適なソリューションは計算が指数関数的であり、ほんの数回の支払いしか節約できません。つまり、これがシンプルさと速度の最良のトレードオフでした!
export const groupGetPayments = (group) => { const payments = []; const balances = Object.entries(groupGetBalances(group)).map(([a, b]) => [ b, a, ]); balances.sort(); let i = 0, j = balances.length - 1; while (i balances[j][0]) { payments.push({ from: balances[i][1], to: balances[j][1], value: round(balances[j][0]), }); balances[i][0] = balances[j][0]; balances[j][0] = 0; } else { payments.push({ from: balances[i][1], to: balances[j][1], value: round(-balances[i][0]), }); balances[j][0] = balances[i][0]; balances[i][0] = 0; } } return payments; };
PeerSplit をオフライン アプリとして機能させたいと考えていましたが、複数のネイティブ アプリケーションを構築したり、アプリ ストアに公開するという長いプロセスに対処したりする手間はかけたくありませんでした。したがって、Progressive Web App (PWA) を選択するのは明らかな選択でした。
PWA はウェブ アプリとモバイル アプリの長所を組み合わせたもので、ユーザーはオフライン機能を利用しながらデバイスにインストールできます。
Nuxt アプリを PWA に変換するために、vite-pwa を使用しました。
私は Figma で SVG ロゴをデザインし、それを使用して vite-pwa のアセット ジェネレーターを通じて必要なすべての PWA アセットを生成しました。
その後、PWA マニフェストを構成すると、vite-pwa が Service Worker を自動的にセットアップしました。
アプリがオフラインでも完全に機能できるように、すべてのルートを事前レンダリングするように Nuxt を構成しました。
これで終わりです。読んでいただきありがとうございます!
PeerSplit が Product Hunt でリリースされました!初めての立ち上げなので、サポートとフィードバックをお待ちしています。
Product Hunt で PeerSplit をチェックしてください
PeerSplit は公正なソースであるため、GitHub で自由に貢献したり、機能リクエストを送信したりできます。
PeerSplit は、グループ費用を簡単かつ非公開で分割して追跡できる無料のローカルファーストのピアツーピア アプリです。
免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。
Copyright© 2022 湘ICP备2022001581号-3