29-02-1403 / Rhmn / Widget Android Created.
This commit is contained in:
parent
d4afdeb688
commit
e609feab7b
|
|
@ -75,6 +75,9 @@ android {
|
||||||
disable 'InvalidPackage'
|
disable 'InvalidPackage'
|
||||||
checkReleaseBuilds false
|
checkReleaseBuilds false
|
||||||
}
|
}
|
||||||
|
buildFeatures {
|
||||||
|
viewBinding true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flutter {
|
flutter {
|
||||||
|
|
@ -84,4 +87,7 @@ flutter {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation platform('com.google.firebase:firebase-bom:29.1.0')
|
implementation platform('com.google.firebase:firebase-bom:29.1.0')
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
|
implementation 'com.google.code.gson:gson:2.10.1'
|
||||||
|
// implementation 'com.github.bumptech.glide:glide:4.16.0'
|
||||||
|
implementation 'com.squareup.picasso:picasso:2.8'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,67 +1,94 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.didvan.didvanapp">
|
package="com.didvan.didvanapp">
|
||||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
|
||||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
|
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
|
||||||
|
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:label="Didvan"
|
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:usesCleartextTraffic="true"
|
android:label="Didvan"
|
||||||
|
android:requestLegacyExternalStorage="true"
|
||||||
|
android:usesCleartextTraffic="true">
|
||||||
|
<receiver
|
||||||
|
android:name=".FavWidget"
|
||||||
|
android:exported="false">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.appwidget.provider"
|
||||||
|
android:resource="@xml/favourite_widget_info" />
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<receiver android:name="es.antonborri.home_widget.HomeWidgetBackgroundReceiver"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="es.antonborri.home_widget.action.BACKGROUND" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
<service android:name="es.antonborri.home_widget.HomeWidgetBackgroundService"
|
||||||
|
android:permission="android.permission.BIND_JOB_SERVICE" android:exported="true"/>
|
||||||
|
|
||||||
android:requestLegacyExternalStorage="true">
|
|
||||||
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
|
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:launchMode="singleTop"
|
|
||||||
android:theme="@style/LaunchTheme"
|
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
|
android:launchMode="singleTop"
|
||||||
android:showOnLockScreen="true"
|
android:showOnLockScreen="true"
|
||||||
android:showWhenLocked="true"
|
android:showWhenLocked="true"
|
||||||
|
android:theme="@style/LaunchTheme"
|
||||||
android:turnScreenOn="true"
|
android:turnScreenOn="true"
|
||||||
android:windowSoftInputMode="adjustResize">
|
android:windowSoftInputMode="adjustResize">
|
||||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
|
||||||
|
<!--
|
||||||
|
Specifies an Android theme to apply to this Activity as soon as
|
||||||
the Android process has started. This theme is visible to the user
|
the Android process has started. This theme is visible to the user
|
||||||
while the Flutter UI initializes. After that, this theme continues
|
while the Flutter UI initializes. After that, this theme continues
|
||||||
to determine the Window background behind the Flutter UI. -->
|
to determine the Window background behind the Flutter UI.
|
||||||
<meta-data
|
-->
|
||||||
android:name="flutterEmbedding"
|
|
||||||
android:value="2" />
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="io.flutter.embedding.android.NormalTheme"
|
android:name="flutterEmbedding"
|
||||||
android:resource="@style/NormalTheme"
|
android:value="2" />
|
||||||
/>
|
<meta-data
|
||||||
|
android:name="io.flutter.embedding.android.NormalTheme"
|
||||||
|
android:resource="@style/NormalTheme" />
|
||||||
|
|
||||||
<!-- Displays an Android View that continues showing the launch screen
|
<!--
|
||||||
|
Displays an Android View that continues showing the launch screen
|
||||||
Drawable until Flutter paints its first frame, then this splash
|
Drawable until Flutter paints its first frame, then this splash
|
||||||
screen fades out. A splash screen is useful to avoid any visual
|
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
|
gap between the end of Android's launch screen and the painting of
|
||||||
Flutter's first frame. -->
|
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>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.yalantis.ucrop.UCropActivity"
|
android:name="com.yalantis.ucrop.UCropActivity"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
|
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".MyFirebaseMessagingService"
|
android:name=".MyFirebaseMessagingService"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.google.firebase.messaging.RECEIVE" />
|
<action android:name="com.google.firebase.messaging.RECEIVE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
|
||||||
<!-- Don't delete the meta-data below.
|
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
|
||||||
|
</manifest>
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
package com.didvan.didvanapp
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.appwidget.AppWidgetManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import android.net.Uri
|
||||||
|
import android.widget.RemoteViews
|
||||||
|
import com.squareup.picasso.Picasso
|
||||||
|
import com.squareup.picasso.Transformation
|
||||||
|
import es.antonborri.home_widget.HomeWidgetBackgroundIntent
|
||||||
|
import es.antonborri.home_widget.HomeWidgetLaunchIntent
|
||||||
|
import es.antonborri.home_widget.HomeWidgetProvider
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of App Widget functionality.
|
||||||
|
*/
|
||||||
|
class FavWidget : HomeWidgetProvider() {
|
||||||
|
|
||||||
|
@SuppressLint("RemoteViewLayout")
|
||||||
|
override fun onUpdate(
|
||||||
|
context: Context,
|
||||||
|
appWidgetManager: AppWidgetManager,
|
||||||
|
appWidgetIds: IntArray,
|
||||||
|
widgetData: SharedPreferences
|
||||||
|
) {
|
||||||
|
appWidgetIds.forEach { widgetId ->
|
||||||
|
val views = RemoteViews(context.packageName, R.layout.favourite_widget).apply {
|
||||||
|
|
||||||
|
// Open App on Widget Click
|
||||||
|
val pendingIntent = HomeWidgetLaunchIntent.getActivity(
|
||||||
|
context,
|
||||||
|
MainActivity::class.java
|
||||||
|
)
|
||||||
|
setOnClickPendingIntent(R.id.logo_btn, pendingIntent)
|
||||||
|
|
||||||
|
val responses: ArrayList<WidgetResponse> = ArrayList();
|
||||||
|
val token = widgetData.getString("token", "").toString()
|
||||||
|
|
||||||
|
for (i in 0..2) {
|
||||||
|
responses.add(
|
||||||
|
WidgetResponse(
|
||||||
|
id = widgetData.getString("id${i + 1}", "")?.toInt() ?: 0,
|
||||||
|
title = widgetData.getString("title${i + 1}", "").toString(),
|
||||||
|
createdAt = widgetData.getString("createdAt${i + 1}", "").toString(),
|
||||||
|
type = widgetData.getString("type${i + 1}", "").toString(),
|
||||||
|
link = widgetData.getString("link${i + 1}", "").toString(),
|
||||||
|
category = widgetData.getString("category${i + 1}", "").toString(),
|
||||||
|
image = widgetData.getString("image${i + 1}", "").toString(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
setTextViewText(R.id.first_title, responses[0].title.toString())
|
||||||
|
setTextViewText(R.id.middle_title, responses[1].title.toString())
|
||||||
|
setTextViewText(R.id.last_title, responses[2].title.toString())
|
||||||
|
//
|
||||||
|
setTextViewText(R.id.first_tag, responses[0].category)
|
||||||
|
setTextViewText(R.id.middle_tag, responses[1].category)
|
||||||
|
setTextViewText(R.id.last_tag, responses[2].category)
|
||||||
|
|
||||||
|
setTextViewText(R.id.first_duration, responses[0].createdAt)
|
||||||
|
setTextViewText(R.id.middle_duration, responses[1].createdAt)
|
||||||
|
setTextViewText(R.id.last_duration, responses[2].createdAt)
|
||||||
|
|
||||||
|
Picasso.get()
|
||||||
|
.load("https://api.didvan.app${responses[0].image}?accessToken=${token}")
|
||||||
|
.transform(RoundedTransformation(50, 0))
|
||||||
|
.into(this, R.id.first_image, appWidgetIds);
|
||||||
|
Picasso.get()
|
||||||
|
.load("https://api.didvan.app${responses[1].image}?accessToken=${token}")
|
||||||
|
.transform(RoundedTransformation(50, 0))
|
||||||
|
.into(this, R.id.middle_image, appWidgetIds);
|
||||||
|
Picasso.get()
|
||||||
|
.load("https://api.didvan.app${responses[2].image}?accessToken=${token}")
|
||||||
|
.transform(RoundedTransformation(50, 0))
|
||||||
|
.into(this, R.id.last_image, appWidgetIds);
|
||||||
|
|
||||||
|
|
||||||
|
// Pending intent to update counter on button click
|
||||||
|
val settingIntent = HomeWidgetBackgroundIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
Uri.parse("myAppWidget://setting"),
|
||||||
|
|
||||||
|
)
|
||||||
|
setOnClickPendingIntent(R.id.setting_btn, settingIntent)
|
||||||
|
|
||||||
|
val rowFirst = HomeWidgetBackgroundIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
Uri.parse("myAppWidget://rowFirst"),
|
||||||
|
|
||||||
|
)
|
||||||
|
setOnClickPendingIntent(R.id.first_row, settingIntent)
|
||||||
|
val rowMiddle = HomeWidgetBackgroundIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
Uri.parse("myAppWidget://rowMiddle"),
|
||||||
|
|
||||||
|
)
|
||||||
|
setOnClickPendingIntent(R.id.middle_row, settingIntent)
|
||||||
|
val rowLast = HomeWidgetBackgroundIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
Uri.parse("myAppWidget://rowLast"),
|
||||||
|
|
||||||
|
)
|
||||||
|
setOnClickPendingIntent(R.id.last_row, settingIntent)
|
||||||
|
|
||||||
|
}
|
||||||
|
appWidgetManager.updateAppWidget(widgetId, views)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.didvan.didvanapp
|
||||||
|
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.BitmapShader
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Paint
|
||||||
|
import android.graphics.RectF
|
||||||
|
import android.graphics.Shader
|
||||||
|
import com.squareup.picasso.Transformation
|
||||||
|
|
||||||
|
|
||||||
|
class RoundedTransformation(private val radius: Int, private val margin: Int) : Transformation {
|
||||||
|
override fun transform(source: Bitmap): Bitmap {
|
||||||
|
val paint = Paint()
|
||||||
|
paint.isAntiAlias = true
|
||||||
|
paint.setShader(
|
||||||
|
BitmapShader(
|
||||||
|
source, Shader.TileMode.CLAMP,
|
||||||
|
Shader.TileMode.CLAMP
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val output = Bitmap.createBitmap(
|
||||||
|
source.getWidth(), source.getHeight(),
|
||||||
|
Bitmap.Config.ARGB_8888
|
||||||
|
)
|
||||||
|
val canvas = Canvas(output)
|
||||||
|
canvas.drawRoundRect(
|
||||||
|
RectF(
|
||||||
|
margin.toFloat(), margin.toFloat(), (source.getWidth() - margin).toFloat(),
|
||||||
|
(
|
||||||
|
source.getHeight() - margin).toFloat()
|
||||||
|
), radius.toFloat(), radius.toFloat(), paint
|
||||||
|
)
|
||||||
|
if (source != output) {
|
||||||
|
source.recycle()
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun key(): String {
|
||||||
|
return "rounded(r=$radius, m=$margin)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.didvan.didvanapp
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
data class WidgetResponse(
|
||||||
|
@SerializedName("id")
|
||||||
|
var id: Int = 0,
|
||||||
|
@SerializedName("title")
|
||||||
|
var title: String = "",
|
||||||
|
@SerializedName("createdAt")
|
||||||
|
var createdAt: String = "",
|
||||||
|
@SerializedName("type")
|
||||||
|
var type: String = "",
|
||||||
|
@SerializedName("link")
|
||||||
|
var link: String = "",
|
||||||
|
@SerializedName("category")
|
||||||
|
var category: String = "",
|
||||||
|
@SerializedName("image")
|
||||||
|
var image: String = "",
|
||||||
|
|
||||||
|
)
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
Background for widgets to make the rounded corners based on the
|
||||||
|
appWidgetRadius attribute value
|
||||||
|
-->
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
|
||||||
|
<corners android:radius="?attr/appWidgetRadius" />
|
||||||
|
<solid android:color="?android:attr/colorBackground" />
|
||||||
|
</shape>
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
Background for views inside widgets to make the rounded corners based on the
|
||||||
|
appWidgetInnerRadius attribute value
|
||||||
|
-->
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
|
||||||
|
<corners android:radius="?attr/appWidgetInnerRadius" />
|
||||||
|
<solid android:color="?android:attr/colorAccent" />
|
||||||
|
</shape>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 773 B |
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
|
@ -0,0 +1,300 @@
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
style="@style/Widget.Android.AppWidget.Container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="#ffffff"
|
||||||
|
android:theme="@style/Theme.Android.AppWidgetContainer">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:id="@+id/root_lay"
|
||||||
|
|
||||||
|
>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/setting_btn"
|
||||||
|
android:layout_width="32dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:src="@drawable/setting_logo" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_weight="1">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/logo_btn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:src="@drawable/logo" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_marginVertical="16dp"
|
||||||
|
android:background="#E0E0E0" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/first_row"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="78dp"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
|
||||||
|
>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/first_image"
|
||||||
|
android:layout_width="74dp"
|
||||||
|
android:layout_height="74dp"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:scaleType="fitXY"
|
||||||
|
android:src="@drawable/test" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_toLeftOf="@id/first_image"
|
||||||
|
android:orientation="vertical"
|
||||||
|
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/first_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:text=" تحلیل شکاف فناوری صنعت فولاد ایران تحلیل شکاف فناوری صنعت فولاد ایران"
|
||||||
|
android:textColor="#012348"
|
||||||
|
android:textSize="13dp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="2">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/first_duration"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_weight="3"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="۳ دقیقه مطالعه"
|
||||||
|
android:textColor="#666666"
|
||||||
|
android:textSize="12dp" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="1dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginHorizontal="8dp"
|
||||||
|
android:background="#E0E0E0" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/first_tag"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_weight="4"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="رادار فناوری"
|
||||||
|
android:textColor="#292929"
|
||||||
|
android:textSize="12dp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/middle_row"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="78dp"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/middle_image"
|
||||||
|
android:layout_width="74dp"
|
||||||
|
android:layout_height="74dp"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:scaleType="fitXY"
|
||||||
|
android:src="@drawable/test" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_toLeftOf="@id/middle_image"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/middle_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:text=" تحلیل شکاف فناوری صنعت فولاد ایران تحلیل شکاف فناوری صنعت فولاد ایران"
|
||||||
|
android:textColor="#012348"
|
||||||
|
android:textSize="13dp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="2">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/middle_duration"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_weight="3"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="۳ دقیقه مطالعه"
|
||||||
|
android:textColor="#666666"
|
||||||
|
android:textSize="12dp"
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="1dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginHorizontal="8dp"
|
||||||
|
android:background="#E0E0E0" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/middle_tag"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_weight="4"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="رادار فناوری"
|
||||||
|
android:textColor="#292929"
|
||||||
|
android:textSize="12dp"
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/last_row"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="78dp"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/last_image"
|
||||||
|
android:layout_width="74dp"
|
||||||
|
android:layout_height="74dp"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:scaleType="fitXY"
|
||||||
|
android:src="@drawable/test" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_toLeftOf="@id/last_image"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/last_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:text=" تحلیل شکاف فناوری صنعت فولاد ایران تحلیل شکاف فناوری صنعت فولاد ایران"
|
||||||
|
android:textColor="#012348"
|
||||||
|
android:textSize="13dp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="2"
|
||||||
|
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/last_duration"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_weight="3"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="۳ دقیقه مطالعه"
|
||||||
|
android:textColor="#666666"
|
||||||
|
android:textSize="12dp"
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="1dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginHorizontal="8dp"
|
||||||
|
android:background="#E0E0E0" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/last_tag"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_weight="4"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="رادار فناوری"
|
||||||
|
android:textColor="#292929"
|
||||||
|
android:textSize="12dp"
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<style name="Widget.Android.AppWidget.Container" parent="android:Widget">
|
||||||
|
<item name="android:id">@android:id/background</item>
|
||||||
|
<item name="android:padding">?attr/appWidgetPadding</item>
|
||||||
|
<item name="android:background">@drawable/app_widget_background</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="Widget.Android.AppWidget.InnerView" parent="android:Widget">
|
||||||
|
<item name="android:padding">?attr/appWidgetPadding</item>
|
||||||
|
<item name="android:background">@drawable/app_widget_inner_view_background</item>
|
||||||
|
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
<resources>
|
||||||
|
<declare-styleable name="AppWidgetAttrs">
|
||||||
|
<attr name="appWidgetPadding" format="dimension" />
|
||||||
|
<attr name="appWidgetInnerRadius" format="dimension" />
|
||||||
|
<attr name="appWidgetRadius" format="dimension" />
|
||||||
|
</declare-styleable>
|
||||||
|
</resources>
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<resources>
|
||||||
|
<color name="light_blue_50">#FFE1F5FE</color>
|
||||||
|
<color name="light_blue_200">#FF81D4FA</color>
|
||||||
|
<color name="light_blue_600">#FF039BE5</color>
|
||||||
|
<color name="light_blue_900">#FF01579B</color>
|
||||||
|
</resources>
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Refer to App Widget Documentation for margin information
|
||||||
|
http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout
|
||||||
|
-->
|
||||||
|
<dimen name="widget_margin">0dp</dimen>
|
||||||
|
|
||||||
|
</resources>
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="appwidget_text">EXAMPLE</string>
|
||||||
|
<string name="add_widget">Add widget</string>
|
||||||
|
<string name="app_widget_description">This is an app widget description</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -15,4 +15,14 @@
|
||||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||||
<item name="android:windowBackground">?android:colorBackground</item>
|
<item name="android:windowBackground">?android:colorBackground</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="Widget.Android.AppWidget.Container" parent="android:Widget">
|
||||||
|
<item name="android:id">@android:id/background</item>
|
||||||
|
<item name="android:background">?android:attr/colorBackground</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="Widget.Android.AppWidget.InnerView" parent="android:Widget">
|
||||||
|
<item name="android:background">?android:attr/colorBackground</item>
|
||||||
|
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<style name="Theme.Android.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault">
|
||||||
|
<!-- Radius of the outer bound of widgets to make the rounded corners -->
|
||||||
|
<item name="appWidgetRadius">16dp</item>
|
||||||
|
<!--
|
||||||
|
Radius of the inner view's bound of widgets to make the rounded corners.
|
||||||
|
It needs to be 8dp or less than the value of appWidgetRadius
|
||||||
|
-->
|
||||||
|
<item name="appWidgetInnerRadius">8dp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="Theme.Android.AppWidgetContainer" parent="Theme.Android.AppWidgetContainerParent">
|
||||||
|
<!-- Apply padding to avoid the content of the widget colliding with the rounded corners -->
|
||||||
|
<item name="appWidgetPadding">16dp</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:description="@string/app_widget_description"
|
||||||
|
android:initialKeyguardLayout="@layout/favourite_widget"
|
||||||
|
android:initialLayout="@layout/favourite_widget"
|
||||||
|
android:minWidth="250dp"
|
||||||
|
android:minHeight="180dp"
|
||||||
|
android:previewImage="@drawable/favwidg"
|
||||||
|
android:targetCellWidth="4"
|
||||||
|
android:targetCellHeight="3"
|
||||||
|
android:updatePeriodMillis="86400000"
|
||||||
|
android:widgetCategory="home_screen" />
|
||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
151
lib/main.dart
151
lib/main.dart
|
|
@ -1,25 +1,25 @@
|
||||||
import 'dart:developer';
|
import 'package:android_intent_plus/android_intent.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/providers/media.dart';
|
import 'package:didvan/providers/media.dart';
|
||||||
import 'package:didvan/providers/theme.dart';
|
import 'package:didvan/providers/theme.dart';
|
||||||
import 'package:didvan/providers/user.dart';
|
import 'package:didvan/providers/user.dart';
|
||||||
import 'package:didvan/routes/route_generator.dart';
|
import 'package:didvan/routes/route_generator.dart';
|
||||||
import 'package:didvan/services/app_initalizer.dart';
|
import 'package:didvan/routes/routes.dart';
|
||||||
import 'package:didvan/services/notification/awsome/awsome_notification_handler.dart';
|
import 'package:didvan/services/notification/awsome/awsome_notification_handler.dart';
|
||||||
import 'package:didvan/services/notification/fcm/firebase_notification_handler.dart';
|
import 'package:didvan/services/notification/fcm/firebase_notification_handler.dart';
|
||||||
import 'package:didvan/views/podcasts/podcasts_state.dart';
|
import 'package:didvan/views/podcasts/podcasts_state.dart';
|
||||||
import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart';
|
import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart';
|
||||||
import 'package:didvan/services/notification/lc/local_notification_service.dart';
|
|
||||||
import 'package:didvan/services/notification/lc/show_notification_handler.dart';
|
|
||||||
import 'package:firebase_core/firebase_core.dart';
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
|
import 'package:home_widget/home_widget.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||||
|
|
||||||
@pragma('vm:entry-point')
|
@pragma('vm:entry-point')
|
||||||
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||||
// If you're going to use other Firebase services in the background, such as Firestore,
|
// If you're going to use other Firebase services in the background, such as Firestore,
|
||||||
|
|
@ -46,28 +46,98 @@ Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||||
// LocalNotificationService.initialize();
|
// LocalNotificationService.initialize();
|
||||||
// LocalNotificationService.display(message);
|
// LocalNotificationService.display(message);
|
||||||
// LocalNotificationService.showBigPictureNotification();
|
// LocalNotificationService.showBigPictureNotification();
|
||||||
AwsomeNotificationHandler().main();
|
AwsomeNotificationHandler().alarm();
|
||||||
AwsomeNotificationHandler().show(message);
|
AwsomeNotificationHandler().show(message);
|
||||||
|
|
||||||
print("Handling a background message: ${message.messageId}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
try {
|
try {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
|
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
|
||||||
|
HomeWidget.registerBackgroundCallback(backgroundCallback);
|
||||||
|
// HomeWidget.registerInteractivityCallback(backgroundCallback);
|
||||||
|
HomeWidget.widgetClicked.listen((Uri? uri) {});
|
||||||
FirebaseNotificationHandler().initial();
|
FirebaseNotificationHandler().initial();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e.toString());
|
print(e.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
runApp(const Didvan());
|
runApp(const Didvan());
|
||||||
}
|
}
|
||||||
|
|
||||||
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
Future<void> backgroundCallback(Uri? uri) async {
|
||||||
|
AndroidIntent intent = const AndroidIntent(
|
||||||
|
action: 'android.intent.action.RUN',
|
||||||
|
package: 'com.didvan.didvanapp',
|
||||||
|
componentName: 'com.didvan.didvanapp.MainActivity',
|
||||||
|
);
|
||||||
|
|
||||||
class Didvan extends StatelessWidget {
|
await intent.launch();
|
||||||
|
switch (uri!.host) {
|
||||||
|
case 'setting':
|
||||||
|
HomeWidget.saveWidgetData("r", Routes.notificationStatusStep);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'rowFirst':
|
||||||
|
HomeWidget.saveWidgetData("r", Routes.generalSettings);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'rowMiddle':
|
||||||
|
HomeWidget.saveWidgetData("r", Routes.generalSettings);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'rowLast':
|
||||||
|
HomeWidget.saveWidgetData("r", Routes.generalSettings);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Add more cases for other routes as needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String r = "";
|
||||||
|
|
||||||
|
class Didvan extends StatefulWidget {
|
||||||
const Didvan({Key? key}) : super(key: key);
|
const Didvan({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<Didvan> createState() => _DidvanState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DidvanState extends State<Didvan> with WidgetsBindingObserver {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
WidgetsBinding.instance?.addObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
WidgetsBinding.instance?.removeObserver(this);
|
||||||
|
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeAppLifecycleState(AppLifecycleState state) async {
|
||||||
|
var v = context;
|
||||||
|
|
||||||
|
if (state == AppLifecycleState.resumed) {
|
||||||
|
await HomeWidget.getWidgetData<String>('r', defaultValue: "")
|
||||||
|
.then((value) {
|
||||||
|
if (value!.isNotEmpty) {
|
||||||
|
navigatorKey.currentState?.pushNamed(
|
||||||
|
value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
HomeWidget.saveWidgetData("r", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
|
|
@ -92,37 +162,36 @@ class Didvan extends StatelessWidget {
|
||||||
builder: (context, themeProvider, child) => Container(
|
builder: (context, themeProvider, child) => Container(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
navigatorKey: navigatorKey,
|
navigatorKey: navigatorKey,
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
title: 'Didvan',
|
title: 'Didvan',
|
||||||
theme: LightThemeConfig.themeData.copyWith(
|
theme: LightThemeConfig.themeData.copyWith(
|
||||||
textTheme: LightThemeConfig.themeData.textTheme.apply(
|
textTheme: LightThemeConfig.themeData.textTheme.apply(
|
||||||
fontFamily: themeProvider.fontFamily,
|
fontFamily: themeProvider.fontFamily,
|
||||||
)),
|
)),
|
||||||
darkTheme: DarkThemeConfig.themeData.copyWith(
|
darkTheme: DarkThemeConfig.themeData.copyWith(
|
||||||
textTheme: DarkThemeConfig.themeData.textTheme.apply(
|
textTheme: DarkThemeConfig.themeData.textTheme.apply(
|
||||||
fontFamily: themeProvider.fontFamily,
|
fontFamily: themeProvider.fontFamily,
|
||||||
)),
|
)),
|
||||||
color: LightThemeConfig.themeData.primaryColor,
|
color: LightThemeConfig.themeData.primaryColor,
|
||||||
themeMode: themeProvider.themeMode,
|
themeMode: themeProvider.themeMode,
|
||||||
onGenerateRoute: (settings) =>
|
onGenerateRoute: (settings) =>
|
||||||
RouteGenerator.generateRoute(settings),
|
RouteGenerator.generateRoute(settings),
|
||||||
builder: BotToastInit(),
|
builder: BotToastInit(),
|
||||||
//1. call BotToastInit
|
//1. call BotToastInit
|
||||||
navigatorObservers: [BotToastNavigatorObserver()],
|
navigatorObservers: [BotToastNavigatorObserver()],
|
||||||
initialRoute: '/',
|
initialRoute: "/",
|
||||||
localizationsDelegates: const [
|
localizationsDelegates: const [
|
||||||
GlobalCupertinoLocalizations.delegate,
|
GlobalCupertinoLocalizations.delegate,
|
||||||
GlobalMaterialLocalizations.delegate,
|
GlobalMaterialLocalizations.delegate,
|
||||||
GlobalWidgetsLocalizations.delegate,
|
GlobalWidgetsLocalizations.delegate,
|
||||||
],
|
],
|
||||||
supportedLocales: const [
|
supportedLocales: const [
|
||||||
Locale("fa", "IR"),
|
Locale("fa", "IR"),
|
||||||
],
|
],
|
||||||
locale: const Locale("fa", "IR"),
|
locale: const Locale("fa", "IR"),
|
||||||
),
|
)),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,26 @@ import '../views/notification_time/notification_time.dart';
|
||||||
class RouteGenerator {
|
class RouteGenerator {
|
||||||
static Route<dynamic> generateRoute(RouteSettings settings) {
|
static Route<dynamic> generateRoute(RouteSettings settings) {
|
||||||
switch (settings.name) {
|
switch (settings.name) {
|
||||||
|
case Routes.widgetSetting:
|
||||||
|
_createRoute(
|
||||||
|
const Splash(),
|
||||||
|
);
|
||||||
|
_createRoute(
|
||||||
|
const ProfilePage(),
|
||||||
|
);
|
||||||
|
_createRoute(
|
||||||
|
ChangeNotifierProvider<GeneralSettingsState>(
|
||||||
|
create: (context) => GeneralSettingsState(),
|
||||||
|
child: const GeneralSettings(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return _createRoute(
|
||||||
|
ChangeNotifierProvider<CustomizeCategoryState>(
|
||||||
|
create: (context) => CustomizeCategoryState(),
|
||||||
|
child: FavoritesStep()),
|
||||||
|
);
|
||||||
|
|
||||||
case Routes.splash:
|
case Routes.splash:
|
||||||
return _createRoute(
|
return _createRoute(
|
||||||
const Splash(),
|
const Splash(),
|
||||||
|
|
@ -64,7 +84,7 @@ class RouteGenerator {
|
||||||
return _createRoute(
|
return _createRoute(
|
||||||
ChangeNotifierProvider<NotificationTimeState>(
|
ChangeNotifierProvider<NotificationTimeState>(
|
||||||
create: (context) => NotificationTimeState(),
|
create: (context) => NotificationTimeState(),
|
||||||
child: NotificationTime(
|
child: NotificationTime(
|
||||||
pageData: settings.arguments as Map<String, dynamic>,
|
pageData: settings.arguments as Map<String, dynamic>,
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
|
|
@ -73,14 +93,14 @@ class RouteGenerator {
|
||||||
return _createRoute(
|
return _createRoute(
|
||||||
ChangeNotifierProvider<CustomizeCategoryState>(
|
ChangeNotifierProvider<CustomizeCategoryState>(
|
||||||
create: (context) => CustomizeCategoryState(),
|
create: (context) => CustomizeCategoryState(),
|
||||||
child: FavoritesStep()),
|
child: FavoritesStep()),
|
||||||
);
|
);
|
||||||
|
|
||||||
case Routes.notificationStatusStep:
|
case Routes.notificationStatusStep:
|
||||||
return _createRoute(
|
return _createRoute(
|
||||||
ChangeNotifierProvider<CustomizeCategoryState>(
|
ChangeNotifierProvider<CustomizeCategoryState>(
|
||||||
create: (context) => CustomizeCategoryState(),
|
create: (context) => CustomizeCategoryState(),
|
||||||
child: NotificationStatusStep()),
|
child: NotificationStatusStep()),
|
||||||
);
|
);
|
||||||
case Routes.authenticaion:
|
case Routes.authenticaion:
|
||||||
return _createRoute(
|
return _createRoute(
|
||||||
|
|
|
||||||
|
|
@ -28,4 +28,5 @@ class Routes {
|
||||||
static const String favouritesStep = '/favourites-step';
|
static const String favouritesStep = '/favourites-step';
|
||||||
static const String notificationStatusStep = '/notification-status-step';
|
static const String notificationStatusStep = '/notification-status-step';
|
||||||
static const String notificationTime = '/notification-time';
|
static const String notificationTime = '/notification-time';
|
||||||
|
static const String widgetSetting = '/widget-setting';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,11 +43,11 @@ class RequestService {
|
||||||
}) {
|
}) {
|
||||||
if (body != null) _requestBody = body;
|
if (body != null) _requestBody = body;
|
||||||
if (requestHeaders != null) _headers.addAll(requestHeaders);
|
if (requestHeaders != null) _headers.addAll(requestHeaders);
|
||||||
if (useAutherization) _headers.addAll({'Authorization': 'Bearer $token'});
|
// if (useAutherization) _headers.addAll({'Authorization': 'Bearer $token'});
|
||||||
// _headers.addAll({
|
_headers.addAll({
|
||||||
// 'Authorization':
|
'Authorization':
|
||||||
// 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NCwicm9sZUlkIjo0LCJhcHBJZCI6MCwiaWF0IjoxNzEzOTM1NzkwfQ.i-SO9tLy0M9j-_C2Wh8tdp01vtYGlDZIBFPygglHQF0'
|
'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NCwicm9sZUlkIjo0LCJhcHBJZCI6MCwiaWF0IjoxNzEzOTM1NzkwfQ.i-SO9tLy0M9j-_C2Wh8tdp01vtYGlDZIBFPygglHQF0'
|
||||||
// });
|
});
|
||||||
if (body != null) _requestBody = body;
|
if (body != null) _requestBody = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,7 @@ class RequestHelper {
|
||||||
'$baseUrl/$type/$id/comments/add';
|
'$baseUrl/$type/$id/comments/add';
|
||||||
static String deleteComment(int id) => '$baseUrl/comment/$id/v2';
|
static String deleteComment(int id) => '$baseUrl/comment/$id/v2';
|
||||||
static String reportComment(int id) => '$baseUrl/comment/$id/report';
|
static String reportComment(int id) => '$baseUrl/comment/$id/report';
|
||||||
|
static String widgetNews() => '$baseUrl/user/widget';
|
||||||
|
|
||||||
static String _urlConcatGenerator(List<MapEntry<String, dynamic>> additions) {
|
static String _urlConcatGenerator(List<MapEntry<String, dynamic>> additions) {
|
||||||
String result = '';
|
String result = '';
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
|
|
||||||
import 'package:awesome_notifications/awesome_notifications.dart';
|
import 'package:awesome_notifications/awesome_notifications.dart';
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
import '../../../models/notification_message.dart';
|
import '../../../models/notification_message.dart';
|
||||||
|
import '../../network/request.dart';
|
||||||
|
import '../../network/request_helper.dart';
|
||||||
import 'awsome_notification_controller.dart';
|
import 'awsome_notification_controller.dart';
|
||||||
|
|
||||||
class AwsomeNotificationHandler {
|
class AwsomeNotificationHandler {
|
||||||
main() async {
|
alarm() async {
|
||||||
late ReceivedAction? initialAction;
|
late ReceivedAction? initialAction;
|
||||||
|
|
||||||
AwesomeNotifications().initialize(
|
AwesomeNotifications().initialize(
|
||||||
|
|
@ -83,6 +85,11 @@ class AwsomeNotificationHandler {
|
||||||
case "3":
|
case "3":
|
||||||
await showNotificationTypeEmoji(notificationMessage);
|
await showNotificationTypeEmoji(notificationMessage);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "4":
|
||||||
|
await showNotificationScheduled(notificationMessage);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -146,4 +153,49 @@ class AwsomeNotificationHandler {
|
||||||
'largeImage': 'path/to/largeImage.png', // Path to large image
|
'largeImage': 'path/to/largeImage.png', // Path to large image
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<DateTime> _getTime() async {
|
||||||
|
final service = RequestService(
|
||||||
|
RequestHelper.notificationTime(),
|
||||||
|
);
|
||||||
|
await service.httpGet();
|
||||||
|
if (service.isSuccess) {
|
||||||
|
final time = service.data('time');
|
||||||
|
DateFormat format = DateFormat("HH:mm");
|
||||||
|
DateTime dateTime = format.parse(time);
|
||||||
|
DateTime result = DateTime.now()
|
||||||
|
.copyWith(hour: dateTime.hour, minute: dateTime.minute);
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return DateTime.now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showNotificationScheduled(NotificationMessage message) async {
|
||||||
|
DateTime time = await _getTime();
|
||||||
|
AwesomeNotifications().createNotification(
|
||||||
|
content: NotificationContent(
|
||||||
|
id: DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
||||||
|
channelKey: 'alerts',
|
||||||
|
title: 'Emojis are awes'
|
||||||
|
'ome too! ${Emojis.animals_lady_beetle}${Emojis.activites_balloon}${Emojis.emotion_red_heart}',
|
||||||
|
body:
|
||||||
|
'Simple body with a bunch of Emojis! ${Emojis.transport_police_car} ${Emojis.animals_dog} ${Emojis.flag_UnitedStates} ${Emojis.person_baby}',
|
||||||
|
largeIcon:
|
||||||
|
'https://cdn.britannica.com/72/232772-050-4E3D86CC/mind-blown-emoji-head-exploding-emoticon.jpg',
|
||||||
|
notificationLayout: NotificationLayout.BigPicture,
|
||||||
|
wakeUpScreen: true,
|
||||||
|
category: NotificationCategory.Alarm,
|
||||||
|
payload: {
|
||||||
|
'title': 'Notification Title',
|
||||||
|
'body': 'Notification Body',
|
||||||
|
'image': 'path/to/smallImage.png', // Path to small image
|
||||||
|
'largeImage': 'path/to/largeImage.png', // Path to large image
|
||||||
|
}),
|
||||||
|
schedule: NotificationCalendar(
|
||||||
|
hour: time.hour,
|
||||||
|
minute: time.minute,
|
||||||
|
// timezone: await AwesomeNotifications().getLocalTimeZoneIdentifier()
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ class FirebaseNotificationHandler {
|
||||||
// LocalNotificationService.initialize();
|
// LocalNotificationService.initialize();
|
||||||
// LocalNotificationService.showBigPictureNotification();
|
// LocalNotificationService.showBigPictureNotification();
|
||||||
// LocalNotificationService.display(message);
|
// LocalNotificationService.display(message);
|
||||||
AwsomeNotificationHandler().main();
|
AwsomeNotificationHandler().alarm();
|
||||||
AwsomeNotificationHandler().show(message);
|
AwsomeNotificationHandler().show(message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,12 @@ import 'package:didvan/config/design_config.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/models/view/action_sheet_data.dart';
|
import 'package:didvan/models/view/action_sheet_data.dart';
|
||||||
|
import 'package:didvan/models/widget_response.dart';
|
||||||
import 'package:didvan/providers/theme.dart';
|
import 'package:didvan/providers/theme.dart';
|
||||||
import 'package:didvan/routes/routes.dart';
|
import 'package:didvan/routes/routes.dart';
|
||||||
import 'package:didvan/services/app_initalizer.dart';
|
import 'package:didvan/services/app_initalizer.dart';
|
||||||
|
import 'package:didvan/services/network/request.dart';
|
||||||
|
import 'package:didvan/services/network/request_helper.dart';
|
||||||
import 'package:didvan/utils/action_sheet.dart';
|
import 'package:didvan/utils/action_sheet.dart';
|
||||||
import 'package:didvan/views/home/bookmarks/bookmarks.dart';
|
import 'package:didvan/views/home/bookmarks/bookmarks.dart';
|
||||||
import 'package:didvan/views/home/categories/categories_page.dart';
|
import 'package:didvan/views/home/categories/categories_page.dart';
|
||||||
|
|
@ -17,6 +20,8 @@ import 'package:didvan/views/widgets/ink_wrapper.dart';
|
||||||
import 'package:didvan/views/widgets/logo_app_bar.dart';
|
import 'package:didvan/views/widgets/logo_app_bar.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/bnb.dart';
|
import 'package:didvan/views/widgets/didvan/bnb.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:home_widget/home_widget.dart';
|
||||||
|
import 'package:persian_number_utility/persian_number_utility.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class Home extends StatefulWidget {
|
class Home extends StatefulWidget {
|
||||||
|
|
@ -26,7 +31,8 @@ class Home extends StatefulWidget {
|
||||||
State<Home> createState() => _HomeState();
|
State<Home> createState() => _HomeState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
|
class _HomeState extends State<Home>
|
||||||
|
with SingleTickerProviderStateMixin, WidgetsBindingObserver {
|
||||||
late final TabController _tabController;
|
late final TabController _tabController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -49,10 +55,47 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Future<void> _fetchWidget() async {
|
||||||
|
final service = RequestService(
|
||||||
|
RequestHelper.widgetNews(),
|
||||||
|
);
|
||||||
|
await service.httpGet();
|
||||||
|
List<WidgetResponse> responseList = [];
|
||||||
|
if (service.isSuccess) {
|
||||||
|
final favourites = service.data('content');
|
||||||
|
HomeWidget.saveWidgetData("token",
|
||||||
|
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NCwicm9sZUlkIjo0LCJhcHBJZCI6MCwiaWF0IjoxNzEzOTM1NzkwfQ.i-SO9tLy0M9j-_C2Wh8tdp01vtYGlDZIBFPygglHQF0");
|
||||||
|
for (var i = 0; i < favourites.length; i++) {
|
||||||
|
HomeWidget.saveWidgetData(
|
||||||
|
"id${i + 1}", WidgetResponse.fromJson(favourites[i]).id.toString());
|
||||||
|
HomeWidget.saveWidgetData("title${i + 1}",
|
||||||
|
WidgetResponse.fromJson(favourites[i]).title.toString());
|
||||||
|
HomeWidget.saveWidgetData(
|
||||||
|
"createdAt${i + 1}",
|
||||||
|
DateTime.parse(
|
||||||
|
WidgetResponse.fromJson(favourites[i]).createdAt.toString())
|
||||||
|
.toPersianDateStr());
|
||||||
|
HomeWidget.saveWidgetData("type${i + 1}",
|
||||||
|
WidgetResponse.fromJson(favourites[i]).type.toString());
|
||||||
|
HomeWidget.saveWidgetData("link${i + 1}",
|
||||||
|
WidgetResponse.fromJson(favourites[i]).link.toString());
|
||||||
|
HomeWidget.saveWidgetData("category${i + 1}",
|
||||||
|
WidgetResponse.fromJson(favourites[i]).category.toString());
|
||||||
|
HomeWidget.saveWidgetData("image${i + 1}",
|
||||||
|
WidgetResponse.fromJson(favourites[i]).image.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
HomeWidget.updateWidget(
|
||||||
|
androidName: "FavWidget",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
_fetchWidget();
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: const LogoAppBar(),
|
appBar: const LogoAppBar(),
|
||||||
body: Consumer<HomeState>(
|
body: Consumer<HomeState>(
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ class _SplashState extends State<Splash> {
|
||||||
|
|
||||||
Future<void> _initialize() async {
|
Future<void> _initialize() async {
|
||||||
try {
|
try {
|
||||||
|
var v = navigatorKey.currentContext;
|
||||||
ActionSheetUtils.context = navigatorKey.currentContext!;
|
ActionSheetUtils.context = navigatorKey.currentContext!;
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
html.window.onBeforeUnload.listen((event) {
|
html.window.onBeforeUnload.listen((event) {
|
||||||
|
|
|
||||||
24
pubspec.lock
24
pubspec.lock
|
|
@ -9,6 +9,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.33"
|
version: "1.3.33"
|
||||||
|
android_intent_plus:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: android_intent_plus
|
||||||
|
sha256: "2bfdbee8d65e7c26f88b66f0a91f2863da4d3596d8a658b4162c8de5cf04b074"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.0.2"
|
||||||
animated_custom_dropdown:
|
animated_custom_dropdown:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -510,6 +518,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.23.8"
|
version: "2.23.8"
|
||||||
|
get:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: get
|
||||||
|
sha256: e4e7335ede17452b391ed3b2ede016545706c01a02292a6c97619705e7d2a85e
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.6.6"
|
||||||
graphs:
|
graphs:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -518,6 +534,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.1"
|
version: "2.3.1"
|
||||||
|
home_widget:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: home_widget
|
||||||
|
sha256: "29565bfee4b32eaf9e7e8b998d504618b779a74b2b1ac62dd4dac7468e66f1a3"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.5.0"
|
||||||
html:
|
html:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,9 @@ dependencies:
|
||||||
flutter_local_notifications: ^17.1.2
|
flutter_local_notifications: ^17.1.2
|
||||||
awesome_notifications_core: ^0.9.0
|
awesome_notifications_core: ^0.9.0
|
||||||
awesome_notifications: any
|
awesome_notifications: any
|
||||||
|
home_widget: ^0.5.0
|
||||||
|
android_intent_plus: ^5.0.2
|
||||||
|
get: ^4.6.6
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue