App updates & web deeplink

This commit is contained in:
LittleSheep 2024-12-21 23:26:42 +08:00
parent 392aebcad7
commit 39fb4d474f
10 changed files with 227 additions and 64 deletions

View File

@ -33,22 +33,6 @@
</intent-filter> </intent-filter>
<!-- Sharing Intents --> <!-- Sharing Intents -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="sn.solsynth.dev"
android:pathPrefix="/invite"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:mimeType="*/*"
android:scheme="content" />
</intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.SEND" /> <action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />

View File

@ -370,6 +370,8 @@
"dailyCheckNegativeHint6": "Going out", "dailyCheckNegativeHint6": "Going out",
"dailyCheckNegativeHint6Description": "Forgot your umbrella and got caught in the rain", "dailyCheckNegativeHint6Description": "Forgot your umbrella and got caught in the rain",
"happyBirthday": "Happy birthday, {}!", "happyBirthday": "Happy birthday, {}!",
"celebrateMerryXmas": "Merry christmas, {}",
"celebrateNewYear": "Happy new year, {}",
"friendNew": "Add Friend", "friendNew": "Add Friend",
"friendRequests": "Friend Requests", "friendRequests": "Friend Requests",
"friendRequestsDescription": { "friendRequestsDescription": {
@ -455,5 +457,7 @@
"poweredBy": "Powered by {}", "poweredBy": "Powered by {}",
"shareIntent": "Share", "shareIntent": "Share",
"shareIntentDescription": "What do you want to do with the content you are sharing?", "shareIntentDescription": "What do you want to do with the content you are sharing?",
"shareIntentPostStory": "Post a Story" "shareIntentPostStory": "Post a Story",
"updateAvailable": "Update Available",
"updateOngoing": "正在更新,请稍后..."
} }

View File

@ -368,6 +368,8 @@
"dailyCheckNegativeHint6": "出门", "dailyCheckNegativeHint6": "出门",
"dailyCheckNegativeHint6Description": "忘带伞遇上大雨", "dailyCheckNegativeHint6Description": "忘带伞遇上大雨",
"happyBirthday": "生日快乐,{}", "happyBirthday": "生日快乐,{}",
"celebrateMerryXmas": "圣诞快乐,{}",
"celebrateNewYear": "新年快乐,{}",
"friendNew": "添加好友", "friendNew": "添加好友",
"friendRequests": "好友请求", "friendRequests": "好友请求",
"friendRequestsDescription": { "friendRequestsDescription": {
@ -453,5 +455,7 @@
"poweredBy": "由 {} 提供支持", "poweredBy": "由 {} 提供支持",
"shareIntent": "分享", "shareIntent": "分享",
"shareIntentDescription": "您想对您分享的内容做些什么?", "shareIntentDescription": "您想对您分享的内容做些什么?",
"shareIntentPostStory": "发布动态" "shareIntentPostStory": "发布动态",
"updateAvailable": "检测到更新可用",
"updateOngoing": "正在更新,请稍后……"
} }

View File

