Backend: - Prisma PushToken model + chat_push_enabled flag on profiles - Migration 20260530_add_push_tokens (push_tokens table + profile flag) - Service sendChatPush with expo-server-sdk (auto-disable invalid tokens) - Fire-and-forget push trigger in sendDirectMessage + createRoomMessage - API POST /users/me/push-token (upsert) + DELETE (soft-disable) Client (rebreak-native): - usePushTokenRegistration hook: permission, getExpoPushTokenAsync, Android channel 'chat', POST to backend; idempotent per session - Notification tap deep-link: dm -> /dm?userId, room -> /room?roomId Deploy: - run_quiet spinner for silent altool/xcodebuild/gradle phases - Release-notes pipeline (--notes flag / NEXT_RELEASE.md / interactive) archived to CHANGELOG.md, printed with ASC + Play Console links - Default version bump ON (--no-bump opt-out), build cleanup - NEXT_RELEASE.md with push-notification release note
39 lines
2.1 KiB
SQL
39 lines
2.1 KiB
SQL
-- PushToken — Expo-Push-Tokens pro User-Device.
|
|
--
|
|
-- Ein User kann mehrere Geräte (iPhone + Android-Tablet etc.) haben, jedes mit eigenem
|
|
-- ExponentPushToken[xxx]. Token ist unique (kommt von Expo, nicht von uns).
|
|
--
|
|
-- Genutzt von:
|
|
-- - POST /api/users/me/push-token (Client registriert Token nach permission grant)
|
|
-- - DELETE /api/users/me/push-token (Client deregistriert bei Logout/permission revoke)
|
|
-- - server/services/push.ts sendChatPush() (Backend triggert Push nach Chat-Message)
|
|
--
|
|
-- DSGVO: bei Profile-Delete (Art-17) kaskadiert via FK ON DELETE CASCADE → alle Tokens gelöscht.
|
|
|
|
CREATE TABLE IF NOT EXISTS "rebreak"."push_tokens" (
|
|
"id" UUID NOT NULL DEFAULT gen_random_uuid(),
|
|
"user_id" UUID NOT NULL,
|
|
"token" TEXT NOT NULL,
|
|
"platform" TEXT NOT NULL, -- 'ios' | 'android'
|
|
"device_id" TEXT, -- optional: Capacitor/Expo persistent UUID
|
|
"enabled" BOOLEAN NOT NULL DEFAULT true,
|
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
"last_used_at" TIMESTAMPTZ,
|
|
|
|
CONSTRAINT "push_tokens_pkey" PRIMARY KEY ("id"),
|
|
CONSTRAINT "push_tokens_token_key" UNIQUE ("token"),
|
|
CONSTRAINT "push_tokens_user_id_fkey" FOREIGN KEY ("user_id")
|
|
REFERENCES "rebreak"."profiles"("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS "push_tokens_user_id_idx" ON "rebreak"."push_tokens"("user_id");
|
|
CREATE INDEX IF NOT EXISTS "push_tokens_enabled_idx" ON "rebreak"."push_tokens"("enabled") WHERE "enabled" = true;
|
|
|
|
-- ─── Profile.chat_push_enabled ─────────────────────────────────────────────
|
|
-- Per-User Opt-out für Chat-Push (Default ON). Granularer als Token-Enabled
|
|
-- weil hier User-Präferenz, nicht Device-State. Beide werden im Send-Pfad
|
|
-- berücksichtigt (UND-Verknüpfung).
|
|
ALTER TABLE "rebreak"."profiles"
|
|
ADD COLUMN IF NOT EXISTS "chat_push_enabled" BOOLEAN NOT NULL DEFAULT true;
|