Mobile notifications for iOS (#210)

* mobile: wire notification registration and listener

* implement backend components for push notifications

* refactor: agentic comment cleanup

* docs: use proper module name for particle processor

* set required env variables for push notifications

* bump version

* fix: always upsert push token on mobile start

* Revert "fix: always upsert push token on mobile start"

This reverts commit 90ff18a788.

* send push notifications regardless of online status
This commit was merged in pull request #210.
This commit is contained in:
Arjun Patel
2026-05-18 12:44:31 -07:00
committed by GitHub
parent a564ea819b
commit d262f734f0
61 changed files with 1682 additions and 531 deletions
+4 -23
View File
@@ -6,7 +6,6 @@ import (
"time"
)
// ParticleType represents the type of particle
type ParticleType string
const (
@@ -20,7 +19,6 @@ const (
// TypeThink ParticleType = "think"
)
// VisibilityMode represents how access to a particle is determined
type VisibilityMode string
const (
@@ -32,7 +30,6 @@ const (
var ErrInvalidParticleType = errors.New("invalid particle type")
var ErrInvalidVisibilityMode = errors.New("invalid visibility mode")
// ParseParticleType parses a string into a ParticleType
func ParseParticleType(s string) (ParticleType, error) {
switch s {
case string(TypeStream):
@@ -54,7 +51,6 @@ func ParseParticleType(s string) (ParticleType, error) {
}
}
// ParseVisibilityMode parses a string into a VisibilityMode
func ParseVisibilityMode(s string) (VisibilityMode, error) {
switch s {
case "", string(VisibilityNetworkAll):
@@ -68,7 +64,6 @@ func ParseVisibilityMode(s string) (VisibilityMode, error) {
}
}
// Stream status values
type StreamStatus string
const (
@@ -76,7 +71,6 @@ const (
StreamStatusClosed StreamStatus = "closed"
)
// Particle represents a content particle in the system
type Particle struct {
ID string
Type ParticleType
@@ -89,7 +83,6 @@ type Particle struct {
CreatedAt time.Time
}
// CreateInput represents the input for creating a new particle
type CreateInput struct {
Type ParticleType
NetworkID string
@@ -99,18 +92,15 @@ type CreateInput struct {
Visibility VisibilityMode
}
// ListFilter represents filtering options for listing particles
type ListFilter struct {
Types []ParticleType
}
// Cursor represents a pagination cursor for bidirectional pagination
type Cursor struct {
Position string // particle ID or timestamp
Direction string // "before" or "after"
}
// ParticleList represents a paginated list of particles
type ParticleList struct {
Particles []*Particle
HasMore bool
@@ -118,57 +108,48 @@ type ParticleList struct {
PrevCursor *Cursor
}
// StreamData represents the data stored for stream particles
type StreamData struct {
Name string `json:"name"`
Status string `json:"status"` // "open" or "closed"
Description *string `json:"description"`
}
// FolderData represents the data stored for folder particles
type FolderData struct {
Name string `json:"name"`
Color *string `json:"color"`
}
// MediaData represents the data stored for media particles
type MediaData struct {
ObjectID string `json:"object_id"` // reference to storage object
ObjectID string `json:"object_id"`
MimeType string `json:"mime_type"`
DurationMs int `json:"duration_ms"`
// Caption *string `json:"caption"`
}
// FileData represents the data stored for file particles
type FileData struct {
ObjectID string `json:"object_id"` // reference to storage object
ObjectID string `json:"object_id"`
Filename string `json:"filename"`
MimeType string `json:"mime_type"`
Size int64 `json:"size"` // in bytes
Size int64 `json:"size"` // bytes
}
// TextData represents the data stored for text particles
type TextData struct {
Content string `json:"content"`
}
// QuestData represents the data stored for quest particles
type QuestData struct {
Title string `json:"title"`
Description string `json:"description"`
Done bool `json:"done"`
Status *string `json:"status"`
AssignedTo *string `json:"assigned_to,omitempty"` // email
DueDate *string `json:"due_date,omitempty"` // ISO date string
DueDate *string `json:"due_date,omitempty"` // ISO date
}
// PaperData represents the data stored for paper particles
type PaperData struct {
Title string `json:"title"`
Content string `json:"content"` // markdown
}
// AckInfo represents an acknowledgment record
type AckInfo struct {
Email string
AckedAt time.Time