Compare commits
3 Commits
develop-wi
...
develop
Author | SHA1 | Date | |
---|---|---|---|
7dea44d1e8 | |||
5f27956035 | |||
32799f648c |
@@ -57,9 +57,6 @@ android {
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
}
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
|
@@ -1,73 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
>
|
||||
|
||||
<!--
|
||||
Required to query activities that can process text, see:
|
||||
https://developer.android.com/training/package-visibility?hl=en and
|
||||
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
||||
|
||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin.
|
||||
-->
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.PROCESS_TEXT" />
|
||||
|
||||
<data android:mimeType="text/plain" />
|
||||
</intent>
|
||||
</queries>
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<application
|
||||
tools:replace="android:label"
|
||||
android:label="Marianum Fulda"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="Marianum Fulda">
|
||||
<receiver
|
||||
android:name=".TimetableWidget"
|
||||
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/timetable_widget_info" />
|
||||
</receiver>
|
||||
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:exported="true"
|
||||
android:hardwareAccelerated="true"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
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
|
||||
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="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme" />
|
||||
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme"
|
||||
/>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<!--
|
||||
Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java
|
||||
-->
|
||||
<!-- Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
</application>
|
||||
<!-- Required to query activities that can process text, see:
|
||||
https://developer.android.com/training/package-visibility?hl=en and
|
||||
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
||||
|
||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
||||
<data android:mimeType="text/plain"/>
|
||||
</intent>
|
||||
</queries>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
@@ -1,39 +0,0 @@
|
||||
package eu.mhsl.marianum.mobile.client
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.appwidget.AppWidgetProvider
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.widget.RemoteViews
|
||||
|
||||
import es.antonborri.home_widget.HomeWidgetPlugin
|
||||
import android.util.Base64
|
||||
|
||||
/**
|
||||
* Implementation of App Widget functionality.
|
||||
*/
|
||||
class TimetableWidget : AppWidgetProvider() {
|
||||
override fun onUpdate(
|
||||
context: Context,
|
||||
appWidgetManager: AppWidgetManager,
|
||||
appWidgetIds: IntArray,
|
||||
) {
|
||||
for (appWidgetId in appWidgetIds) {
|
||||
val widgetData = HomeWidgetPlugin.getData(context)
|
||||
val views = RemoteViews(context.packageName, R.layout.timetable_widget).apply {
|
||||
val imageBase64 = widgetData.getString("screen", null) ?: return@apply
|
||||
val imageBytes = Base64.decode(imageBase64, Base64.DEFAULT);
|
||||
val imageBitmap: Bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
|
||||
setImageViewBitmap(R.id.widget_image, imageBitmap)
|
||||
}
|
||||
|
||||
val launchIntent = context.packageManager.getLaunchIntentForPackage(context.packageName)
|
||||
val pendingIntent = PendingIntent.getActivity(context, 0, launchIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
views.setOnClickPendingIntent(R.id.background, pendingIntent)
|
||||
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 98 KiB |
Binary file not shown.
Before Width: | Height: | Size: 48 KiB |
@@ -1,10 +0,0 @@
|
||||
<?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>
|
@@ -1,10 +0,0 @@
|
||||
<?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>
|
@@ -1,26 +0,0 @@
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/background"
|
||||
style="@style/Widget.Android.AppWidget.Container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/transparent"
|
||||
android:padding="0dp"
|
||||
android:theme="@style/Theme.Android.AppWidgetContainer">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/widget_image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_marginLeft="0dp"
|
||||
android:layout_marginTop="0dp"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:layout_weight="1"
|
||||
android:adjustViewBounds="false"
|
||||
android:background="@android:color/transparent"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/timetable_widget_default"
|
||||
android:visibility="visible"
|
||||
tools:visibility="visible" />
|
||||
</RelativeLayout>
|
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!--
|
||||
Having themes.xml for night-v31 because of the priority order of the resource qualifiers.
|
||||
-->
|
||||
<style name="Theme.Android.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault.DayNight">
|
||||
<item name="appWidgetRadius">@android:dimen/system_app_widget_background_radius</item>
|
||||
<item name="appWidgetInnerRadius">@android:dimen/system_app_widget_inner_radius</item>
|
||||
</style>
|
||||
</resources>
|
@@ -1,14 +0,0 @@
|
||||
<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>
|
@@ -18,18 +18,4 @@
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
|
||||
<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>
|
||||
<item name="android:clipToOutline">true</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>
|
||||
<item name="android:clipToOutline">true</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!--
|
||||
Having themes.xml for v31 variant because @android:dimen/system_app_widget_background_radius
|
||||
and @android:dimen/system_app_widget_internal_padding requires API level 31
|
||||
-->
|
||||
<style name="Theme.Android.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault.DayNight">
|
||||
<item name="appWidgetRadius">@android:dimen/system_app_widget_background_radius</item>
|
||||
<item name="appWidgetInnerRadius">@android:dimen/system_app_widget_inner_radius</item>
|
||||
</style>
|
||||
</resources>
|
@@ -1,7 +0,0 @@
|
||||
<resources>
|
||||
<declare-styleable name="AppWidgetAttrs">
|
||||
<attr name="appWidgetPadding" format="dimension" />
|
||||
<attr name="appWidgetInnerRadius" format="dimension" />
|
||||
<attr name="appWidgetRadius" format="dimension" />
|
||||
</declare-styleable>
|
||||
</resources>
|
@@ -1,6 +0,0 @@
|
||||
<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>
|
@@ -1,10 +0,0 @@
|
||||
<?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>
|
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="appwidget_text">Marianum Vertretungsplan</string>
|
||||
<string name="add_widget">Hinzufügen</string>
|
||||
<string name="app_widget_description">Übersicht zum Vertretungsplan</string>
|
||||
</resources>
|
@@ -19,14 +19,4 @@
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</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>
|
||||
|
@@ -1,17 +0,0 @@
|
||||
<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>
|
@@ -1,16 +0,0 @@
|
||||
<?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/timetable_widget"
|
||||
android:initialLayout="@layout/timetable_widget"
|
||||
android:minWidth="220dp"
|
||||
android:minHeight="294dp"
|
||||
android:minResizeWidth="110dp"
|
||||
android:minResizeHeight="147dp"
|
||||
android:previewImage="@drawable/timetable_widget_preview"
|
||||
android:previewLayout="@layout/timetable_widget"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:targetCellWidth="3"
|
||||
android:targetCellHeight="4"
|
||||
android:updatePeriodMillis="86400000"
|
||||
android:widgetCategory="home_screen" />
|
@@ -2,21 +2,6 @@ allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
|
||||
// [required] background_fetch
|
||||
maven {
|
||||
url "${project(':background_fetch').projectDir}/libs"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10'
|
||||
}
|
||||
}
|
||||
|
||||
|
BIN
ios/.DS_Store
vendored
BIN
ios/.DS_Store
vendored
Binary file not shown.
@@ -21,6 +21,6 @@
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>11.0</string>
|
||||
<string>13.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# Uncomment this line to define a global platform for your project
|
||||
platform :ios, '11.0'
|
||||
platform :ios, '15.0'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
@@ -31,6 +31,8 @@ target 'Runner' do
|
||||
use_frameworks!
|
||||
use_modular_headers!
|
||||
|
||||
pod 'PhoneNumberKit', '~> 3.7.6'
|
||||
|
||||
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||
# target 'RunnerTests' do
|
||||
# inherit! :search_paths
|
||||
|
313
ios/Podfile.lock
313
ios/Podfile.lock
@@ -1,185 +1,194 @@
|
||||
PODS:
|
||||
- better_open_file (0.0.1):
|
||||
- connectivity_plus (0.0.1):
|
||||
- Flutter
|
||||
- device_info_plus (0.0.1):
|
||||
- Flutter
|
||||
- DKImagePickerController/Core (4.3.4):
|
||||
- DKImagePickerController/Core (4.3.9):
|
||||
- DKImagePickerController/ImageDataManager
|
||||
- DKImagePickerController/Resource
|
||||
- DKImagePickerController/ImageDataManager (4.3.4)
|
||||
- DKImagePickerController/PhotoGallery (4.3.4):
|
||||
- DKImagePickerController/ImageDataManager (4.3.9)
|
||||
- DKImagePickerController/PhotoGallery (4.3.9):
|
||||
- DKImagePickerController/Core
|
||||
- DKPhotoGallery
|
||||
- DKImagePickerController/Resource (4.3.4)
|
||||
- DKPhotoGallery (0.0.17):
|
||||
- DKPhotoGallery/Core (= 0.0.17)
|
||||
- DKPhotoGallery/Model (= 0.0.17)
|
||||
- DKPhotoGallery/Preview (= 0.0.17)
|
||||
- DKPhotoGallery/Resource (= 0.0.17)
|
||||
- DKImagePickerController/Resource (4.3.9)
|
||||
- DKPhotoGallery (0.0.19):
|
||||
- DKPhotoGallery/Core (= 0.0.19)
|
||||
- DKPhotoGallery/Model (= 0.0.19)
|
||||
- DKPhotoGallery/Preview (= 0.0.19)
|
||||
- DKPhotoGallery/Resource (= 0.0.19)
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Core (0.0.17):
|
||||
- DKPhotoGallery/Core (0.0.19):
|
||||
- DKPhotoGallery/Model
|
||||
- DKPhotoGallery/Preview
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Model (0.0.17):
|
||||
- DKPhotoGallery/Model (0.0.19):
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Preview (0.0.17):
|
||||
- DKPhotoGallery/Preview (0.0.19):
|
||||
- DKPhotoGallery/Model
|
||||
- DKPhotoGallery/Resource
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Resource (0.0.17):
|
||||
- DKPhotoGallery/Resource (0.0.19):
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- emoji_picker_flutter (0.0.1):
|
||||
- Flutter
|
||||
- fast_rsa (0.6.0):
|
||||
- Flutter
|
||||
- file_picker (0.0.1):
|
||||
- DKImagePickerController/PhotoGallery
|
||||
- Flutter
|
||||
- Firebase/CoreOnly (10.12.0):
|
||||
- FirebaseCore (= 10.12.0)
|
||||
- Firebase/InAppMessaging (10.12.0):
|
||||
- Firebase/CoreOnly (12.2.0):
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- Firebase/InAppMessaging (12.2.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseInAppMessaging (~> 10.12.0-beta)
|
||||
- Firebase/Messaging (10.12.0):
|
||||
- FirebaseInAppMessaging (~> 12.2.0-beta)
|
||||
- Firebase/Messaging (12.2.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseMessaging (~> 10.12.0)
|
||||
- firebase_core (2.15.1):
|
||||
- Firebase/CoreOnly (= 10.12.0)
|
||||
- FirebaseMessaging (~> 12.2.0)
|
||||
- firebase_core (4.1.0):
|
||||
- Firebase/CoreOnly (= 12.2.0)
|
||||
- Flutter
|
||||
- firebase_in_app_messaging (0.7.3-5):
|
||||
- Firebase/InAppMessaging (= 10.12.0)
|
||||
- firebase_in_app_messaging (0.9.0-1):
|
||||
- Firebase/InAppMessaging (= 12.2.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- firebase_messaging (14.6.6):
|
||||
- Firebase/Messaging (= 10.12.0)
|
||||
- firebase_messaging (16.0.1):
|
||||
- Firebase/Messaging (= 12.2.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- FirebaseABTesting (10.13.0):
|
||||
- FirebaseCore (~> 10.0)
|
||||
- FirebaseCore (10.12.0):
|
||||
- FirebaseCoreInternal (~> 10.0)
|
||||
- GoogleUtilities/Environment (~> 7.8)
|
||||
- GoogleUtilities/Logger (~> 7.8)
|
||||
- FirebaseCoreInternal (10.13.0):
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.8)"
|
||||
- FirebaseInAppMessaging (10.12.0-beta):
|
||||
- FirebaseABTesting (~> 10.0)
|
||||
- FirebaseCore (~> 10.0)
|
||||
- FirebaseInstallations (~> 10.0)
|
||||
- GoogleUtilities/Environment (~> 7.8)
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- FirebaseInstallations (10.13.0):
|
||||
- FirebaseCore (~> 10.0)
|
||||
- GoogleUtilities/Environment (~> 7.8)
|
||||
- GoogleUtilities/UserDefaults (~> 7.8)
|
||||
- PromisesObjC (~> 2.1)
|
||||
- FirebaseMessaging (10.12.0):
|
||||
- FirebaseCore (~> 10.0)
|
||||
- FirebaseInstallations (~> 10.0)
|
||||
- GoogleDataTransport (~> 9.2)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
|
||||
- GoogleUtilities/Environment (~> 7.8)
|
||||
- GoogleUtilities/Reachability (~> 7.8)
|
||||
- GoogleUtilities/UserDefaults (~> 7.8)
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- FirebaseABTesting (12.2.0):
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- FirebaseCore (12.2.0):
|
||||
- FirebaseCoreInternal (~> 12.2.0)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/Logger (~> 8.1)
|
||||
- FirebaseCoreInternal (12.2.0):
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- FirebaseInAppMessaging (12.2.0-beta):
|
||||
- FirebaseABTesting (~> 12.2.0)
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- FirebaseInstallations (~> 12.2.0)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- FirebaseInstallations (12.2.0):
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
- PromisesObjC (~> 2.4)
|
||||
- FirebaseMessaging (12.2.0):
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- FirebaseInstallations (~> 12.2.0)
|
||||
- GoogleDataTransport (~> 10.1)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/Reachability (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- Flutter (1.0.0)
|
||||
- flutter_app_badger (1.3.0):
|
||||
- flutter_app_badge (2.0.0):
|
||||
- Flutter
|
||||
- flutter_local_notifications (0.0.1):
|
||||
- Flutter
|
||||
- flutter_native_splash (0.0.1):
|
||||
- flutter_native_splash (2.4.3):
|
||||
- Flutter
|
||||
- fluttertoast (0.0.2):
|
||||
- Flutter
|
||||
- Toast
|
||||
- FMDB (2.7.5):
|
||||
- FMDB/standard (= 2.7.5)
|
||||
- FMDB/standard (2.7.5)
|
||||
- GoogleDataTransport (9.2.5):
|
||||
- GoogleUtilities/Environment (~> 7.7)
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- PromisesObjC (< 3.0, >= 1.2)
|
||||
- GoogleUtilities/AppDelegateSwizzler (7.11.5):
|
||||
- GoogleDataTransport (10.1.0):
|
||||
- nanopb (~> 3.30910.0)
|
||||
- PromisesObjC (~> 2.4)
|
||||
- GoogleUtilities/AppDelegateSwizzler (8.1.0):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Network
|
||||
- GoogleUtilities/Environment (7.11.5):
|
||||
- PromisesObjC (< 3.0, >= 1.2)
|
||||
- GoogleUtilities/Logger (7.11.5):
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Environment (8.1.0):
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Logger (8.1.0):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Network (7.11.5):
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Network (8.1.0):
|
||||
- GoogleUtilities/Logger
|
||||
- "GoogleUtilities/NSData+zlib"
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Reachability
|
||||
- "GoogleUtilities/NSData+zlib (7.11.5)"
|
||||
- GoogleUtilities/Reachability (7.11.5):
|
||||
- "GoogleUtilities/NSData+zlib (8.1.0)":
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Privacy (8.1.0)
|
||||
- GoogleUtilities/Reachability (8.1.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/UserDefaults (7.11.5):
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/UserDefaults (8.1.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Privacy
|
||||
- image_picker_ios (0.0.1):
|
||||
- Flutter
|
||||
- in_app_review (2.0.0):
|
||||
- Flutter
|
||||
- libphonenumber_plugin (0.0.1):
|
||||
- Flutter
|
||||
- PhoneNumberKit
|
||||
- nanopb (2.30909.0):
|
||||
- nanopb/decode (= 2.30909.0)
|
||||
- nanopb/encode (= 2.30909.0)
|
||||
- nanopb/decode (2.30909.0)
|
||||
- nanopb/encode (2.30909.0)
|
||||
- package_info (0.0.1):
|
||||
- nanopb (3.30910.0):
|
||||
- nanopb/decode (= 3.30910.0)
|
||||
- nanopb/encode (= 3.30910.0)
|
||||
- nanopb/decode (3.30910.0)
|
||||
- nanopb/encode (3.30910.0)
|
||||
- open_filex (0.0.2):
|
||||
- Flutter
|
||||
- package_info_plus (0.4.5):
|
||||
- Flutter
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- PhoneNumberKit (3.6.7):
|
||||
- PhoneNumberKit/PhoneNumberKitCore (= 3.6.7)
|
||||
- PhoneNumberKit/UIKit (= 3.6.7)
|
||||
- PhoneNumberKit/PhoneNumberKitCore (3.6.7)
|
||||
- PhoneNumberKit/UIKit (3.6.7):
|
||||
- PhoneNumberKit (3.7.11):
|
||||
- PhoneNumberKit/PhoneNumberKitCore (= 3.7.11)
|
||||
- PhoneNumberKit/UIKit (= 3.7.11)
|
||||
- PhoneNumberKit/PhoneNumberKitCore (3.7.11)
|
||||
- PhoneNumberKit/UIKit (3.7.11):
|
||||
- PhoneNumberKit/PhoneNumberKitCore
|
||||
- PromisesObjC (2.3.1)
|
||||
- SDWebImage (5.17.0):
|
||||
- SDWebImage/Core (= 5.17.0)
|
||||
- SDWebImage/Core (5.17.0)
|
||||
- PromisesObjC (2.4.0)
|
||||
- SDWebImage (5.21.2):
|
||||
- SDWebImage/Core (= 5.21.2)
|
||||
- SDWebImage/Core (5.21.2)
|
||||
- share_plus (0.0.1):
|
||||
- Flutter
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- sqflite (0.0.3):
|
||||
- sqflite_darwin (0.0.4):
|
||||
- Flutter
|
||||
- FMDB (>= 2.7.5)
|
||||
- SwiftyGif (5.4.4)
|
||||
- FlutterMacOS
|
||||
- SwiftyGif (5.4.5)
|
||||
- syncfusion_flutter_pdfviewer (0.0.1):
|
||||
- Flutter
|
||||
- Toast (4.0.0)
|
||||
- url_launcher_ios (0.0.1):
|
||||
- Flutter
|
||||
|
||||
DEPENDENCIES:
|
||||
- better_open_file (from `.symlinks/plugins/better_open_file/ios`)
|
||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||
- emoji_picker_flutter (from `.symlinks/plugins/emoji_picker_flutter/ios`)
|
||||
- fast_rsa (from `.symlinks/plugins/fast_rsa/ios`)
|
||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||
- firebase_in_app_messaging (from `.symlinks/plugins/firebase_in_app_messaging/ios`)
|
||||
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- flutter_app_badger (from `.symlinks/plugins/flutter_app_badger/ios`)
|
||||
- flutter_app_badge (from `.symlinks/plugins/flutter_app_badge/ios`)
|
||||
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
|
||||
- libphonenumber_plugin (from `.symlinks/plugins/libphonenumber_plugin/ios`)
|
||||
- package_info (from `.symlinks/plugins/package_info/ios`)
|
||||
- open_filex (from `.symlinks/plugins/open_filex/ios`)
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- PhoneNumberKit (~> 3.7.6)
|
||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
||||
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
|
||||
- syncfusion_flutter_pdfviewer (from `.symlinks/plugins/syncfusion_flutter_pdfviewer/ios`)
|
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||
|
||||
@@ -194,7 +203,6 @@ SPEC REPOS:
|
||||
- FirebaseInAppMessaging
|
||||
- FirebaseInstallations
|
||||
- FirebaseMessaging
|
||||
- FMDB
|
||||
- GoogleDataTransport
|
||||
- GoogleUtilities
|
||||
- nanopb
|
||||
@@ -202,13 +210,14 @@ SPEC REPOS:
|
||||
- PromisesObjC
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- Toast
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
better_open_file:
|
||||
:path: ".symlinks/plugins/better_open_file/ios"
|
||||
connectivity_plus:
|
||||
:path: ".symlinks/plugins/connectivity_plus/ios"
|
||||
device_info_plus:
|
||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||
emoji_picker_flutter:
|
||||
:path: ".symlinks/plugins/emoji_picker_flutter/ios"
|
||||
fast_rsa:
|
||||
:path: ".symlinks/plugins/fast_rsa/ios"
|
||||
file_picker:
|
||||
@@ -221,74 +230,76 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/firebase_messaging/ios"
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
flutter_app_badger:
|
||||
:path: ".symlinks/plugins/flutter_app_badger/ios"
|
||||
flutter_app_badge:
|
||||
:path: ".symlinks/plugins/flutter_app_badge/ios"
|
||||
flutter_local_notifications:
|
||||
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
||||
flutter_native_splash:
|
||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||
fluttertoast:
|
||||
:path: ".symlinks/plugins/fluttertoast/ios"
|
||||
image_picker_ios:
|
||||
:path: ".symlinks/plugins/image_picker_ios/ios"
|
||||
in_app_review:
|
||||
:path: ".symlinks/plugins/in_app_review/ios"
|
||||
libphonenumber_plugin:
|
||||
:path: ".symlinks/plugins/libphonenumber_plugin/ios"
|
||||
package_info:
|
||||
:path: ".symlinks/plugins/package_info/ios"
|
||||
open_filex:
|
||||
:path: ".symlinks/plugins/open_filex/ios"
|
||||
package_info_plus:
|
||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||
path_provider_foundation:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
share_plus:
|
||||
:path: ".symlinks/plugins/share_plus/ios"
|
||||
shared_preferences_foundation:
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||
sqflite:
|
||||
:path: ".symlinks/plugins/sqflite/ios"
|
||||
sqflite_darwin:
|
||||
:path: ".symlinks/plugins/sqflite_darwin/darwin"
|
||||
syncfusion_flutter_pdfviewer:
|
||||
:path: ".symlinks/plugins/syncfusion_flutter_pdfviewer/ios"
|
||||
url_launcher_ios:
|
||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
better_open_file: 03cf320415d4d3f46b6e00adc4a567d76c1a399d
|
||||
device_info_plus: 7545d84d8d1b896cb16a4ff98c19f07ec4b298ea
|
||||
DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
|
||||
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
|
||||
fast_rsa: f696740d492d562e76f17b0a81dfc8ec3e635374
|
||||
file_picker: ce3938a0df3cc1ef404671531facef740d03f920
|
||||
Firebase: 07150e75d142fb9399f6777fa56a187b17f833a0
|
||||
firebase_core: 4a3246a02f828a01c74a2c26427037786d90f17f
|
||||
firebase_in_app_messaging: aebdbc10109a0ce44a3294f4ea57ed89ebe1d8bd
|
||||
firebase_messaging: 13b378c8449cae7ec96c79570170943dd73d4738
|
||||
FirebaseABTesting: 86ac5a4fc749088bb4d55a1cbfb2c4cb42c6d5de
|
||||
FirebaseCore: f86a1394906b97ac445ae49c92552a9425831bed
|
||||
FirebaseCoreInternal: b342e37cd4f5b4454ec34308f073420e7920858e
|
||||
FirebaseInAppMessaging: dc24f50aebaf81a377f0b8abf360778f94208931
|
||||
FirebaseInstallations: b28af1b9f997f1a799efe818c94695a3728c352f
|
||||
FirebaseMessaging: bb2c4f6422a753038fe137d90ae7c1af57251316
|
||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||
flutter_app_badger: b87fc231847b03b92ce1412aa351842e7e97932f
|
||||
flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
|
||||
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
|
||||
fluttertoast: fafc4fa4d01a6a9e4f772ecd190ffa525e9e2d9c
|
||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||
GoogleDataTransport: 54dee9d48d14580407f8f5fbf2f496e92437a2f2
|
||||
GoogleUtilities: 13e2c67ede716b8741c7989e26893d151b2b2084
|
||||
image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5
|
||||
libphonenumber_plugin: e8a7d64a6624a7c25f2c4ab0b7ead2a8e341e35e
|
||||
nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431
|
||||
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
PhoneNumberKit: 43b5169526cc417398c8f13f77c97552c1c6ed76
|
||||
PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4
|
||||
SDWebImage: 750adf017a315a280c60fde706ab1e552a3ae4e9
|
||||
share_plus: 599aa54e4ea31d4b4c0e9c911bcc26c55e791028
|
||||
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
|
||||
sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a
|
||||
SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
|
||||
syncfusion_flutter_pdfviewer: bb9998884b864cfedf72628df3503bdf57e397c0
|
||||
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
|
||||
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
|
||||
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
||||
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||
emoji_picker_flutter: ece213fc274bdddefb77d502d33080dc54e616cc
|
||||
fast_rsa: 8cf0f70421610bbe9462db881cdeef1cdd626153
|
||||
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
||||
Firebase: 26f6f8d460603af3df970ad505b16b15f5e2e9a1
|
||||
firebase_core: 3ff52146406557dddd01d570e807e203ec7e1302
|
||||
firebase_in_app_messaging: 42894eb8e92aa83ac58f1c534dc9f9f9546f23b9
|
||||
firebase_messaging: 3dcc998dd98e1e54af75d0cccae8606eba43553c
|
||||
FirebaseABTesting: 32f3fc079d72c9b93e000b60877c4e4f62ef7031
|
||||
FirebaseCore: 311c48a147ad4a0ab7febbaed89e8025c67510cd
|
||||
FirebaseCoreInternal: 56ea29f3dad2894f81b060f706f9d53509b6ed3b
|
||||
FirebaseInAppMessaging: fecba63d44c5cd8f874e9d661a5aa5047380c7d0
|
||||
FirebaseInstallations: 3e884b01feabdf67582a80f3250425a00979b4ed
|
||||
FirebaseMessaging: 43ec73bbfedd0c385a849bb91593ab4ad4b9e48e
|
||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||
flutter_app_badge: ca742dd659a157c1090ef7cd881cb78f48f3bcdf
|
||||
flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb
|
||||
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
|
||||
in_app_review: 5596fe56fab799e8edb3561c03d053363ab13457
|
||||
libphonenumber_plugin: d134f173b22bfa5ede50887071f087f309277f8c
|
||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||
open_filex: 432f3cd11432da3e39f47fcc0df2b1603854eff1
|
||||
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||
PhoneNumberKit: ced55861269312a5e3bc2ef82a58d6255b1c976a
|
||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||
SDWebImage: 9f177d83116802728e122410fb25ad88f5c7608a
|
||||
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
||||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||
syncfusion_flutter_pdfviewer: 90dc48305d2e33d4aa20681d1e98ddeda891bc14
|
||||
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
||||
|
||||
PODFILE CHECKSUM: 3d89a90682e2cd438911ad748b8ba5992f8b6a0e
|
||||
PODFILE CHECKSUM: e21c9d4c7b9623c73c6784ddc132fd50a603ad93
|
||||
|
||||
COCOAPODS: 1.12.1
|
||||
COCOAPODS: 1.16.2
|
||||
|
@@ -144,6 +144,7 @@
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
174B54D80220E5F588BD9737 /* [CP] Embed Pods Frameworks */,
|
||||
859FAB4E05FAC31B7B1A62D7 /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -161,7 +162,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastUpgradeCheck = 1430;
|
||||
LastUpgradeCheck = 1510;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
97C146ED1CF9000F007C117D = {
|
||||
@@ -237,6 +238,23 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||
};
|
||||
859FAB4E05FAC31B7B1A62D7 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
@@ -349,7 +367,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
@@ -434,7 +452,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -483,7 +501,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1430"
|
||||
LastUpgradeVersion = "1510"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
@@ -26,6 +26,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
@@ -43,11 +44,13 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
enableGPUValidationMode = "1"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import UIKit
|
||||
import Flutter
|
||||
|
||||
@UIApplicationMain
|
||||
@main
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
override func application(
|
||||
_ application: UIApplication,
|
||||
|
@@ -19,7 +19,7 @@ abstract class WebuntisApi extends ApiRequest {
|
||||
WebuntisApi(this.method, this.genericParam, {this.authenticatedResponse = true});
|
||||
|
||||
|
||||
Future<String> query(WebuntisApi untis) async {
|
||||
Future<String> query(WebuntisApi untis, {bool retry = false}) async {
|
||||
var query = '{"id":"ID","method":"$method","params":${untis._body()},"jsonrpc":"2.0"}';
|
||||
|
||||
var sessionId = '0';
|
||||
@@ -32,8 +32,9 @@ abstract class WebuntisApi extends ApiRequest {
|
||||
dynamic jsonData = jsonDecode(data.body);
|
||||
if(jsonData['error'] != null) {
|
||||
if(jsonData['error']['code'] == -8520) {
|
||||
if(retry) throw WebuntisError('Authentication was tried (probably session timeout), but was not successful!', 1);
|
||||
await Authenticate.createSession();
|
||||
this.query(untis);
|
||||
return await this.query(untis, retry: true);
|
||||
} else {
|
||||
throw WebuntisError(jsonData['error']['message'], jsonData['error']['code']);
|
||||
}
|
||||
|
@@ -24,7 +24,6 @@ import 'storage/base/settingsProvider.dart';
|
||||
import 'view/pages/overhang.dart';
|
||||
|
||||
class App extends StatefulWidget {
|
||||
static GlobalKey appContext = GlobalKey();
|
||||
const App({super.key});
|
||||
|
||||
@override
|
||||
@@ -32,6 +31,7 @@ class App extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _AppState extends State<App> with WidgetsBindingObserver {
|
||||
|
||||
late Timer refetchChats;
|
||||
late Timer updateTimings;
|
||||
|
||||
|
@@ -1,64 +0,0 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:background_fetch/background_fetch.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../app.dart';
|
||||
import '../homescreen_widgets/timetable/timetableHomeWidget.dart';
|
||||
|
||||
class ScheduledTask {
|
||||
static final String fetchApiLastRunTimestampKey = 'fetchApiLastRunTimestamp';
|
||||
|
||||
static Future<void> configure() async {
|
||||
var status = await BackgroundFetch.configure(BackgroundFetchConfig(
|
||||
minimumFetchInterval: 15,
|
||||
stopOnTerminate: false,
|
||||
enableHeadless: true,
|
||||
requiresBatteryNotLow: false,
|
||||
requiresCharging: false,
|
||||
requiresStorageNotLow: false,
|
||||
requiresDeviceIdle: false,
|
||||
requiredNetworkType: NetworkType.ANY,
|
||||
startOnBoot: true,
|
||||
), (String taskId) async {
|
||||
log('Background fetch started with id $taskId');
|
||||
await ScheduledTask.backgroundFetch();
|
||||
BackgroundFetch.finish(taskId);
|
||||
}, (String taskId) async {
|
||||
log('Background fetch stopped because of an timeout with id $taskId');
|
||||
BackgroundFetch.finish(taskId);
|
||||
});
|
||||
|
||||
log('Background Fetch-API status: $status');
|
||||
}
|
||||
|
||||
// called periodically, iOS and Android
|
||||
static Future<void> backgroundFetch() async {
|
||||
var sp = await SharedPreferences.getInstance();
|
||||
var history = sp.getStringList(fetchApiLastRunTimestampKey) ?? List.empty(growable: true);
|
||||
history.add(DateTime.now().toIso8601String());
|
||||
try {
|
||||
TimetableHomeWidget.update(App.appContext.currentContext!);
|
||||
} on Exception catch(e) {
|
||||
history.add('Got Error:');
|
||||
history.add(e.toString());
|
||||
history.add('--- EXCEPTION END ---');
|
||||
}
|
||||
sp.setStringList(fetchApiLastRunTimestampKey, history.take(100).toList());
|
||||
}
|
||||
|
||||
// only Android, starts when app is terminated
|
||||
@pragma('vm:entry-point')
|
||||
static Future<void> headless(HeadlessTask task) async {
|
||||
var taskId = task.taskId;
|
||||
var isTimeout = task.timeout;
|
||||
if (isTimeout) {
|
||||
log('Background fetch headless task timed-out: $taskId');
|
||||
BackgroundFetch.finish(taskId);
|
||||
return;
|
||||
}
|
||||
log('Background fetch headless event received.');
|
||||
await backgroundFetch();
|
||||
BackgroundFetch.finish(taskId);
|
||||
}
|
||||
}
|
@@ -1,88 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:home_widget/home_widget.dart';
|
||||
import 'package:screenshot/screenshot.dart';
|
||||
import 'package:syncfusion_flutter_calendar/calendar.dart';
|
||||
|
||||
import '../../model/accountData.dart';
|
||||
import '../../model/timetable/timetableProps.dart';
|
||||
import '../../storage/base/settingsProvider.dart';
|
||||
import '../../theming/darkAppTheme.dart';
|
||||
import '../../theming/lightAppTheme.dart';
|
||||
import '../../view/pages/timetable/calendar.dart';
|
||||
|
||||
class TimetableHomeWidget {
|
||||
static Future<void> update(BuildContext context) async {
|
||||
await AccountData().waitForPopulation();
|
||||
var data = TimetableProps();
|
||||
var settings = SettingsProvider();
|
||||
settings.waitForPopulation();
|
||||
var completer = Completer();
|
||||
|
||||
data.addListener(() async {
|
||||
if(completer.isCompleted) return;
|
||||
if(data.primaryLoading()) return;
|
||||
await _generate(data, settings);
|
||||
if(completer.isCompleted) return;
|
||||
completer.complete();
|
||||
});
|
||||
|
||||
data.run();
|
||||
await completer.future;
|
||||
}
|
||||
|
||||
static Future<void> _generate(TimetableProps data, SettingsProvider settings) async {
|
||||
log('Generating widget screen...');
|
||||
log('data: ${data.getTimetableResponse.toJson().toString().substring(0, 400)}...');
|
||||
var screenshotController = ScreenshotController();
|
||||
var calendarController = CalendarController();
|
||||
calendarController.displayDate = DateTime.now().copyWith(hour: 07, minute: 00);
|
||||
|
||||
var imageData = await screenshotController.captureFromWidget(
|
||||
SizedBox(
|
||||
height: 700,
|
||||
width: 300,
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: MediaQueryData(),
|
||||
child: MaterialApp(
|
||||
localizationsDelegates: const [
|
||||
...GlobalMaterialLocalizations.delegates,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
],
|
||||
supportedLocales: const [
|
||||
Locale('de'),
|
||||
Locale('en'),
|
||||
],
|
||||
locale: const Locale('de'),
|
||||
darkTheme: DarkAppTheme.theme,
|
||||
theme: LightAppTheme.theme,
|
||||
themeMode: settings.val().appTheme,
|
||||
home: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
child: Scaffold(
|
||||
body: Calendar(
|
||||
controller: calendarController,
|
||||
timetableProps: data,
|
||||
settings: settings,
|
||||
isHomeWidget: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
delay: Duration(seconds: 5),
|
||||
);
|
||||
|
||||
HomeWidget.saveWidgetData<String>('screen', base64.encode(imageData));
|
||||
HomeWidget.updateWidget(name: 'TimetableWidget');
|
||||
log('Widget screen successfully updated! (${imageData.length})');
|
||||
}
|
||||
}
|
@@ -2,7 +2,6 @@ import 'dart:async';
|
||||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:background_fetch/background_fetch.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@@ -18,7 +17,6 @@ import 'package:provider/provider.dart';
|
||||
|
||||
import 'api/mhsl/breaker/getBreakers/getBreakersResponse.dart';
|
||||
import 'app.dart';
|
||||
import 'background_tasks/scheduledTask.dart';
|
||||
import 'firebase_options.dart';
|
||||
import 'model/accountData.dart';
|
||||
import 'model/accountModel.dart';
|
||||
@@ -86,8 +84,6 @@ Future<void> main() async {
|
||||
child: const Main(),
|
||||
)
|
||||
);
|
||||
|
||||
BackgroundFetch.registerHeadlessTask(ScheduledTask.headless);
|
||||
}
|
||||
|
||||
class Main extends StatefulWidget {
|
||||
@@ -115,7 +111,6 @@ class _MainState extends State<Main> {
|
||||
Provider.of<BreakerProps>(context, listen: false).run();
|
||||
});
|
||||
|
||||
ScheduledTask.configure();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@@ -130,6 +125,7 @@ class _MainState extends State<Main> {
|
||||
checkerboardOffscreenLayers: devToolsSettings.checkerboardOffscreenLayers,
|
||||
checkerboardRasterCacheImages: devToolsSettings.checkerboardRasterCacheImages,
|
||||
|
||||
debugShowCheckedModeBanner: false,
|
||||
localizationsDelegates: const [
|
||||
...GlobalMaterialLocalizations.delegates,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
@@ -151,7 +147,7 @@ class _MainState extends State<Main> {
|
||||
child: Consumer<AccountModel>(
|
||||
builder: (context, accountModel, child) {
|
||||
switch(accountModel.state) {
|
||||
case AccountModelState.loggedIn: return App(key: App.appContext);
|
||||
case AccountModelState.loggedIn: return const App();
|
||||
case AccountModelState.loggedOut: return const Login();
|
||||
case AccountModelState.undefined: return const PlaceholderView(icon: Icons.timer, text: 'Daten werden geladen');
|
||||
}
|
||||
|
@@ -1,4 +1,3 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
import 'package:easy_debounce/easy_debounce.dart';
|
||||
@@ -14,8 +13,6 @@ class SettingsProvider extends ChangeNotifier {
|
||||
late SharedPreferences _storage;
|
||||
late Settings _settings = DefaultSettings.get();
|
||||
|
||||
final Completer<void> _populated = Completer();
|
||||
|
||||
Settings val({bool write = false}) {
|
||||
if(write) {
|
||||
notifyListeners();
|
||||
@@ -59,7 +56,6 @@ class SettingsProvider extends ChangeNotifier {
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
_populated.complete();
|
||||
}
|
||||
|
||||
Future<void> update() async {
|
||||
@@ -81,8 +77,4 @@ class SettingsProvider extends ChangeNotifier {
|
||||
|
||||
return mergedMap;
|
||||
}
|
||||
|
||||
Future<void> waitForPopulation() async {
|
||||
await _populated.future;
|
||||
}
|
||||
}
|
||||
|
@@ -1,287 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:syncfusion_flutter_calendar/calendar.dart';
|
||||
|
||||
import '../../../api/webuntis/queries/getHolidays/getHolidaysResponse.dart';
|
||||
import '../../../api/webuntis/queries/getTimetable/getTimetableResponse.dart';
|
||||
import '../../../extensions/dateTime.dart';
|
||||
import '../../../model/timetable/timetableProps.dart';
|
||||
import '../../../storage/base/settingsProvider.dart';
|
||||
import 'appointmenetComponent.dart';
|
||||
import 'appointmentDetails.dart';
|
||||
import 'arbitraryAppointment.dart';
|
||||
import 'customTimetableColors.dart';
|
||||
import 'timeRegionComponent.dart';
|
||||
import 'timetableEvents.dart';
|
||||
import 'timetableNameMode.dart';
|
||||
|
||||
class Calendar extends StatefulWidget {
|
||||
final CalendarController controller;
|
||||
final TimetableProps timetableProps;
|
||||
final SettingsProvider settings;
|
||||
final bool isHomeWidget;
|
||||
const Calendar({super.key, required this.controller, required this.timetableProps, required this.settings, this.isHomeWidget = false});
|
||||
|
||||
@override
|
||||
State<Calendar> createState() => _CalendarState();
|
||||
}
|
||||
|
||||
class _CalendarState extends State<Calendar> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var holidays = widget.timetableProps.getHolidaysResponse;
|
||||
return SfCalendar(
|
||||
timeZone: 'W. Europe Standard Time',
|
||||
view: widget.isHomeWidget ? CalendarView.day : CalendarView.workWeek,
|
||||
dataSource: _buildTableEvents(widget.timetableProps),
|
||||
|
||||
maxDate: DateTime.now().add(const Duration(days: 7)).nextWeekday(DateTime.saturday),
|
||||
minDate: DateTime.now().subtract(const Duration (days: 14)).nextWeekday(DateTime.sunday),
|
||||
|
||||
controller: widget.controller,
|
||||
|
||||
onViewChanged: (ViewChangedDetails details) {
|
||||
if(widget.isHomeWidget) return;
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
Provider.of<TimetableProps>(context, listen: false).updateWeek(details.visibleDates.first, details.visibleDates.last);
|
||||
});
|
||||
},
|
||||
|
||||
onTap: (calendarTapDetails) {
|
||||
if(calendarTapDetails.appointments == null) return;
|
||||
Appointment tapped = calendarTapDetails.appointments!.first;
|
||||
AppointmentDetails.show(context, widget.timetableProps, tapped);
|
||||
},
|
||||
|
||||
firstDayOfWeek: DateTime.monday,
|
||||
specialRegions: _buildSpecialTimeRegions(holidays),
|
||||
timeSlotViewSettings: TimeSlotViewSettings(
|
||||
startHour: widget.isHomeWidget ? 08 : 07.5,
|
||||
endHour: widget.isHomeWidget ? 16 : 16.5,
|
||||
timeInterval: Duration(minutes: 30),
|
||||
timeFormat: 'HH:mm',
|
||||
dayFormat: 'EE',
|
||||
timeIntervalHeight: 40,
|
||||
),
|
||||
|
||||
timeRegionBuilder: (BuildContext context, TimeRegionDetails timeRegionDetails) => TimeRegionComponent(details: timeRegionDetails),
|
||||
appointmentBuilder: (BuildContext context, CalendarAppointmentDetails details) => AppointmentComponent(
|
||||
details: details,
|
||||
crossedOut: _isCrossedOut(details)
|
||||
),
|
||||
|
||||
headerHeight: 0,
|
||||
selectionDecoration: const BoxDecoration(),
|
||||
|
||||
allowAppointmentResize: false,
|
||||
allowDragAndDrop: false,
|
||||
allowViewNavigation: false,
|
||||
);
|
||||
}
|
||||
|
||||
List<TimeRegion> _buildSpecialTimeRegions(GetHolidaysResponse holidays) {
|
||||
var lastMonday = DateTime.now().subtract(const Duration(days: 14)).nextWeekday(DateTime.monday);
|
||||
var firstBreak = lastMonday.copyWith(hour: 10, minute: 15);
|
||||
var secondBreak = lastMonday.copyWith(hour: 13, minute: 50);
|
||||
|
||||
var holidayList = holidays.result.map((holiday) {
|
||||
var startDay = _parseWebuntisTimestamp(holiday.startDate, 0);
|
||||
var dayCount = _parseWebuntisTimestamp(holiday.endDate, 0)
|
||||
.difference(startDay)
|
||||
.inDays;
|
||||
var days = List<DateTime>.generate(dayCount, (index) => startDay.add(Duration(days: index)));
|
||||
|
||||
return days.map((holidayDay) => TimeRegion(
|
||||
startTime: holidayDay.copyWith(hour: 07, minute: 55),
|
||||
endTime: holidayDay.copyWith(hour: 16, minute: 30),
|
||||
text: 'holiday:${holiday.name}',
|
||||
color: Theme
|
||||
.of(context)
|
||||
.disabledColor
|
||||
.withAlpha(50),
|
||||
iconData: Icons.holiday_village_outlined
|
||||
));
|
||||
}).expand((e) => e);
|
||||
|
||||
bool isInHoliday(DateTime time) => holidayList.any((element) => element.startTime.isSameDay(time));
|
||||
|
||||
return [
|
||||
...holidayList,
|
||||
|
||||
if(!isInHoliday(firstBreak))
|
||||
TimeRegion(
|
||||
startTime: firstBreak,
|
||||
endTime: firstBreak.add(const Duration(minutes: 20)),
|
||||
recurrenceRule: 'FREQ=DAILY;INTERVAL=1',
|
||||
text: 'centerIcon',
|
||||
color: Theme.of(context).primaryColor.withAlpha(50),
|
||||
iconData: Icons.restaurant
|
||||
),
|
||||
|
||||
if(!isInHoliday(secondBreak))
|
||||
TimeRegion(
|
||||
startTime: secondBreak,
|
||||
endTime: secondBreak.add(const Duration(minutes: 15)),
|
||||
recurrenceRule: 'FREQ=DAILY;INTERVAL=1',
|
||||
text: 'centerIcon',
|
||||
color: Theme.of(context).primaryColor.withAlpha(50),
|
||||
iconData: Icons.restaurant
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
List<GetTimetableResponseObject> _removeDuplicates(TimetableProps data, Duration maxTimeBetweenDouble) {
|
||||
|
||||
var timetableList = data.getTimetableResponse.result.toList();
|
||||
|
||||
if(timetableList.isEmpty) return timetableList;
|
||||
|
||||
timetableList.sort((a, b) => _parseWebuntisTimestamp(a.date, a.startTime).compareTo(_parseWebuntisTimestamp(b.date, b.startTime)));
|
||||
|
||||
var previousElement = timetableList.first;
|
||||
for(var i = 1; i < timetableList.length; i++) {
|
||||
var currentElement = timetableList.elementAt(i);
|
||||
|
||||
bool isSameLesson() {
|
||||
var currentSubjectId = currentElement.su.firstOrNull?.id;
|
||||
var previousSubjectId = previousElement.su.firstOrNull?.id;
|
||||
|
||||
if(currentSubjectId == null || previousSubjectId == null || currentSubjectId != previousSubjectId) return false;
|
||||
|
||||
var currentRoomId = currentElement.ro.firstOrNull?.id;
|
||||
var previousRoomId = previousElement.ro.firstOrNull?.id;
|
||||
|
||||
if(currentRoomId != previousRoomId) return false;
|
||||
|
||||
var currentTeacherId = currentElement.te.firstOrNull?.id;
|
||||
var previousTeacherId = previousElement.te.firstOrNull?.id;
|
||||
|
||||
if(currentTeacherId != previousTeacherId) return false;
|
||||
|
||||
var currentStatusCode = currentElement.code;
|
||||
var previousStatusCode = previousElement.code;
|
||||
|
||||
if(currentStatusCode != previousStatusCode) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isNotSeparated() => _parseWebuntisTimestamp(previousElement.date, previousElement.endTime).add(maxTimeBetweenDouble)
|
||||
.isSameOrAfter(_parseWebuntisTimestamp(currentElement.date, currentElement.startTime));
|
||||
|
||||
if(isSameLesson() && isNotSeparated()) {
|
||||
previousElement.endTime = currentElement.endTime;
|
||||
timetableList.remove(currentElement);
|
||||
i--;
|
||||
} else {
|
||||
previousElement = currentElement;
|
||||
}
|
||||
}
|
||||
|
||||
return timetableList;
|
||||
}
|
||||
|
||||
TimetableEvents _buildTableEvents(TimetableProps data) {
|
||||
|
||||
var timetableList = data.getTimetableResponse.result.toList();
|
||||
|
||||
if(widget.settings.val().timetableSettings.connectDoubleLessons) {
|
||||
timetableList = _removeDuplicates(data, const Duration(minutes: 5));
|
||||
}
|
||||
|
||||
var appointments = timetableList.map((element) {
|
||||
|
||||
var rooms = data.getRoomsResponse;
|
||||
var subjects = data.getSubjectsResponse;
|
||||
|
||||
try {
|
||||
var startTime = _parseWebuntisTimestamp(element.date, element.startTime);
|
||||
var endTime = _parseWebuntisTimestamp(element.date, element.endTime);
|
||||
|
||||
var subject = subjects.result.firstWhere((subject) => subject.id == element.su[0].id);
|
||||
var subjectName = {
|
||||
TimetableNameMode.name: subject.name,
|
||||
TimetableNameMode.longName: subject.longName,
|
||||
TimetableNameMode.alternateName: subject.alternateName,
|
||||
}[widget.settings.val().timetableSettings.timetableNameMode];
|
||||
|
||||
|
||||
return Appointment(
|
||||
id: ArbitraryAppointment(webuntis: element),
|
||||
startTime: startTime,
|
||||
endTime: endTime,
|
||||
subject: subjectName!,
|
||||
location: ''
|
||||
'${rooms.result.firstWhere((room) => room.id == element.ro[0].id).name}'
|
||||
'\n'
|
||||
'${element.te.first.longname}',
|
||||
notes: element.activityType,
|
||||
color: _getEventColor(element, startTime, endTime),
|
||||
);
|
||||
} catch(e) {
|
||||
var endTime = _parseWebuntisTimestamp(element.date, element.endTime);
|
||||
return Appointment(
|
||||
id: ArbitraryAppointment(webuntis: element),
|
||||
startTime: _parseWebuntisTimestamp(element.date, element.startTime),
|
||||
endTime: endTime,
|
||||
subject: 'Änderung',
|
||||
notes: element.info,
|
||||
location: 'Unbekannt',
|
||||
color: endTime.isBefore(DateTime.now()) ? Theme.of(context).primaryColor.withAlpha(100) : Theme.of(context).primaryColor,
|
||||
startTimeZone: '',
|
||||
endTimeZone: '',
|
||||
);
|
||||
}
|
||||
}).toList();
|
||||
|
||||
appointments.addAll(data.getCustomTimetableEventResponse.events.map((customEvent) => Appointment(
|
||||
id: ArbitraryAppointment(custom: customEvent),
|
||||
startTime: customEvent.startDate,
|
||||
endTime: customEvent.endDate,
|
||||
location: customEvent.description,
|
||||
subject: customEvent.title,
|
||||
recurrenceRule: customEvent.rrule,
|
||||
color: TimetableColors.getColorFromString(customEvent.color ?? TimetableColors.defaultColor.name),
|
||||
startTimeZone: '',
|
||||
endTimeZone: '',
|
||||
)));
|
||||
|
||||
return TimetableEvents(appointments);
|
||||
}
|
||||
|
||||
DateTime _parseWebuntisTimestamp(int date, int time) {
|
||||
var timeString = time.toString().padLeft(4, '0');
|
||||
return DateTime.parse('$date ${timeString.substring(0, 2)}:${timeString.substring(2, 4)}');
|
||||
}
|
||||
|
||||
Color _getEventColor(GetTimetableResponseObject webuntisElement, DateTime startTime, DateTime endTime) {
|
||||
// Make element darker, when it already took place
|
||||
var alpha = endTime.isBefore(DateTime.now()) ? 100 : 255;
|
||||
|
||||
// Cancelled
|
||||
if(webuntisElement.code == 'cancelled') return const Color(0xff000000).withAlpha(alpha);
|
||||
|
||||
// Any changes or no teacher at this element
|
||||
if(webuntisElement.code == 'irregular' || webuntisElement.te.first.id == 0) return const Color(0xff8F19B3).withAlpha(alpha);
|
||||
|
||||
// Teacher has changed
|
||||
if(webuntisElement.te.any((element) => element.orgname != null)) return const Color(0xFF29639B).withAlpha(alpha);
|
||||
|
||||
// Event was in the past
|
||||
if(endTime.isBefore(DateTime.now())) return Theme.of(context).primaryColor.withAlpha(alpha);
|
||||
|
||||
// Event takes currently place
|
||||
if(endTime.isAfter(DateTime.now()) && startTime.isBefore(DateTime.now())) return Theme.of(context).primaryColor.withRed(200);
|
||||
|
||||
// Fallback
|
||||
return Theme.of(context).primaryColor.withAlpha(alpha);
|
||||
}
|
||||
|
||||
bool _isCrossedOut(CalendarAppointmentDetails calendarEntry) {
|
||||
var appointment = calendarEntry.appointments.first.id as ArbitraryAppointment;
|
||||
if(appointment.hasWebuntis()) {
|
||||
return appointment.webuntis!.code == 'cancelled';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -2,21 +2,22 @@ import 'dart:async';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../extensions/dateTime.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:syncfusion_flutter_calendar/calendar.dart';
|
||||
|
||||
import '../../../api/webuntis/queries/getHolidays/getHolidaysResponse.dart';
|
||||
import '../../../api/webuntis/queries/getTimetable/getTimetableResponse.dart';
|
||||
import '../../../extensions/dateTime.dart';
|
||||
import '../../../homescreen_widgets/timetable/timetableHomeWidget.dart';
|
||||
import '../../../model/timetable/timetableProps.dart';
|
||||
import '../../../storage/base/settingsProvider.dart';
|
||||
import '../../../widget/loadingSpinner.dart';
|
||||
import '../../../widget/placeholderView.dart';
|
||||
import 'appointmenetComponent.dart';
|
||||
import 'appointmentDetails.dart';
|
||||
import 'arbitraryAppointment.dart';
|
||||
import 'calendar.dart';
|
||||
import 'customTimetableColors.dart';
|
||||
import 'customTimetableEventEditDialog.dart';
|
||||
import 'timeRegionComponent.dart';
|
||||
import 'timetableEvents.dart';
|
||||
import 'timetableNameMode.dart';
|
||||
import 'viewCustomTimetableEvents.dart';
|
||||
@@ -33,7 +34,7 @@ enum CalendarActions { addEvent, viewEvents }
|
||||
class _TimetableState extends State<Timetable> {
|
||||
CalendarController controller = CalendarController();
|
||||
late Timer updateTimings;
|
||||
late SettingsProvider settings;
|
||||
late final SettingsProvider settings;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -55,7 +56,6 @@ class _TimetableState extends State<Timetable> {
|
||||
appBar: AppBar(
|
||||
title: const Text('Stunden & Vertretungsplan'),
|
||||
actions: [
|
||||
IconButton(onPressed: () => TimetableHomeWidget.update(context), icon: Icon(Icons.screen_share_outlined)),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.home_outlined),
|
||||
onPressed: () {
|
||||
@@ -119,19 +119,62 @@ class _TimetableState extends State<Timetable> {
|
||||
|
||||
if(value.primaryLoading()) return const LoadingSpinner();
|
||||
|
||||
var holidays = value.getHolidaysResponse;
|
||||
|
||||
return RefreshIndicator(
|
||||
child: Calendar(
|
||||
controller: controller,
|
||||
timetableProps: value,
|
||||
settings: settings,
|
||||
),
|
||||
onRefresh: () async {
|
||||
Provider.of<TimetableProps>(context, listen: false).run(renew: true);
|
||||
return Future.delayed(const Duration(seconds: 3));
|
||||
}
|
||||
);
|
||||
child: SfCalendar(
|
||||
timeZone: 'W. Europe Standard Time',
|
||||
view: CalendarView.workWeek,
|
||||
dataSource: _buildTableEvents(value),
|
||||
|
||||
maxDate: DateTime.now().add(const Duration(days: 7)).nextWeekday(DateTime.saturday),
|
||||
minDate: DateTime.now().subtract(const Duration (days: 14)).nextWeekday(DateTime.sunday),
|
||||
|
||||
controller: controller,
|
||||
|
||||
onViewChanged: (ViewChangedDetails details) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
Provider.of<TimetableProps>(context, listen: false).updateWeek(details.visibleDates.first, details.visibleDates.last);
|
||||
});
|
||||
},
|
||||
|
||||
onTap: (calendarTapDetails) {
|
||||
if(calendarTapDetails.appointments == null) return;
|
||||
Appointment tapped = calendarTapDetails.appointments!.first;
|
||||
AppointmentDetails.show(context, value, tapped);
|
||||
},
|
||||
|
||||
firstDayOfWeek: DateTime.monday,
|
||||
specialRegions: _buildSpecialTimeRegions(holidays),
|
||||
timeSlotViewSettings: const TimeSlotViewSettings(
|
||||
startHour: 07.5,
|
||||
endHour: 16.5,
|
||||
timeInterval: Duration(minutes: 30),
|
||||
timeFormat: 'HH:mm',
|
||||
dayFormat: 'EE',
|
||||
timeIntervalHeight: 40,
|
||||
),
|
||||
|
||||
timeRegionBuilder: (BuildContext context, TimeRegionDetails timeRegionDetails) => TimeRegionComponent(details: timeRegionDetails),
|
||||
appointmentBuilder: (BuildContext context, CalendarAppointmentDetails details) => AppointmentComponent(
|
||||
details: details,
|
||||
crossedOut: _isCrossedOut(details)
|
||||
),
|
||||
|
||||
headerHeight: 0,
|
||||
selectionDecoration: const BoxDecoration(),
|
||||
|
||||
allowAppointmentResize: false,
|
||||
allowDragAndDrop: false,
|
||||
allowViewNavigation: false,
|
||||
),
|
||||
onRefresh: () async {
|
||||
Provider.of<TimetableProps>(context, listen: false).run(renew: true);
|
||||
return Future.delayed(const Duration(seconds: 3));
|
||||
}
|
||||
);
|
||||
},
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
@override
|
||||
|
@@ -1,18 +1,14 @@
|
||||
|
||||
import 'package:background_fetch/background_fetch.dart';
|
||||
import 'package:filesize/filesize.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../../background_tasks/scheduledTask.dart';
|
||||
import '../../storage/base/settingsProvider.dart';
|
||||
import '../../widget/centeredLeading.dart';
|
||||
import '../../widget/confirmDialog.dart';
|
||||
import '../../widget/debug/cacheView.dart';
|
||||
import '../../widget/debug/jsonViewer.dart';
|
||||
import '../../widget/infoDialog.dart';
|
||||
|
||||
class DevToolsSettings extends StatefulWidget {
|
||||
final SettingsProvider settings;
|
||||
@@ -26,84 +22,6 @@ class _DevToolsSettingsState extends State<DevToolsSettings> {
|
||||
@override
|
||||
Widget build(BuildContext context) => Column(
|
||||
children: [
|
||||
ListTile(
|
||||
leading: const CenteredLeading(Icon(Icons.task_outlined)),
|
||||
title: const Text('Background app fetch task'),
|
||||
trailing: const Icon(Icons.arrow_right),
|
||||
onTap: () {
|
||||
showDialog(context: context, builder: (context) => AlertDialog(
|
||||
title: Text('Background fetch task'),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
FutureBuilder(future: BackgroundFetch.status, builder: (context, snapshot) {
|
||||
if(snapshot.hasData) {
|
||||
var fetchStatus = switch(snapshot.data) {
|
||||
BackgroundFetch.STATUS_AVAILABLE => 'STATUS_AVAILABLE, Background updates are available for the app.',
|
||||
BackgroundFetch.STATUS_DENIED => 'STATUS_DENIED, The user explicitly disabled background behavior for this app or for the whole system.',
|
||||
BackgroundFetch.STATUS_RESTRICTED => 'STATUS_RESTRICTED, Background updates are unavailable and the user cannot enable them again. For example, this status can occur when parental controls are in effect for the current user.',
|
||||
_ => 'UNKNOWN',
|
||||
};
|
||||
return Text('(${snapshot.data}): $fetchStatus');
|
||||
}
|
||||
return LinearProgressIndicator();
|
||||
}),
|
||||
const Divider(),
|
||||
const Text('There is no indicator if the Fetch-API is currently running or not!'),
|
||||
const Divider(),
|
||||
FutureBuilder(
|
||||
future: SharedPreferences.getInstance(),
|
||||
builder: (context, snapshot) {
|
||||
if(!snapshot.hasData) return LinearProgressIndicator();
|
||||
return Text('Last fetch timestamp: ${snapshot.data?.getStringList(ScheduledTask.fetchApiLastRunTimestampKey)?.last ?? 'No entry'}');
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
FutureBuilder(future: SharedPreferences.getInstance(), builder: (context, snapshot) {
|
||||
if(!snapshot.hasData) return LinearProgressIndicator();
|
||||
return TextButton(
|
||||
onPressed: () {
|
||||
InfoDialog.show(
|
||||
context,
|
||||
(snapshot.data!.getStringList(ScheduledTask.fetchApiLastRunTimestampKey) ?? []).reversed.join('\n')
|
||||
);
|
||||
},
|
||||
child: Text('Fetch history')
|
||||
);
|
||||
}),
|
||||
TextButton(
|
||||
onPressed: () => ConfirmDialog(
|
||||
title: 'Warning',
|
||||
content: 'Background Fetch worker will be started! This basically happens on every app startup.',
|
||||
onConfirm: BackgroundFetch.start
|
||||
).asDialog(context),
|
||||
child: Text('Fetch-API Start')
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => ConfirmDialog(
|
||||
title: 'Warning',
|
||||
content: 'Background Fetch worker will be terminated. This will result in outdated Information when App is not in foreground!',
|
||||
onConfirm: BackgroundFetch.stop
|
||||
).asDialog(context),
|
||||
child: Text('Fetch-API Stop')
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => ConfirmDialog(
|
||||
title: 'Warning',
|
||||
content: 'Background fetch will run now! This happens in the application layer and does not interact with the Fetch-API!',
|
||||
confirmButton: 'Run',
|
||||
onConfirm: ScheduledTask.backgroundFetch
|
||||
).asDialog(context),
|
||||
child: Text('Run task manually')
|
||||
),
|
||||
TextButton(onPressed: () => Navigator.of(context).pop(), child: Text('Zurück'))
|
||||
],
|
||||
));
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const CenteredLeading(Icon(Icons.speed_outlined)),
|
||||
title: const Text('Performance overlays'),
|
||||
|
@@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions while build-number is used as the build suffix.
|
||||
version: 0.1.5+43
|
||||
version: 0.1.4+42
|
||||
|
||||
environment:
|
||||
sdk: '>3.0.0'
|
||||
@@ -102,9 +102,6 @@ dependencies:
|
||||
uuid: ^4.5.1
|
||||
open_filex: ^4.7.0
|
||||
collection: ^1.19.0
|
||||
home_widget: ^0.7.0+1
|
||||
screenshot: ^3.0.0
|
||||
background_fetch: ^1.3.7
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Reference in New Issue
Block a user