✨ App updates & web deeplink
This commit is contained in:
parent
392aebcad7
commit
39fb4d474f
@ -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" />
|
||||||
|
@ -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": "正在更新,请稍后..."
|
||||||
}
|
}
|
||||||
|
@ -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": "正在更新,请稍后……"
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -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"))
|
||||||
|
36
pubspec.lock
36
pubspec.lock
@ -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:
|
||||||
|
@ -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:
|
||||||
|
25
web/.well-known/apple-app-site-association
Normal file
25
web/.well-known/apple-app-site-association
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"applinks": {
|
||||||
|
"apps": [],
|
||||||
|
"details": [
|
||||||
|
{
|
||||||
|
"appIDs": [
|
||||||
|
"W7HPZ53V6B.dev.solsynth.solian"
|
||||||
|
],
|
||||||
|
"paths": [
|
||||||
|
"*"
|
||||||
|
],
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"/": "/*"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"webcredentials": {
|
||||||
|
"apps": [
|
||||||
|
"W7HPZ53V6B.dev.solsynth.solian"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user