@ -4,6 +4,7 @@ import 'dart:io';
import 'package:bitsdojo_window/bitsdojo_window.dart'; import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:croppy/croppy.dart'; import 'package:croppy/croppy.dart';
import 'package:dio/dio.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:easy_localization_loader/easy_localization_loader.dart'; import 'package:easy_localization_loader/easy_localization_loader.dart';
import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core/firebase_core.dart';
@ -12,9 +13,11 @@ import 'package:flutter/material.dart';
import 'package:gap/gap.dart'; import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:hive_flutter/hive_flutter.dart'; import 'package:hive_flutter/hive_flutter.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:relative_time/relative_time.dart'; import 'package:relative_time/relative_time.dart';
import 'package:responsive_framework/responsive_framework.dart'; import 'package:responsive_framework/responsive_framework.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
import 'package:surface/firebase_options.dart'; import 'package:surface/firebase_options.dart';
import 'package:surface/providers/channel.dart'; import 'package:surface/providers/channel.dart';
@ -38,7 +41,9 @@ import 'package:surface/types/realm.dart';
import 'package:flutter_web_plugins/url_strategy.dart' show usePathUrlStrategy; import 'package:flutter_web_plugins/url_strategy.dart' show usePathUrlStrategy;
import 'package:surface/widgets/dialog.dart'; import 'package:surface/widgets/dialog.dart';
import 'package:surface/widgets/version_label.dart'; import 'package:surface/widgets/version_label.dart';
import 'package:version/version.dart';
import 'package:workmanager/workmanager.dart'; import 'package:workmanager/workmanager.dart';
import 'package:in_app_review/in_app_review.dart';
@pragma('vm:entry-point') @pragma('vm:entry-point')
void appBackgroundDispatcher() { void appBackgroundDispatcher() {
@ -125,7 +130,7 @@ class SolianApp extends StatelessWidget {
Provider(create: (ctx) => HomeWidgetProvider(ctx)), Provider(create: (ctx) => HomeWidgetProvider(ctx)),
// Preferences layer // Preferences layer
Provider(create: (ctx) => ConfigProvider(ctx)), ChangeNotifierProvider(create: (ctx) => ConfigProvider(ctx)),
// Display layer // Display layer
ChangeNotifierProvider(create: (_) => ThemeProvider()), ChangeNotifierProvider(create: (_) => ThemeProvider()),
@ -201,6 +206,56 @@ class _AppSplashScreen extends StatefulWidget {
class _AppSplashScreenState extends State<_AppSplashScreen> { class _AppSplashScreenState extends State<_AppSplashScreen> {
bool _isReady = false; bool _isReady = false;
void _tryRequestRating() async {
final prefs = await SharedPreferences.getInstance();
if (prefs.containsKey('first_boot_time')) {
final rawTime = prefs.getString('first_boot_time');
final time = DateTime.tryParse(rawTime ?? '');
if (time != null && time.isBefore(DateTime.now().subtract(const Duration(days: 3)))) {
final inAppReview = InAppReview.instance;
if (prefs.getBool('rating_requested') == true) return;
if (await inAppReview.isAvailable()) {
await inAppReview.requestReview();
prefs.setBool('rating_requested', true);
} else {
log('Unable request app review, unavailable');
}
}
} else {
prefs.setString('first_boot_time', DateTime.now().toIso8601String());
}
}
Future<void> _checkForUpdate() async {
if (kIsWeb) return;
try {
final info = await PackageInfo.fromPlatform();
final localVersionString = '${info.version}+${info.buildNumber}';
final resp = await Dio(
BaseOptions(
sendTimeout: const Duration(seconds: 60),
receiveTimeout: const Duration(seconds: 60),
),
).get(
'https://git.solsynth.dev/api/v1/repos/HyperNet/Surface/tags?page=1&limit=1',
);
final remoteVersionString = (resp.data as List).firstOrNull?['name'] ?? '0.0.0+0';
final remoteVersion = Version.parse(remoteVersionString.split('+').first);
final localVersion = Version.parse(localVersionString.split('+').first);
final remoteBuildNumber = int.tryParse(remoteVersionString.split('+').last) ?? 0;
final localBuildNumber = int.tryParse(localVersionString.split('+').last) ?? 0;
log("[Update] Local: $localVersionString, Remote: $remoteVersionString");
// TODO remove this true
if ((remoteVersion > localVersion || remoteBuildNumber > localBuildNumber) && mounted) {
final config = context.read<ConfigProvider>();
config.setUpdate(remoteVersionString);
log("[Update] Update available: $remoteVersionString");
}
} catch (e) {
if (mounted) context.showErrorDialog('Unable to check update: $e');
}
}
Future<void> _initialize() async { Future<void> _initialize() async {
try { try {
final home = context.read<HomeWidgetProvider>(); final home = context.read<HomeWidgetProvider>();
@ -235,7 +290,11 @@ class _AppSplashScreenState extends State<_AppSplashScreen> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_initialize().then((_) => _postInitialization()); _initialize().then((_) {
_postInitialization();
_tryRequestRating();
_checkForUpdate();
});
} }
@override @override

View File

@ -16,7 +16,7 @@ const Map<String, FilterQuality> kImageQualityLevel = {
'settingsImageQualityHigh': FilterQuality.high, 'settingsImageQualityHigh': FilterQuality.high,
}; };
class ConfigProvider { class ConfigProvider extends ChangeNotifier {
late final SharedPreferences prefs; late final SharedPreferences prefs;
late final HomeWidgetProvider _home; late final HomeWidgetProvider _home;
@ -36,8 +36,16 @@ class ConfigProvider {
String get serverUrl { String get serverUrl {
return prefs.getString(kNetworkServerStoreKey) ?? kNetworkServerDefault; return prefs.getString(kNetworkServerStoreKey) ?? kNetworkServerDefault;
} }
set serverUrl(String url) { set serverUrl(String url) {
prefs.setString(kNetworkServerStoreKey, url); prefs.setString(kNetworkServerStoreKey, url);
_home.saveWidgetData("nex_server_url", url); _home.saveWidgetData("nex_server_url", url);
} }
String? updatableVersion;
void setUpdate(String newVersion) {
updatableVersion = newVersion;
notifyListeners();
}
} }

View File

@ -1,7 +1,10 @@
import 'dart:io';
import 'dart:math' as math; import 'dart:math' as math;
import 'dart:ui'; import 'dart:ui';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_app_update/flutter_app_update.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:gap/gap.dart'; import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@ -10,6 +13,7 @@ import 'package:material_symbols_icons/symbols.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:surface/providers/config.dart';
import 'package:surface/providers/post.dart'; import 'package:surface/providers/post.dart';
import 'package:surface/providers/sn_network.dart'; import 'package:surface/providers/sn_network.dart';
import 'package:surface/providers/userinfo.dart'; import 'package:surface/providers/userinfo.dart';
@ -69,18 +73,15 @@ class _HomeScreenState extends State<HomeScreen> {
body: LayoutBuilder( body: LayoutBuilder(
builder: (context, constraints) { builder: (context, constraints) {
return Align( return Align(
alignment: constraints.maxWidth > 640 alignment: constraints.maxWidth > 640 ? Alignment.center : Alignment.topCenter,
? Alignment.center
: Alignment.topCenter,
child: Container( child: Container(
constraints: const BoxConstraints(maxWidth: 640), constraints: const BoxConstraints(maxWidth: 640),
child: SingleChildScrollView( child: SingleChildScrollView(
child: Column( child: Column(
mainAxisAlignment: constraints.maxWidth > 640 mainAxisAlignment: constraints.maxWidth > 640 ? MainAxisAlignment.center : MainAxisAlignment.start,
? MainAxisAlignment.center
: MainAxisAlignment.start,
children: [ children: [
_HomeDashSpecialDayWidget().padding(top: 8, horizontal: 8), _HomeDashSpecialDayWidget().padding(bottom: 8, horizontal: 8),
_HomeDashUpdateWidget(padding: const EdgeInsets.only(bottom: 8, left: 8, right: 8)),
StaggeredGrid.extent( StaggeredGrid.extent(
maxCrossAxisExtent: 280, maxCrossAxisExtent: 280,
mainAxisSpacing: 8, mainAxisSpacing: 8,
@ -104,6 +105,52 @@ class _HomeScreenState extends State<HomeScreen> {
} }
} }
class _HomeDashUpdateWidget extends StatelessWidget {
final EdgeInsets? padding;
const _HomeDashUpdateWidget({super.key, this.padding});
@override
Widget build(BuildContext context) {
final config = context.watch<ConfigProvider>();
return ListenableBuilder(
listenable: config,
builder: (context, _) {
if (config.updatableVersion != null) {
return Container(
padding: padding,
child: Card(
child: ListTile(
leading: Icon(Symbols.update),
title: Text('updateAvailable').tr(),
subtitle: Text(config.updatableVersion!),
trailing: (kIsWeb || Platform.isWindows || Platform.isLinux)
? null
: IconButton(
icon: const Icon(Symbols.arrow_right_alt),
onPressed: () {
final model = UpdateModel(
'https://files.solsynth.dev/d/production01/solian/app-arm64-v8a-release.apk',
'solian-app-release-${config.updatableVersion!}.apk',
'ic_notification',
'https://apps.apple.com/us/app/solian/id6499032345',
);
AzhonAppUpdate.update(model);
context.showSnackbar('updateOngoing'.tr());
},
),
),
),
);
}
return SizedBox.shrink();
},
);
}
}
class _HomeDashSpecialDayWidget extends StatelessWidget { class _HomeDashSpecialDayWidget extends StatelessWidget {
const _HomeDashSpecialDayWidget({super.key}); const _HomeDashSpecialDayWidget({super.key});
@ -112,10 +159,10 @@ class _HomeDashSpecialDayWidget extends StatelessWidget {
final ua = context.watch<UserProvider>(); final ua = context.watch<UserProvider>();
final today = DateTime.now(); final today = DateTime.now();
final birthday = ua.user?.profile?.birthday?.toLocal(); final birthday = ua.user?.profile?.birthday?.toLocal();
final isBirthday = birthday != null && final isBirthday = birthday != null && birthday.day == today.day && birthday.month == today.month;
birthday.day == today.day &&
birthday.month == today.month;
return Column( return Column(
spacing: 8,
children: [ children: [
if (isBirthday) if (isBirthday)
Card( Card(
@ -124,6 +171,20 @@ class _HomeDashSpecialDayWidget extends StatelessWidget {
title: Text('happyBirthday').tr(args: [ua.user?.nick ?? 'user']), title: Text('happyBirthday').tr(args: [ua.user?.nick ?? 'user']),
), ),
).padding(bottom: 8), ).padding(bottom: 8),
if (today.month == 12 && today.day == 25)
Card(
child: ListTile(
leading: Text('🎄').fontSize(24),
title: Text('celebrateMerryXmas').tr(args: [ua.user?.nick ?? 'user']),
),
),
if (today.month == 1 && today.day == 1)
Card(
child: ListTile(
leading: Text('🎉').fontSize(24),
title: Text('celebrateNewYear').tr(args: [ua.user?.nick ?? 'user']),
),
),
], ],
); );
} }
@ -174,20 +235,15 @@ class _HomeDashCheckInWidgetState extends State<_HomeDashCheckInWidget> {
} }
Widget _buildDetailChunk(int index, bool positive) { Widget _buildDetailChunk(int index, bool positive) {
final prefix = final prefix = positive ? 'dailyCheckPositiveHint' : 'dailyCheckNegativeHint';
positive ? 'dailyCheckPositiveHint' : 'dailyCheckNegativeHint'; final mod = positive ? kSuggestionPositiveHintCount : kSuggestionNegativeHintCount;
final mod =
positive ? kSuggestionPositiveHintCount : kSuggestionNegativeHintCount;
final pos = math.max(1, _todayRecord!.resultModifiers[index] % mod); final pos = math.max(1, _todayRecord!.resultModifiers[index] % mod);
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
prefix.tr(args: ['$prefix$pos'.tr()]), prefix.tr(args: ['$prefix$pos'.tr()]),
style: Theme.of(context) style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.bold),
.textTheme
.titleMedium!
.copyWith(fontWeight: FontWeight.bold),
), ),
Text( Text(
'$prefix${pos}Description', '$prefix${pos}Description',
@ -222,10 +278,7 @@ class _HomeDashCheckInWidgetState extends State<_HomeDashCheckInWidget> {
else else
Text( Text(
'dailyCheckEverythingIsNegative', 'dailyCheckEverythingIsNegative',
style: Theme.of(context) style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.bold),
.textTheme
.titleMedium!
.copyWith(fontWeight: FontWeight.bold),
).tr(), ).tr(),
const Gap(8), const Gap(8),
if (_todayRecord?.resultTier != 4) if (_todayRecord?.resultTier != 4)
@ -241,10 +294,7 @@ class _HomeDashCheckInWidgetState extends State<_HomeDashCheckInWidget> {
else else
Text( Text(
'dailyCheckEverythingIsPositive', 'dailyCheckEverythingIsPositive',
style: Theme.of(context) style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.bold),
.textTheme
.titleMedium!
.copyWith(fontWeight: FontWeight.bold),
).tr(), ).tr(),
], ],
), ),
@ -362,12 +412,10 @@ class _HomeDashNotificationWidget extends StatefulWidget {
const _HomeDashNotificationWidget({super.key}); const _HomeDashNotificationWidget({super.key});
@override @override
State<_HomeDashNotificationWidget> createState() => State<_HomeDashNotificationWidget> createState() => _HomeDashNotificationWidgetState();
_HomeDashNotificationWidgetState();
} }
class _HomeDashNotificationWidgetState class _HomeDashNotificationWidgetState extends State<_HomeDashNotificationWidget> {
extends State<_HomeDashNotificationWidget> {
int? _count; int? _count;
Future<void> _fetchNotificationCount() async { Future<void> _fetchNotificationCount() async {
@ -404,9 +452,7 @@ class _HomeDashNotificationWidgetState
style: Theme.of(context).textTheme.titleLarge, style: Theme.of(context).textTheme.titleLarge,
).tr(), ).tr(),
Text( Text(
_count == null _count == null ? 'loading'.tr() : 'notificationUnreadCount'.plural(_count ?? 0),
? 'loading'.tr()
: 'notificationUnreadCount'.plural(_count ?? 0),
style: Theme.of(context).textTheme.bodyLarge, style: Theme.of(context).textTheme.bodyLarge,
), ),
], ],
@ -437,12 +483,10 @@ class _HomeDashRecommendationPostWidget extends StatefulWidget {
const _HomeDashRecommendationPostWidget({super.key}); const _HomeDashRecommendationPostWidget({super.key});
@override @override
State<_HomeDashRecommendationPostWidget> createState() => State<_HomeDashRecommendationPostWidget> createState() => _HomeDashRecommendationPostWidgetState();
_HomeDashRecommendationPostWidgetState();
} }
class _HomeDashRecommendationPostWidgetState class _HomeDashRecommendationPostWidgetState extends State<_HomeDashRecommendationPostWidget> {
extends State<_HomeDashRecommendationPostWidget> {
bool _isBusy = false; bool _isBusy = false;
List<SnPost>? _posts; List<SnPost>? _posts;
@ -491,8 +535,7 @@ class _HomeDashRecommendationPostWidgetState
).padding(horizontal: 18, top: 12, bottom: 8), ).padding(horizontal: 18, top: 12, bottom: 8),
Expanded( Expanded(
child: PageView.builder( child: PageView.builder(
scrollBehavior: scrollBehavior: ScrollConfiguration.of(context).copyWith(dragDevices: {
ScrollConfiguration.of(context).copyWith(dragDevices: {
PointerDeviceKind.mouse, PointerDeviceKind.mouse,
PointerDeviceKind.touch, PointerDeviceKind.touch,
}), }),
@ -505,8 +548,7 @@ class _HomeDashRecommendationPostWidgetState
showMenu: false, showMenu: false,
).padding(bottom: 8), ).padding(bottom: 8),
onTap: () { onTap: () {
GoRouter.of(context) GoRouter.of(context).pushNamed('postDetail', pathParameters: {
.pushNamed('postDetail', pathParameters: {
'slug': _posts![index].id.toString(), 'slug': _posts![index].id.toString(),
}); });
}, },

View File

@ -16,6 +16,7 @@ import firebase_messaging
import flutter_udid import flutter_udid
import flutter_webrtc import flutter_webrtc
import gal import gal
import in_app_review
import livekit_client import livekit_client
import media_kit_libs_macos_video import media_kit_libs_macos_video
import media_kit_video import media_kit_video
@ -41,6 +42,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin")) FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin"))
FlutterWebRTCPlugin.register(with: registry.registrar(forPlugin: "FlutterWebRTCPlugin")) FlutterWebRTCPlugin.register(with: registry.registrar(forPlugin: "FlutterWebRTCPlugin"))
GalPlugin.register(with: registry.registrar(forPlugin: "GalPlugin")) GalPlugin.register(with: registry.registrar(forPlugin: "GalPlugin"))
InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin"))
LiveKitPlugin.register(with: registry.registrar(forPlugin: "LiveKitPlugin")) LiveKitPlugin.register(with: registry.registrar(forPlugin: "LiveKitPlugin"))
MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin")) MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin"))
MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin")) MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin"))

View File

@ -627,6 +627,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.5.2" version: "4.5.2"
flutter_app_update:
dependency: "direct main"
description:
name: flutter_app_update
sha256: "09290240949c4651581cd6fc535e52d019e189e694d6019c56b5a56c2e69ba65"
url: "https://pub.dev"
source: hosted
version: "3.2.2"
flutter_cache_manager: flutter_cache_manager:
dependency: transitive dependency: transitive
description: description:
@ -729,10 +737,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_udid name: flutter_udid
sha256: "63384bd96203aaefccfd7137fab642edda18afede12b0e9e1a2c96fe2589fd07" sha256: be464dc5b1fb7ee894f6a32d65c086ca5e177fdcf9375ac08d77495b98150f84
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.0" version: "3.0.1"
flutter_web_plugins: flutter_web_plugins:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -962,6 +970,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.1+1" version: "0.2.1+1"
in_app_review:
dependency: "direct main"
description:
name: in_app_review
sha256: "36a06771b88fb0e79985b15e7f2ac0f1142e903fe72517f3c055d78bc3bc1819"
url: "https://pub.dev"
source: hosted
version: "2.0.10"
in_app_review_platform_interface:
dependency: transitive
description:
name: in_app_review_platform_interface
sha256: fed2c755f2125caa9ae10495a3c163aa7fab5af3585a9c62ef4a6920c5b45f10
url: "https://pub.dev"
source: hosted
version: "2.0.5"
intl: intl:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1975,6 +1999,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.1.4"
version:
dependency: "direct main"
description:
name: version
sha256: "3d4140128e6ea10d83da32fef2fa4003fccbf6852217bb854845802f04191f94"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
very_good_infinite_list: very_good_infinite_list:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@ -108,6 +108,9 @@ dependencies:
home_widget: ^0.7.0 home_widget: ^0.7.0
receive_sharing_intent: ^1.8.1 receive_sharing_intent: ^1.8.1
workmanager: ^0.5.2 workmanager: ^0.5.2
flutter_app_update: ^3.2.2
in_app_review: ^2.0.10
version: ^3.0.2
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

View File

@ -0,0 +1,25 @@
{
"applinks": {
"apps": [],
"details": [
{
"appIDs": [
"W7HPZ53V6B.dev.solsynth.solian"
],
"paths": [
"*"
],
"components": [
{
"/": "/*"
}
]
}
]
},
"webcredentials": {
"apps": [
"W7HPZ53V6B.dev.solsynth.solian"
]
}
}