m3
28
mobile/FIREBASE_SETUP.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# Firebase Setup
|
||||
|
||||
## Initial Setup for New Developers
|
||||
|
||||
1. **Google Services Configuration**:
|
||||
- Copy `android/app/google-services.json.template` to `android/app/google-services.json`
|
||||
- Replace all placeholder values with your actual Firebase project configuration
|
||||
- Get this file from the Firebase Console > Project Settings > General > Your apps
|
||||
|
||||
2. **Required Configuration Files**:
|
||||
- `android/app/google-services.json` - Firebase configuration for Android
|
||||
- `ios/Runner/GoogleService-Info.plist` - Firebase configuration for iOS (if applicable)
|
||||
|
||||
3. **Environment Variables** (if using):
|
||||
- Create `.env` file in project root
|
||||
- Add your API keys and configuration
|
||||
|
||||
## Security Notes
|
||||
|
||||
- Never commit sensitive files like:
|
||||
- `google-services.json`
|
||||
- `GoogleService-Info.plist`
|
||||
- `.keystore` files
|
||||
- `key.properties`
|
||||
- Any files containing API keys or secrets
|
||||
|
||||
- These files are in `.gitignore` for security reasons
|
||||
- Use template files and environment variables for team development
|
||||
565
mobile/README.md
|
|
@ -1,16 +1,561 @@
|
|||
# mobile
|
||||
# BottleCRM Mobile
|
||||
|
||||
A new Flutter project.
|
||||
<div align="center">
|
||||
|
||||
## Getting Started
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
This project is a starting point for a Flutter application.
|
||||
[](https://play.google.com/store/apps/details?id=io.bottlecrm)
|
||||
|
||||
A few resources to get you started if this is your first Flutter project:
|
||||
</div>
|
||||
|
||||
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
||||
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
|
||||
A modern, feature-rich Flutter CRM application for startups and enterprises. Built with a scalable architecture, BottleCRM Mobile provides comprehensive customer relationship management capabilities with multi-tenant support, real-time synchronization, and intuitive user experience.
|
||||
|
||||
For help getting started with Flutter development, view the
|
||||
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
||||
samples, guidance on mobile development, and a full API reference.
|
||||
## 🚀 Overview
|
||||
|
||||
BottleCRM Mobile is designed to streamline your sales and customer management processes with:
|
||||
- **Multi-tenant Architecture**: Organization-based data isolation and role management
|
||||
- **Offline-First Design**: Local caching with smart synchronization
|
||||
- **Modern UI/UX**: Material Design 3 with adaptive layouts
|
||||
- **Enterprise Security**: OAuth 2.0, JWT tokens, and secure API communication
|
||||
|
||||
## ✨ Features
|
||||
|
||||
### 🔐 Authentication & Security
|
||||
- **Google OAuth 2.0**: Seamless single sign-on integration
|
||||
- **JWT Authentication**: Secure token-based API communication
|
||||
- **Multi-tenant Support**: Organization-based data isolation
|
||||
- **Role-based Access**: Granular permissions and user management
|
||||
|
||||
### 📊 Core CRM Modules
|
||||
- **Dashboard**: Real-time metrics, KPIs, and activity feeds
|
||||
- **Contacts**: Complete contact management with search and filtering
|
||||
- **Leads**: Lead capture, qualification, and conversion tracking
|
||||
- **Opportunities**: Sales pipeline management with stages
|
||||
- **Tasks**: Task assignment, tracking, and deadline management
|
||||
- **Accounts**: Customer account profiles and relationship history
|
||||
- **Cases**: Customer support ticket management
|
||||
- **Events**: Calendar integration and meeting scheduling
|
||||
- **Documents**: File management with cloud storage
|
||||
- **Teams**: Collaboration tools and team management
|
||||
- **Invoices**: Billing and invoice generation
|
||||
|
||||
### 🎨 User Experience
|
||||
- **Material Design 3**: Modern, consistent UI patterns
|
||||
- **Responsive Design**: Optimized for phones, tablets, and foldables
|
||||
- **Dark/Light Theme**: System-aware theme switching
|
||||
- **Offline Support**: Local data caching with smart sync
|
||||
- **Pull-to-Refresh**: Intuitive data refresh patterns
|
||||
- **Infinite Scrolling**: Smooth pagination for large datasets
|
||||
|
||||
## 📋 Requirements
|
||||
|
||||
### System Requirements
|
||||
- **Flutter SDK**: 3.8.1 or later
|
||||
- **Dart SDK**: 3.0.0 or later
|
||||
- **Android Studio/VS Code**: Latest stable version
|
||||
- **Git**: For version control
|
||||
|
||||
### Platform Support
|
||||
- **Android**: API level 31+ (Android 12+)
|
||||
- **iOS**: iOS 11.0+ (for iOS builds)
|
||||
- **Web**: Modern browsers (Chrome, Firefox, Safari, Edge)
|
||||
- **Desktop**: Windows, macOS, Linux (experimental)
|
||||
|
||||
### Development Tools
|
||||
- **Android SDK**: For Android development
|
||||
- **Xcode**: For iOS development (macOS only)
|
||||
- **CocoaPods**: iOS dependency management
|
||||
|
||||
## 🚀 Getting Started
|
||||
|
||||
### 📱 For End Users
|
||||
|
||||
**Download the app directly from Google Play Store:**
|
||||
|
||||
<div align="center">
|
||||
|
||||
[](https://play.google.com/store/apps/details?id=io.bottlecrm)
|
||||
|
||||
*Package ID: `io.bottlecrm`*
|
||||
|
||||
</div>
|
||||
|
||||
### 👨💻 For Developers
|
||||
|
||||
### Quick Start
|
||||
|
||||
1. **Clone the repository**:
|
||||
```bash
|
||||
git clone https://github.com/your-username/bottlecrm_mobile_v2.git
|
||||
cd bottlecrm_mobile_v2
|
||||
```
|
||||
|
||||
2. **Install Flutter dependencies**:
|
||||
```bash
|
||||
flutter pub get
|
||||
```
|
||||
|
||||
3. **Set up Firebase & Google Sign-In**:
|
||||
```bash
|
||||
# Copy template and configure
|
||||
cp android/app/google-services.json.template android/app/google-services.json
|
||||
# Edit the file with your Firebase project configuration
|
||||
```
|
||||
|
||||
4. **Run the application**:
|
||||
```bash
|
||||
flutter run
|
||||
```
|
||||
|
||||
### 🔧 Detailed Setup
|
||||
|
||||
#### Firebase Configuration
|
||||
1. Create a new Firebase project at [Firebase Console](https://console.firebase.google.com)
|
||||
2. Enable Google Sign-In authentication
|
||||
3. Download `google-services.json` for Android
|
||||
4. Download `GoogleService-Info.plist` for iOS (if building for iOS)
|
||||
5. Place files in their respective directories:
|
||||
- Android: `android/app/google-services.json`
|
||||
- iOS: `ios/Runner/GoogleService-Info.plist`
|
||||
|
||||
#### Google Cloud Console Setup
|
||||
1. Navigate to [Google Cloud Console](https://console.cloud.google.com)
|
||||
2. Create OAuth 2.0 Client ID for Android:
|
||||
```bash
|
||||
# Get your SHA-1 fingerprint
|
||||
cd android
|
||||
./gradlew signingReport
|
||||
```
|
||||
3. Add the SHA-1 fingerprint to your OAuth client
|
||||
4. Configure OAuth consent screen
|
||||
|
||||
#### Environment Configuration
|
||||
The app automatically switches between environments:
|
||||
- **Debug builds**: Uses development API (ngrok URL)
|
||||
- **Release builds**: Uses production API (bottlecrm.io)
|
||||
|
||||
You can modify URLs in `lib/config/api_config.dart`
|
||||
|
||||
## 🛠 Development
|
||||
|
||||
### Development Commands
|
||||
|
||||
```bash
|
||||
# Run the app with hot reload
|
||||
flutter run
|
||||
|
||||
# Run with specific device
|
||||
flutter run -d <device-id>
|
||||
|
||||
# Run in debug mode with detailed logging
|
||||
flutter run --debug --verbose
|
||||
|
||||
# Format code
|
||||
dart format .
|
||||
|
||||
# Analyze code quality
|
||||
flutter analyze --no-fatal-infos
|
||||
|
||||
# Run tests
|
||||
flutter test
|
||||
|
||||
# Generate code coverage
|
||||
flutter test --coverage
|
||||
```
|
||||
|
||||
### Code Quality & Standards
|
||||
|
||||
This project follows strict coding standards:
|
||||
- **Linting**: Uses `flutter_lints` for consistent code style
|
||||
- **Architecture**: Singleton services with dependency injection
|
||||
- **Error Handling**: Comprehensive try-catch with user-friendly messages
|
||||
- **Naming**: Dart conventions (camelCase, PascalCase, snake_case)
|
||||
- **Documentation**: Comprehensive inline documentation
|
||||
|
||||
### Debugging
|
||||
|
||||
```bash
|
||||
# Connect to Android device over WiFi
|
||||
adb connect <device-ip>:5555
|
||||
|
||||
# View logs
|
||||
flutter logs
|
||||
|
||||
# Launch DevTools
|
||||
flutter pub global activate devtools
|
||||
flutter pub global run devtools
|
||||
```
|
||||
|
||||
## 📦 Build & Deployment
|
||||
|
||||
### Android Builds
|
||||
|
||||
```bash
|
||||
# Clean and prepare
|
||||
flutter clean
|
||||
flutter pub get
|
||||
|
||||
# Debug build (uses development API)
|
||||
flutter build apk --debug
|
||||
|
||||
# Release build (uses production API)
|
||||
flutter build apk --release
|
||||
|
||||
# App Bundle for Play Store
|
||||
flutter build appbundle --release
|
||||
|
||||
# Install APK directly
|
||||
flutter install build/app/outputs/flutter-apk/app-release.apk
|
||||
```
|
||||
|
||||
### iOS Builds (macOS only)
|
||||
|
||||
```bash
|
||||
# Build for iOS
|
||||
flutter build ios --release
|
||||
|
||||
# Build for iOS Simulator
|
||||
flutter build ios --debug --simulator
|
||||
```
|
||||
|
||||
### Build Configurations
|
||||
|
||||
The app uses different API endpoints based on build type:
|
||||
- **Debug builds**: Development server (ngrok tunnel)
|
||||
- **Release builds**: Production API (`https://api.bottlecrm.io`)
|
||||
|
||||
Build configurations are managed in:
|
||||
- `lib/config/api_config.dart` - API endpoint configuration
|
||||
- `android/app/build.gradle.kts` - Android build settings
|
||||
- `ios/Runner.xcodeproj` - iOS build settings
|
||||
|
||||
## 🏗 Architecture
|
||||
|
||||
BottleCRM Mobile follows a robust, scalable architecture designed for enterprise applications:
|
||||
|
||||
### Core Architecture Patterns
|
||||
|
||||
- **Singleton Services**: All services use the singleton pattern for consistent state management
|
||||
- **Service-First Design**: Business logic is encapsulated in service classes
|
||||
- **Repository Pattern**: Data access abstraction with caching layers
|
||||
- **Multi-tenant Support**: Organization-based data isolation at the API level
|
||||
|
||||
### Project Structure
|
||||
|
||||
```
|
||||
lib/
|
||||
├── app.dart # Main app configuration & routing
|
||||
├── main.dart # Application entry point
|
||||
├── config/
|
||||
│ └── api_config.dart # Environment-aware API configuration
|
||||
├── models/
|
||||
│ └── api_models.dart # Type-safe data models with JSON serialization
|
||||
├── services/ # Business logic & API communication
|
||||
│ ├── api_service.dart # HTTP client with auto-authentication
|
||||
│ ├── auth_service.dart # Google OAuth & organization management
|
||||
│ ├── contacts_service.dart
|
||||
│ ├── dashboard_service.dart
|
||||
│ ├── leads_service.dart
|
||||
│ └── tasks_service.dart
|
||||
└── screens/ # UI screens organized by feature
|
||||
├── dashboard_screen.dart
|
||||
├── login_screen.dart
|
||||
├── company_selection_screen.dart
|
||||
└── ...
|
||||
```
|
||||
|
||||
### Key Architecture Components
|
||||
|
||||
#### 1. Authentication Flow
|
||||
```
|
||||
Login → Google OAuth → JWT Token → Organization Selection → Dashboard
|
||||
```
|
||||
|
||||
#### 2. Service Pattern
|
||||
```dart
|
||||
class SomeService {
|
||||
static final SomeService _instance = SomeService._internal();
|
||||
factory SomeService() => _instance;
|
||||
SomeService._internal();
|
||||
|
||||
// Service methods...
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. API Communication
|
||||
- Centralized HTTP client with automatic JWT token injection
|
||||
- Organization header (`X-Organization-ID`) for multi-tenant requests
|
||||
- Automatic logout on 401 responses
|
||||
- Comprehensive error handling with user-friendly messages
|
||||
|
||||
#### 4. State Management
|
||||
- Service-based state management with singleton pattern
|
||||
- Local caching using SharedPreferences
|
||||
- Reactive UI updates with StatefulWidget patterns
|
||||
- Navigation state preserved with IndexedStack
|
||||
|
||||
### Data Flow
|
||||
|
||||
1. **Authentication**: Google OAuth → JWT storage → Organization selection
|
||||
2. **API Requests**: Service → ApiService → HTTP → Backend API
|
||||
3. **Data Processing**: JSON → Model classes → UI widgets
|
||||
4. **Local Storage**: Critical data cached in SharedPreferences
|
||||
5. **Error Handling**: Service level → UI feedback → User notification
|
||||
|
||||
For detailed architectural guidelines, see [CLAUDE.md](CLAUDE.md) and [.github/copilot-instructions.md](.github/copilot-instructions.md).
|
||||
|
||||
## ⚙️ Configuration
|
||||
|
||||
### API Configuration
|
||||
|
||||
The application uses environment-based API URLs configured in `lib/config/api_config.dart`:
|
||||
|
||||
```dart
|
||||
// Development (debug builds)
|
||||
static const String _developmentUrl = 'https://b2ad5166b831.ngrok-free.app';
|
||||
|
||||
// Production (release builds)
|
||||
static const String _productionUrl = 'https://api.bottlecrm.io';
|
||||
```
|
||||
|
||||
**Environment Detection**: Automatic switching based on `kDebugMode` flag
|
||||
|
||||
### Authentication Setup
|
||||
|
||||
#### Google Sign-In Configuration
|
||||
|
||||
1. **Firebase Console Setup**:
|
||||
- Create Firebase project
|
||||
- Enable Google Sign-In authentication provider
|
||||
- Configure OAuth consent screen
|
||||
|
||||
2. **Get Android SHA-1 fingerprint**:
|
||||
```bash
|
||||
cd android
|
||||
./gradlew signingReport
|
||||
```
|
||||
|
||||
3. **Google Cloud Console**:
|
||||
- Create OAuth 2.0 Client ID for Android
|
||||
- Add SHA-1 fingerprint to OAuth client
|
||||
- Download `google-services.json`
|
||||
|
||||
4. **Firebase Configuration Files**:
|
||||
```bash
|
||||
android/app/google-services.json # Android configuration
|
||||
ios/Runner/GoogleService-Info.plist # iOS configuration (if applicable)
|
||||
```
|
||||
|
||||
#### Authentication Flow
|
||||
|
||||
```
|
||||
1. User clicks "Sign in with Google"
|
||||
2. Google OAuth flow → JWT token received
|
||||
3. Token stored in SharedPreferences
|
||||
4. User selects organization from available list
|
||||
5. Organization ID added to all API requests via X-Organization-ID header
|
||||
6. Dashboard and metadata loaded for selected organization
|
||||
```
|
||||
|
||||
### Multi-tenancy Configuration
|
||||
|
||||
- **Organization-based Data Isolation**: All API requests include organization context
|
||||
- **Automatic Header Injection**: `ApiService` adds `X-Organization-ID` to requests
|
||||
- **Organization Switching**: Clear cached data when switching organizations
|
||||
- **Role-based Access**: Different permissions based on user role in organization
|
||||
|
||||
### Storage Configuration
|
||||
|
||||
- **JWT Tokens**: Stored securely in SharedPreferences
|
||||
- **Organization Data**: Cached locally for offline access
|
||||
- **Metadata Caching**: Lead statuses, sources, and other metadata cached per organization
|
||||
- **Auto-cleanup**: Cached data cleared on logout and organization switch
|
||||
|
||||
## 📚 Dependencies
|
||||
|
||||
### Core Dependencies
|
||||
|
||||
| Package | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| `flutter` | SDK | Flutter framework |
|
||||
| `cupertino_icons` | ^1.0.8 | iOS-style icons |
|
||||
| `http` | ^1.1.0 | HTTP client for API requests |
|
||||
| `google_sign_in` | ^7.1.1 | Google OAuth authentication |
|
||||
| `shared_preferences` | ^2.2.2 | Local data persistence |
|
||||
| `jwt_decoder` | ^2.0.1 | JWT token parsing |
|
||||
| `font_awesome_flutter` | ^10.7.0 | FontAwesome icons |
|
||||
| `intl` | ^0.19.0 | Internationalization support |
|
||||
| `package_info_plus` | ^8.0.2 | App version and build info |
|
||||
|
||||
### Development Dependencies
|
||||
|
||||
| Package | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| `flutter_test` | SDK | Testing framework |
|
||||
| `flutter_lints` | ^6.0.0 | Dart linting rules |
|
||||
| `flutter_launcher_icons` | ^0.14.4 | App icon generation |
|
||||
|
||||
### Key Features by Dependency
|
||||
|
||||
- **Authentication**: Google Sign-In with JWT token management
|
||||
- **HTTP Communication**: Robust API client with error handling
|
||||
- **Local Storage**: Secure token and metadata caching
|
||||
- **UI Components**: Material Design with FontAwesome icons
|
||||
- **Code Quality**: Comprehensive linting and formatting
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
### Test Structure
|
||||
```bash
|
||||
test/
|
||||
├── unit/ # Unit tests for services and models
|
||||
├── widget/ # Widget tests for UI components
|
||||
└── integration/ # End-to-end integration tests
|
||||
```
|
||||
|
||||
### Running Tests
|
||||
```bash
|
||||
# Run all tests
|
||||
flutter test
|
||||
|
||||
# Run with coverage
|
||||
flutter test --coverage
|
||||
|
||||
# Run specific test file
|
||||
flutter test test/unit/auth_service_test.dart
|
||||
```
|
||||
|
||||
### Testing Guidelines
|
||||
- **Unit Tests**: All service methods and model classes
|
||||
- **Widget Tests**: Critical UI components and interactions
|
||||
- **Integration Tests**: End-to-end user flows
|
||||
- **Mocking**: Use mockito for external dependencies
|
||||
|
||||
## 🚀 Performance Optimization
|
||||
|
||||
### App Performance
|
||||
- **Lazy Loading**: Screens and data loaded on demand
|
||||
- **Image Optimization**: Compressed assets and caching
|
||||
- **Memory Management**: Proper disposal of controllers and streams
|
||||
- **Network Optimization**: Request batching and intelligent caching
|
||||
|
||||
## 🔧 Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### Firebase/Google Sign-In Issues
|
||||
```bash
|
||||
# Problem: Google Sign-In not working
|
||||
# Solution: Check SHA-1 fingerprint configuration
|
||||
cd android && ./gradlew signingReport
|
||||
|
||||
# Problem: google-services.json not found
|
||||
# Solution: Ensure file is in correct location
|
||||
ls android/app/google-services.json
|
||||
```
|
||||
|
||||
#### Build Issues
|
||||
```bash
|
||||
# Problem: Build failures after dependency updates
|
||||
# Solution: Clean and rebuild
|
||||
flutter clean
|
||||
flutter pub get
|
||||
flutter run
|
||||
|
||||
# Problem: Android build issues
|
||||
# Solution: Verify Android SDK and NDK versions
|
||||
flutter doctor -v
|
||||
```
|
||||
|
||||
#### API Connection Issues
|
||||
```bash
|
||||
# Problem: API requests failing in debug mode
|
||||
# Solution: Check ngrok tunnel status and update URL in api_config.dart
|
||||
|
||||
# Problem: 401 Unauthorized errors
|
||||
# Solution: Clear app data and re-authenticate
|
||||
flutter clean
|
||||
# Uninstall app from device and reinstall
|
||||
```
|
||||
|
||||
### Development Tips
|
||||
|
||||
1. **Hot Reload**: Use `r` in terminal for hot reload during development
|
||||
2. **Hot Restart**: Use `R` for hot restart when changing app state
|
||||
3. **DevTools**: Use Flutter DevTools for debugging and performance analysis
|
||||
4. **Logging**: Check console output for detailed error information
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
### Development Workflow
|
||||
|
||||
1. **Fork the repository**
|
||||
2. **Create a feature branch**: `git checkout -b feature/amazing-feature`
|
||||
3. **Follow coding standards**: Use `dart format` and `flutter analyze`
|
||||
4. **Write tests**: Ensure adequate test coverage
|
||||
5. **Commit changes**: Use conventional commit messages
|
||||
6. **Create Pull Request**: Provide detailed description
|
||||
|
||||
### Code Style Guidelines
|
||||
|
||||
- Follow Dart naming conventions
|
||||
- Use meaningful variable and function names
|
||||
- Add inline documentation for complex logic
|
||||
- Implement proper error handling
|
||||
- Write unit tests for new features
|
||||
|
||||
### Commit Message Format
|
||||
```
|
||||
type(scope): description
|
||||
|
||||
feat(auth): add biometric authentication
|
||||
fix(api): resolve null pointer exception
|
||||
docs(readme): update installation instructions
|
||||
```
|
||||
|
||||
## 📄 License
|
||||
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 BottleCRM
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
## 🌟 Support
|
||||
|
||||
- ** Documentation**: [CLAUDE.md](CLAUDE.md) for detailed architecture information
|
||||
- **🐛 Issues**: [GitHub Issues](https://github.com/your-username/bottlecrm_mobile_v2/issues) for bug reports
|
||||
- **💬 Discussions**: [GitHub Discussions](https://github.com/your-username/bottlecrm_mobile_v2/discussions) for questions
|
||||
- **🔥 Firebase Setup**: [FIREBASE_SETUP.md](FIREBASE_SETUP.md) for Firebase configuration
|
||||
|
||||
---
|
||||
|
||||
<div align="center">
|
||||
|
||||
**BottleCRM Mobile** - Free CRM for startups and enterprises
|
||||
|
||||
Made with ❤️ using Flutter
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,40 +1,65 @@
|
|||
import java.util.Properties
|
||||
import java.io.FileInputStream
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("kotlin-android")
|
||||
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||
id("dev.flutter.flutter-gradle-plugin")
|
||||
id("com.google.gms.google-services")
|
||||
}
|
||||
dependencies {
|
||||
// ...
|
||||
implementation("com.google.android.material:material:1.12.0")
|
||||
// ...
|
||||
}
|
||||
|
||||
val keystoreProperties = Properties()
|
||||
val keystorePropertiesFile = rootProject.file("key.properties")
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.example.mobile"
|
||||
namespace = "io.bottlecrm"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = flutter.ndkVersion
|
||||
ndkVersion = "27.0.12077973" // Use latest available NDK
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_17.toString()
|
||||
jvmTarget = JavaVersion.VERSION_11.toString()
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId = "com.example.mobile"
|
||||
applicationId = "io.bottlecrm"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||
minSdk = flutter.minSdkVersion
|
||||
minSdk = 28 // Android 9 (API 28)
|
||||
targetSdk = flutter.targetSdkVersion
|
||||
versionCode = flutter.versionCode
|
||||
versionName = flutter.versionName
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
create("release") {
|
||||
keyAlias = keystoreProperties["keyAlias"] as String
|
||||
keyPassword = keystoreProperties["keyPassword"] as String
|
||||
storeFile = keystoreProperties["storeFile"]?.let { file(it) }
|
||||
storePassword = keystoreProperties["storePassword"] as String
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
// signingConfig = signingConfigs.getByName("debug")
|
||||
signingConfig = signingConfigs.getByName("release")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
63
mobile/android/app/google-services.json
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
"project_info": {
|
||||
"project_number": "1072513761792",
|
||||
"project_id": "bottlecrm-io",
|
||||
"storage_bucket": "bottlecrm-io.firebasestorage.app"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:1072513761792:android:c170ae72445200ecd74ee5",
|
||||
"android_client_info": {
|
||||
"package_name": "io.bottlecrm"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "1072513761792-6cnavnfp5p4me4peah0vgoc477ndkd3h.apps.googleusercontent.com",
|
||||
"client_type": 1,
|
||||
"android_info": {
|
||||
"package_name": "io.bottlecrm",
|
||||
"certificate_hash": "5227cfe6b33aceb349e54aaf1ea3cfc191aef324"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "1072513761792-r70ldlpqkbkb654tdpu41sqqrs5b4uf4.apps.googleusercontent.com",
|
||||
"client_type": 1,
|
||||
"android_info": {
|
||||
"package_name": "io.bottlecrm",
|
||||
"certificate_hash": "f980d3a3e81564ea45f3634dd706eb5261ec222b"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "1072513761792-vp1nq9690h2v94oge513ejr7d01rh0e8.apps.googleusercontent.com",
|
||||
"client_type": 1,
|
||||
"android_info": {
|
||||
"package_name": "io.bottlecrm",
|
||||
"certificate_hash": "67c4be5a9739470b402c1405f181abc7e6cfa7df"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "1072513761792-p59rct7b1c3go7l58e51r3geuqff2tfl.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyDsA2wgQIw-bVgwODNMIF482gVRn5xdANU"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "1072513761792-dvcv8cj147oj6nav40u7jfjp1r3f0a1d.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<application
|
||||
android:label="mobile"
|
||||
android:label="BottleCRM"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
android:icon="@mipmap/launcher_icon">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package com.example.mobile
|
||||
package io.bottlecrm
|
||||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
|
||||
BIN
mobile/android/app/src/main/res/mipmap-hdpi/launcher_icon.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
mobile/android/app/src/main/res/mipmap-mdpi/launcher_icon.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
mobile/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png
Normal file
|
After Width: | Height: | Size: 6 KiB |
BIN
mobile/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
mobile/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
|
|
@ -12,7 +12,7 @@
|
|||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<style name="NormalTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@
|
|||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<style name="NormalTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,13 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath("com.google.gms:google-services:4.4.0")
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
|
|
@ -5,10 +15,7 @@ allprojects {
|
|||
}
|
||||
}
|
||||
|
||||
val newBuildDir: Directory =
|
||||
rootProject.layout.buildDirectory
|
||||
.dir("../../build")
|
||||
.get()
|
||||
val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get()
|
||||
rootProject.layout.buildDirectory.value(newBuildDir)
|
||||
|
||||
subprojects {
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
|
|
|||
|
|
@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
|||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
pluginManagement {
|
||||
val flutterSdkPath =
|
||||
run {
|
||||
val properties = java.util.Properties()
|
||||
file("local.properties").inputStream().use { properties.load(it) }
|
||||
val flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
|
||||
flutterSdkPath
|
||||
}
|
||||
val flutterSdkPath = run {
|
||||
val properties = java.util.Properties()
|
||||
file("local.properties").inputStream().use { properties.load(it) }
|
||||
val flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
|
||||
flutterSdkPath
|
||||
}
|
||||
|
||||
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
||||
|
||||
|
|
@ -19,8 +18,8 @@ pluginManagement {
|
|||
|
||||
plugins {
|
||||
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
||||
id("com.android.application") version "8.11.1" apply false
|
||||
id("org.jetbrains.kotlin.android") version "2.2.20" apply false
|
||||
id("com.android.application") version "8.9.1" apply false
|
||||
id("org.jetbrains.kotlin.android") version "2.1.0" apply false
|
||||
}
|
||||
|
||||
include(":app")
|
||||
|
|
|
|||
BIN
mobile/assets/icon/icon.png
Normal file
|
After Width: | Height: | Size: 244 KiB |
3
mobile/devtools_options.yaml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
description: This file stores settings for Dart & Flutter DevTools.
|
||||
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
|
||||
extensions:
|
||||
|
|
@ -21,6 +21,6 @@
|
|||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>13.0</string>
|
||||
<string>12.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
|
|
@ -368,7 +368,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.mobile;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bottlecrm;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
|
@ -384,7 +384,7 @@
|
|||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.mobile.RunnerTests;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bottlecrm.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
|
|
@ -401,7 +401,7 @@
|
|||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.mobile.RunnerTests;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bottlecrm.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
|
|
@ -416,7 +416,7 @@
|
|||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.mobile.RunnerTests;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bottlecrm.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
|
|
@ -427,7 +427,7 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
|
|
@ -472,7 +472,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
|
|
@ -484,7 +484,7 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
|
|
@ -523,7 +523,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
|
|
@ -547,7 +547,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.mobile;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bottlecrm;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
|
|
@ -569,7 +569,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.mobile;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bottlecrm;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
|
|
|||
|
|
@ -1,122 +1 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-20x20@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-20x20@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-29x29@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-29x29@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-29x29@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-40x40@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-40x40@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-60x60@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-60x60@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-20x20@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-20x20@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-29x29@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-29x29@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-40x40@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-40x40@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-76x76@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-76x76@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "83.5x83.5",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-83.5x83.5@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "1024x1024",
|
||||
"idiom" : "ios-marketing",
|
||||
"filename" : "Icon-App-1024x1024@1x.png",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
{"images":[{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@3x.png","scale":"3x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}}
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 469 KiB |
|
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 541 B |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 840 B |
|
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 6 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 8 KiB |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 18 KiB |
|
|
@ -5,7 +5,7 @@
|
|||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Mobile</string>
|
||||
<string>Bottlecrm</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>mobile</string>
|
||||
<string>bottle_crm</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,22 @@
|
|||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.7"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.7.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -25,6 +41,22 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
checked_yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: checked_yaml
|
||||
sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.4"
|
||||
cli_util:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cli_util
|
||||
sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.2"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -81,6 +113,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
fl_chart:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -94,6 +134,14 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_launcher_icons:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_launcher_icons
|
||||
sha256: "10f13781741a2e3972126fae08393d3c4e01fa4cd7473326b94b72cf594195e7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.14.4"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
|
|
@ -136,8 +184,56 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.3"
|
||||
http:
|
||||
google_identity_services_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: google_identity_services_web
|
||||
sha256: "5d187c46dc59e02646e10fe82665fc3884a9b71bc1c90c2b8b749316d33ee454"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.3+1"
|
||||
google_sign_in:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: google_sign_in
|
||||
sha256: "521031b65853b4409b8213c0387d57edaad7e2a949ce6dea0d8b2afc9cb29763"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.2.0"
|
||||
google_sign_in_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: google_sign_in_android
|
||||
sha256: "5ec98ab35387c68c0050495bb211bd88375873723a80fae7c2e9266ea0bdd8bb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.2.7"
|
||||
google_sign_in_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: google_sign_in_ios
|
||||
sha256: aee8bb29484611a37607849175a2009d423de6bd7c129326c69fd7068f0b6ed7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.4"
|
||||
google_sign_in_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: google_sign_in_platform_interface
|
||||
sha256: "7f59208c42b415a3cca203571128d6f84f885fead2d5b53eb65a9e27f2965bb5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
google_sign_in_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: google_sign_in_web
|
||||
sha256: "2fc1f941e6443b2d6984f4056a727a3eaeab15d8ee99ba7125d79029be75a1da"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
http:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: http
|
||||
sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412"
|
||||
|
|
@ -152,6 +248,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.2"
|
||||
image:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image
|
||||
sha256: "51555e36056541237b15b57afc31a0f53d4f9aefd9bd00873a6dc0090e54e332"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.6.0"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -160,6 +264,22 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.19.0"
|
||||
json_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: json_annotation
|
||||
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.9.0"
|
||||
jwt_decoder:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: jwt_decoder
|
||||
sha256: "54774aebf83f2923b99e6416b4ea915d47af3bde56884eb622de85feabbc559f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -232,6 +352,22 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.17.0"
|
||||
package_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: package_info_plus
|
||||
sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.3.1"
|
||||
package_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_platform_interface
|
||||
sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -288,6 +424,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: petitparser
|
||||
sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -304,6 +448,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
posix:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: posix
|
||||
sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.3"
|
||||
riverpod:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -312,6 +464,62 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.6.1"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: shared_preferences
|
||||
sha256: "2939ae520c9024cb197fc20dee269cd8cdbf564c8b5746374ec6cacdc5169e64"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.4"
|
||||
shared_preferences_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_android
|
||||
sha256: "83af5c682796c0f7719c2bbf74792d113e40ae97981b8f266fa84574573556bc"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.18"
|
||||
shared_preferences_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_foundation
|
||||
sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.6"
|
||||
shared_preferences_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_linux
|
||||
sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
shared_preferences_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_platform_interface
|
||||
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
shared_preferences_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_web
|
||||
sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.3"
|
||||
shared_preferences_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_windows
|
||||
sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
simple_gesture_detector:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -485,6 +693,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.15.0"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -493,6 +709,22 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xml
|
||||
sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.6.1"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
sdks:
|
||||
dart: ">=3.10.4 <4.0.0"
|
||||
dart: ">=3.9.0 <4.0.0"
|
||||
flutter: ">=3.35.0"
|
||||
|
|
|
|||
|
|
@ -1,16 +1,23 @@
|
|||
name: mobile
|
||||
description: "SalesPro CRM - A professional sales CRM mobile application"
|
||||
publish_to: 'none'
|
||||
name: bottle_crm
|
||||
description: "CRM for everyone."
|
||||
# The following line prevents the package from being accidentally published to
|
||||
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
||||
publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
||||
|
||||
version: 1.0.0+1
|
||||
version: 1.0.0+9
|
||||
|
||||
environment:
|
||||
sdk: ^3.10.4
|
||||
sdk: ^3.8.1
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
http: ^1.1.0
|
||||
google_sign_in: ^7.1.1
|
||||
shared_preferences: ^2.2.2
|
||||
jwt_decoder: ^2.0.1
|
||||
package_info_plus: ^8.0.2
|
||||
# Icons
|
||||
cupertino_icons: ^1.0.8
|
||||
lucide_icons: ^0.257.0
|
||||
|
|
@ -37,7 +44,27 @@ dependencies:
|
|||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^6.0.0
|
||||
|
||||
# The "flutter_lints" package below contains a set of recommended lints to
|
||||
# encourage good coding practices. The lint set provided by the package is
|
||||
# activated in the `analysis_options.yaml` file located at the root of your
|
||||
# package. See that file for information about deactivating specific lint
|
||||
# rules and activating additional ones.
|
||||
flutter_lints: ^6.0.0
|
||||
flutter_launcher_icons: "^0.14.4"
|
||||
|
||||
flutter_launcher_icons:
|
||||
android: "launcher_icon"
|
||||
ios: true
|
||||
image_path: "assets/icon/icon.png"
|
||||
min_sdk_android: 31 # android min sdk Android 12 (API 31)
|
||||
remove_alpha_ios: true # remove alpha channel from iOS icons, default false
|
||||
|
||||
# The following section is specific to Flutter packages.
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
assets:
|
||||
- assets/icon/
|
||||
- assets/images/
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
// SalesPro CRM Widget Test
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import 'package:mobile/main.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('SalesPro app smoke test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: SalesProApp(),
|
||||
),
|
||||
);
|
||||
|
||||
// Wait for splash screen animation
|
||||
await tester.pump(const Duration(seconds: 1));
|
||||
|
||||
// Verify that the app starts
|
||||
expect(find.byType(SalesProApp), findsOneWidget);
|
||||
});
|
||||
}
|
||||