last version 3.3.0 houshvan
This commit is contained in:
parent
9ea80f21fb
commit
1708bcffc8
Binary file not shown.
|
After Width: | Height: | Size: 333 KiB |
|
|
@ -42,6 +42,7 @@ class Assets {
|
|||
static String get studioLogo => '$_baseLogosPath/studio-$_themeSuffix.svg';
|
||||
|
||||
static String loadingAnimation = '$_baseAnimationsPath/loading.gif';
|
||||
static String bookmarkAnimation = '$_baseAnimationsPath/bookmark.gif';
|
||||
|
||||
static String get businessCategoryIcon =>
|
||||
'$_baseCategoriesPath/business-$_themeSuffix.svg';
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@ Future<void> _backgroundCallbackHomeWidget(Uri? uri) async {
|
|||
}
|
||||
|
||||
void main() async {
|
||||
await runZonedGuarded(() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
try {
|
||||
|
|
@ -80,9 +79,6 @@ void main() async {
|
|||
}
|
||||
|
||||
runApp(const Didvan());
|
||||
}, (error, stack) async {
|
||||
error.printError();
|
||||
});
|
||||
}
|
||||
|
||||
class Didvan extends StatefulWidget {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ class Content {
|
|||
final String createdAt;
|
||||
bool marked;
|
||||
bool liked;
|
||||
int likes;
|
||||
|
||||
final List<Tag> tags;
|
||||
|
||||
|
|
@ -30,6 +31,7 @@ class Content {
|
|||
{required this.id,
|
||||
required this.marked,
|
||||
required this.liked,
|
||||
required this.likes,
|
||||
required this.createdAt,
|
||||
required this.title,
|
||||
required this.image,
|
||||
|
|
@ -41,6 +43,7 @@ class Content {
|
|||
id: json['id'],
|
||||
marked: json['marked'],
|
||||
liked: json['liked'],
|
||||
likes: json['likes'],
|
||||
createdAt: json['createdAt'],
|
||||
title: json['title'],
|
||||
image: json['image'],
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ class NewsDetailsData {
|
|||
final String createdAt;
|
||||
bool marked;
|
||||
bool liked;
|
||||
int likes;
|
||||
int comments;
|
||||
final int order;
|
||||
final List<Tag> tags;
|
||||
|
|
@ -25,6 +26,7 @@ class NewsDetailsData {
|
|||
required this.createdAt,
|
||||
required this.marked,
|
||||
required this.liked,
|
||||
required this.likes,
|
||||
required this.comments,
|
||||
required this.tags,
|
||||
required this.contents,
|
||||
|
|
@ -41,6 +43,7 @@ class NewsDetailsData {
|
|||
createdAt: json['createdAt'],
|
||||
marked: json['marked'],
|
||||
liked: json['liked'] ?? false,
|
||||
likes: json['likes'],
|
||||
comments: json['comments'],
|
||||
order: json['order'],
|
||||
tags: List<Tag>.from(json['tags'].map((tag) => Tag.fromJson(tag))),
|
||||
|
|
@ -59,6 +62,7 @@ class NewsDetailsData {
|
|||
'createdAt': createdAt,
|
||||
'marked': marked,
|
||||
'liked': liked,
|
||||
'likes': likes,
|
||||
'comments': comments,
|
||||
'tags': tags.map((e) => e.toJson()).toList(),
|
||||
'contents': contents.map((e) => e.toJson()).toList(),
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ class OverviewData {
|
|||
int comments;
|
||||
bool marked;
|
||||
bool liked;
|
||||
int likes;
|
||||
final List<CategoryData>? categories;
|
||||
|
||||
OverviewData({
|
||||
|
|
@ -31,6 +32,7 @@ class OverviewData {
|
|||
required this.type,
|
||||
required this.marked,
|
||||
required this.liked,
|
||||
required this.likes,
|
||||
required this.comments,
|
||||
required this.forManagers,
|
||||
this.category,
|
||||
|
|
@ -87,6 +89,7 @@ class OverviewData {
|
|||
type: json['type'] ?? '',
|
||||
marked: json['marked'] ?? true,
|
||||
liked: json['liked'] ?? true,
|
||||
likes: json['likes'] ?? 0,
|
||||
link: json['link'],
|
||||
iframe: json['iframe'],
|
||||
categories: json['categories'] != null
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ class ActionSheetData {
|
|||
final Widget content;
|
||||
final String? confrimTitle;
|
||||
final String? dismissTitle;
|
||||
final VoidCallback? onConfirmed;
|
||||
final VoidCallback? onDismissed;
|
||||
final Function()? onConfirmed;
|
||||
final Function()? onDismissed;
|
||||
final String? title;
|
||||
final bool hasPadding;
|
||||
final IconData? titleIcon;
|
||||
|
|
|
|||
|
|
@ -132,7 +132,9 @@ class RouteGenerator {
|
|||
ChangeNotifierProvider<NewStatisticState>(
|
||||
create: (context) => NewStatisticState())
|
||||
],
|
||||
child: const Home(),
|
||||
child: Home(
|
||||
showDialogs: settings.arguments as bool?,
|
||||
),
|
||||
),
|
||||
);
|
||||
case Routes.editProfile:
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class FirebaseApi {
|
|||
e.printError();
|
||||
}
|
||||
|
||||
await _firebaseMessaging.requestPermission(
|
||||
_firebaseMessaging.requestPermission(
|
||||
alert: true,
|
||||
announcement: true,
|
||||
badge: true,
|
||||
|
|
|
|||
|
|
@ -169,8 +169,8 @@ class ActionSheetUtils {
|
|||
child: DidvanButton(
|
||||
style: ButtonStyleMode.primary,
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
data.onConfirmed?.call();
|
||||
pop();
|
||||
},
|
||||
title: data.confrimTitle ?? 'تایید',
|
||||
),
|
||||
|
|
@ -251,7 +251,10 @@ class ActionSheetUtils {
|
|||
if (data.hasDismissButton)
|
||||
Expanded(
|
||||
child: DidvanButton(
|
||||
onPressed: data.onDismissed ?? () => pop(),
|
||||
onPressed: () {
|
||||
data.onDismissed?.call();
|
||||
pop();
|
||||
},
|
||||
title: data.dismissTitle ?? 'بازگشت',
|
||||
style: ButtonStyleMode.flat,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ class _AiState extends State<Ai> {
|
|||
Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
height: 24,
|
||||
),
|
||||
Icon(
|
||||
DidvanIcons.ai_solid,
|
||||
|
|
@ -134,16 +134,6 @@ class _AiState extends State<Ai> {
|
|||
const SizedBox(
|
||||
width: 8,
|
||||
),
|
||||
Container(
|
||||
width: 32,
|
||||
height: 32,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Theme.of(context).colorScheme.border),
|
||||
child: const Icon(
|
||||
DidvanIcons.mic_regular,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
|
|
|
|||
|
|
@ -409,9 +409,13 @@ class _AiChatPageState extends State<AiChatPage> {
|
|||
},
|
||||
);
|
||||
}),
|
||||
SpinKitThreeBounce(
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: SpinKitThreeBounce(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
size: 18,
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -34,11 +34,6 @@ class AiChatState extends CoreProvier {
|
|||
FilesModel? file;
|
||||
TextEditingController message = TextEditingController();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _scrolledEnd() async {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
await scrollController.animateTo(
|
||||
|
|
@ -166,12 +161,8 @@ class AiChatState extends CoreProvier {
|
|||
file = null;
|
||||
update();
|
||||
|
||||
final stream = res
|
||||
.transform(utf8.decoder)
|
||||
.transform(const LineSplitter()); // <--- Add this line
|
||||
|
||||
final r = stream.listen((str) {
|
||||
// var str = utf8.decode(value);
|
||||
final r = res.listen((value) async {
|
||||
var str = utf8.decode(value);
|
||||
if (!kIsWeb) {
|
||||
if (str.contains('{{{')) {
|
||||
dataMessgae += str;
|
||||
|
|
@ -197,6 +188,7 @@ class AiChatState extends CoreProvier {
|
|||
}
|
||||
}
|
||||
messageOnstream.value = Stream.value(responseMessgae);
|
||||
|
||||
print("responseMessgae: $str");
|
||||
// update();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ import 'package:get/get.dart';
|
|||
import 'package:image_cropper/image_cropper.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:persian_number_utility/persian_number_utility.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:record/record.dart';
|
||||
|
|
@ -161,23 +160,25 @@ class _AiMessageBarState extends State<AiMessageBar> {
|
|||
FilePickerResult? result =
|
||||
await MediaService.pickPdfFile();
|
||||
if (result != null) {
|
||||
// if (kIsWeb) {
|
||||
// Uint8List bytes = result.files.first
|
||||
// .bytes!; // Access the bytes property
|
||||
if (kIsWeb) {
|
||||
Uint8List? bytes = result.files.first
|
||||
.bytes; // Access the bytes property
|
||||
String? name = result.files.first.name;
|
||||
|
||||
// File file = File.fromRawPath(bytes);
|
||||
// state.file = FilesModel(file.path,
|
||||
// name: result.files.first.name,
|
||||
// bytes: bytes,
|
||||
// audio: false,
|
||||
// image: false);
|
||||
// print(result.files.first.name);
|
||||
// } else {
|
||||
// Store bytes and file name directly in your state or model
|
||||
state.file = FilesModel(
|
||||
'', // No need for a file path on web
|
||||
name: name,
|
||||
bytes: bytes,
|
||||
audio: false,
|
||||
image: false,
|
||||
);
|
||||
} else {
|
||||
state.file = FilesModel(
|
||||
result.files.single.path!,
|
||||
audio: false,
|
||||
image: false);
|
||||
// }
|
||||
}
|
||||
|
||||
openAttach = false;
|
||||
}
|
||||
|
|
@ -243,6 +244,7 @@ class _AiMessageBarState extends State<AiMessageBar> {
|
|||
);
|
||||
},
|
||||
),
|
||||
if (!kIsWeb || !Platform.isIOS)
|
||||
if (historyState.bot!.attachmentType!
|
||||
.contains('audio'))
|
||||
attachBtn(
|
||||
|
|
@ -319,7 +321,8 @@ class _AiMessageBarState extends State<AiMessageBar> {
|
|||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: 8.0),
|
||||
child: (snapshot.hasData &&
|
||||
child: (!kIsWeb &&
|
||||
snapshot.hasData &&
|
||||
snapshot.data! !=
|
||||
RecordState.stop)
|
||||
? MessageBarBtn(
|
||||
|
|
@ -342,7 +345,9 @@ class _AiMessageBarState extends State<AiMessageBar> {
|
|||
state.update();
|
||||
},
|
||||
)
|
||||
: widget.bot.attachmentType!
|
||||
: (!kIsWeb || !Platform.isIOS) &&
|
||||
widget.bot
|
||||
.attachmentType!
|
||||
.contains(
|
||||
'audio') &&
|
||||
value.isEmpty &&
|
||||
|
|
@ -523,11 +528,23 @@ class _AiMessageBarState extends State<AiMessageBar> {
|
|||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.center,
|
||||
children: List
|
||||
.generate(
|
||||
3,
|
||||
(index) =>
|
||||
SpinKitWave(
|
||||
children: List.generate(
|
||||
4,
|
||||
(index) => snapshot.data! == RecordState.pause
|
||||
? Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: List.generate(
|
||||
8,
|
||||
(index) => Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 1.0, vertical: 12),
|
||||
child: Container(
|
||||
width: 3,
|
||||
height: 8,
|
||||
decoration: BoxDecoration(color: Theme.of(context).colorScheme.primary.withOpacity(0.4)),
|
||||
),
|
||||
)),
|
||||
)
|
||||
: SpinKitWave(
|
||||
color: Theme.of(context).colorScheme.primary.withOpacity(0.4),
|
||||
size: 32,
|
||||
itemCount: 10,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import 'package:didvan/views/ai/widgets/message_bar_btn.dart';
|
|||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:just_audio/just_audio.dart';
|
||||
|
|
@ -35,6 +36,7 @@ class _AudioWaveState extends State<AudioWave> {
|
|||
double currentPosition = 0;
|
||||
bool loading = true;
|
||||
bool faile = false;
|
||||
bool onChanging = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
|
@ -56,7 +58,7 @@ class _AudioWaveState extends State<AudioWave> {
|
|||
void setRandoms() {
|
||||
for (var i = 0; i < itemCount; i++) {
|
||||
randoms.value.add(0);
|
||||
randomsDisable.value.add(2 + Random().nextDouble() * (42 - 2));
|
||||
randomsDisable.value.add(1 + Random().nextDouble() * (38 - 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -94,7 +96,7 @@ class _AudioWaveState extends State<AudioWave> {
|
|||
|
||||
Future<void> listeners() async {
|
||||
audioPlayer.positionStream.listen((position) async {
|
||||
if (randomsDisable.value.isEmpty) return;
|
||||
if (randomsDisable.value.isEmpty || onChanging) return;
|
||||
|
||||
try {
|
||||
for (var i = 0; i < itemCount; i++) {
|
||||
|
|
@ -219,12 +221,9 @@ class _AudioWaveState extends State<AudioWave> {
|
|||
.primary
|
||||
.withOpacity(0.4)),
|
||||
if (totalDuration != Duration.zero)
|
||||
Opacity(
|
||||
Positioned.fill(
|
||||
child: Opacity(
|
||||
opacity: 0,
|
||||
child: Container(
|
||||
width: 12,
|
||||
color: Colors.transparent
|
||||
.withOpacity(1),
|
||||
child: Theme(
|
||||
data: Theme.of(context)
|
||||
.copyWith(
|
||||
|
|
@ -252,22 +251,22 @@ class _AudioWaveState extends State<AudioWave> {
|
|||
// audioPlayer.pause();
|
||||
},
|
||||
onChanged: (value) {
|
||||
for (var i = 0;
|
||||
i < itemCount;
|
||||
i++) {
|
||||
if (i <
|
||||
((value * 40) /
|
||||
totalDuration
|
||||
.inMilliseconds)) {
|
||||
final ran =
|
||||
randomsDisable
|
||||
.value[i];
|
||||
randoms.value[i] =
|
||||
ran;
|
||||
} else {
|
||||
randoms.value[i] = 0;
|
||||
}
|
||||
}
|
||||
// for (var i = 0;
|
||||
// i < itemCount;
|
||||
// i++) {
|
||||
// if (i <
|
||||
// ((value * 40) /
|
||||
// totalDuration
|
||||
// .inMilliseconds)) {
|
||||
// final ran =
|
||||
// randomsDisable
|
||||
// .value[i];
|
||||
// randoms.value[i] =
|
||||
// ran;
|
||||
// } else {
|
||||
// randoms.value[i] = 0;
|
||||
// }
|
||||
// }
|
||||
setState(() {
|
||||
currentPosition = value;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -80,78 +80,11 @@ class _PasswordInputState extends State<PasswordInput> {
|
|||
await ServerDataProvider.getData();
|
||||
|
||||
if (mounted) {
|
||||
Future.delayed(Duration.zero,
|
||||
() => Navigator.of(context).pushReplacementNamed(Routes.home));
|
||||
}
|
||||
|
||||
_showResetPasswordDialog();
|
||||
await Future.delayed(
|
||||
Duration.zero,
|
||||
() => Navigator.of(context)
|
||||
.pushReplacementNamed(Routes.home, arguments: true));
|
||||
}
|
||||
}
|
||||
|
||||
void _showResetPasswordDialog() {
|
||||
ActionSheetUtils(context).openDialog(
|
||||
data: ActionSheetData(
|
||||
content: const DidvanText(
|
||||
'خوش آمدید!\nبرای امنیت بیشتر، رمز عبور خود را تغییر دهید.',
|
||||
),
|
||||
onConfirmed: () => Navigator.of(navigatorKey.currentContext!).pushNamed(
|
||||
Routes.authenticaion,
|
||||
arguments: true,
|
||||
),
|
||||
isBackgroundDropBlur: false,
|
||||
confrimTitle: 'تغییر رمز عبور',
|
||||
onDismissed: Navigator.of(navigatorKey.currentContext!).pop,
|
||||
dismissTitle: 'بعدا',
|
||||
),
|
||||
);
|
||||
_showCustomizeDialog();
|
||||
}
|
||||
|
||||
void _showCustomizeDialog() {
|
||||
ActionSheetUtils(context).openDialog(
|
||||
data: ActionSheetData(
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
isBackgroundDropBlur: true,
|
||||
content: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
InkWrapper(
|
||||
onPressed: Navigator.of(navigatorKey.currentContext!).pop,
|
||||
child: const Icon(
|
||||
DidvanIcons.close_solid,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
DidvanText(
|
||||
'شخصی سازی محتوا',
|
||||
style: Theme.of(context).textTheme.displaySmall,
|
||||
color: Theme.of(context).colorScheme.text,
|
||||
),
|
||||
const InkWrapper(
|
||||
child: Icon(
|
||||
DidvanIcons.close_regular,
|
||||
size: 24,
|
||||
color: Colors.transparent,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
const DidvanText(
|
||||
"کاربر گرامی\nلطفا جهت شخصیسازی و استفاده بهتر از برنامه، دستهبندیهای مورد علاقه خود و زمان دریافت اعلانات را انتخاب نمایید.")
|
||||
],
|
||||
),
|
||||
hasDismissButton: false,
|
||||
onConfirmed: () => Navigator.of(navigatorKey.currentContext!).pushNamed(
|
||||
Routes.favouritesStep,
|
||||
arguments: {"toTimer": true},
|
||||
),
|
||||
confrimTitle: 'تایید',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class _UsernameInputState extends State<UsernameInput> {
|
|||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: DidvanText(
|
||||
'نام کاربری میتواند شامل کاراکترهای کوچک و بزرگ انگلیسی و اعداد باشد.',
|
||||
'نام کاربری میتواند شامل کاراکترهای انگلیسی و اعداد باشد.',
|
||||
style: Theme.of(context).textTheme.labelSmall,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ class _HashtagState extends State<Hashtag> {
|
|||
liked: item.liked,
|
||||
onLikedChanged: (_, value, __) =>
|
||||
_changeLiked(item.id, value, 'banner'),
|
||||
likes: item.likes,
|
||||
);
|
||||
|
||||
case 'radar':
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/constants/app_icons.dart';
|
||||
import 'package:didvan/constants/assets.dart';
|
||||
import 'package:didvan/models/view/app_bar_data.dart';
|
||||
import 'package:didvan/routes/routes.dart';
|
||||
import 'package:didvan/views/home/bookmarks/bookmark_state.dart';
|
||||
import 'package:didvan/views/widgets/didvan/scaffold.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:didvan/views/widgets/menu_item.dart';
|
||||
import 'package:didvan/views/widgets/overview/multitype.dart';
|
||||
// import 'package:didvan/views/widgets/search_field.dart';
|
||||
|
|
@ -124,7 +127,9 @@ class _BookmarksState extends State<Bookmarks> {
|
|||
),
|
||||
),
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
),
|
||||
sliver: SliverStateHandler<BookmarksState>(
|
||||
state: state,
|
||||
centerEmptyState: state.searching,
|
||||
|
|
@ -144,9 +149,24 @@ class _BookmarksState extends State<Bookmarks> {
|
|||
},
|
||||
placeholder: MultitypeOverview.placeholder,
|
||||
itemPadding: const EdgeInsets.only(bottom: 8),
|
||||
paddingEmptyState: 0,
|
||||
emptyState: state.searching
|
||||
? EmptyResult(onNewSearch: _focuseNode.requestFocus)
|
||||
: const EmptyList(),
|
||||
: Column(
|
||||
children: [
|
||||
DidvanText(
|
||||
'در قسمت رصدخانه من، تمامی محتواهایی که در قسمتهای مختلف سوپراپلیکیشن دیدوان، بوکمارک (نشاندار) کردهاید، به تفکیک نمایش داده میشوند. همچنین امکان درج یادداشت شخصی بصورت ضمیمه برای هر محتوا وجود دارد.',
|
||||
fontSize: 14,
|
||||
color: Theme.of(context).colorScheme.title,
|
||||
textAlign: TextAlign.justify,
|
||||
),
|
||||
Image.asset(
|
||||
Assets.bookmarkAnimation,
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
height: 180,
|
||||
),
|
||||
],
|
||||
),
|
||||
enableEmptyState: state.bookmarks.isEmpty,
|
||||
childCount:
|
||||
state.bookmarks.length + (state.page != state.lastPage ? 1 : 0),
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import 'package:didvan/views/home/new_statistic/new_statistic.dart';
|
|||
import 'package:didvan/views/home/search/search.dart';
|
||||
import 'package:didvan/views/widgets/didvan/divider.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:didvan/views/widgets/ink_wrapper.dart';
|
||||
import 'package:didvan/views/widgets/logo_app_bar.dart';
|
||||
import 'package:didvan/views/widgets/didvan/bnb.dart';
|
||||
import 'package:didvan/views/widgets/shimmer_placeholder.dart';
|
||||
|
|
@ -35,13 +36,15 @@ import 'package:flutter/cupertino.dart';
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../services/app_home_widget/home_widget_repository.dart';
|
||||
|
||||
final GlobalKey<ScaffoldState> homeScaffKey = GlobalKey<ScaffoldState>();
|
||||
|
||||
class Home extends StatefulWidget {
|
||||
const Home({Key? key}) : super(key: key);
|
||||
final bool? showDialogs;
|
||||
const Home({Key? key, this.showDialogs}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<Home> createState() => _HomeState();
|
||||
|
|
@ -51,8 +54,90 @@ class _HomeState extends State<Home>
|
|||
with SingleTickerProviderStateMixin, WidgetsBindingObserver {
|
||||
late final TabController _tabController;
|
||||
|
||||
Future<void> _showDialog(BuildContext context) async {
|
||||
WidgetsBinding.instance?.addPostFrameCallback((_) {
|
||||
ActionSheetUtils(context)
|
||||
.openDialog(
|
||||
data: ActionSheetData(
|
||||
content: const DidvanText(
|
||||
'خوش آمدید!\nبرای امنیت بیشتر، رمز عبور خود را تغییر دهید.',
|
||||
),
|
||||
onConfirmed: () {
|
||||
Future.delayed(
|
||||
Duration.zero,
|
||||
() => Navigator.of(context)
|
||||
.pushNamed(Routes.authenticaion, arguments: true),
|
||||
);
|
||||
},
|
||||
isBackgroundDropBlur: false,
|
||||
confrimTitle: 'تغییر رمز عبور',
|
||||
dismissTitle: 'بعدا',
|
||||
),
|
||||
)
|
||||
.then((value) => ActionSheetUtils(context).openDialog(
|
||||
data: ActionSheetData(
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
isBackgroundDropBlur: true,
|
||||
content: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
InkWrapper(
|
||||
onPressed: () {
|
||||
Future.delayed(
|
||||
Duration.zero,
|
||||
() => Navigator.of(context).pop(),
|
||||
);
|
||||
},
|
||||
child: const Icon(
|
||||
DidvanIcons.close_solid,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
DidvanText(
|
||||
'شخصی سازی محتوا',
|
||||
style: Theme.of(context).textTheme.displaySmall,
|
||||
color: Theme.of(context).colorScheme.text,
|
||||
),
|
||||
const InkWrapper(
|
||||
child: Icon(
|
||||
DidvanIcons.close_regular,
|
||||
size: 24,
|
||||
color: Colors.transparent,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
const DidvanText(
|
||||
"کاربر گرامی\nلطفا جهت شخصیسازی و استفاده بهتر از برنامه، دستهبندیهای مورد علاقه خود و زمان دریافت اعلانات را انتخاب نمایید.")
|
||||
],
|
||||
),
|
||||
// hasDismissButton: false,
|
||||
onConfirmed: () {
|
||||
Future.delayed(
|
||||
Duration.zero,
|
||||
() =>
|
||||
Navigator.of(navigatorKey.currentContext!).pushNamed(
|
||||
Routes.favouritesStep,
|
||||
arguments: {"toTimer": true},
|
||||
),
|
||||
);
|
||||
},
|
||||
confrimTitle: 'تایید',
|
||||
),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
if (widget.showDialogs ?? false) {
|
||||
_showDialog(context);
|
||||
}
|
||||
if (!kIsWeb) {
|
||||
NotificationService.startListeningNotificationEvents();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ class _InfographyScreenState extends State<InfographyScreen> {
|
|||
Wrap(
|
||||
children: [
|
||||
for (var i = 0; i < state.categories.length; i++)
|
||||
if (state.categories[i].label != 'هوشان')
|
||||
SizedBox(
|
||||
width: (MediaQuery.of(context).size.width - 40) / 2,
|
||||
child: DidvanCheckbox(
|
||||
|
|
@ -232,6 +233,7 @@ class _InfographyScreenState extends State<InfographyScreen> {
|
|||
liked: state.contents[index].liked,
|
||||
onLikedChanged: (id, value, _) =>
|
||||
state.changeLiked(id, value),
|
||||
likes: state.contents[index].likes,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ class InfographyItem extends StatelessWidget {
|
|||
final int id;
|
||||
final bool marked;
|
||||
final bool liked;
|
||||
final int likes;
|
||||
final void Function(int id, bool value, bool shouldUpdate) onMarkChanged;
|
||||
final void Function(int id, bool value, bool shouldUpdate) onLikedChanged;
|
||||
|
||||
|
|
@ -72,6 +73,7 @@ class InfographyItem extends StatelessWidget {
|
|||
required this.id,
|
||||
required this.marked,
|
||||
required this.liked,
|
||||
required this.likes,
|
||||
required this.onLikedChanged});
|
||||
|
||||
void _openInteractiveViewer(BuildContext context, String image) {
|
||||
|
|
@ -152,6 +154,17 @@ class InfographyItem extends StatelessWidget {
|
|||
),
|
||||
Row(
|
||||
children: [
|
||||
LikedButton(
|
||||
itemId: id,
|
||||
type: 'infography',
|
||||
gestureSize: 32,
|
||||
value: liked,
|
||||
onMarkChanged: (value) => onLikedChanged(id, value, true),
|
||||
likes: likes,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 4.0,
|
||||
),
|
||||
DidvanIconButton(
|
||||
gestureSize: 32,
|
||||
onPressed: () => Navigator.of(context).pushNamed(
|
||||
|
|
@ -164,19 +177,6 @@ class InfographyItem extends StatelessWidget {
|
|||
),
|
||||
icon: DidvanIcons.mention_icon,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 8.0,
|
||||
),
|
||||
LikedButton(
|
||||
itemId: id,
|
||||
type: 'infography',
|
||||
gestureSize: 32,
|
||||
value: liked,
|
||||
onMarkChanged: (value) => onLikedChanged(id, value, true),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 8.0,
|
||||
),
|
||||
BookmarkButton(
|
||||
itemId: id,
|
||||
type: 'infography',
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ class SearchPage extends StatelessWidget {
|
|||
isColapsed: state.selectedCats.length <= 1,
|
||||
selectedCats: state.selectedCats,
|
||||
categories: state.categoryFilters,
|
||||
disableHoushan: true,
|
||||
onSelected: (id) {
|
||||
state.selectedCats.clear();
|
||||
final cat = state.categoryFilters
|
||||
|
|
|
|||
|
|
@ -70,7 +70,18 @@ class _MentionsState extends State<Mentions> {
|
|||
}
|
||||
}
|
||||
_bottomPadding = bottomViewInset;
|
||||
return Material(
|
||||
return WillPopScope(
|
||||
onWillPop: () async {
|
||||
if (mentionsState.showUsersForMentionsLayout) {
|
||||
mentionsState.showUsersForMentionsLayout = false;
|
||||
mentionsState.searchUsers.text = '';
|
||||
|
||||
mentionsState.update();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
child: Material(
|
||||
child: Stack(
|
||||
children: [
|
||||
DidvanScaffold(
|
||||
|
|
@ -119,9 +130,12 @@ class _MentionsState extends State<Mentions> {
|
|||
filter: ImageFilter.blur(sigmaX: 8.0, sigmaY: 8.0),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
Theme.of(context).colorScheme.focused.withOpacity(0.5)),
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.focused
|
||||
.withOpacity(0.5)),
|
||||
child: DidvanScaffold(
|
||||
hidePlayer: true,
|
||||
appBarData: null,
|
||||
padding: const EdgeInsets.only(
|
||||
left: 16, right: 16, top: 16, bottom: 92),
|
||||
|
|
@ -182,7 +196,8 @@ class _MentionsState extends State<Mentions> {
|
|||
DidvanIconButton(
|
||||
icon: DidvanIcons.close_regular,
|
||||
onPressed: () {
|
||||
mentionsState.showUsersForMentionsLayout = false;
|
||||
mentionsState.showUsersForMentionsLayout =
|
||||
false;
|
||||
mentionsState.searchUsers.text = '';
|
||||
|
||||
mentionsState.update();
|
||||
|
|
@ -215,6 +230,7 @@ class _MentionsState extends State<Mentions> {
|
|||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,11 +80,9 @@ class _StudioSliderState extends State<StudioSlider> {
|
|||
horizontal: 8,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: (state.videosSelected
|
||||
? Theme.of(context)
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondaryDisabled
|
||||
: Theme.of(context).colorScheme.focused)
|
||||
.focused
|
||||
.withOpacity(0.9),
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
bottom: Radius.circular(10),
|
||||
|
|
@ -103,9 +101,11 @@ class _StudioSliderState extends State<StudioSlider> {
|
|||
width: 52,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Theme.of(context)
|
||||
color: (state.videosSelected
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondary
|
||||
.focusedBorder)
|
||||
.withOpacity(0.7),
|
||||
),
|
||||
child: Icon(
|
||||
|
|
@ -155,13 +155,6 @@ class _SliderIndicator extends StatelessWidget {
|
|||
required this.isVideo,
|
||||
}) : super(key: key);
|
||||
|
||||
Color _color(BuildContext context) {
|
||||
if (isVideo) {
|
||||
return Theme.of(context).colorScheme.secondary;
|
||||
}
|
||||
return Theme.of(context).colorScheme.focusedBorder;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedContainer(
|
||||
|
|
@ -171,10 +164,11 @@ class _SliderIndicator extends StatelessWidget {
|
|||
margin: const EdgeInsets.only(left: 4),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: _color(context),
|
||||
color: Theme.of(context).colorScheme.focusedBorder,
|
||||
),
|
||||
shape: BoxShape.circle,
|
||||
color: isCurrentIndex ? _color(context) : null,
|
||||
color:
|
||||
isCurrentIndex ? Theme.of(context).colorScheme.focusedBorder : null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class StudioTabBar extends StatelessWidget {
|
|||
Expanded(
|
||||
child: _StudioTypeButton(
|
||||
icon: DidvanIcons.video_solid,
|
||||
selectedColor: Theme.of(context).colorScheme.secondary,
|
||||
selectedColor: Theme.of(context).colorScheme.focusedBorder,
|
||||
title: 'ویدیو',
|
||||
onTap: () => state.videosSelected = true,
|
||||
isSelected: state.videosSelected,
|
||||
|
|
|
|||
|
|
@ -347,7 +347,7 @@ class _ProfilePageState extends State<ProfilePage> {
|
|||
),
|
||||
const SizedBox(height: 16),
|
||||
DidvanText(
|
||||
'نسخه نرمافزار: 3.2.2',
|
||||
'نسخه نرمافزار: 3.3.0',
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// ignore_for_file: library_private_types_in_public_api, deprecated_member_use
|
||||
|
||||
import 'package:didvan/constants/assets.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
|
||||
|
|
@ -62,7 +63,18 @@ class _WebViewState extends State<WebView> {
|
|||
return true;
|
||||
}
|
||||
},
|
||||
child: loading
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Padding(
|
||||
padding: EdgeInsets.only(top: 12.0),
|
||||
child: DidvanText(
|
||||
'بازگشت به دیدوان',
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
toolbarHeight: 32,
|
||||
),
|
||||
body: loading
|
||||
? Center(
|
||||
child: Image.asset(
|
||||
Assets.loadingAnimation,
|
||||
|
|
@ -70,6 +82,7 @@ class _WebViewState extends State<WebView> {
|
|||
height: 60,
|
||||
),
|
||||
)
|
||||
: WebViewWidget(controller: controller));
|
||||
: WebViewWidget(controller: controller),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ class CategoriesList extends StatefulWidget {
|
|||
final bool isAppBar;
|
||||
final List<CategoryData> selectedCats;
|
||||
final List<CategoryData> categories;
|
||||
final bool disableHoushan;
|
||||
final void Function(int id) onSelected;
|
||||
final double top;
|
||||
const CategoriesList({
|
||||
|
|
@ -19,6 +20,7 @@ class CategoriesList extends StatefulWidget {
|
|||
required this.categories,
|
||||
required this.onSelected,
|
||||
this.isAppBar = true,
|
||||
this.disableHoushan = false,
|
||||
required this.top,
|
||||
}) : super(key: key);
|
||||
|
||||
|
|
@ -69,7 +71,9 @@ class _CategoriesListState extends State<CategoriesList> {
|
|||
context,
|
||||
),
|
||||
for (var i = 0; i < widget.categories.length; i++)
|
||||
_itemBuilder(widget.categories[i], context),
|
||||
widget.disableHoushan && widget.categories[i].label == 'هوشان'
|
||||
? const SizedBox()
|
||||
: _itemBuilder(widget.categories[i], context),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:didvan/providers/user.dart';
|
|||
import 'package:didvan/utils/action_sheet.dart';
|
||||
import 'package:didvan/views/widgets/didvan/icon_button.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class LikedButton extends StatefulWidget {
|
||||
|
|
@ -15,6 +16,7 @@ class LikedButton extends StatefulWidget {
|
|||
final double gestureSize;
|
||||
final String type;
|
||||
final int itemId;
|
||||
final int likes;
|
||||
const LikedButton({
|
||||
Key? key,
|
||||
required this.value,
|
||||
|
|
@ -22,6 +24,7 @@ class LikedButton extends StatefulWidget {
|
|||
required this.gestureSize,
|
||||
required this.type,
|
||||
required this.itemId,
|
||||
required this.likes,
|
||||
this.askForConfirmation = false,
|
||||
this.color,
|
||||
}) : super(key: key);
|
||||
|
|
@ -45,16 +48,23 @@ class _LikedButtonState extends State<LikedButton> {
|
|||
super.initState();
|
||||
}
|
||||
|
||||
late int likes = widget.likes;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DidvanIconButton(
|
||||
gestureSize: widget.gestureSize,
|
||||
color: widget.color ??
|
||||
(DesignConfig.isDark || !_value
|
||||
? null
|
||||
: Theme.of(context).colorScheme.primary),
|
||||
icon: _value ? DidvanIcons.like_solid : DidvanIcons.like_regular,
|
||||
onPressed: () async {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
if (likes != 0)
|
||||
SizedBox(
|
||||
height: 16,
|
||||
child: DidvanText(
|
||||
likes.toString(),
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
bool confirm = false;
|
||||
if (widget.askForConfirmation) {
|
||||
await ActionSheetUtils(context).openDialog(
|
||||
|
|
@ -72,11 +82,24 @@ class _LikedButtonState extends State<LikedButton> {
|
|||
if (!widget.askForConfirmation || confirm) {
|
||||
setState(() {
|
||||
_value = !_value;
|
||||
if (_value) {
|
||||
likes += 1;
|
||||
} else {
|
||||
likes -= 1;
|
||||
}
|
||||
});
|
||||
widget.onMarkChanged(_value);
|
||||
UserProvider.changeItemLiked(widget.type, widget.itemId, _value);
|
||||
}
|
||||
},
|
||||
child: Icon(
|
||||
_value ? CupertinoIcons.heart_fill : CupertinoIcons.heart,
|
||||
size: 24,
|
||||
color: widget.color ??
|
||||
(!_value ? null : Theme.of(context).colorScheme.error),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -193,12 +193,13 @@ class LogoAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|||
Wrap(
|
||||
children: [
|
||||
for (var i = 0; i < state.categoryFilters.length; i++)
|
||||
if (state.categoryFilters[i].label != 'هوشان')
|
||||
SizedBox(
|
||||
width: (MediaQuery.of(context).size.width - 40) / 2,
|
||||
child: DidvanCheckbox(
|
||||
title: state.categoryFilters[i].label,
|
||||
value:
|
||||
state.selectedCats.contains(state.categoryFilters[i]),
|
||||
value: state.selectedCats
|
||||
.contains(state.categoryFilters[i]),
|
||||
onChanged: (value) {
|
||||
if (value) {
|
||||
state.selectedCats.add(state.categoryFilters[i]);
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ class MultitypeOverview extends StatelessWidget {
|
|||
case 'podcast':
|
||||
return DidvanIcons.podcast_light;
|
||||
case 'delphi':
|
||||
case 'survey':
|
||||
return DidvanIcons.saha_light;
|
||||
case 'infography':
|
||||
return DidvanIcons.infography_regular;
|
||||
|
|
|
|||
|
|
@ -93,6 +93,10 @@ class NewsOverview extends StatelessWidget {
|
|||
onMarkChanged: (value) =>
|
||||
onLikedChanged(news.id, value, false),
|
||||
askForConfirmation: hasUnmarkConfirmation,
|
||||
likes: news.likes,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 4.0,
|
||||
),
|
||||
BookmarkButton(
|
||||
itemId: news.id,
|
||||
|
|
|
|||
|
|
@ -132,6 +132,10 @@ class RadarOverview extends StatelessWidget {
|
|||
onMarkChanged: (value) =>
|
||||
onLikedChanged(radar.id, value, false),
|
||||
askForConfirmation: hasUnmarkConfirmation,
|
||||
likes: radar.likes,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 4.0,
|
||||
),
|
||||
BookmarkButton(
|
||||
itemId: radar.id,
|
||||
|
|
|
|||
|
|
@ -133,12 +133,13 @@ class SearchAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|||
Wrap(
|
||||
children: [
|
||||
for (var i = 0; i < state.categoryFilters.length; i++)
|
||||
if (state.categoryFilters[i].label != 'هوشان')
|
||||
SizedBox(
|
||||
width: (MediaQuery.of(context).size.width - 40) / 2,
|
||||
child: DidvanCheckbox(
|
||||
title: state.categoryFilters[i].label,
|
||||
value:
|
||||
state.selectedCats.contains(state.categoryFilters[i]),
|
||||
value: state.selectedCats
|
||||
.contains(state.categoryFilters[i]),
|
||||
onChanged: (value) {
|
||||
if (value) {
|
||||
state.selectedCats.add(state.categoryFilters[i]);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ class SliverStateHandler<T extends CoreProvier> extends SliverList {
|
|||
final bool centerEmptyState;
|
||||
final bool hasConstraints;
|
||||
final int placeholderCount;
|
||||
final double? paddingEmptyState;
|
||||
SliverStateHandler({
|
||||
Key? key,
|
||||
required this.state,
|
||||
|
|
@ -28,6 +29,7 @@ class SliverStateHandler<T extends CoreProvier> extends SliverList {
|
|||
this.centerEmptyState = true,
|
||||
this.hasConstraints = false,
|
||||
this.placeholderCount = 3,
|
||||
this.paddingEmptyState,
|
||||
}) : super(
|
||||
key: key,
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
|
|
@ -45,7 +47,8 @@ class SliverStateHandler<T extends CoreProvier> extends SliverList {
|
|||
if (enableEmptyState && state.appState == AppState.idle) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(
|
||||
top: centerEmptyState ? deviceHight / 4 : deviceHight / 8,
|
||||
top: paddingEmptyState ??
|
||||
(centerEmptyState ? deviceHight / 4 : deviceHight / 8),
|
||||
bottom: 20,
|
||||
),
|
||||
child: emptyState,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 3.2.2+3220
|
||||
version: 3.3.0+3300
|
||||
|
||||
environment:
|
||||
sdk: ">=2.19.0 <3.0.0"
|
||||
|
|
|
|||
Loading…
Reference in New Issue