diff --git a/android/app/build.gradle b/android/app/build.gradle
index 071c50d..6d239c3 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -113,4 +113,5 @@ dependencies {
implementation "androidx.sqlite:sqlite-framework:2.1.0"
implementation "androidx.sqlite:sqlite:2.1.0"
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
+ implementation 'androidx.appcompat:appcompat:1.6.1'
}
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index c841e84..1ba4137 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -74,6 +74,11 @@
+
+
+
()
+ for (resource in requestedResources) {
+ when (resource) {
+ PermissionRequest.RESOURCE_VIDEO_CAPTURE -> {
+ if (ContextCompat.checkSelfPermission(this@FullscreenWebViewActivity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
+ permissionsNeeded.add(Manifest.permission.CAMERA)
+ }
+ }
+ PermissionRequest.RESOURCE_AUDIO_CAPTURE -> {
+ if (ContextCompat.checkSelfPermission(this@FullscreenWebViewActivity, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
+ permissionsNeeded.add(Manifest.permission.RECORD_AUDIO)
+ }
+ }
+ }
+ }
+
+ if (permissionsNeeded.isNotEmpty()) {
+ // درخواست پرمیژن runtime
+ pendingPermissionRequest = request
+ ActivityCompat.requestPermissions(this@FullscreenWebViewActivity, permissionsNeeded.toTypedArray(), PERMISSION_REQUEST_CODE)
+ } else {
+ // پرمیژن ها داده شده، قبول کن درخواست رو
+ request.grant(request.resources)
+ }
+ }
+ }
+ }
+
+ webView.loadUrl(url)
+ }
+
+ override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
+ if (requestCode == PERMISSION_REQUEST_CODE) {
+ var allGranted = true
+ for (result in grantResults) {
+ if (result != PackageManager.PERMISSION_GRANTED) {
+ allGranted = false
+ break
+ }
+ }
+ if (allGranted) {
+ pendingPermissionRequest?.grant(pendingPermissionRequest?.resources)
+ } else {
+ pendingPermissionRequest?.deny()
+ }
+ pendingPermissionRequest = null
+ } else {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ }
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ webView.destroy()
+ }
+}
diff --git a/android/app/src/main/kotlin/com/example/didvan/MainActivity.kt b/android/app/src/main/kotlin/com/example/didvan/MainActivity.kt
index cfe4bf5..0dd0cc0 100644
--- a/android/app/src/main/kotlin/com/example/didvan/MainActivity.kt
+++ b/android/app/src/main/kotlin/com/example/didvan/MainActivity.kt
@@ -1,20 +1,87 @@
package com.didvan.didvanapp
-import android.app.NotificationChannel
-import android.app.NotificationManager
+import android.content.ContentValues
+import android.content.Context
+import android.content.Intent
import android.os.Build
import android.os.Bundle
-import android.os.PersistableBundle
+import android.provider.MediaStore
+import android.util.Log
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
-import io.flutter.plugins.GeneratedPluginRegistrant
+import io.flutter.plugin.common.MethodChannel
+import java.io.File
+import java.io.FileInputStream
class MainActivity: FlutterActivity() {
- @Override
- override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
- GeneratedPluginRegistrant.registerWith(flutterEngine)
+ private val CHANNEL = "com.didvan.shareFile"
+
+ @Override
+ override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
+ super.configureFlutterEngine(flutterEngine)
+
+ MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
+ when (call.method) {
+ "copyToDownloads" -> {
+ val filePath = call.argument("filePath") ?: return@setMethodCallHandler
+ val fileName = call.argument("fileName") ?: return@setMethodCallHandler
+
+ val success = copyFileToDownloads(filePath, fileName)
+ if (success) {
+ result.success("File copied successfully")
+ } else {
+ result.error("FILE_COPY_ERROR", "Failed to copy file", null)
+ }
+ }
+ "openWebView" -> {
+ val url = call.argument("url") ?: return@setMethodCallHandler
+ openWebView(url)
+ result.success(null)
+ }
+ else -> result.notImplemented()
+ }
+ }
}
+ private fun copyFileToDownloads(filePath: String, fileName: String): Boolean {
+ return try {
+ val context: Context = applicationContext
+ val file = File(filePath)
+ if (!file.exists()) return false
+
+ val resolver = context.contentResolver
+ val contentValues = ContentValues().apply {
+ put(MediaStore.Downloads.DISPLAY_NAME, fileName)
+ put(MediaStore.Downloads.MIME_TYPE, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
+ put(MediaStore.Downloads.IS_PENDING, 1)
+ }
+
+ val uri = resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues)
+ ?: return false
+
+ resolver.openOutputStream(uri).use { outputStream ->
+ FileInputStream(file).use { inputStream ->
+ inputStream.copyTo(outputStream!!)
+ }
+ }
+
+ contentValues.clear()
+ contentValues.put(MediaStore.Downloads.IS_PENDING, 0)
+ resolver.update(uri, contentValues, null, null)
+
+ true
+ } catch (e: Exception) {
+ Log.e("FileCopy", "Error copying file to downloads", e)
+ false
+ }
+ }
+
+ private fun openWebView(url: String) {
+ Log.d("MainActivity", "Opening WebView with URL: $url")
+ val intent = Intent(this, FullscreenWebViewActivity::class.java)
+ intent.putExtra("url", url)
+ startActivity(intent)
+ }
}
diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml
index 08abd17..2e8bc2c 100644
--- a/android/app/src/main/res/values/styles.xml
+++ b/android/app/src/main/res/values/styles.xml
@@ -1,17 +1,9 @@
-
-
+
@@ -25,4 +17,9 @@
- ?android:attr/colorBackground
- ?android:attr/textColorPrimary
+
+
+
diff --git a/lib/services/webview.dart b/lib/services/webview.dart
new file mode 100644
index 0000000..9a6600b
--- /dev/null
+++ b/lib/services/webview.dart
@@ -0,0 +1,13 @@
+import 'package:flutter/services.dart';
+
+class NativeWebViewLauncher {
+ static const MethodChannel _channel = MethodChannel('com.didvan.shareFile');
+
+ static Future openWebView(String url) async {
+ try {
+ await _channel.invokeMethod('openWebView', {'url': url});
+ } on PlatformException catch (e) {
+ print("Failed to open native webview: '${e.message}'.");
+ }
+ }
+}
diff --git a/lib/views/home/main/widgets/main_content.dart b/lib/views/home/main/widgets/main_content.dart
index d0de86a..5fe9349 100644
--- a/lib/views/home/main/widgets/main_content.dart
+++ b/lib/views/home/main/widgets/main_content.dart
@@ -3,6 +3,7 @@
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/views/home/main/widgets/banner.dart';
import 'package:didvan/views/home/widgets/categories.dart';
+import 'package:didvan/views/widgets/ai_banner.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
diff --git a/lib/views/widgets/ai_banner.dart b/lib/views/widgets/ai_banner.dart
new file mode 100644
index 0000000..2efb873
--- /dev/null
+++ b/lib/views/widgets/ai_banner.dart
@@ -0,0 +1,31 @@
+import 'package:didvan/services/webview.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_svg/svg.dart';
+
+class AiBanner extends StatelessWidget {
+ const AiBanner({
+ super.key,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return GestureDetector(
+ onTap: () {
+ NativeWebViewLauncher.openWebView(
+ 'https://www.aisada.ir/app/page1.html');
+ },
+ child: Padding(
+ padding: const EdgeInsets.only(top: 20),
+ child: Stack(
+ children: [
+ Icon(Icons.insert_comment_sharp),
+ Positioned(
+ left: 15,
+ child: Icon(Icons.import_contacts))
+ ],
+ ),
+ ),
+ );
+ }
+}