feat: 알림 재예약 개선과 패키지 업그레이드
This commit is contained in:
@@ -36,6 +36,7 @@ Sensitive Areas (require explicit approval)
|
|||||||
Operational Conventions
|
Operational Conventions
|
||||||
- Branch naming: `codex/<type>-<slug>` (e.g., `codex/fix-url-matcher`).
|
- Branch naming: `codex/<type>-<slug>` (e.g., `codex/fix-url-matcher`).
|
||||||
- Commits: Conventional Commits preferred (e.g., `fix: correct url matching for X`).
|
- Commits: Conventional Commits preferred (e.g., `fix: correct url matching for X`).
|
||||||
|
- Git push 후 공유하는 설명/보고는 반드시 한국어로 작성합니다.
|
||||||
- PR description template:
|
- PR description template:
|
||||||
- Summary: what/why
|
- Summary: what/why
|
||||||
- Changes: key files and decisions
|
- Changes: key files and decisions
|
||||||
|
|||||||
@@ -45,5 +45,5 @@ flutter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
|
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,7 +126,7 @@
|
|||||||
"repeatSubscriptionNotFound": "No repeated subscription information found.",
|
"repeatSubscriptionNotFound": "No repeated subscription information found.",
|
||||||
"newSubscriptionNotFound": "No new subscription SMS found",
|
"newSubscriptionNotFound": "No new subscription SMS found",
|
||||||
"findRepeatSubscriptions": "Find subscriptions paid 2+ times",
|
"findRepeatSubscriptions": "Find subscriptions paid 2+ times",
|
||||||
"scanTextMessages": "Scan text messages to automatically find repeatedly paid subscriptions. Service names and amounts can be extracted for easy subscription addition.",
|
"scanTextMessages": "Scan text messages to automatically find repeatedly paid subscriptions.\nService names and amounts can be extracted for easy subscription addition.\nThis auto-detection feature is still under development, and might miss or misidentify some subscriptions.\nPlease review the detected results and add or edit subscriptions manually if needed.",
|
||||||
"startScanning": "Start Scanning",
|
"startScanning": "Start Scanning",
|
||||||
"foundSubscription": "Found subscription",
|
"foundSubscription": "Found subscription",
|
||||||
"serviceName": "Service Name",
|
"serviceName": "Service Name",
|
||||||
@@ -357,7 +357,7 @@
|
|||||||
"repeatSubscriptionNotFound": "반복 결제된 구독 정보를 찾을 수 없습니다.",
|
"repeatSubscriptionNotFound": "반복 결제된 구독 정보를 찾을 수 없습니다.",
|
||||||
"newSubscriptionNotFound": "신규 구독 관련 SMS를 찾을 수 없습니다",
|
"newSubscriptionNotFound": "신규 구독 관련 SMS를 찾을 수 없습니다",
|
||||||
"findRepeatSubscriptions": "2회 이상 결제된 구독 서비스 찾기",
|
"findRepeatSubscriptions": "2회 이상 결제된 구독 서비스 찾기",
|
||||||
"scanTextMessages": "문자 메시지를 스캔하여 반복적으로 결제된 구독 서비스를 자동으로 찾습니다. 서비스명과 금액을 추출하여 쉽게 구독을 추가할 수 있습니다.",
|
"scanTextMessages": "문자 메시지를 스캔하여 반복적으로 결제된 구독 서비스를 자동으로 찾습니다.\n서비스명과 금액을 추출하여 쉽게 구독을 추가할 수 있습니다.\n이 자동 감지 기능은 일부 구독 서비스를 놓치거나 잘못 인식할 수 있습니다.\n감지 결과를 확인하신 후 필요에 따라 수동으로 추가하거나 수정해 주세요.",
|
||||||
"startScanning": "스캔 시작하기",
|
"startScanning": "스캔 시작하기",
|
||||||
"foundSubscription": "다음 구독을 찾았습니다",
|
"foundSubscription": "다음 구독을 찾았습니다",
|
||||||
"serviceName": "서비스명",
|
"serviceName": "서비스명",
|
||||||
@@ -588,7 +588,7 @@
|
|||||||
"repeatSubscriptionNotFound": "繰り返し決済されたサブスクリプション情報が見つかりません。",
|
"repeatSubscriptionNotFound": "繰り返し決済されたサブスクリプション情報が見つかりません。",
|
||||||
"newSubscriptionNotFound": "新規サブスクリプションSMSが見つかりません",
|
"newSubscriptionNotFound": "新規サブスクリプションSMSが見つかりません",
|
||||||
"findRepeatSubscriptions": "2回以上決済されたサブスクリプションを検索",
|
"findRepeatSubscriptions": "2回以上決済されたサブスクリプションを検索",
|
||||||
"scanTextMessages": "テキストメッセージをスキャンして、繰り返し決済されたサブスクリプションを自動的に検出します。サービス名と金額を抽出して簡単にサブスクリプションを追加できます。",
|
"scanTextMessages": "テキストメッセージをスキャンして、繰り返し決済されたサブスクリプションを自動的に検出します。\nサービス名と金額を抽出して簡単にサブスクリプションを追加できます。\nこの自動検出機能は、一部のサブスクリプションを見落としたり誤検出する可能性があります。\n検出結果を確認し、必要に応じて手動で追加または修正してください。",
|
||||||
"startScanning": "スキャン開始",
|
"startScanning": "スキャン開始",
|
||||||
"foundSubscription": "サブスクリプションが見つかりました",
|
"foundSubscription": "サブスクリプションが見つかりました",
|
||||||
"serviceName": "サービス名",
|
"serviceName": "サービス名",
|
||||||
@@ -808,7 +808,7 @@
|
|||||||
"repeatSubscriptionNotFound": "未找到重复付款的订阅信息。",
|
"repeatSubscriptionNotFound": "未找到重复付款的订阅信息。",
|
||||||
"newSubscriptionNotFound": "未找到新订阅短信",
|
"newSubscriptionNotFound": "未找到新订阅短信",
|
||||||
"findRepeatSubscriptions": "查找支付2次以上的订阅",
|
"findRepeatSubscriptions": "查找支付2次以上的订阅",
|
||||||
"scanTextMessages": "扫描短信以自动查找重复付款的订阅。可以提取服务名称和金额,轻松添加订阅。",
|
"scanTextMessages": "扫描短信以自动查找重复付款的订阅。\n可以提取服务名称和金额,轻松添加订阅。\n该自动检测功能可能会遗漏或误识别某些订阅。\n请检查检测结果,并在需要时手动添加或修改。",
|
||||||
"startScanning": "开始扫描",
|
"startScanning": "开始扫描",
|
||||||
"foundSubscription": "找到订阅",
|
"foundSubscription": "找到订阅",
|
||||||
"serviceName": "服务名称",
|
"serviceName": "服务名称",
|
||||||
|
|||||||
@@ -114,6 +114,23 @@ class NotificationProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
// 알림이 활성화된 경우에만 알림 재예약 (비활성화 시에는 필요 없음)
|
// 알림이 활성화된 경우에만 알림 재예약 (비활성화 시에는 필요 없음)
|
||||||
if (value) {
|
if (value) {
|
||||||
|
final hasPermission = await NotificationService.checkPermission();
|
||||||
|
if (!hasPermission) {
|
||||||
|
final granted = await NotificationService.requestPermission();
|
||||||
|
if (!granted) {
|
||||||
|
debugPrint('알림 권한이 부여되지 않았습니다. 일부 알림이 제한될 수 있습니다.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final canExact = await NotificationService.canScheduleExactAlarms();
|
||||||
|
if (!canExact) {
|
||||||
|
final exactGranted =
|
||||||
|
await NotificationService.requestExactAlarmsPermission();
|
||||||
|
if (!exactGranted) {
|
||||||
|
debugPrint('정확 알람 권한이 없어 근사 알림으로 예약됩니다.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 알림 설정 변경 시 모든 구독의 알림 재예약
|
// 알림 설정 변경 시 모든 구독의 알림 재예약
|
||||||
// 지연 실행으로 UI 응답성 향상
|
// 지연 실행으로 UI 응답성 향상
|
||||||
Future.microtask(() => _rescheduleNotificationsIfNeeded());
|
Future.microtask(() => _rescheduleNotificationsIfNeeded());
|
||||||
|
|||||||
@@ -103,6 +103,14 @@ class SubscriptionProvider extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _reschedulePaymentNotifications() async {
|
||||||
|
try {
|
||||||
|
await NotificationService.reschedulAllNotifications(_subscriptions);
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('결제 알림 재예약 중 오류 발생: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> addSubscription({
|
Future<void> addSubscription({
|
||||||
required String serviceName,
|
required String serviceName,
|
||||||
required double monthlyCost,
|
required double monthlyCost,
|
||||||
@@ -145,6 +153,8 @@ class SubscriptionProvider extends ChangeNotifier {
|
|||||||
if (isEventActive && eventEndDate != null) {
|
if (isEventActive && eventEndDate != null) {
|
||||||
await _scheduleEventEndNotification(subscription);
|
await _scheduleEventEndNotification(subscription);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await _reschedulePaymentNotifications();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint('구독 추가 중 오류 발생: $e');
|
debugPrint('구독 추가 중 오류 발생: $e');
|
||||||
rethrow;
|
rethrow;
|
||||||
@@ -176,6 +186,8 @@ class SubscriptionProvider extends ChangeNotifier {
|
|||||||
debugPrint('[SubscriptionProvider] 구독 업데이트 완료, '
|
debugPrint('[SubscriptionProvider] 구독 업데이트 완료, '
|
||||||
'현재 총 월간 지출: ${totalMonthlyExpense.toStringAsFixed(2)}');
|
'현재 총 월간 지출: ${totalMonthlyExpense.toStringAsFixed(2)}');
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
||||||
|
await _reschedulePaymentNotifications();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint('구독 업데이트 중 오류 발생: $e');
|
debugPrint('구독 업데이트 중 오류 발생: $e');
|
||||||
rethrow;
|
rethrow;
|
||||||
@@ -186,6 +198,8 @@ class SubscriptionProvider extends ChangeNotifier {
|
|||||||
try {
|
try {
|
||||||
await _subscriptionBox.delete(id);
|
await _subscriptionBox.delete(id);
|
||||||
await refreshSubscriptions();
|
await refreshSubscriptions();
|
||||||
|
|
||||||
|
await _reschedulePaymentNotifications();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint('구독 삭제 중 오류 발생: $e');
|
debugPrint('구독 삭제 중 오류 발생: $e');
|
||||||
rethrow;
|
rethrow;
|
||||||
@@ -213,6 +227,8 @@ class SubscriptionProvider extends ChangeNotifier {
|
|||||||
} finally {
|
} finally {
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
||||||
|
await _reschedulePaymentNotifications();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,6 +242,7 @@ class SubscriptionProvider extends ChangeNotifier {
|
|||||||
title: '이벤트 종료 알림',
|
title: '이벤트 종료 알림',
|
||||||
body: '${subscription.serviceName}의 할인 이벤트가 종료되었습니다.',
|
body: '${subscription.serviceName}의 할인 이벤트가 종료되었습니다.',
|
||||||
scheduledDate: subscription.eventEndDate!,
|
scheduledDate: subscription.eventEndDate!,
|
||||||
|
channelId: NotificationService.expirationChannelId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import '../widgets/add_subscription/add_subscription_save_button.dart';
|
|||||||
|
|
||||||
/// 새로운 구독을 추가하는 화면
|
/// 새로운 구독을 추가하는 화면
|
||||||
class AddSubscriptionScreen extends StatefulWidget {
|
class AddSubscriptionScreen extends StatefulWidget {
|
||||||
const AddSubscriptionScreen({Key? key}) : super(key: key);
|
const AddSubscriptionScreen({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<AddSubscriptionScreen> createState() => _AddSubscriptionScreenState();
|
State<AddSubscriptionScreen> createState() => _AddSubscriptionScreenState();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
import 'package:flutter/foundation.dart' show kIsWeb, kDebugMode;
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import '../providers/notification_provider.dart';
|
import '../providers/notification_provider.dart';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
@@ -694,6 +694,25 @@ class SettingsScreen extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (kDebugMode)
|
||||||
|
Padding(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.only(
|
||||||
|
top: 16.0),
|
||||||
|
child: SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
child: OutlinedButton.icon(
|
||||||
|
icon: const Icon(Icons
|
||||||
|
.notifications_active),
|
||||||
|
label:
|
||||||
|
const Text('테스트 알림'),
|
||||||
|
onPressed: () {
|
||||||
|
NotificationService
|
||||||
|
.showTestPaymentNotification();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -16,18 +16,21 @@ class SmsScanScreen extends StatefulWidget {
|
|||||||
|
|
||||||
class _SmsScanScreenState extends State<SmsScanScreen> {
|
class _SmsScanScreenState extends State<SmsScanScreen> {
|
||||||
late SmsScanController _controller;
|
late SmsScanController _controller;
|
||||||
|
late final ScrollController _scrollController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_controller = SmsScanController();
|
_controller = SmsScanController();
|
||||||
_controller.addListener(_handleControllerUpdate);
|
_controller.addListener(_handleControllerUpdate);
|
||||||
|
_scrollController = ScrollController();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_controller.removeListener(_handleControllerUpdate);
|
_controller.removeListener(_handleControllerUpdate);
|
||||||
_controller.dispose();
|
_controller.dispose();
|
||||||
|
_scrollController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,16 +96,37 @@ class _SmsScanScreenState extends State<SmsScanScreen> {
|
|||||||
websiteUrlController: _controller.websiteUrlController,
|
websiteUrlController: _controller.websiteUrlController,
|
||||||
selectedCategoryId: _controller.selectedCategoryId,
|
selectedCategoryId: _controller.selectedCategoryId,
|
||||||
onCategoryChanged: _controller.setSelectedCategoryId,
|
onCategoryChanged: _controller.setSelectedCategoryId,
|
||||||
onAdd: () => _controller.addCurrentSubscription(context),
|
onAdd: _handleAddSubscription,
|
||||||
onSkip: () => _controller.skipCurrentSubscription(context),
|
onSkip: _handleSkipSubscription,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _handleAddSubscription() async {
|
||||||
|
await _controller.addCurrentSubscription(context);
|
||||||
|
if (!mounted) return;
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) => _scrollToTop());
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleSkipSubscription() {
|
||||||
|
_controller.skipCurrentSubscription(context);
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) => _scrollToTop());
|
||||||
|
}
|
||||||
|
|
||||||
|
void _scrollToTop() {
|
||||||
|
if (!_scrollController.hasClients) return;
|
||||||
|
_scrollController.animateTo(
|
||||||
|
0,
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
curve: Curves.easeOut,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
|
controller: _scrollController,
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ class _SplashScreenState extends State<SplashScreen>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}),
|
||||||
|
|
||||||
// 상단 원형 장식 제거(단색 배경 유지)
|
// 상단 원형 장식 제거(단색 배경 유지)
|
||||||
Positioned(
|
Positioned(
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
/// URL Matcher 패키지의 export 파일
|
// URL Matcher 패키지의 export 파일
|
||||||
export 'models/service_info.dart';
|
export 'models/service_info.dart';
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ class EventAnalysisCard extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -226,10 +226,10 @@ class MonthlyExpenseChartCard extends StatelessWidget {
|
|||||||
barTouchData: BarTouchData(
|
barTouchData: BarTouchData(
|
||||||
enabled: true,
|
enabled: true,
|
||||||
touchTooltipData: BarTouchTooltipData(
|
touchTooltipData: BarTouchTooltipData(
|
||||||
tooltipBgColor: Theme.of(context)
|
tooltipBorderRadius: BorderRadius.circular(8),
|
||||||
|
getTooltipColor: (group) => Theme.of(context)
|
||||||
.colorScheme
|
.colorScheme
|
||||||
.inverseSurface,
|
.inverseSurface,
|
||||||
tooltipRoundedRadius: 8,
|
|
||||||
getTooltipItem:
|
getTooltipItem:
|
||||||
(group, groupIndex, rod, rodIndex) {
|
(group, groupIndex, rod, rodIndex) {
|
||||||
return BarTooltipItem(
|
return BarTooltipItem(
|
||||||
@@ -261,10 +261,10 @@ class MonthlyExpenseChartCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
swapAnimationDuration: ReduceMotion.isEnabled(context)
|
duration: ReduceMotion.isEnabled(context)
|
||||||
? const Duration(milliseconds: 0)
|
? Duration.zero
|
||||||
: const Duration(milliseconds: 300),
|
: const Duration(milliseconds: 300),
|
||||||
swapAnimationCurve: Curves.easeOut,
|
curve: Curves.easeOut,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -390,12 +390,10 @@ class _SubscriptionPieChartCardState extends State<SubscriptionPieChartCard> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
swapAnimationDuration:
|
duration: ReduceMotion.isEnabled(context)
|
||||||
ReduceMotion.isEnabled(context)
|
? Duration.zero
|
||||||
? const Duration(milliseconds: 0)
|
: const Duration(milliseconds: 300),
|
||||||
: const Duration(
|
curve: Curves.easeOut,
|
||||||
milliseconds: 300),
|
|
||||||
swapAnimationCurve: Curves.easeOut,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ class AnimatedWaveBackground extends StatelessWidget {
|
|||||||
final AnimationController pulseController;
|
final AnimationController pulseController;
|
||||||
|
|
||||||
const AnimatedWaveBackground({
|
const AnimatedWaveBackground({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.controller,
|
required this.controller,
|
||||||
required this.pulseController,
|
required this.pulseController,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ class CategoryHeaderWidget extends StatelessWidget {
|
|||||||
final double totalCostCNY;
|
final double totalCostCNY;
|
||||||
|
|
||||||
const CategoryHeaderWidget({
|
const CategoryHeaderWidget({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.categoryName,
|
required this.categoryName,
|
||||||
required this.subscriptionCount,
|
required this.subscriptionCount,
|
||||||
required this.totalCostUSD,
|
required this.totalCostUSD,
|
||||||
required this.totalCostKRW,
|
required this.totalCostKRW,
|
||||||
required this.totalCostJPY,
|
required this.totalCostJPY,
|
||||||
required this.totalCostCNY,
|
required this.totalCostCNY,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ class EmptyStateWidget extends StatelessWidget {
|
|||||||
final VoidCallback onAddPressed;
|
final VoidCallback onAddPressed;
|
||||||
|
|
||||||
const EmptyStateWidget({
|
const EmptyStateWidget({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.fadeController,
|
required this.fadeController,
|
||||||
required this.rotateController,
|
required this.rotateController,
|
||||||
required this.slideController,
|
required this.slideController,
|
||||||
required this.onAddPressed,
|
required this.onAddPressed,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|||||||
@@ -18,13 +18,13 @@ class MainScreenSummaryCard extends StatelessWidget {
|
|||||||
final AnimationController waveController;
|
final AnimationController waveController;
|
||||||
final AnimationController slideController;
|
final AnimationController slideController;
|
||||||
const MainScreenSummaryCard({
|
const MainScreenSummaryCard({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.provider,
|
required this.provider,
|
||||||
required this.fadeController,
|
required this.fadeController,
|
||||||
required this.pulseController,
|
required this.pulseController,
|
||||||
required this.waveController,
|
required this.waveController,
|
||||||
required this.slideController,
|
required this.slideController,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ import '../theme/ui_constants.dart';
|
|||||||
/// SRP에 따라 광고 전용 위젯으로 분리
|
/// SRP에 따라 광고 전용 위젯으로 분리
|
||||||
class NativeAdWidget extends StatefulWidget {
|
class NativeAdWidget extends StatefulWidget {
|
||||||
final bool useOuterPadding; // true이면 외부에서 페이지 패딩을 제공
|
final bool useOuterPadding; // true이면 외부에서 페이지 패딩을 제공
|
||||||
const NativeAdWidget({Key? key, this.useOuterPadding = false})
|
const NativeAdWidget({super.key, this.useOuterPadding = false});
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<NativeAdWidget> createState() => _NativeAdWidgetState();
|
State<NativeAdWidget> createState() => _NativeAdWidgetState();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
// import '../../theme/app_colors.dart';
|
import '../../widgets/native_ad_widget.dart';
|
||||||
import '../../widgets/themed_text.dart';
|
import '../../widgets/themed_text.dart';
|
||||||
import '../../l10n/app_localizations.dart';
|
import '../../l10n/app_localizations.dart';
|
||||||
|
|
||||||
@@ -8,9 +8,12 @@ class ScanLoadingWidget extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Padding(
|
return Column(
|
||||||
|
children: [
|
||||||
|
const NativeAdWidget(key: ValueKey('sms_scan_loading_ad')),
|
||||||
|
const SizedBox(height: 48),
|
||||||
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
child: Center(
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
@@ -31,6 +34,7 @@ class ScanLoadingWidget extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ class SubscriptionListWidget extends StatelessWidget {
|
|||||||
final AnimationController fadeController;
|
final AnimationController fadeController;
|
||||||
|
|
||||||
const SubscriptionListWidget({
|
const SubscriptionListWidget({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.categorizedSubscriptions,
|
required this.categorizedSubscriptions,
|
||||||
required this.fadeController,
|
required this.fadeController,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -188,9 +188,9 @@ class MultiSliver extends StatelessWidget {
|
|||||||
final List<Widget> children;
|
final List<Widget> children;
|
||||||
|
|
||||||
const MultiSliver({
|
const MultiSliver({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.children,
|
required this.children,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import FlutterMacOS
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
import flutter_local_notifications
|
import flutter_local_notifications
|
||||||
import flutter_secure_storage_macos
|
import flutter_secure_storage_darwin
|
||||||
import local_auth_darwin
|
import local_auth_darwin
|
||||||
import path_provider_foundation
|
import path_provider_foundation
|
||||||
import share_plus
|
import share_plus
|
||||||
@@ -17,7 +17,7 @@ import webview_flutter_wkwebview
|
|||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
|
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
|
||||||
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
|
FlutterSecureStorageDarwinPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageDarwinPlugin"))
|
||||||
LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin"))
|
LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin"))
|
||||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||||
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
|
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
|
||||||
|
|||||||
108
pubspec.lock
108
pubspec.lock
@@ -293,10 +293,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: fl_chart
|
name: fl_chart
|
||||||
sha256: "00b74ae680df6b1135bdbea00a7d1fc072a9180b7c3f3702e4b19a9943f5ed7d"
|
sha256: "7ca9a40f4eb85949190e54087be8b4d6ac09dc4c54238d782a34cf1f7c011de9"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.66.2"
|
version: "1.1.1"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -314,50 +314,58 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_dotenv
|
name: flutter_dotenv
|
||||||
sha256: b7c7be5cd9f6ef7a78429cabd2774d3c4af50e79cb2b7593e3d5d763ef95c61b
|
sha256: d4130c4a43e0b13fefc593bc3961f2cb46e30cb79e253d4a526b1b5d24ae1ce4
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.2.1"
|
version: "6.0.0"
|
||||||
flutter_launcher_icons:
|
flutter_launcher_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_launcher_icons
|
name: flutter_launcher_icons
|
||||||
sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea"
|
sha256: "10f13781741a2e3972126fae08393d3c4e01fa4cd7473326b94b72cf594195e7"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.13.1"
|
version: "0.14.4"
|
||||||
flutter_lints:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: flutter_lints
|
name: flutter_lints
|
||||||
sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
|
sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.3"
|
version: "6.0.0"
|
||||||
flutter_local_notifications:
|
flutter_local_notifications:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_local_notifications
|
name: flutter_local_notifications
|
||||||
sha256: "674173fd3c9eda9d4c8528da2ce0ea69f161577495a9cc835a2a4ecd7eadeb35"
|
sha256: "7ed76be64e8a7d01dfdf250b8434618e2a028c9dfa2a3c41dc9b531d4b3fc8a5"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "17.2.4"
|
version: "19.4.2"
|
||||||
flutter_local_notifications_linux:
|
flutter_local_notifications_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_local_notifications_linux
|
name: flutter_local_notifications_linux
|
||||||
sha256: c49bd06165cad9beeb79090b18cd1eb0296f4bf4b23b84426e37dd7c027fc3af
|
sha256: e3c277b2daab8e36ac5a6820536668d07e83851aeeb79c446e525a70710770a5
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.1"
|
version: "6.0.0"
|
||||||
flutter_local_notifications_platform_interface:
|
flutter_local_notifications_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_local_notifications_platform_interface
|
name: flutter_local_notifications_platform_interface
|
||||||
sha256: "85f8d07fe708c1bdcf45037f2c0109753b26ae077e9d9e899d55971711a4ea66"
|
sha256: "277d25d960c15674ce78ca97f57d0bae2ee401c844b6ac80fcd972a9c99d09fe"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.2.0"
|
version: "9.1.0"
|
||||||
|
flutter_local_notifications_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_local_notifications_windows
|
||||||
|
sha256: "8d658f0d367c48bd420e7cf2d26655e2d1130147bca1eea917e576ca76668aaf"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.3"
|
||||||
flutter_localizations:
|
flutter_localizations:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -383,50 +391,50 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_secure_storage
|
name: flutter_secure_storage
|
||||||
sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea"
|
sha256: f7eceb0bc6f4fd0441e29d43cab9ac2a1c5ffd7ea7b64075136b718c46954874
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "9.2.4"
|
version: "10.0.0-beta.4"
|
||||||
|
flutter_secure_storage_darwin:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_secure_storage_darwin
|
||||||
|
sha256: f226f2a572bed96bc6542198ebaec227150786e34311d455a7e2d3d06d951845
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.0"
|
||||||
flutter_secure_storage_linux:
|
flutter_secure_storage_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_secure_storage_linux
|
name: flutter_secure_storage_linux
|
||||||
sha256: be76c1d24a97d0b98f8b54bce6b481a380a6590df992d0098f868ad54dc8f688
|
sha256: "9b4b73127e857cd3117d43a70fa3dddadb6e0b253be62e6a6ab85caa0742182c"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.3"
|
version: "2.0.1"
|
||||||
flutter_secure_storage_macos:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: flutter_secure_storage_macos
|
|
||||||
sha256: "6c0a2795a2d1de26ae202a0d78527d163f4acbb11cde4c75c670f3a0fc064247"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.1.3"
|
|
||||||
flutter_secure_storage_platform_interface:
|
flutter_secure_storage_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_secure_storage_platform_interface
|
name: flutter_secure_storage_platform_interface
|
||||||
sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8
|
sha256: "8ceea1223bee3c6ac1a22dabd8feefc550e4729b3675de4b5900f55afcb435d6"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.2"
|
version: "2.0.1"
|
||||||
flutter_secure_storage_web:
|
flutter_secure_storage_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_secure_storage_web
|
name: flutter_secure_storage_web
|
||||||
sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9
|
sha256: "4c3f233e739545c6cb09286eeec1cc4744138372b985113acc904f7263bef517"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.1"
|
version: "2.0.0"
|
||||||
flutter_secure_storage_windows:
|
flutter_secure_storage_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_secure_storage_windows
|
name: flutter_secure_storage_windows
|
||||||
sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709
|
sha256: ff32af20f70a8d0e59b2938fc92de35b54a74671041c814275afd80e27df9f21
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "4.0.0"
|
||||||
flutter_sms_inbox:
|
flutter_sms_inbox:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -481,10 +489,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: google_mobile_ads
|
name: google_mobile_ads
|
||||||
sha256: d2ef5ec1e1f31137fc241bdeab3037c31062d387dd221fd884fb1160444c788b
|
sha256: a4f59019f2c32769fb6c60ed8aa321e9c21a36297e2c4f23452b3e779a3e7a26
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "6.0.0"
|
||||||
graphs:
|
graphs:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -617,10 +625,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: lints
|
name: lints
|
||||||
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
|
sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "6.0.0"
|
||||||
local_auth:
|
local_auth:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -793,18 +801,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: permission_handler
|
name: permission_handler
|
||||||
sha256: "59adad729136f01ea9e35a48f5d1395e25cba6cea552249ddbe9cf950f5d7849"
|
sha256: bc917da36261b00137bbc8896bf1482169cd76f866282368948f032c8c1caae1
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "11.4.0"
|
version: "12.0.1"
|
||||||
permission_handler_android:
|
permission_handler_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: permission_handler_android
|
name: permission_handler_android
|
||||||
sha256: d3971dcdd76182a0c198c096b5db2f0884b0d4196723d21a866fc4cdea057ebc
|
sha256: "1e3bc410ca1bf84662104b100eb126e066cb55791b7451307f9708d4007350e6"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "12.1.0"
|
version: "13.0.1"
|
||||||
permission_handler_apple:
|
permission_handler_apple:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -929,18 +937,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: share_plus
|
name: share_plus
|
||||||
sha256: "3ef39599b00059db0990ca2e30fca0a29d8b37aae924d60063f8e0184cf20900"
|
sha256: "3424e9d5c22fd7f7590254ba09465febd6f8827c8b19a44350de4ac31d92d3a6"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.2.2"
|
version: "12.0.0"
|
||||||
share_plus_platform_interface:
|
share_plus_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: share_plus_platform_interface
|
name: share_plus_platform_interface
|
||||||
sha256: "251eb156a8b5fa9ce033747d73535bf53911071f8d3b6f4f0b578505ce0d4496"
|
sha256: "88023e53a13429bd65d8e85e11a9b484f49d4c190abbd96c7932b74d6927cc9a"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.4.0"
|
version: "6.1.0"
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -1150,10 +1158,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: timezone
|
name: timezone
|
||||||
sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d"
|
sha256: dd14a3b83cfd7cb19e7888f1cbc20f258b8d71b54c06f79ac585f14093a287d1
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.9.4"
|
version: "0.10.1"
|
||||||
timing:
|
timing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1326,18 +1334,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: webview_flutter
|
name: webview_flutter
|
||||||
sha256: ec81f57aa1611f8ebecf1d2259da4ef052281cb5ad624131c93546c79ccc7736
|
sha256: c3e4fe614b1c814950ad07186007eff2f2e5dd2935eba7b9a9a1af8e5885f1ba
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.9.0"
|
version: "4.13.0"
|
||||||
webview_flutter_android:
|
webview_flutter_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: webview_flutter_android
|
name: webview_flutter_android
|
||||||
sha256: "47a8da40d02befda5b151a26dba71f47df471cddd91dfdb7802d0a87c5442558"
|
sha256: "3c4eb4fcc252b40c2b5ce7be20d0481428b70f3ff589b0a8b8aaeb64c6bed701"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.16.9"
|
version: "4.10.2"
|
||||||
webview_flutter_platform_interface:
|
webview_flutter_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
20
pubspec.yaml
20
pubspec.yaml
@@ -13,40 +13,40 @@ dependencies:
|
|||||||
provider: ^6.1.1
|
provider: ^6.1.1
|
||||||
hive: ^2.2.3
|
hive: ^2.2.3
|
||||||
hive_flutter: ^1.1.0
|
hive_flutter: ^1.1.0
|
||||||
flutter_local_notifications: ^17.2.4
|
flutter_local_notifications: ^19.4.2
|
||||||
flutter_secure_storage: ^9.0.0
|
flutter_secure_storage: ^10.0.0-beta.4
|
||||||
local_auth: ^2.1.6
|
local_auth: ^2.1.6
|
||||||
fl_chart: ^0.66.2
|
fl_chart: ^1.1.1
|
||||||
http: ^1.4.0
|
http: ^1.4.0
|
||||||
qr_flutter: ^4.1.0
|
qr_flutter: ^4.1.0
|
||||||
url_launcher: ^6.2.4
|
url_launcher: ^6.2.4
|
||||||
intl: ^0.20.2
|
intl: ^0.20.2
|
||||||
permission_handler: ^11.3.0
|
permission_handler: ^12.0.1
|
||||||
uuid: ^4.2.1
|
uuid: ^4.2.1
|
||||||
timezone: ^0.9.2
|
timezone: ^0.10.1
|
||||||
flutter_localizations:
|
flutter_localizations:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
share_plus: ^7.2.1
|
share_plus: ^12.0.0
|
||||||
font_awesome_flutter: ^10.7.0
|
font_awesome_flutter: ^10.7.0
|
||||||
cached_network_image: ^3.3.1
|
cached_network_image: ^3.3.1
|
||||||
flutter_cache_manager: ^3.3.1
|
flutter_cache_manager: ^3.3.1
|
||||||
shared_preferences: ^2.5.3
|
shared_preferences: ^2.5.3
|
||||||
flutter_launcher_icons: ^0.13.1
|
flutter_launcher_icons: ^0.14.4
|
||||||
flutter_native_splash: ^2.3.10
|
flutter_native_splash: ^2.3.10
|
||||||
flutter_sms_inbox: ^1.0.3
|
flutter_sms_inbox: ^1.0.3
|
||||||
flutter_dotenv: ^5.1.0
|
flutter_dotenv: ^6.0.0
|
||||||
flutter_svg: ^2.1.0
|
flutter_svg: ^2.1.0
|
||||||
html: ^0.15.6
|
html: ^0.15.6
|
||||||
octo_image: ^2.0.0
|
octo_image: ^2.0.0
|
||||||
path_provider: ^2.1.5
|
path_provider: ^2.1.5
|
||||||
crypto: ^3.0.6
|
crypto: ^3.0.6
|
||||||
image: ^4.5.4
|
image: ^4.5.4
|
||||||
google_mobile_ads: ^4.0.0
|
google_mobile_ads: ^6.0.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_lints: ^2.0.0
|
flutter_lints: ^6.0.0
|
||||||
build_runner: ^2.4.6
|
build_runner: ^2.4.6
|
||||||
hive_generator: ^2.0.1
|
hive_generator: ^2.0.1
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
flutter_local_notifications_windows
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
|||||||
Reference in New Issue
Block a user