Compare commits
3 Commits
deep-link-
...
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/explicit-function-return-type": "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.hasVisibleDid = !this.hasVisibleDid;
|
||||
|
||||
await this.$updateSettings({
|
||||
await this.$saveMySettings({
|
||||
filterFeedByVisible: this.hasVisibleDid,
|
||||
});
|
||||
}
|
||||
@@ -156,7 +156,7 @@ export default class FeedFilters extends Vue {
|
||||
activeDid: this.activeDid,
|
||||
});
|
||||
|
||||
await this.$updateSettings({
|
||||
await this.$saveMySettings({
|
||||
filterFeedByNearby: this.isNearby,
|
||||
});
|
||||
|
||||
@@ -168,7 +168,7 @@ export default class FeedFilters extends Vue {
|
||||
this.settingChanged = true;
|
||||
}
|
||||
|
||||
await this.$updateSettings({
|
||||
await this.$saveMySettings({
|
||||
filterFeedByNearby: false,
|
||||
filterFeedByVisible: false,
|
||||
});
|
||||
@@ -182,7 +182,7 @@ export default class FeedFilters extends Vue {
|
||||
this.settingChanged = true;
|
||||
}
|
||||
|
||||
await this.$updateSettings({
|
||||
await this.$saveMySettings({
|
||||
filterFeedByNearby: true,
|
||||
filterFeedByVisible: true,
|
||||
});
|
||||
|
||||
@@ -282,7 +282,7 @@ export default class OnboardingDialog extends Vue {
|
||||
this.visible = true;
|
||||
if (this.page === OnboardPage.Create) {
|
||||
// we'll assume that they've been through all the other pages
|
||||
await this.$updateSettings({
|
||||
await this.$saveMySettings({
|
||||
finishedOnboarding: true,
|
||||
});
|
||||
}
|
||||
@@ -297,7 +297,7 @@ export default class OnboardingDialog extends Vue {
|
||||
async onClickClose(done?: boolean, goHome?: boolean) {
|
||||
this.visible = false;
|
||||
if (done) {
|
||||
await this.$updateSettings({
|
||||
await this.$saveMySettings({
|
||||
finishedOnboarding: true,
|
||||
});
|
||||
if (goHome) {
|
||||
|
||||
@@ -95,7 +95,7 @@ export default class UserNameDialog extends Vue {
|
||||
*/
|
||||
async onClickSaveChanges() {
|
||||
try {
|
||||
await this.$updateSettings({ firstName: this.givenName });
|
||||
await this.$saveMySettings({ firstName: this.givenName });
|
||||
this.visible = false;
|
||||
this.callback(this.givenName);
|
||||
} 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
|
||||
* @param changes Settings changes to save
|
||||
* @returns Promise<boolean> Success status
|
||||
@@ -1022,7 +1022,7 @@ export const PlatformServiceMixin = {
|
||||
if (!record) {
|
||||
return [];
|
||||
}
|
||||
return this.$mapColumnsToValues(record.columns, record.values) as Array<
|
||||
return this._mapColumnsToValues(record.columns, record.values) as Array<
|
||||
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()
|
||||
* Eliminates verbose settings retrieval patterns
|
||||
@@ -1617,7 +1582,33 @@ export const PlatformServiceMixin = {
|
||||
* Enhanced interface with caching utility methods
|
||||
*/
|
||||
export interface IPlatformServiceMixin {
|
||||
// Core platform service access
|
||||
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(
|
||||
sql: string,
|
||||
params?: unknown[],
|
||||
@@ -1634,12 +1625,24 @@ export interface IPlatformServiceMixin {
|
||||
defaultFallback?: Settings,
|
||||
): Promise<Settings>;
|
||||
$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>(
|
||||
results: QueryExecResult | undefined,
|
||||
mapper: (row: unknown[]) => T,
|
||||
@@ -1649,7 +1652,6 @@ export interface IPlatformServiceMixin {
|
||||
$getAllContacts(): Promise<Contact[]>;
|
||||
$getContact(did: string): Promise<Contact | null>;
|
||||
$deleteContact(did: string): Promise<boolean>;
|
||||
$contactCount(): Promise<number>;
|
||||
$getAllAccounts(): Promise<Account[]>;
|
||||
$getAllAccountDids(): Promise<string[]>;
|
||||
$insertEntity(
|
||||
@@ -1657,7 +1659,6 @@ export interface IPlatformServiceMixin {
|
||||
entity: Record<string, unknown>,
|
||||
fields: string[],
|
||||
): Promise<boolean>;
|
||||
$updateSettings(changes: Partial<Settings>, did?: string): Promise<boolean>;
|
||||
$getSettingsRow(
|
||||
fields: string[],
|
||||
did?: string,
|
||||
@@ -1712,141 +1713,8 @@ export interface IPlatformServiceMixin {
|
||||
|
||||
// TypeScript declaration merging to eliminate (this as any) type assertions
|
||||
declare module "@vue/runtime-core" {
|
||||
interface ComponentCustomProperties {
|
||||
// Core platform service access
|
||||
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(
|
||||
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>;
|
||||
interface ComponentCustomProperties extends IPlatformServiceMixin {
|
||||
// All methods inherited from IPlatformServiceMixin
|
||||
// No additional methods needed - single source of truth
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,7 +182,6 @@
|
||||
@change="onLocationCheckboxChange"
|
||||
/>
|
||||
<label for="includeUserProfileLocation">Include Location</label>
|
||||
|
||||
</div>
|
||||
<div v-if="includeUserProfileLocation" class="mb-4 aspect-video">
|
||||
<p class="text-sm mb-2 text-slate-500">
|
||||
|
||||
@@ -750,7 +750,7 @@ export default class ContactQRScanShow extends Vue {
|
||||
{
|
||||
onCancel: async (stopAsking?: boolean) => {
|
||||
if (stopAsking) {
|
||||
await this.$updateSettings({
|
||||
await this.$saveMySettings({
|
||||
hideRegisterPromptOnNewContact: stopAsking,
|
||||
});
|
||||
this.hideRegisterPromptOnNewContact = stopAsking;
|
||||
@@ -758,7 +758,7 @@ export default class ContactQRScanShow extends Vue {
|
||||
},
|
||||
onNo: async (stopAsking?: boolean) => {
|
||||
if (stopAsking) {
|
||||
await this.$updateSettings({
|
||||
await this.$saveMySettings({
|
||||
hideRegisterPromptOnNewContact: stopAsking,
|
||||
});
|
||||
this.hideRegisterPromptOnNewContact = stopAsking;
|
||||
|
||||
@@ -524,9 +524,8 @@ export default class HelpNotificationsView extends Vue {
|
||||
DIRECT_PUSH_TITLE,
|
||||
async (success: boolean, timeText: string, message?: string) => {
|
||||
if (success) {
|
||||
await this.$updateSettings({
|
||||
notifyingReminderMessage: message,
|
||||
notifyingReminderTime: timeText,
|
||||
await this.$saveMySettings({
|
||||
hideHelpOnStart: true,
|
||||
});
|
||||
this.notifyingReminder = true;
|
||||
this.notifyingReminderMessage = message || "";
|
||||
|
||||
@@ -680,9 +680,8 @@ export default class HelpView extends Vue {
|
||||
const settings = await this.$accountSettings();
|
||||
|
||||
if (settings.activeDid) {
|
||||
await this.$updateSettings({
|
||||
...settings,
|
||||
finishedOnboarding: false,
|
||||
await this.$saveMySettings({
|
||||
hideHelpOnStart: true,
|
||||
});
|
||||
|
||||
this.$log(
|
||||
|
||||
@@ -242,7 +242,7 @@ export default class NewActivityView extends Vue {
|
||||
async expandOffersToUserAndMarkRead() {
|
||||
this.showOffersDetails = !this.showOffersDetails;
|
||||
if (this.showOffersDetails) {
|
||||
await this.$updateSettings({
|
||||
await this.$saveMySettings({
|
||||
lastAckedOfferToUserJwtId: this.newOffersToUser[0].jwtId,
|
||||
});
|
||||
// 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) {
|
||||
// Set to the next offer's jwtId
|
||||
await this.$updateSettings({
|
||||
await this.$saveMySettings({
|
||||
lastAckedOfferToUserJwtId: this.newOffersToUser[index + 1].jwtId,
|
||||
});
|
||||
} else {
|
||||
// it's the last entry (or not found), so just keep it the same
|
||||
await this.$updateSettings({
|
||||
await this.$saveMySettings({
|
||||
lastAckedOfferToUserJwtId: this.lastAckedOfferToUserJwtId,
|
||||
});
|
||||
}
|
||||
@@ -279,7 +279,7 @@ export default class NewActivityView extends Vue {
|
||||
this.showOffersToUserProjectsDetails =
|
||||
!this.showOffersToUserProjectsDetails;
|
||||
if (this.showOffersToUserProjectsDetails) {
|
||||
await this.$updateSettings({
|
||||
await this.$saveMySettings({
|
||||
lastAckedOfferToUserProjectsJwtId:
|
||||
this.newOffersToUserProjects[0].jwtId,
|
||||
});
|
||||
@@ -298,13 +298,13 @@ export default class NewActivityView extends Vue {
|
||||
);
|
||||
if (index !== -1 && index < this.newOffersToUserProjects.length - 1) {
|
||||
// Set to the next offer's jwtId
|
||||
await this.$updateSettings({
|
||||
await this.$saveMySettings({
|
||||
lastAckedOfferToUserProjectsJwtId:
|
||||
this.newOffersToUserProjects[index + 1].jwtId,
|
||||
});
|
||||
} else {
|
||||
// it's the last entry (or not found), so just keep it the same
|
||||
await this.$updateSettings({
|
||||
await this.$saveMySettings({
|
||||
lastAckedOfferToUserProjectsJwtId:
|
||||
this.lastAckedOfferToUserProjectsJwtId,
|
||||
});
|
||||
|
||||
@@ -110,7 +110,7 @@ export default class NewEditAccountView extends Vue {
|
||||
* @async
|
||||
*/
|
||||
async onClickSaveChanges() {
|
||||
await this.$updateSettings({
|
||||
await this.$saveMySettings({
|
||||
firstName: this.givenName,
|
||||
lastName: "", // deprecated, pre v 0.1.3
|
||||
});
|
||||
|
||||
@@ -311,8 +311,8 @@ export default class SearchAreaView extends Vue {
|
||||
};
|
||||
|
||||
// Store search box configuration using platform service
|
||||
// searchBoxes will be automatically converted to JSON string by $updateSettings
|
||||
await this.$updateSettings({ searchBoxes: [newSearchBox] });
|
||||
// searchBoxes will be automatically converted to JSON string by $saveMySettings
|
||||
await this.$saveMySettings({ searchBoxes: [newSearchBox] });
|
||||
|
||||
this.searchBox = newSearchBox;
|
||||
this.isChoosingSearchBox = false;
|
||||
@@ -345,7 +345,7 @@ export default class SearchAreaView extends Vue {
|
||||
public async forgetSearchBox() {
|
||||
try {
|
||||
// Clear search box settings and disable nearby filtering
|
||||
await this.$updateSettings({
|
||||
await this.$saveMySettings({
|
||||
searchBoxes: [],
|
||||
filterFeedByNearby: false,
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
Migration Status: ✅ Complete Enhanced Triple Migration Pattern
|
||||
- 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 4: Template Streamlining (Simple template) ✅
|
||||
|
||||
@@ -235,7 +235,7 @@ export default class SharedPhotoView extends Vue {
|
||||
recordProfile() {
|
||||
(this.$refs.photoDialog as PhotoDialog).open(
|
||||
async (imgUrl) => {
|
||||
await this.$updateSettings({ profileImageUrl: imgUrl });
|
||||
await this.$saveMySettings({ profileImageUrl: imgUrl });
|
||||
this.$router.push({ name: "account" });
|
||||
},
|
||||
IMAGE_TYPE_PROFILE,
|
||||
|
||||
Reference in New Issue
Block a user