deep linking
This commit is contained in:
parent
3827209ade
commit
047de45e3b
|
|
@ -17,7 +17,6 @@
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="Didvan"
|
android:label="Didvan"
|
||||||
android:requestLegacyExternalStorage="true"
|
android:requestLegacyExternalStorage="true"
|
||||||
|
|
||||||
android:usesCleartextTraffic="true">
|
android:usesCleartextTraffic="true">
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".FavWidget"
|
android:name=".FavWidget"
|
||||||
|
|
@ -50,8 +49,6 @@
|
||||||
android:resource="@xml/provider_paths" />
|
android:resource="@xml/provider_paths" />
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<!-- Begin FlutterDownloader customization -->
|
|
||||||
<!-- disable default Initializer -->
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.startup.InitializationProvider"
|
android:name="androidx.startup.InitializationProvider"
|
||||||
android:authorities="${applicationId}.androidx-startup"
|
android:authorities="${applicationId}.androidx-startup"
|
||||||
|
|
@ -63,18 +60,14 @@
|
||||||
tools:node="remove" />
|
tools:node="remove" />
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<!-- declare customized Initializer -->
|
|
||||||
<provider
|
<provider
|
||||||
android:name="vn.hunghd.flutterdownloader.FlutterDownloaderInitializer"
|
android:name="vn.hunghd.flutterdownloader.FlutterDownloaderInitializer"
|
||||||
android:authorities="${applicationId}.flutter-downloader-init"
|
android:authorities="${applicationId}.flutter-downloader-init"
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
<!-- changes this number to configure the maximum number of concurrent tasks -->
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="vn.hunghd.flutterdownloader.MAX_CONCURRENT_TASKS"
|
android:name="vn.hunghd.flutterdownloader.MAX_CONCURRENT_TASKS"
|
||||||
android:value="5" />
|
android:value="5" />
|
||||||
</provider>
|
</provider>
|
||||||
<!-- End FlutterDownloader customization -->
|
|
||||||
|
|
||||||
<activity android:name=".WebActivity" />
|
<activity android:name=".WebActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".FullscreenWebViewActivity"
|
android:name=".FullscreenWebViewActivity"
|
||||||
|
|
@ -92,17 +85,6 @@
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:windowSoftInputMode="adjustResize">
|
android:windowSoftInputMode="adjustResize">
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Specifies an Android theme to apply to this Activity as soon as
|
|
||||||
the Android process has started. This theme is visible to the user
|
|
||||||
while the Flutter UI initializes. After that, this theme continues
|
|
||||||
to determine the Window background behind the Flutter UI.
|
|
||||||
-->
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
android:value="2" />
|
||||||
|
|
@ -110,18 +92,22 @@
|
||||||
android:name="io.flutter.embedding.android.NormalTheme"
|
android:name="io.flutter.embedding.android.NormalTheme"
|
||||||
android:resource="@style/NormalTheme" />
|
android:resource="@style/NormalTheme" />
|
||||||
|
|
||||||
<!--
|
|
||||||
Displays an Android View that continues showing the launch screen
|
|
||||||
Drawable until Flutter paints its first frame, then this splash
|
|
||||||
screen fades out. A splash screen is useful to avoid any visual
|
|
||||||
gap between the end of Android's launch screen and the painting of
|
|
||||||
Flutter's first frame.
|
|
||||||
-->
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<intent-filter android:autoVerify="true">
|
||||||
|
<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="web.didvan.com" />
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:android_intent_plus/android_intent.dart';
|
import 'package:android_intent_plus/android_intent.dart';
|
||||||
|
import 'package:app_links/app_links.dart';
|
||||||
import 'package:bot_toast/bot_toast.dart';
|
import 'package:bot_toast/bot_toast.dart';
|
||||||
import 'package:didvan/config/theme_data.dart';
|
import 'package:didvan/config/theme_data.dart';
|
||||||
import 'package:didvan/firebase_options.dart';
|
import 'package:didvan/firebase_options.dart';
|
||||||
|
|
@ -95,6 +96,8 @@ class Didvan extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _DidvanState extends State<Didvan> with WidgetsBindingObserver {
|
class _DidvanState extends State<Didvan> with WidgetsBindingObserver {
|
||||||
|
late AppLinks _appLinks;
|
||||||
|
StreamSubscription<Uri>? _linkSubscription;
|
||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
|
|
@ -104,17 +107,46 @@ class _DidvanState extends State<Didvan> with WidgetsBindingObserver {
|
||||||
void initState() {
|
void initState() {
|
||||||
WidgetsBinding.instance.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_initDeepLinks();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
WidgetsBinding.instance.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
|
_linkSubscription?.cancel();
|
||||||
if (MediaService.currentPodcast != null) {
|
if (MediaService.currentPodcast != null) {
|
||||||
MediaService.audioPlayer.dispose();
|
MediaService.audioPlayer.dispose();
|
||||||
}
|
}
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _initDeepLinks() async {
|
||||||
|
_appLinks = AppLinks();
|
||||||
|
|
||||||
|
// بررسی لینک اولیه در زمان باز شدن اپلیکیشن
|
||||||
|
final initialUri = await _appLinks.getInitialLink();
|
||||||
|
if (initialUri != null) {
|
||||||
|
_navigateTo(initialUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// گوش دادن به لینکهای جدید زمانی که اپلیکیشن در حال اجراست
|
||||||
|
_linkSubscription = _appLinks.uriLinkStream.listen((uri) {
|
||||||
|
_navigateTo(uri);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// تابع کمکی برای ناوبری
|
||||||
|
void _navigateTo(Uri uri) {
|
||||||
|
if (mounted) {
|
||||||
|
String path = uri.path;
|
||||||
|
if (uri.fragment.isNotEmpty) {
|
||||||
|
path = "/${uri.fragment}";
|
||||||
|
}
|
||||||
|
navigatorKey.currentState?.pushNamed(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool b = true;
|
bool b = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// ignore_for_file: avoid_print
|
// ignore_for_file: avoid_print
|
||||||
|
|
||||||
import 'package:didvan/models/ai/ai_chat_args.dart';
|
import 'package:didvan/models/ai/ai_chat_args.dart';
|
||||||
|
import 'package:didvan/models/requests/news.dart';
|
||||||
|
import 'package:didvan/models/requests/radar.dart';
|
||||||
import 'package:didvan/models/story_model.dart';
|
import 'package:didvan/models/story_model.dart';
|
||||||
import 'package:didvan/views/ai/ai_chat_page.dart';
|
import 'package:didvan/views/ai/ai_chat_page.dart';
|
||||||
import 'package:didvan/views/ai/ai_chat_state.dart';
|
import 'package:didvan/views/ai/ai_chat_state.dart';
|
||||||
|
|
@ -74,6 +76,35 @@ import '../views/notification_time/notification_time.dart';
|
||||||
|
|
||||||
class RouteGenerator {
|
class RouteGenerator {
|
||||||
static Route<dynamic> generateRoute(RouteSettings settings) {
|
static Route<dynamic> generateRoute(RouteSettings settings) {
|
||||||
|
final uri = Uri.parse(settings.name ?? '');
|
||||||
|
if (uri.pathSegments.isNotEmpty) {
|
||||||
|
if (uri.pathSegments.first == 'news' && uri.pathSegments.length > 1) {
|
||||||
|
final id = int.tryParse(uri.pathSegments[1]);
|
||||||
|
if (id != null) {
|
||||||
|
return _createRoute(
|
||||||
|
ChangeNotifierProvider<NewsDetailsState>(
|
||||||
|
create: (context) => NewsDetailsState(),
|
||||||
|
child: NewsDetails(
|
||||||
|
pageData: {'id': id, 'args': const NewsRequestArgs(page: 0)},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (uri.pathSegments.first == 'radar' && uri.pathSegments.length > 1) {
|
||||||
|
final id = int.tryParse(uri.pathSegments[1]);
|
||||||
|
if (id != null) {
|
||||||
|
return _createRoute(
|
||||||
|
ChangeNotifierProvider<RadarDetailsState>(
|
||||||
|
create: (context) => RadarDetailsState(),
|
||||||
|
child: RadarDetails(
|
||||||
|
pageData: {'id': id, 'args': const RadarRequestArgs(page: 0)},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!kIsWeb) {
|
if (!kIsWeb) {
|
||||||
HomeWidget.saveWidgetData("cRoute", settings.name!);
|
HomeWidget.saveWidgetData("cRoute", settings.name!);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ class RequestService {
|
||||||
_requestBody == null ? null : jsonEncode(_requestBody);
|
_requestBody == null ? null : jsonEncode(_requestBody);
|
||||||
|
|
||||||
Future<void> httpGet() async {
|
Future<void> httpGet() async {
|
||||||
|
log('req is: $url', name: 'RequestService');
|
||||||
try {
|
try {
|
||||||
final response = await http
|
final response = await http
|
||||||
.get(
|
.get(
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,11 @@ class _AuthenticationState extends State<Authentication> {
|
||||||
if (state.currentPageIndex == 0) {
|
if (state.currentPageIndex == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// Check if on OTP screen and no password exists
|
||||||
|
if (state.currentPageIndex == 2 && !state.hasPassword) {
|
||||||
|
state.currentPageIndex = 0; // Go back to username screen
|
||||||
|
return false;
|
||||||
|
}
|
||||||
state.currentPageIndex--;
|
state.currentPageIndex--;
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ class AuthenticationState extends CoreProvier {
|
||||||
String password = '';
|
String password = '';
|
||||||
String _verificationCode = '';
|
String _verificationCode = '';
|
||||||
bool isShowCustomDialog = true;
|
bool isShowCustomDialog = true;
|
||||||
|
bool hasPassword = true;
|
||||||
|
|
||||||
set currentPageIndex(int value) {
|
set currentPageIndex(int value) {
|
||||||
_currentPageIndex = value;
|
_currentPageIndex = value;
|
||||||
|
|
@ -36,6 +37,7 @@ class AuthenticationState extends CoreProvier {
|
||||||
appState = AppState.idle;
|
appState = AppState.idle;
|
||||||
|
|
||||||
final bool hasPassword = service.result['hasPassword'];
|
final bool hasPassword = service.result['hasPassword'];
|
||||||
|
this.hasPassword = hasPassword;
|
||||||
|
|
||||||
if (hasPassword) {
|
if (hasPassword) {
|
||||||
currentPageIndex = 1;
|
currentPageIndex = 1;
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ class _ResetPasswordState extends State<ResetPassword> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final authState = context.watch<AuthenticationState>();
|
||||||
return Form(
|
return Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: AuthenticationLayout(
|
child: AuthenticationLayout(
|
||||||
|
|
@ -74,7 +75,7 @@ class _ResetPasswordState extends State<ResetPassword> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
title: 'تغییر رمز عبور',
|
title: authState.hasPassword ? 'تغییر رمز عبور' : 'تایید رمز عبور',
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 48,
|
height: 48,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
// lib/views/authentication/widgets/authentication_app_bar.dart
|
||||||
|
|
||||||
import 'package:didvan/config/theme_data.dart';
|
import 'package:didvan/config/theme_data.dart';
|
||||||
import 'package:didvan/constants/app_icons.dart';
|
import 'package:didvan/constants/app_icons.dart';
|
||||||
import 'package:didvan/views/authentication/authentication_state.dart';
|
import 'package:didvan/views/authentication/authentication_state.dart';
|
||||||
|
|
@ -18,12 +20,24 @@ class AuthenticationAppBar extends StatelessWidget {
|
||||||
DidvanIconButton(
|
DidvanIconButton(
|
||||||
icon: DidvanIcons.back_regular,
|
icon: DidvanIcons.back_regular,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
// اگر در صفحه اول باشیم، از صفحه احراز هویت خارج میشویم
|
||||||
if (state.currentPageIndex == 0) {
|
if (state.currentPageIndex == 0) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ** منطق جدید برای بازگشت از صفحه OTP **
|
||||||
|
// اگر کاربر رمز عبور نداشته و در صفحه OTP باشد
|
||||||
|
if (state.currentPageIndex == 2 && !state.hasPassword) {
|
||||||
|
// او را به صفحه اول (ورود شماره) برمیگردانیم
|
||||||
|
state.currentPageIndex = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// در غیر این صورت، به صفحه قبلی برمیگردیم
|
||||||
state.currentPageIndex--;
|
state.currentPageIndex--;
|
||||||
}),
|
},
|
||||||
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 4,
|
width: 4,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -43,14 +43,13 @@ class MainPageState extends CoreProvier {
|
||||||
try {
|
try {
|
||||||
swotItems = await SwotService.fetchSwotItems();
|
swotItems = await SwotService.fetchSwotItems();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// در صورت بروز خطا، میتوانید اینجا آن را مدیریت کنید
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _fetchStories() async {
|
Future<void> _fetchStories() async {
|
||||||
try {
|
try {
|
||||||
stories = await StoryService.getStories();
|
stories = await StoryService.getStories();
|
||||||
// ignore: avoid_print
|
|
||||||
print("Fetched ${stories.length} stories.");
|
print("Fetched ${stories.length} stories.");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
stories = [];
|
stories = [];
|
||||||
|
|
|
||||||
|
|
@ -23,14 +23,11 @@ class StorySection extends StatelessWidget {
|
||||||
child: _StoryCircle(
|
child: _StoryCircle(
|
||||||
userStories: userStories,
|
userStories: userStories,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
bool allStoriesViewed = stories.every((userStories) =>
|
|
||||||
userStories.stories.every((story) => story.isViewed.value));
|
|
||||||
|
|
||||||
Navigator.of(context).pushNamed(
|
Navigator.of(context).pushNamed(
|
||||||
Routes.storyViewer,
|
Routes.storyViewer,
|
||||||
arguments: {
|
arguments: {
|
||||||
'stories': stories,
|
'stories': stories,
|
||||||
'tappedIndex': allStoriesViewed ? 0 : index,
|
'tappedIndex': index,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
@ -50,9 +47,11 @@ class _StoryCircle extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
// ValueNotifier برای پیگیری وضعیت مشاهده همه استوریها
|
||||||
final allStoriesViewed = ValueNotifier<bool>(
|
final allStoriesViewed = ValueNotifier<bool>(
|
||||||
userStories.stories.every((story) => story.isViewed.value));
|
userStories.stories.every((story) => story.isViewed.value));
|
||||||
|
|
||||||
|
// افزودن Listener به هر استوری
|
||||||
for (var story in userStories.stories) {
|
for (var story in userStories.stories) {
|
||||||
story.isViewed.addListener(() {
|
story.isViewed.addListener(() {
|
||||||
allStoriesViewed.value =
|
allStoriesViewed.value =
|
||||||
|
|
@ -65,6 +64,7 @@ class _StoryCircle extends StatelessWidget {
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
|
// استفاده از ValueListenableBuilder برای تغییر رنگ حاشیه
|
||||||
ValueListenableBuilder<bool>(
|
ValueListenableBuilder<bool>(
|
||||||
valueListenable: allStoriesViewed,
|
valueListenable: allStoriesViewed,
|
||||||
builder: (context, isViewed, child) {
|
builder: (context, isViewed, child) {
|
||||||
|
|
@ -104,7 +104,7 @@ class _StoryCircle extends StatelessWidget {
|
||||||
child: ClipOval(
|
child: ClipOval(
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
userStories.user
|
userStories.user
|
||||||
.profileImageUrl,
|
.profileImageUrl, // Assuming this is a local asset
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
width: 50.0,
|
width: 50.0,
|
||||||
height: 50.0,
|
height: 50.0,
|
||||||
|
|
|
||||||
|
|
@ -92,14 +92,14 @@ class _UserStoryViewerState extends State<UserStoryViewer>
|
||||||
super.initState();
|
super.initState();
|
||||||
_animationController = AnimationController(vsync: this);
|
_animationController = AnimationController(vsync: this);
|
||||||
|
|
||||||
final allStoriesInGroupViewed =
|
// final allStoriesInGroupViewed =
|
||||||
widget.userStories.stories.every((story) => story.isViewed.value);
|
// widget.userStories.stories.every((story) => story.isViewed.value);
|
||||||
|
|
||||||
if (allStoriesInGroupViewed) {
|
// if (allStoriesInGroupViewed) {
|
||||||
for (final story in widget.userStories.stories) {
|
// for (final story in widget.userStories.stories) {
|
||||||
story.isViewed.value = false;
|
// story.isViewed.value = false;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
_currentStoryIndex =
|
_currentStoryIndex =
|
||||||
widget.userStories.stories.indexWhere((story) => !story.isViewed.value);
|
widget.userStories.stories.indexWhere((story) => !story.isViewed.value);
|
||||||
|
|
@ -244,12 +244,12 @@ class _UserStoryViewerState extends State<UserStoryViewer>
|
||||||
return CachedNetworkImage(
|
return CachedNetworkImage(
|
||||||
placeholder: (context, url) => const ShimmerPlaceholder(),
|
placeholder: (context, url) => const ShimmerPlaceholder(),
|
||||||
imageUrl: story.url,
|
imageUrl: story.url,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.fill,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: double.infinity);
|
height: double.infinity);
|
||||||
case MediaType.gif:
|
case MediaType.gif:
|
||||||
return Image.network(story.url,
|
return Image.network(story.url,
|
||||||
fit: BoxFit.cover, width: double.infinity, height: double.infinity);
|
fit: BoxFit.fill, width: double.infinity, height: double.infinity);
|
||||||
case MediaType.video:
|
case MediaType.video:
|
||||||
if (_videoController?.value.isInitialized ?? false) {
|
if (_videoController?.value.isInitialized ?? false) {
|
||||||
return FittedBox(
|
return FittedBox(
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import 'package:didvan/constants/app_icons.dart';
|
||||||
import 'package:didvan/utils/extension.dart';
|
import 'package:didvan/utils/extension.dart';
|
||||||
import 'package:didvan/views/widgets/animated_visibility.dart';
|
import 'package:didvan/views/widgets/animated_visibility.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
|
@ -108,7 +109,8 @@ class _DidvanTextFieldState extends State<DidvanTextField> {
|
||||||
? TextDirection.ltr
|
? TextDirection.ltr
|
||||||
: TextDirection.rtl,
|
: TextDirection.rtl,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(8,8,0,15),
|
padding: const EdgeInsets.fromLTRB(kIsWeb?8:8,kIsWeb?4:8,kIsWeb?8:0,kIsWeb?0:8),
|
||||||
|
child: Center(
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
inputFormatters: <TextInputFormatter>[
|
inputFormatters: <TextInputFormatter>[
|
||||||
if (!widget.acceptSpace)
|
if (!widget.acceptSpace)
|
||||||
|
|
@ -154,6 +156,7 @@ class _DidvanTextFieldState extends State<DidvanTextField> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
40
pubspec.lock
40
pubspec.lock
|
|
@ -33,6 +33,38 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.4"
|
version: "0.8.4"
|
||||||
|
app_links:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: app_links
|
||||||
|
sha256: "85ed8fc1d25a76475914fff28cc994653bd900bc2c26e4b57a49e097febb54ba"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.4.0"
|
||||||
|
app_links_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: app_links_linux
|
||||||
|
sha256: f5f7173a78609f3dfd4c2ff2c95bd559ab43c80a87dc6a095921d96c05688c81
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.3"
|
||||||
|
app_links_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: app_links_platform_interface
|
||||||
|
sha256: "05f5379577c513b534a29ddea68176a4d4802c46180ee8e2e966257158772a3f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.2"
|
||||||
|
app_links_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: app_links_web
|
||||||
|
sha256: af060ed76183f9e2b87510a9480e56a5352b6c249778d07bd2c95fc35632a555
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.4"
|
||||||
args:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -669,6 +701,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.2"
|
version: "2.3.2"
|
||||||
|
gtk:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: gtk
|
||||||
|
sha256: e8ce9ca4b1df106e4d72dad201d345ea1a036cc12c360f1a7d5a758f78ffa42c
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
highlight:
|
highlight:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
# Read more about iOS versioning at
|
# Read more about iOS versioning at
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
version: 4.0.1+4380
|
version: 4.0.3+5000
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.19.0 <3.0.0"
|
sdk: ">=2.19.0 <3.0.0"
|
||||||
|
|
@ -113,6 +113,7 @@ dependencies:
|
||||||
sms_autofill: ^2.4.1
|
sms_autofill: ^2.4.1
|
||||||
shimmer: ^3.0.0
|
shimmer: ^3.0.0
|
||||||
device_info_plus: ^11.5.0
|
device_info_plus: ^11.5.0
|
||||||
|
app_links: ^6.4.0
|
||||||
# image_gallery_saver: ^2.0.3
|
# image_gallery_saver: ^2.0.3
|
||||||
# fading_edge_scrollview: ^4.1.1
|
# fading_edge_scrollview: ^4.1.1
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue