feat: 알림 재예약 개선과 패키지 업그레이드

This commit is contained in:
JiWoong Sul
2025-09-19 18:10:47 +09:00
parent e909ba59a4
commit 87f82546a4
24 changed files with 210 additions and 122 deletions

View File

@@ -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

View File

@@ -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")
} }

View File

@@ -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": "服务名称",

View File

@@ -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());

View File

@@ -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,
); );
} }
} }

View File

@@ -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();

View File

@@ -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();
},
),
),
),
], ],
), ),
), ),

View File

@@ -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: [

View File

@@ -186,7 +186,7 @@ class _SplashScreenState extends State<SplashScreen>
), ),
), ),
); );
}).toList(), }),
// 상단 원형 장식 제거(단색 배경 유지) // 상단 원형 장식 제거(단색 배경 유지)
Positioned( Positioned(

View File

@@ -1,2 +1,2 @@
/// URL Matcher 패키지의 export 파일 // URL Matcher 패키지의 export 파일
export 'models/service_info.dart'; export 'models/service_info.dart';

View File

@@ -298,7 +298,7 @@ class EventAnalysisCard extends StatelessWidget {
], ],
), ),
); );
}).toList(), }),
], ],
), ),
), ),

View File

@@ -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,
), ),
), ),
), ),

View File

@@ -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,
), ),
); );
}, },

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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();

View File

@@ -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,29 +8,33 @@ class ScanLoadingWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( return Column(
padding: const EdgeInsets.symmetric(horizontal: 16.0), children: [
child: Center( const NativeAdWidget(key: ValueKey('sms_scan_loading_ad')),
child: Column( const SizedBox(height: 48),
mainAxisAlignment: MainAxisAlignment.center, Padding(
children: [ padding: const EdgeInsets.symmetric(horizontal: 16.0),
CircularProgressIndicator( child: Column(
color: Theme.of(context).colorScheme.primary, mainAxisAlignment: MainAxisAlignment.center,
), children: [
const SizedBox(height: 16), CircularProgressIndicator(
ThemedText( color: Theme.of(context).colorScheme.primary,
AppLocalizations.of(context).scanningMessages, ),
forceDark: true, const SizedBox(height: 16),
), ThemedText(
const SizedBox(height: 8), AppLocalizations.of(context).scanningMessages,
ThemedText( forceDark: true,
AppLocalizations.of(context).findingSubscriptions, ),
opacity: 0.7, const SizedBox(height: 8),
forceDark: true, ThemedText(
), AppLocalizations.of(context).findingSubscriptions,
], opacity: 0.7,
forceDark: true,
),
],
),
), ),
), ],
); );
} }
} }

View File

@@ -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) {

View File

@@ -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"))

View File

@@ -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:

View File

@@ -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

View File

@@ -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)