Implement Android subscription system with freemium limitations
Major subscription system implementation for Android: BillingManager (Android): - Full Google Play Billing Library integration - Product loading, purchase flow, and acknowledgment - Backend verification via APILayer.verifyAndroidPurchase() - Purchase restoration for returning users - Error handling and connection state management SubscriptionHelper (Shared): - New limit checking methods: isResidencesBlocked(), isTasksBlocked(), isContractorsBlocked(), isDocumentsBlocked() - Add permission checks: canAddProperty(), canAddTask(), canAddContractor(), canAddDocument() - Enforces freemium rules based on backend limitationsEnabled flag Screen Updates: - ContractorsScreen: Show upgrade prompt when contractors limit=0 - DocumentsScreen: Show upgrade prompt when documents limit=0 - ResidencesScreen: Show upgrade prompt when properties limit reached - ResidenceDetailScreen: Show upgrade prompt when tasks limit reached UpgradeFeatureScreen: - Enhanced with feature benefits comparison - Dynamic content from backend upgrade triggers - Platform-specific purchase buttons Additional changes: - DataCache: Added O(1) lookup maps for ID resolution - New minimal models (TaskMinimal, ContractorMinimal, ResidenceMinimal) - TaskApi: Added archive/unarchive endpoints - Added Google Billing Library dependency - iOS SubscriptionCache and UpgradePromptView updates 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -112,6 +112,37 @@ data class TaskCancelResponse(
|
||||
val task: TaskDetail
|
||||
)
|
||||
|
||||
/**
|
||||
* Request model for PATCH updates to a task.
|
||||
* Used for status changes and archive/unarchive operations.
|
||||
* All fields are optional - only provided fields will be updated.
|
||||
*/
|
||||
@Serializable
|
||||
data class TaskPatchRequest(
|
||||
val status: Int? = null, // Status ID to update
|
||||
val archived: Boolean? = null // Archive/unarchive flag
|
||||
)
|
||||
|
||||
/**
|
||||
* Minimal task model for list/kanban views.
|
||||
* Uses IDs instead of nested objects for efficiency.
|
||||
* Resolve IDs to full objects via DataCache.getTaskCategory(), etc.
|
||||
*/
|
||||
@Serializable
|
||||
data class TaskMinimal(
|
||||
val id: Int,
|
||||
val title: String,
|
||||
val description: String? = null,
|
||||
@SerialName("due_date") val dueDate: String? = null,
|
||||
@SerialName("next_scheduled_date") val nextScheduledDate: String? = null,
|
||||
@SerialName("category_id") val categoryId: Int? = null,
|
||||
@SerialName("frequency_id") val frequencyId: Int,
|
||||
@SerialName("priority_id") val priorityId: Int,
|
||||
@SerialName("status_id") val statusId: Int? = null,
|
||||
@SerialName("completion_count") val completionCount: Int? = null,
|
||||
val archived: Boolean = false
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TaskColumn(
|
||||
val name: String,
|
||||
@@ -119,7 +150,7 @@ data class TaskColumn(
|
||||
@SerialName("button_types") val buttonTypes: List<String>,
|
||||
val icons: Map<String, String>,
|
||||
val color: String,
|
||||
val tasks: List<TaskDetail>,
|
||||
val tasks: List<TaskDetail>, // Keep using TaskDetail for now - will be TaskMinimal after full migration
|
||||
val count: Int
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user