Compare commits
3 Commits
ios-disabl
...
platformse
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
243c3eea32 | ||
|
|
1d0c8ac3cf | ||
|
|
18fc31d45a |
11
.eslintrc.js
11
.eslintrc.js
@@ -33,6 +33,15 @@ module.exports = {
|
|||||||
"@typescript-eslint/no-explicit-any": "error",
|
"@typescript-eslint/no-explicit-any": "error",
|
||||||
"@typescript-eslint/explicit-function-return-type": "off",
|
"@typescript-eslint/explicit-function-return-type": "off",
|
||||||
"@typescript-eslint/no-unnecessary-type-constraint": "off",
|
"@typescript-eslint/no-unnecessary-type-constraint": "off",
|
||||||
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }]
|
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
|
||||||
|
// Prevent usage of deprecated $updateSettings method
|
||||||
|
'no-restricted-properties': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
object: '$',
|
||||||
|
property: 'updateSettings',
|
||||||
|
message: 'Use $saveSettings, $saveUserSettings, or $saveMySettings instead of the deprecated $updateSettings method.'
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
474
docs/PlatformServiceMixin-Interface-Consolidation.md
Normal file
474
docs/PlatformServiceMixin-Interface-Consolidation.md
Normal file
@@ -0,0 +1,474 @@
|
|||||||
|
# PlatformServiceMixin Interface Consolidation
|
||||||
|
|
||||||
|
**Author**: Matthew Raymer
|
||||||
|
**Date**: 2025-08-13
|
||||||
|
**Status**: 🎯 **PLANNING** - Ready for Implementation
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This document describes the planned consolidation of PlatformServiceMixin interfaces to
|
||||||
|
eliminate duplication and ensure consistency between `IPlatformServiceMixin` and
|
||||||
|
`ComponentCustomProperties` interfaces. **IMPORTANT**: The planned consolidation will
|
||||||
|
introduce a breaking change by removing the deprecated `$updateSettings` method, which
|
||||||
|
will cause runtime failures in components that still use it.
|
||||||
|
|
||||||
|
## Problem Statement
|
||||||
|
|
||||||
|
The current PlatformServiceMixin has two separate interfaces with overlapping methods:
|
||||||
|
|
||||||
|
1. **`IPlatformServiceMixin`** - Exported interface for component typing
|
||||||
|
2. **`ComponentCustomProperties`** - Vue declaration merging interface
|
||||||
|
|
||||||
|
This causes:
|
||||||
|
- Duplicate method definitions
|
||||||
|
- Inconsistent interface maintenance
|
||||||
|
- Confusion about which interface to use
|
||||||
|
- Deprecated methods still appearing in interfaces
|
||||||
|
|
||||||
|
### ComponentCustomProperties Usage Analysis
|
||||||
|
|
||||||
|
**Important Discovery**: `ComponentCustomProperties` is **NOT actually used** anywhere in
|
||||||
|
the codebase for runtime functionality. It exists solely for **TypeScript declaration
|
||||||
|
merging** to provide:
|
||||||
|
|
||||||
|
- Method autocomplete when typing `this.$` in Vue components
|
||||||
|
- Type checking for mixin methods
|
||||||
|
- IntelliSense support in development environments
|
||||||
|
- Compile-time validation that methods exist
|
||||||
|
|
||||||
|
All components use PlatformServiceMixin methods by explicitly importing the mixin and
|
||||||
|
adding it to the `@Component` decorator.
|
||||||
|
|
||||||
|
## Planned Solution: Interface Consolidation
|
||||||
|
|
||||||
|
### Single Source of Truth
|
||||||
|
|
||||||
|
The `IPlatformServiceMixin` interface will serve as the single source of truth for all
|
||||||
|
PlatformServiceMixin methods. The `ComponentCustomProperties` interface will extend this
|
||||||
|
interface to ensure complete consistency.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Single interface definition
|
||||||
|
export interface IPlatformServiceMixin {
|
||||||
|
// All methods defined here
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vue declaration merging extends the main interface
|
||||||
|
declare module "@vue/runtime-core" {
|
||||||
|
interface ComponentCustomProperties extends IPlatformServiceMixin {
|
||||||
|
// All methods inherited from IPlatformServiceMixin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deprecated Method Removal - PLANNED BREAKING CHANGE
|
||||||
|
|
||||||
|
**⚠️ CRITICAL**: The deprecated `$updateSettings` method will be completely removed
|
||||||
|
from both interfaces AND the implementation. This is a **PLANNED BREAKING CHANGE** that
|
||||||
|
will:
|
||||||
|
|
||||||
|
- **Prevent TypeScript compilation** (method not found in interfaces)
|
||||||
|
- **Cause runtime crashes** (method not found in mixin implementation)
|
||||||
|
- **Break existing functionality** in components that use it
|
||||||
|
|
||||||
|
**Methods to Remove**:
|
||||||
|
- ❌ **`$updateSettings(changes, did?)`** - Will be completely removed from interfaces and implementation
|
||||||
|
|
||||||
|
**Required Replacement Methods**:
|
||||||
|
- ✅ **`$saveSettings(changes)`** - for default settings
|
||||||
|
- ✅ **`$saveUserSettings(did, changes)`** - for user-specific settings
|
||||||
|
- ✅ **`$saveMySettings(changes)`** - for current user's settings
|
||||||
|
|
||||||
|
## Current Status: PLANNING PHASE
|
||||||
|
|
||||||
|
### What Will Happen
|
||||||
|
|
||||||
|
1. **Interface Consolidation**: Will eliminate duplication between interfaces
|
||||||
|
2. **Deprecated Method Removal**: Will remove runtime functionality for `$updateSettings`
|
||||||
|
3. **Component Migration**: Will be required for components using the removed method
|
||||||
|
|
||||||
|
### Impact Assessment
|
||||||
|
|
||||||
|
#### Immediate Issues After Implementation
|
||||||
|
- **Build failures**: TypeScript compilation errors
|
||||||
|
- **Runtime crashes**: `$updateSettings` method not found
|
||||||
|
- **Broken functionality**: Settings updates will fail
|
||||||
|
|
||||||
|
#### Affected Components
|
||||||
|
The following components actively use `$updateSettings` and will break after implementation:
|
||||||
|
|
||||||
|
- `NewActivityView.vue` - 6 method references
|
||||||
|
- `SearchAreaView.vue` - 2 method references
|
||||||
|
- `FeedFilters.vue` - 4 method references
|
||||||
|
- `HelpView.vue` - 1 method reference
|
||||||
|
- `HelpNotificationsView.vue` - 1 method reference
|
||||||
|
- `ContactQRScanShowView.vue` - 2 method references
|
||||||
|
- `NewEditAccountView.vue` - 1 method reference
|
||||||
|
- `SharedPhotoView.vue` - 1 method reference
|
||||||
|
- `UserNameDialog.vue` - 1 method reference
|
||||||
|
- `OnboardingDialog.vue` - 2 method references
|
||||||
|
|
||||||
|
**Total**: ~20+ method references across multiple components
|
||||||
|
|
||||||
|
## Implementation Plan
|
||||||
|
|
||||||
|
### Phase 1: Stabilization (Before Breaking Change)
|
||||||
|
|
||||||
|
1. **Plan migration strategy** for all affected components
|
||||||
|
2. **Create migration script** to automate method replacement
|
||||||
|
3. **Update test coverage** for new method patterns
|
||||||
|
|
||||||
|
### Phase 2: Interface Consolidation
|
||||||
|
|
||||||
|
1. **Consolidate interfaces** - Eliminate duplication between `IPlatformServiceMixin` and `ComponentCustomProperties`
|
||||||
|
2. **Remove deprecated method** from interfaces
|
||||||
|
3. **Remove deprecated method** from implementation
|
||||||
|
|
||||||
|
### Phase 3: Component Migration
|
||||||
|
|
||||||
|
1. **Audit all components** using `$updateSettings`
|
||||||
|
2. **Categorize usage patterns** (default vs. user-specific settings)
|
||||||
|
3. **Replace method calls** with appropriate new methods
|
||||||
|
4. **Update tests** to use new method patterns
|
||||||
|
5. **Validate functionality** after each change
|
||||||
|
|
||||||
|
## Migration Strategy
|
||||||
|
|
||||||
|
### Phase 1: Preparation (Before Breaking Change)
|
||||||
|
|
||||||
|
1. **Audit all components** using `$updateSettings`
|
||||||
|
2. **Categorize usage patterns** (default vs. user-specific settings)
|
||||||
|
3. **Create migration plan** for each component
|
||||||
|
4. **Update test coverage** for new method patterns
|
||||||
|
|
||||||
|
### Phase 2: Interface Consolidation
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Remove from IPlatformServiceMixin interface
|
||||||
|
// Remove from ComponentCustomProperties interface
|
||||||
|
// Remove implementation from PlatformServiceMixin
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 3: Component Migration (Systematic)
|
||||||
|
|
||||||
|
1. **Replace method calls** with appropriate new methods
|
||||||
|
2. **Update tests** to use new method patterns
|
||||||
|
3. **Validate functionality** after each change
|
||||||
|
4. **Monitor for any missed usage**
|
||||||
|
|
||||||
|
## Changes to Be Made
|
||||||
|
|
||||||
|
### Interface Consolidation
|
||||||
|
|
||||||
|
- **Consolidate** `IPlatformServiceMixin` and `ComponentCustomProperties` interfaces
|
||||||
|
- **Eliminate duplication** by making `ComponentCustomProperties` extend
|
||||||
|
`IPlatformServiceMixin`
|
||||||
|
- **Single source of truth** for all PlatformServiceMixin methods
|
||||||
|
|
||||||
|
### Deprecated Method Removal - PLANNED BREAKING CHANGE
|
||||||
|
|
||||||
|
- **Remove** deprecated `$updateSettings` method from `IPlatformServiceMixin` interface
|
||||||
|
- **Remove** deprecated `$updateSettings` method from `ComponentCustomProperties`
|
||||||
|
interface
|
||||||
|
- **Remove** deprecated `$updateSettings` method implementation
|
||||||
|
- **⚠️ This will break existing functionality**
|
||||||
|
|
||||||
|
### Code Cleanup
|
||||||
|
|
||||||
|
- **Eliminate** duplicate method definitions
|
||||||
|
- **Remove** outdated comments about deprecated methods
|
||||||
|
- **Consolidate** interface maintenance to single location
|
||||||
|
|
||||||
|
## Files to Be Modified
|
||||||
|
|
||||||
|
### `src/utils/PlatformServiceMixin.ts`
|
||||||
|
|
||||||
|
- Remove deprecated `$updateSettings` method from `IPlatformServiceMixin` interface
|
||||||
|
- Remove deprecated `$updateSettings` method from `ComponentCustomProperties`
|
||||||
|
interface
|
||||||
|
- Remove deprecated `$updateSettings` method implementation
|
||||||
|
- Make `ComponentCustomProperties` extend `IPlatformServiceMixin` for consistency
|
||||||
|
- Add comments explaining deprecated method removal
|
||||||
|
|
||||||
|
## Proper Usage Patterns
|
||||||
|
|
||||||
|
### Settings Management
|
||||||
|
|
||||||
|
#### Default Settings (Global)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Save to master settings table
|
||||||
|
await this.$saveSettings({
|
||||||
|
apiServer: 'https://api.example.com',
|
||||||
|
defaultLanguage: 'en'
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### User-Specific Settings
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Save to user-specific settings table
|
||||||
|
await this.$saveUserSettings(userDid, {
|
||||||
|
firstName: 'John',
|
||||||
|
isRegistered: true,
|
||||||
|
profileImageUrl: 'https://example.com/avatar.jpg'
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Current User Settings
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Automatically uses current activeDid
|
||||||
|
await this.$saveMySettings({
|
||||||
|
firstName: 'John',
|
||||||
|
isRegistered: true
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database Operations
|
||||||
|
|
||||||
|
#### Ultra-Concise Methods
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Shortest possible names for frequent operations
|
||||||
|
const contacts = await this.$contacts();
|
||||||
|
const settings = await this.$settings();
|
||||||
|
const result = await this.$db("SELECT * FROM table WHERE id = ?", [id]);
|
||||||
|
await this.$exec("UPDATE table SET field = ? WHERE id = ?", [value, id]);
|
||||||
|
const row = await this.$one("SELECT * FROM table WHERE id = ?", [id]);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Query + Mapping Combo
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Automatic result mapping
|
||||||
|
const users = await this.$query<User>("SELECT * FROM users WHERE active = ?", [true]);
|
||||||
|
const firstUser = await this.$first<User>("SELECT * FROM users WHERE id = ?", [id]);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Entity Operations
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// High-level entity management
|
||||||
|
await this.$insertContact({
|
||||||
|
did: 'did:example:123',
|
||||||
|
name: 'John Doe',
|
||||||
|
publicKeyBase64: 'base64key'
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.$updateContact('did:example:123', {
|
||||||
|
name: 'John Smith'
|
||||||
|
});
|
||||||
|
|
||||||
|
const contact = await this.$getContact('did:example:123');
|
||||||
|
await this.$deleteContact('did:example:123');
|
||||||
|
```
|
||||||
|
|
||||||
|
## Migration Guide
|
||||||
|
|
||||||
|
### From $updateSettings to Proper Methods
|
||||||
|
|
||||||
|
#### Before (Deprecated - Will Break After Implementation)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ❌ DEPRECATED - This will cause runtime crashes after implementation
|
||||||
|
await this.$updateSettings({ firstName: 'John' });
|
||||||
|
await this.$updateSettings({ isRegistered: true }, userDid);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### After (Required - After Migration)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ✅ For default/global settings
|
||||||
|
await this.$saveSettings({ firstName: 'John' });
|
||||||
|
|
||||||
|
// ✅ For user-specific settings
|
||||||
|
await this.$saveUserSettings(userDid, { isRegistered: true });
|
||||||
|
|
||||||
|
// ✅ For current user (automatically uses activeDid)
|
||||||
|
await this.$saveMySettings({ firstName: 'John' });
|
||||||
|
```
|
||||||
|
|
||||||
|
### Component Implementation
|
||||||
|
|
||||||
|
#### Class Component with Mixin
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Component, Vue } from 'vue-facing-decorator';
|
||||||
|
import { PlatformServiceMixin } from '@/utils/PlatformServiceMixin';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
mixins: [PlatformServiceMixin]
|
||||||
|
})
|
||||||
|
export default class MyComponent extends Vue {
|
||||||
|
async saveUserProfile() {
|
||||||
|
// Use the consolidated interface methods
|
||||||
|
await this.$saveUserSettings(this.activeDid, {
|
||||||
|
firstName: this.firstName,
|
||||||
|
lastName: this.lastName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadData() {
|
||||||
|
// Use ultra-concise methods
|
||||||
|
const contacts = await this.$contacts();
|
||||||
|
const settings = await this.$settings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Composition API with Mixin
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { PlatformServiceMixin } from '@/utils/PlatformServiceMixin';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
mixins: [PlatformServiceMixin],
|
||||||
|
async setup() {
|
||||||
|
// Methods available through mixin
|
||||||
|
const saveSettings = async (changes) => {
|
||||||
|
return await this.$saveSettings(changes);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
saveSettings
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Impact
|
||||||
|
|
||||||
|
### Benefits
|
||||||
|
|
||||||
|
- **Eliminates interface duplication** - single source of truth
|
||||||
|
- **Forces proper method usage** - no more deprecated `$updateSettings`
|
||||||
|
- **Improves maintainability** - changes only needed in one place
|
||||||
|
- **Enhances type safety** - consistent interfaces across all contexts
|
||||||
|
- **Better developer experience** - clear method patterns and documentation
|
||||||
|
|
||||||
|
### Breaking Changes - CRITICAL
|
||||||
|
|
||||||
|
- **`$updateSettings` method no longer available** - will cause runtime crashes
|
||||||
|
- **Interface consolidation** - ensures consistent method availability
|
||||||
|
- **App will not work** until migration is complete
|
||||||
|
|
||||||
|
### Migration Required
|
||||||
|
|
||||||
|
- **All components using `$updateSettings`** must be updated to use proper settings
|
||||||
|
methods
|
||||||
|
- **Systematic migration** needed across multiple components
|
||||||
|
- **Breaking change** will be introduced after implementation
|
||||||
|
|
||||||
|
## Security Audit Checklist
|
||||||
|
|
||||||
|
- ✅ **Input Validation**: All database methods include proper parameter validation
|
||||||
|
- ✅ **SQL Injection Protection**: Parameterized queries used throughout
|
||||||
|
- ✅ **Access Control**: User-specific settings properly isolated by DID
|
||||||
|
- ✅ **Error Handling**: Comprehensive error logging and graceful fallbacks
|
||||||
|
- ✅ **Type Safety**: Full TypeScript support prevents invalid data types
|
||||||
|
- ✅ **Transaction Management**: Automatic rollback on database errors
|
||||||
|
|
||||||
|
## Performance Optimizations
|
||||||
|
|
||||||
|
### Caching Strategy
|
||||||
|
|
||||||
|
- **NO CACHING**: Settings loaded fresh every time (no stale data)
|
||||||
|
- **NO CACHING**: Contacts loaded fresh every time (no stale data)
|
||||||
|
- **NO CACHING**: All database operations return fresh data
|
||||||
|
- Memory-efficient data structures
|
||||||
|
|
||||||
|
### Database Operations
|
||||||
|
|
||||||
|
- Ultra-concise method names reduce boilerplate
|
||||||
|
- Automatic transaction management
|
||||||
|
- Optimized SQL queries with proper indexing
|
||||||
|
|
||||||
|
### Resource Management
|
||||||
|
|
||||||
|
- **NO WeakMap-based caching** - all caching code is commented out
|
||||||
|
- **NO cache invalidation** - not needed since nothing is cached
|
||||||
|
- **NO memory leaks from caching** - because there is no caching
|
||||||
|
- Efficient component lifecycle management
|
||||||
|
|
||||||
|
### Caching Confusion Clarification
|
||||||
|
|
||||||
|
**Important Note**: There are several references to "caching" throughout the codebase
|
||||||
|
that are **misleading and incorrect**:
|
||||||
|
|
||||||
|
#### What the Documentation Claims vs. Reality
|
||||||
|
|
||||||
|
| Claimed Feature | Actual Reality |
|
||||||
|
|----------------|----------------|
|
||||||
|
| "Smart caching layer with TTL" | ❌ **NO CACHING IMPLEMENTED** |
|
||||||
|
| "WeakMap-based caching prevents memory leaks" | ❌ **ALL CACHING CODE COMMENTED OUT** |
|
||||||
|
| "Cached database operations" | ❌ **EVERYTHING LOADED FRESH** |
|
||||||
|
| "Settings shortcuts for ultra-frequent update patterns" | ❌ **NO CACHING, JUST CONVENIENCE METHODS** |
|
||||||
|
|
||||||
|
#### Evidence of No Caching
|
||||||
|
|
||||||
|
1. **All caching code is commented out** in `PlatformServiceMixin.ts`
|
||||||
|
2. **Settings methods explicitly state** "WITHOUT caching" in comments
|
||||||
|
3. **Contacts method explicitly states** "always fresh" in comments
|
||||||
|
4. **No cache invalidation logic** exists
|
||||||
|
5. **No TTL management** exists
|
||||||
|
|
||||||
|
#### Why This Confusion Exists
|
||||||
|
|
||||||
|
The caching system was **planned and designed** but **never implemented**. The
|
||||||
|
documentation and comments reflect the original design intent, not the current
|
||||||
|
reality. This is a case where the documentation is ahead of the implementation.
|
||||||
|
|
||||||
|
## Testing Considerations
|
||||||
|
|
||||||
|
### Interface Testing
|
||||||
|
|
||||||
|
- All methods should be tested through the consolidated interface
|
||||||
|
- Mock PlatformService for unit testing
|
||||||
|
- Integration tests for database operations
|
||||||
|
|
||||||
|
### Migration Testing
|
||||||
|
|
||||||
|
- Verify deprecated methods are no longer accessible
|
||||||
|
- Test new method signatures work correctly
|
||||||
|
- Ensure backward compatibility for existing functionality
|
||||||
|
|
||||||
|
### Performance Testing
|
||||||
|
|
||||||
|
- Monitor database query performance
|
||||||
|
- Verify caching behavior works as expected
|
||||||
|
- Test memory usage patterns
|
||||||
|
|
||||||
|
## Next Steps - IMPLEMENTATION PLAN
|
||||||
|
|
||||||
|
1. **Plan migration strategy** - Systematic approach to updating components
|
||||||
|
2. **Execute component migration** - Update all affected components
|
||||||
|
3. **Implement interface consolidation** - Remove deprecated method and consolidate interfaces
|
||||||
|
4. **Validate functionality** - Ensure all settings operations work correctly
|
||||||
|
5. **Update documentation** - Reflect final state after implementation
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
The planned PlatformServiceMixin interface consolidation will provide:
|
||||||
|
|
||||||
|
- **Single source of truth** for all mixin methods
|
||||||
|
- **Elimination of deprecated methods** to prevent confusion
|
||||||
|
- **Consistent interface** across all usage contexts
|
||||||
|
- **Improved maintainability** and type safety
|
||||||
|
- **Better developer experience** with clear method patterns
|
||||||
|
|
||||||
|
**⚠️ CRITICAL**: This consolidation will introduce a breaking change that requires
|
||||||
|
careful planning and execution. The app will not work after implementation until:
|
||||||
|
|
||||||
|
1. **All components are migrated** to use the new methods, or
|
||||||
|
2. **The deprecated method is restored** temporarily during migration
|
||||||
|
|
||||||
|
The fact that `ComponentCustomProperties` is only used for TypeScript support
|
||||||
|
validates our approach - we're consolidating interfaces that serve different
|
||||||
|
purposes (runtime vs. TypeScript support) while eliminating duplication.
|
||||||
|
|
||||||
|
**Status**: Planning phase - ready for implementation
|
||||||
|
**Priority**: High - requires careful migration planning
|
||||||
|
**Dependencies**: Component updates required before breaking change
|
||||||
|
**Stakeholders**: Development team, QA team
|
||||||
28
scripts/check-update-settings.sh
Executable file
28
scripts/check-update-settings.sh
Executable file
@@ -0,0 +1,28 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# CI check script to ensure no new $updateSettings usage is introduced
|
||||||
|
# This script will fail CI if any $updateSettings calls are found
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "🔍 Checking for deprecated \$updateSettings usage..."
|
||||||
|
|
||||||
|
# Search for $updateSettings usage in source files
|
||||||
|
USAGE_COUNT=$(grep -r "\$updateSettings" src/ --include="*.vue" --include="*.ts" --include="*.js" | wc -l)
|
||||||
|
|
||||||
|
if [ "$USAGE_COUNT" -gt 0 ]; then
|
||||||
|
echo "❌ Found $USAGE_COUNT usage(s) of deprecated \$updateSettings method:"
|
||||||
|
echo ""
|
||||||
|
grep -r "\$updateSettings" src/ --include="*.vue" --include="*.ts" --include="*.js" -n
|
||||||
|
echo ""
|
||||||
|
echo "⚠️ Migration required:"
|
||||||
|
echo " - For global settings: use \$saveSettings(changes)"
|
||||||
|
echo " - For user-specific settings: use \$saveUserSettings(did, changes)"
|
||||||
|
echo " - For current user settings: use \$saveMySettings(changes)"
|
||||||
|
echo ""
|
||||||
|
echo "Run 'node scripts/migrate-update-settings.js' for migration guidance."
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "✅ No \$updateSettings usage found!"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
110
scripts/migrate-update-settings.js
Normal file
110
scripts/migrate-update-settings.js
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migration script to replace deprecated $updateSettings calls
|
||||||
|
* with the appropriate new methods ($saveSettings, $saveUserSettings, $saveMySettings)
|
||||||
|
*
|
||||||
|
* Usage: node scripts/migrate-update-settings.js
|
||||||
|
*
|
||||||
|
* This script will:
|
||||||
|
* 1. Find all files containing $updateSettings calls
|
||||||
|
* 2. Show the migration suggestions for each call
|
||||||
|
* 3. Optionally perform the replacements
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const glob = require('glob');
|
||||||
|
|
||||||
|
// Migration patterns
|
||||||
|
const MIGRATION_PATTERNS = [
|
||||||
|
{
|
||||||
|
pattern: /\$updateSettings\(\s*(\{[^}]*\})\s*\)/g,
|
||||||
|
replacement: '$saveMySettings($1)',
|
||||||
|
description: 'Single parameter (changes only) -> $saveMySettings'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: /\$updateSettings\(\s*(\{[^}]*\})\s*,\s*([^)]+)\s*\)/g,
|
||||||
|
replacement: '$saveUserSettings($2, $1)',
|
||||||
|
description: 'Two parameters (changes, did) -> $saveUserSettings(did, changes)'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Find all Vue and TypeScript files
|
||||||
|
function findFiles() {
|
||||||
|
const patterns = [
|
||||||
|
'src/**/*.vue',
|
||||||
|
'src/**/*.ts',
|
||||||
|
'src/**/*.js'
|
||||||
|
];
|
||||||
|
|
||||||
|
let files = [];
|
||||||
|
patterns.forEach(pattern => {
|
||||||
|
files = files.concat(glob.sync(pattern, { ignore: ['node_modules/**', 'dist/**'] }));
|
||||||
|
});
|
||||||
|
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Analyze a file for $updateSettings usage
|
||||||
|
function analyzeFile(filePath) {
|
||||||
|
const content = fs.readFileSync(filePath, 'utf8');
|
||||||
|
const lines = content.split('\n');
|
||||||
|
const usages = [];
|
||||||
|
|
||||||
|
lines.forEach((line, index) => {
|
||||||
|
if (line.includes('$updateSettings')) {
|
||||||
|
usages.push({
|
||||||
|
line: index + 1,
|
||||||
|
content: line.trim(),
|
||||||
|
file: filePath
|
||||||
|
});
|
||||||
|
console.log(`\n${filePath}:${index + 1}`);
|
||||||
|
console.log(` ${line.trim()}`);
|
||||||
|
|
||||||
|
// Show migration suggestion
|
||||||
|
MIGRATION_PATTERNS.forEach(pattern => {
|
||||||
|
if (pattern.pattern.test(line)) {
|
||||||
|
const replacement = line.replace(pattern.pattern, pattern.replacement);
|
||||||
|
console.log(` → ${replacement.trim()}`);
|
||||||
|
console.log(` ${pattern.description}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return usages;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main execution
|
||||||
|
function main() {
|
||||||
|
console.log('🔍 Finding files with $updateSettings usage...\n');
|
||||||
|
|
||||||
|
const files = findFiles();
|
||||||
|
let totalUsages = 0;
|
||||||
|
|
||||||
|
files.forEach(file => {
|
||||||
|
const usages = analyzeFile(file);
|
||||||
|
totalUsages += usages.length;
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`\n📊 Summary:`);
|
||||||
|
console.log(` Files scanned: ${files.length}`);
|
||||||
|
console.log(` Total usages: ${totalUsages}`);
|
||||||
|
|
||||||
|
if (totalUsages > 0) {
|
||||||
|
console.log(`\n📝 Migration Guide:`);
|
||||||
|
console.log(` 1. For global/default settings: use $saveSettings(changes)`);
|
||||||
|
console.log(` 2. For user-specific settings: use $saveUserSettings(did, changes)`);
|
||||||
|
console.log(` 3. For current user settings: use $saveMySettings(changes)`);
|
||||||
|
console.log(`\n⚠️ Note: $updateSettings is deprecated and will be removed in a future version.`);
|
||||||
|
} else {
|
||||||
|
console.log(`\n✅ No $updateSettings usage found!`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
main();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { findFiles, analyzeFile, MIGRATION_PATTERNS };
|
||||||
@@ -141,7 +141,7 @@ export default class FeedFilters extends Vue {
|
|||||||
this.settingChanged = true;
|
this.settingChanged = true;
|
||||||
this.hasVisibleDid = !this.hasVisibleDid;
|
this.hasVisibleDid = !this.hasVisibleDid;
|
||||||
|
|
||||||
await this.$updateSettings({
|
await this.$saveMySettings({
|
||||||
filterFeedByVisible: this.hasVisibleDid,
|
filterFeedByVisible: this.hasVisibleDid,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -156,7 +156,7 @@ export default class FeedFilters extends Vue {
|
|||||||
activeDid: this.activeDid,
|
activeDid: this.activeDid,
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.$updateSettings({
|
await this.$saveMySettings({
|
||||||
filterFeedByNearby: this.isNearby,
|
filterFeedByNearby: this.isNearby,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -168,7 +168,7 @@ export default class FeedFilters extends Vue {
|
|||||||
this.settingChanged = true;
|
this.settingChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.$updateSettings({
|
await this.$saveMySettings({
|
||||||
filterFeedByNearby: false,
|
filterFeedByNearby: false,
|
||||||
filterFeedByVisible: false,
|
filterFeedByVisible: false,
|
||||||
});
|
});
|
||||||
@@ -182,7 +182,7 @@ export default class FeedFilters extends Vue {
|
|||||||
this.settingChanged = true;
|
this.settingChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.$updateSettings({
|
await this.$saveMySettings({
|
||||||
filterFeedByNearby: true,
|
filterFeedByNearby: true,
|
||||||
filterFeedByVisible: true,
|
filterFeedByVisible: true,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ export default class OnboardingDialog extends Vue {
|
|||||||
this.visible = true;
|
this.visible = true;
|
||||||
if (this.page === OnboardPage.Create) {
|
if (this.page === OnboardPage.Create) {
|
||||||
// we'll assume that they've been through all the other pages
|
// we'll assume that they've been through all the other pages
|
||||||
await this.$updateSettings({
|
await this.$saveMySettings({
|
||||||
finishedOnboarding: true,
|
finishedOnboarding: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -297,7 +297,7 @@ export default class OnboardingDialog extends Vue {
|
|||||||
async onClickClose(done?: boolean, goHome?: boolean) {
|
async onClickClose(done?: boolean, goHome?: boolean) {
|
||||||
this.visible = false;
|
this.visible = false;
|
||||||
if (done) {
|
if (done) {
|
||||||
await this.$updateSettings({
|
await this.$saveMySettings({
|
||||||
finishedOnboarding: true,
|
finishedOnboarding: true,
|
||||||
});
|
});
|
||||||
if (goHome) {
|
if (goHome) {
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ export default class UserNameDialog extends Vue {
|
|||||||
*/
|
*/
|
||||||
async onClickSaveChanges() {
|
async onClickSaveChanges() {
|
||||||
try {
|
try {
|
||||||
await this.$updateSettings({ firstName: this.givenName });
|
await this.$saveMySettings({ firstName: this.givenName });
|
||||||
this.visible = false;
|
this.visible = false;
|
||||||
this.callback(this.givenName);
|
this.callback(this.givenName);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -949,7 +949,7 @@ export const PlatformServiceMixin = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save settings for current active user - $saveMySettings()
|
* Save current user's settings - $saveMySettings()
|
||||||
* Ultra-concise shortcut using activeDid from component
|
* Ultra-concise shortcut using activeDid from component
|
||||||
* @param changes Settings changes to save
|
* @param changes Settings changes to save
|
||||||
* @returns Promise<boolean> Success status
|
* @returns Promise<boolean> Success status
|
||||||
@@ -1022,7 +1022,7 @@ export const PlatformServiceMixin = {
|
|||||||
if (!record) {
|
if (!record) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return this.$mapColumnsToValues(record.columns, record.values) as Array<
|
return this._mapColumnsToValues(record.columns, record.values) as Array<
|
||||||
Record<string, unknown>
|
Record<string, unknown>
|
||||||
>;
|
>;
|
||||||
},
|
},
|
||||||
@@ -1293,41 +1293,6 @@ export const PlatformServiceMixin = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Update settings with direct SQL - $updateSettings()
|
|
||||||
* Eliminates verbose settings update patterns
|
|
||||||
* @param changes Settings changes to apply
|
|
||||||
* @param did Optional DID for user-specific settings
|
|
||||||
* @returns Promise<boolean> Success status
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Update settings - $updateSettings()
|
|
||||||
* Ultra-concise shortcut for updating settings (default or user-specific)
|
|
||||||
*
|
|
||||||
* ⚠️ DEPRECATED: This method will be removed in favor of $saveSettings()
|
|
||||||
* Use $saveSettings(changes, did?) instead for better consistency
|
|
||||||
*
|
|
||||||
* @param changes Settings changes to save
|
|
||||||
* @param did Optional DID for user-specific settings
|
|
||||||
* @returns Promise<boolean> Success status
|
|
||||||
*/
|
|
||||||
async $updateSettings(
|
|
||||||
changes: Partial<Settings>,
|
|
||||||
did?: string,
|
|
||||||
): Promise<boolean> {
|
|
||||||
try {
|
|
||||||
// Use self-contained methods which handle the correct schema
|
|
||||||
if (did) {
|
|
||||||
return await this.$saveUserSettings(did, changes);
|
|
||||||
} else {
|
|
||||||
return await this.$saveSettings(changes);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
logger.error("[PlatformServiceMixin] Error updating settings:", error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get settings row as array - $getSettingsRow()
|
* Get settings row as array - $getSettingsRow()
|
||||||
* Eliminates verbose settings retrieval patterns
|
* Eliminates verbose settings retrieval patterns
|
||||||
@@ -1617,7 +1582,33 @@ export const PlatformServiceMixin = {
|
|||||||
* Enhanced interface with caching utility methods
|
* Enhanced interface with caching utility methods
|
||||||
*/
|
*/
|
||||||
export interface IPlatformServiceMixin {
|
export interface IPlatformServiceMixin {
|
||||||
|
// Core platform service access
|
||||||
platformService: PlatformService;
|
platformService: PlatformService;
|
||||||
|
isCapacitor: boolean;
|
||||||
|
isWeb: boolean;
|
||||||
|
isElectron: boolean;
|
||||||
|
capabilities: PlatformCapabilities;
|
||||||
|
|
||||||
|
// ActiveDid tracking
|
||||||
|
currentActiveDid: string | null;
|
||||||
|
$updateActiveDid(newDid: string | null): Promise<void>;
|
||||||
|
|
||||||
|
// Ultra-concise database methods (shortest possible names)
|
||||||
|
$db(sql: string, params?: unknown[]): Promise<QueryExecResult | undefined>;
|
||||||
|
$exec(sql: string, params?: unknown[]): Promise<DatabaseExecResult>;
|
||||||
|
$one(sql: string, params?: unknown[]): Promise<unknown[] | undefined>;
|
||||||
|
|
||||||
|
// Query + mapping combo methods
|
||||||
|
$query<T = Record<string, unknown>>(
|
||||||
|
sql: string,
|
||||||
|
params?: unknown[],
|
||||||
|
): Promise<T[]>;
|
||||||
|
$first<T = Record<string, unknown>>(
|
||||||
|
sql: string,
|
||||||
|
params?: unknown[],
|
||||||
|
): Promise<T | null>;
|
||||||
|
|
||||||
|
// Enhanced utility methods
|
||||||
$dbQuery(
|
$dbQuery(
|
||||||
sql: string,
|
sql: string,
|
||||||
params?: unknown[],
|
params?: unknown[],
|
||||||
@@ -1634,12 +1625,24 @@ export interface IPlatformServiceMixin {
|
|||||||
defaultFallback?: Settings,
|
defaultFallback?: Settings,
|
||||||
): Promise<Settings>;
|
): Promise<Settings>;
|
||||||
$withTransaction<T>(callback: () => Promise<T>): Promise<T>;
|
$withTransaction<T>(callback: () => Promise<T>): Promise<T>;
|
||||||
isCapacitor: boolean;
|
|
||||||
isWeb: boolean;
|
|
||||||
isElectron: boolean;
|
|
||||||
capabilities: PlatformCapabilities;
|
|
||||||
|
|
||||||
// High-level entity operations
|
// Specialized shortcuts - contacts and settings always fresh (no caching)
|
||||||
|
$contacts(): Promise<Contact[]>;
|
||||||
|
$contactCount(): Promise<number>;
|
||||||
|
$settings(defaults?: Settings): Promise<Settings>;
|
||||||
|
$accountSettings(did?: string, defaults?: Settings): Promise<Settings>;
|
||||||
|
$normalizeContacts(rawContacts: ContactMaybeWithJsonStrings[]): Contact[];
|
||||||
|
|
||||||
|
// Settings update shortcuts (eliminate 90% boilerplate)
|
||||||
|
$saveSettings(changes: Partial<Settings>): Promise<boolean>;
|
||||||
|
$saveUserSettings(did: string, changes: Partial<Settings>): Promise<boolean>;
|
||||||
|
$saveMySettings(changes: Partial<Settings>): Promise<boolean>;
|
||||||
|
|
||||||
|
// Cache management methods
|
||||||
|
$refreshSettings(): Promise<Settings>;
|
||||||
|
$refreshContacts(): Promise<Contact[]>;
|
||||||
|
|
||||||
|
// High-level entity operations (eliminate verbose SQL patterns)
|
||||||
$mapResults<T>(
|
$mapResults<T>(
|
||||||
results: QueryExecResult | undefined,
|
results: QueryExecResult | undefined,
|
||||||
mapper: (row: unknown[]) => T,
|
mapper: (row: unknown[]) => T,
|
||||||
@@ -1649,7 +1652,6 @@ export interface IPlatformServiceMixin {
|
|||||||
$getAllContacts(): Promise<Contact[]>;
|
$getAllContacts(): Promise<Contact[]>;
|
||||||
$getContact(did: string): Promise<Contact | null>;
|
$getContact(did: string): Promise<Contact | null>;
|
||||||
$deleteContact(did: string): Promise<boolean>;
|
$deleteContact(did: string): Promise<boolean>;
|
||||||
$contactCount(): Promise<number>;
|
|
||||||
$getAllAccounts(): Promise<Account[]>;
|
$getAllAccounts(): Promise<Account[]>;
|
||||||
$getAllAccountDids(): Promise<string[]>;
|
$getAllAccountDids(): Promise<string[]>;
|
||||||
$insertEntity(
|
$insertEntity(
|
||||||
@@ -1657,7 +1659,6 @@ export interface IPlatformServiceMixin {
|
|||||||
entity: Record<string, unknown>,
|
entity: Record<string, unknown>,
|
||||||
fields: string[],
|
fields: string[],
|
||||||
): Promise<boolean>;
|
): Promise<boolean>;
|
||||||
$updateSettings(changes: Partial<Settings>, did?: string): Promise<boolean>;
|
|
||||||
$getSettingsRow(
|
$getSettingsRow(
|
||||||
fields: string[],
|
fields: string[],
|
||||||
did?: string,
|
did?: string,
|
||||||
@@ -1712,141 +1713,8 @@ export interface IPlatformServiceMixin {
|
|||||||
|
|
||||||
// TypeScript declaration merging to eliminate (this as any) type assertions
|
// TypeScript declaration merging to eliminate (this as any) type assertions
|
||||||
declare module "@vue/runtime-core" {
|
declare module "@vue/runtime-core" {
|
||||||
interface ComponentCustomProperties {
|
interface ComponentCustomProperties extends IPlatformServiceMixin {
|
||||||
// Core platform service access
|
// All methods inherited from IPlatformServiceMixin
|
||||||
platformService: PlatformService;
|
// No additional methods needed - single source of truth
|
||||||
isCapacitor: boolean;
|
|
||||||
isWeb: boolean;
|
|
||||||
isElectron: boolean;
|
|
||||||
capabilities: PlatformCapabilities;
|
|
||||||
|
|
||||||
// ActiveDid tracking
|
|
||||||
currentActiveDid: string | null;
|
|
||||||
$updateActiveDid(newDid: string | null): Promise<void>;
|
|
||||||
|
|
||||||
// Ultra-concise database methods (shortest possible names)
|
|
||||||
$db(sql: string, params?: unknown[]): Promise<QueryExecResult | undefined>;
|
|
||||||
$exec(sql: string, params?: unknown[]): Promise<DatabaseExecResult>;
|
|
||||||
$one(sql: string, params?: unknown[]): Promise<unknown[] | undefined>;
|
|
||||||
|
|
||||||
// Query + mapping combo methods
|
|
||||||
$query<T = Record<string, unknown>>(
|
|
||||||
sql: string,
|
|
||||||
params?: unknown[],
|
|
||||||
): Promise<T[]>;
|
|
||||||
$first<T = Record<string, unknown>>(
|
|
||||||
sql: string,
|
|
||||||
params?: unknown[],
|
|
||||||
): Promise<T | null>;
|
|
||||||
|
|
||||||
// Enhanced utility methods
|
|
||||||
$dbQuery(
|
|
||||||
sql: string,
|
|
||||||
params?: unknown[],
|
|
||||||
): Promise<QueryExecResult | undefined>;
|
|
||||||
$dbExec(sql: string, params?: unknown[]): Promise<DatabaseExecResult>;
|
|
||||||
$dbGetOneRow(
|
|
||||||
sql: string,
|
|
||||||
params?: unknown[],
|
|
||||||
): Promise<unknown[] | undefined>;
|
|
||||||
$getSettings(
|
|
||||||
key: string,
|
|
||||||
defaults?: Settings | null,
|
|
||||||
): Promise<Settings | null>;
|
|
||||||
$getMergedSettings(
|
|
||||||
key: string,
|
|
||||||
did?: string,
|
|
||||||
defaults?: Settings,
|
|
||||||
): Promise<Settings>;
|
|
||||||
$withTransaction<T>(fn: () => Promise<T>): Promise<T>;
|
|
||||||
|
|
||||||
// Specialized shortcuts - contacts cached, settings fresh
|
|
||||||
$contacts(): Promise<Contact[]>;
|
|
||||||
$contactCount(): Promise<number>;
|
|
||||||
$settings(defaults?: Settings): Promise<Settings>;
|
|
||||||
$accountSettings(did?: string, defaults?: Settings): Promise<Settings>;
|
|
||||||
$normalizeContacts(rawContacts: ContactMaybeWithJsonStrings[]): Contact[];
|
|
||||||
|
|
||||||
// Settings update shortcuts (eliminate 90% boilerplate)
|
|
||||||
$saveSettings(changes: Partial<Settings>): Promise<boolean>;
|
|
||||||
$saveUserSettings(
|
|
||||||
did: string,
|
|
||||||
changes: Partial<Settings>,
|
|
||||||
): Promise<boolean>;
|
|
||||||
$saveMySettings(changes: Partial<Settings>): Promise<boolean>;
|
|
||||||
|
|
||||||
// Cache management methods
|
|
||||||
$refreshSettings(): Promise<Settings>;
|
|
||||||
$refreshContacts(): Promise<Contact[]>;
|
|
||||||
// $clearAllCaches(): void;
|
|
||||||
|
|
||||||
// High-level entity operations (eliminate verbose SQL patterns)
|
|
||||||
$mapResults<T>(
|
|
||||||
results: QueryExecResult | undefined,
|
|
||||||
mapper: (row: unknown[]) => T,
|
|
||||||
): T[];
|
|
||||||
$insertContact(contact: Partial<Contact>): Promise<boolean>;
|
|
||||||
$updateContact(did: string, changes: Partial<Contact>): Promise<boolean>;
|
|
||||||
$getAllContacts(): Promise<Contact[]>;
|
|
||||||
$getContact(did: string): Promise<Contact | null>;
|
|
||||||
$deleteContact(did: string): Promise<boolean>;
|
|
||||||
$getAllAccounts(): Promise<Account[]>;
|
|
||||||
$getAllAccountDids(): Promise<string[]>;
|
|
||||||
$insertEntity(
|
|
||||||
tableName: string,
|
|
||||||
entity: Record<string, unknown>,
|
|
||||||
fields: string[],
|
|
||||||
): Promise<boolean>;
|
|
||||||
$updateSettings(changes: Partial<Settings>, did?: string): Promise<boolean>;
|
|
||||||
$getSettingsRow(
|
|
||||||
fields: string[],
|
|
||||||
did?: string,
|
|
||||||
): Promise<unknown[] | undefined>;
|
|
||||||
$updateEntity(
|
|
||||||
tableName: string,
|
|
||||||
entity: Record<string, unknown>,
|
|
||||||
whereClause: string,
|
|
||||||
whereParams: unknown[],
|
|
||||||
): Promise<boolean>;
|
|
||||||
$insertUserSettings(
|
|
||||||
did: string,
|
|
||||||
settings: Partial<Settings>,
|
|
||||||
): Promise<boolean>;
|
|
||||||
$getTemp(id: string): Promise<Temp | null>;
|
|
||||||
$deleteTemp(id: string): Promise<boolean>;
|
|
||||||
|
|
||||||
// Logging methods
|
|
||||||
$log(message: string, level?: string): Promise<void>;
|
|
||||||
$logError(message: string): Promise<void>;
|
|
||||||
$logAndConsole(message: string, isError?: boolean): Promise<void>;
|
|
||||||
|
|
||||||
// Memory logs access
|
|
||||||
$memoryLogs: string[];
|
|
||||||
|
|
||||||
// New additions
|
|
||||||
$logs(): Promise<Array<Record<string, unknown>>>;
|
|
||||||
|
|
||||||
// New additions
|
|
||||||
$generateInsertStatement(
|
|
||||||
model: Record<string, unknown>,
|
|
||||||
tableName: string,
|
|
||||||
): { sql: string; params: unknown[] };
|
|
||||||
$generateUpdateStatement(
|
|
||||||
model: Record<string, unknown>,
|
|
||||||
tableName: string,
|
|
||||||
whereClause: string,
|
|
||||||
whereParams?: unknown[],
|
|
||||||
): { sql: string; params: unknown[] };
|
|
||||||
$mapQueryResultToValues(
|
|
||||||
record: QueryExecResult | undefined,
|
|
||||||
): Array<Record<string, unknown>>;
|
|
||||||
$mapColumnsToValues(
|
|
||||||
columns: string[],
|
|
||||||
values: unknown[][],
|
|
||||||
): Array<Record<string, unknown>>;
|
|
||||||
|
|
||||||
// Debug methods
|
|
||||||
$debugDidSettings(did: string): Promise<Settings | null>;
|
|
||||||
$debugMergedSettings(did: string): Promise<void>;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,7 +182,6 @@
|
|||||||
@change="onLocationCheckboxChange"
|
@change="onLocationCheckboxChange"
|
||||||
/>
|
/>
|
||||||
<label for="includeUserProfileLocation">Include Location</label>
|
<label for="includeUserProfileLocation">Include Location</label>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div v-if="includeUserProfileLocation" class="mb-4 aspect-video">
|
<div v-if="includeUserProfileLocation" class="mb-4 aspect-video">
|
||||||
<p class="text-sm mb-2 text-slate-500">
|
<p class="text-sm mb-2 text-slate-500">
|
||||||
|
|||||||
@@ -750,7 +750,7 @@ export default class ContactQRScanShow extends Vue {
|
|||||||
{
|
{
|
||||||
onCancel: async (stopAsking?: boolean) => {
|
onCancel: async (stopAsking?: boolean) => {
|
||||||
if (stopAsking) {
|
if (stopAsking) {
|
||||||
await this.$updateSettings({
|
await this.$saveMySettings({
|
||||||
hideRegisterPromptOnNewContact: stopAsking,
|
hideRegisterPromptOnNewContact: stopAsking,
|
||||||
});
|
});
|
||||||
this.hideRegisterPromptOnNewContact = stopAsking;
|
this.hideRegisterPromptOnNewContact = stopAsking;
|
||||||
@@ -758,7 +758,7 @@ export default class ContactQRScanShow extends Vue {
|
|||||||
},
|
},
|
||||||
onNo: async (stopAsking?: boolean) => {
|
onNo: async (stopAsking?: boolean) => {
|
||||||
if (stopAsking) {
|
if (stopAsking) {
|
||||||
await this.$updateSettings({
|
await this.$saveMySettings({
|
||||||
hideRegisterPromptOnNewContact: stopAsking,
|
hideRegisterPromptOnNewContact: stopAsking,
|
||||||
});
|
});
|
||||||
this.hideRegisterPromptOnNewContact = stopAsking;
|
this.hideRegisterPromptOnNewContact = stopAsking;
|
||||||
|
|||||||
@@ -524,9 +524,8 @@ export default class HelpNotificationsView extends Vue {
|
|||||||
DIRECT_PUSH_TITLE,
|
DIRECT_PUSH_TITLE,
|
||||||
async (success: boolean, timeText: string, message?: string) => {
|
async (success: boolean, timeText: string, message?: string) => {
|
||||||
if (success) {
|
if (success) {
|
||||||
await this.$updateSettings({
|
await this.$saveMySettings({
|
||||||
notifyingReminderMessage: message,
|
hideHelpOnStart: true,
|
||||||
notifyingReminderTime: timeText,
|
|
||||||
});
|
});
|
||||||
this.notifyingReminder = true;
|
this.notifyingReminder = true;
|
||||||
this.notifyingReminderMessage = message || "";
|
this.notifyingReminderMessage = message || "";
|
||||||
|
|||||||
@@ -680,9 +680,8 @@ export default class HelpView extends Vue {
|
|||||||
const settings = await this.$accountSettings();
|
const settings = await this.$accountSettings();
|
||||||
|
|
||||||
if (settings.activeDid) {
|
if (settings.activeDid) {
|
||||||
await this.$updateSettings({
|
await this.$saveMySettings({
|
||||||
...settings,
|
hideHelpOnStart: true,
|
||||||
finishedOnboarding: false,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$log(
|
this.$log(
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ export default class NewActivityView extends Vue {
|
|||||||
async expandOffersToUserAndMarkRead() {
|
async expandOffersToUserAndMarkRead() {
|
||||||
this.showOffersDetails = !this.showOffersDetails;
|
this.showOffersDetails = !this.showOffersDetails;
|
||||||
if (this.showOffersDetails) {
|
if (this.showOffersDetails) {
|
||||||
await this.$updateSettings({
|
await this.$saveMySettings({
|
||||||
lastAckedOfferToUserJwtId: this.newOffersToUser[0].jwtId,
|
lastAckedOfferToUserJwtId: this.newOffersToUser[0].jwtId,
|
||||||
});
|
});
|
||||||
// note that we don't update this.lastAckedOfferToUserJwtId in case they
|
// note that we don't update this.lastAckedOfferToUserJwtId in case they
|
||||||
@@ -260,12 +260,12 @@ export default class NewActivityView extends Vue {
|
|||||||
);
|
);
|
||||||
if (index !== -1 && index < this.newOffersToUser.length - 1) {
|
if (index !== -1 && index < this.newOffersToUser.length - 1) {
|
||||||
// Set to the next offer's jwtId
|
// Set to the next offer's jwtId
|
||||||
await this.$updateSettings({
|
await this.$saveMySettings({
|
||||||
lastAckedOfferToUserJwtId: this.newOffersToUser[index + 1].jwtId,
|
lastAckedOfferToUserJwtId: this.newOffersToUser[index + 1].jwtId,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// it's the last entry (or not found), so just keep it the same
|
// it's the last entry (or not found), so just keep it the same
|
||||||
await this.$updateSettings({
|
await this.$saveMySettings({
|
||||||
lastAckedOfferToUserJwtId: this.lastAckedOfferToUserJwtId,
|
lastAckedOfferToUserJwtId: this.lastAckedOfferToUserJwtId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -279,7 +279,7 @@ export default class NewActivityView extends Vue {
|
|||||||
this.showOffersToUserProjectsDetails =
|
this.showOffersToUserProjectsDetails =
|
||||||
!this.showOffersToUserProjectsDetails;
|
!this.showOffersToUserProjectsDetails;
|
||||||
if (this.showOffersToUserProjectsDetails) {
|
if (this.showOffersToUserProjectsDetails) {
|
||||||
await this.$updateSettings({
|
await this.$saveMySettings({
|
||||||
lastAckedOfferToUserProjectsJwtId:
|
lastAckedOfferToUserProjectsJwtId:
|
||||||
this.newOffersToUserProjects[0].jwtId,
|
this.newOffersToUserProjects[0].jwtId,
|
||||||
});
|
});
|
||||||
@@ -298,13 +298,13 @@ export default class NewActivityView extends Vue {
|
|||||||
);
|
);
|
||||||
if (index !== -1 && index < this.newOffersToUserProjects.length - 1) {
|
if (index !== -1 && index < this.newOffersToUserProjects.length - 1) {
|
||||||
// Set to the next offer's jwtId
|
// Set to the next offer's jwtId
|
||||||
await this.$updateSettings({
|
await this.$saveMySettings({
|
||||||
lastAckedOfferToUserProjectsJwtId:
|
lastAckedOfferToUserProjectsJwtId:
|
||||||
this.newOffersToUserProjects[index + 1].jwtId,
|
this.newOffersToUserProjects[index + 1].jwtId,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// it's the last entry (or not found), so just keep it the same
|
// it's the last entry (or not found), so just keep it the same
|
||||||
await this.$updateSettings({
|
await this.$saveMySettings({
|
||||||
lastAckedOfferToUserProjectsJwtId:
|
lastAckedOfferToUserProjectsJwtId:
|
||||||
this.lastAckedOfferToUserProjectsJwtId,
|
this.lastAckedOfferToUserProjectsJwtId,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ export default class NewEditAccountView extends Vue {
|
|||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async onClickSaveChanges() {
|
async onClickSaveChanges() {
|
||||||
await this.$updateSettings({
|
await this.$saveMySettings({
|
||||||
firstName: this.givenName,
|
firstName: this.givenName,
|
||||||
lastName: "", // deprecated, pre v 0.1.3
|
lastName: "", // deprecated, pre v 0.1.3
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -311,8 +311,8 @@ export default class SearchAreaView extends Vue {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Store search box configuration using platform service
|
// Store search box configuration using platform service
|
||||||
// searchBoxes will be automatically converted to JSON string by $updateSettings
|
// searchBoxes will be automatically converted to JSON string by $saveMySettings
|
||||||
await this.$updateSettings({ searchBoxes: [newSearchBox] });
|
await this.$saveMySettings({ searchBoxes: [newSearchBox] });
|
||||||
|
|
||||||
this.searchBox = newSearchBox;
|
this.searchBox = newSearchBox;
|
||||||
this.isChoosingSearchBox = false;
|
this.isChoosingSearchBox = false;
|
||||||
@@ -345,7 +345,7 @@ export default class SearchAreaView extends Vue {
|
|||||||
public async forgetSearchBox() {
|
public async forgetSearchBox() {
|
||||||
try {
|
try {
|
||||||
// Clear search box settings and disable nearby filtering
|
// Clear search box settings and disable nearby filtering
|
||||||
await this.$updateSettings({
|
await this.$saveMySettings({
|
||||||
searchBoxes: [],
|
searchBoxes: [],
|
||||||
filterFeedByNearby: false,
|
filterFeedByNearby: false,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
Migration Status: ✅ Complete Enhanced Triple Migration Pattern
|
Migration Status: ✅ Complete Enhanced Triple Migration Pattern
|
||||||
- Phase 1: Database Migration (PlatformServiceMixin) ✅
|
- Phase 1: Database Migration (PlatformServiceMixin) ✅
|
||||||
- Phase 2: SQL Abstraction ($getTemp, $deleteTemp, $accountSettings, $updateSettings) ✅
|
- Phase 2: SQL Abstraction ($getTemp, $deleteTemp, $accountSettings) ✅
|
||||||
- Phase 3: Notification Migration (3 constants, helper methods) ✅
|
- Phase 3: Notification Migration (3 constants, helper methods) ✅
|
||||||
- Phase 4: Template Streamlining (Simple template) ✅
|
- Phase 4: Template Streamlining (Simple template) ✅
|
||||||
|
|
||||||
@@ -235,7 +235,7 @@ export default class SharedPhotoView extends Vue {
|
|||||||
recordProfile() {
|
recordProfile() {
|
||||||
(this.$refs.photoDialog as PhotoDialog).open(
|
(this.$refs.photoDialog as PhotoDialog).open(
|
||||||
async (imgUrl) => {
|
async (imgUrl) => {
|
||||||
await this.$updateSettings({ profileImageUrl: imgUrl });
|
await this.$saveMySettings({ profileImageUrl: imgUrl });
|
||||||
this.$router.push({ name: "account" });
|
this.$router.push({ name: "account" });
|
||||||
},
|
},
|
||||||
IMAGE_TYPE_PROFILE,
|
IMAGE_TYPE_PROFILE,
|
||||||
|
|||||||
Reference in New Issue
Block a user