Sign in to Twitch and Kick at the same time (multiple app sessions)
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 25/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Ambito
- authentication, backend-api-design, mobile
Direzione di ricerca
Start with lib/models/user.dart and lib/api.dart, then review the listed follow-up issues, especially #1603, which owns the AccountsModel and persistence spike. This is an epic spanning account persistence, API routing, settings, chat views, onboarding and E2E coverage; the spike and sequenced issues define the work and its completion.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Goal
Let a streamer be signed in to Twitch and Kick (and YouTube) at the same time, so a simulcaster can read, send and moderate on all of their own channels without signing out and back in.
Approach: frontend only. The app keeps one active Firebase session per platform. Accounts are not linked on the server. Each Twitch, Kick or YouTube sign-in stays its own independent Firebase user, as #1379 decided. Multi-channel views are unchanged and still need no account. This epic is about who you can act as.
Where we are today
- Each sign-in goes through
/auth/{provider}/redirectand returns a custom token for that account's own uid.UserModelsigns it in on the single defaultFirebaseAuth.instance(lib/models/user.dart). - Per-user data is owner-only in the rules (
profiles/{uid},streamlabs/{uid},streamelements/{uid},realtimecash/{uid}). Every callable goes through oneApi(FirebaseFunctions.instance)(lib/api.dart:11), so all calls run as that one user. UserModel.userChannelis a singleChannel.ViewsModel.sendChannel(account)only sends on that account's provider.
Design
One FirebaseApp per signed-in account
Firebase scopes auth state to a FirebaseApp. The app therefore initializes one named app per account slot with the same DefaultFirebaseOptions. Each slot has its own FirebaseAuth, FirebaseFirestore and FirebaseFunctions via instanceFor(app:). The native SDKs persist auth per app name, so every session survives restarts. A spike task verifies this on Android, iOS and macOS.
[DEFAULT]keeps whatever account is signed in today, so existing users need no migration.- Each additional account goes in
account-{provider}. - Only one account per provider.
- A new
AccountsModelowns the slots:accounts: List<Account>, whereAccount = {provider, app, user, channel}signIn(provider, customToken)signOut(account)signOutAll()accountFor(Channel), which returns the account on that channel's provider when the channel is that account's own
- Signing in with a provider that already has a slot replaces the account in it.
Routing calls to the right account
Apibecomes per account:Api.forAccount(account)wrapsFirebaseFunctions.instanceFor(app: account.app). Each callable then carries the right user's ID token, and the existing backenduid → profile.{provider}lookups just work.- Send, reply and moderation pick the account by the target channel's provider. Profiles and donation connections (
streamlabs,streamelements,realtimecash, wallet) are read and written through the owning account's Firestore and Auth. - Public chat data (
channels/**) keeps using the default Firestore instance. - Analytics and Crashlytics user id: use the first account. Add a
user_providersproperty listing all of them.
Why not link accounts on the backend
Server-side linking (one uid holding several platform accounts) needs link codes, conflict handling for users who already signed in to Kick separately, account merges, unlink, and parity work in the Go agent. Keeping sessions on the device needs no backend, rules or data migration changes. The cost is that the second account has to be signed in again on each new device.
App UX
- By default, views show all of the user's own channels, so a simulcaster opens to merged Twitch + Kick chat.
- Destination picker on the left of the message input. It lists the channels in view where you have a signed-in account on that channel's provider, and the message goes to the selected one. Emotes, autocomplete, slash commands, the length limit and the hint text all follow the selected channel. There is no send-to-all, because emotes and slash commands are per channel.
- Settings → Accounts lists the signed-in accounts, with "Add account" and per-account sign out. This includes the QR companion path: the companion token is signed in on the target slot.
- After the first sign-in, onboarding offers "Also stream on Kick/Twitch? Add it."
Sequencing
There is no backend work.
- #1603:
AccountsModeland the persistence spike. This is the foundation, and the spike decides whether the design holds. - #1607: per-account
UserModelandApi. - In parallel:
- #1605 (route calls and settings to the owning account), then #1609 (views, sending and moderation)
- #1608 (Accounts settings), then #1610 (onboarding prompt)
- #1611: E2E tests.
Decisions
- No send-to-all. A destination picker on the left of the input selects the one channel a message goes to. This was revised from send-to-all, because emotes and slash commands are per channel.
- Donation connections (Streamlabs, StreamElements, realtimecash, wallet) are per account, matching how the data is already stored.
- Cloud Functions migration (#1551): this epic is frontend only. Callables keep going through
https://rtchat-api.rtirl.com/<name>(the per-accountApiuseshttpsCallableFromUrlwith the same hostname). OAuth and companion sign-in stay on Cloud Functions atchat.rtirl.com/auth/…. No changes infunctions/oragent/.
Out of scope
Server-side account linking. Syncing the set of signed-in accounts across devices. Several accounts on the same provider.
- Lingua principale
- Dart
- Stelle
- 49
- Fork
- 25
- Merge medio
- 12h 6m
- PR unite (30g)
- 188
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di muxable/rtchat
-
enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 79/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 57/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 25/100
I maintainer di solito rispondono entro 1 giorno
-
enhancement
Difficoltà 5/5 Più di una settimana Idoneità per principianti 15/100
I maintainer di solito rispondono entro 1 giorno
-
enhancement
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di muxable/rtchat
Issue simili
-
[Bug] 附近设备权限未申请Apertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 67/100
bggRGjQaUbCoE/PiliPlus#3369 ·
I maintainer di solito rispondono entro 1 giorno
-
auto-implement
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
bannzai/kashakeibo#143 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
-
[lsp] Remove DartAnalysisServerService.serverReadyForRequest() from EnableDartSupportForModuleApertaP1
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
flutter/flutter-intellij#9177 ·
I maintainer di solito rispondono entro 1 giorno
-
bug enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
AOSSIE-Org/Ell-ena#356 ·
I maintainer di solito rispondono entro 1 giorno