16
.gitignore
vendored
@ -1,5 +1,7 @@
|
|||||||
# See https://www.dartlang.org/guides/libraries/private-files
|
# See https://www.dartlang.org/guides/libraries/private-files
|
||||||
|
|
||||||
|
.gitignore
|
||||||
|
|
||||||
termek.txt
|
termek.txt
|
||||||
.DS_Store
|
.DS_Store
|
||||||
filc3.properties
|
filc3.properties
|
||||||
@ -25,9 +27,6 @@ doc/api/
|
|||||||
*.js.map
|
*.js.map
|
||||||
|
|
||||||
*.txt
|
*.txt
|
||||||
filcnaplo/linux/flutter/generated_plugin_registrant.cc
|
|
||||||
filcnaplo/linux/flutter/generated_plugin_registrant.h
|
|
||||||
filcnaplo/linux/flutter/generated_plugins.cmake
|
|
||||||
filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift
|
filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift
|
||||||
filcnaplo/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus
|
filcnaplo/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus
|
||||||
filcnaplo/windows/flutter/ephemeral/.plugin_symlinks/dynamic_color
|
filcnaplo/windows/flutter/ephemeral/.plugin_symlinks/dynamic_color
|
||||||
@ -43,10 +42,9 @@ filcnaplo/windows/flutter/generated_plugins.cmake
|
|||||||
filcnaplo/linux/flutter/generated_plugin_registrant.cc
|
filcnaplo/linux/flutter/generated_plugin_registrant.cc
|
||||||
filcnaplo/linux/flutter/generated_plugin_registrant.h
|
filcnaplo/linux/flutter/generated_plugin_registrant.h
|
||||||
filcnaplo/linux/flutter/generated_plugins.cmake
|
filcnaplo/linux/flutter/generated_plugins.cmake
|
||||||
filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift
|
filcnaplo/macos/Flutter/*
|
||||||
filcnaplo/linux/flutter/generated_plugin_registrant.cc
|
filcnaplo/ios/Podfile.lock
|
||||||
filcnaplo/linux/flutter/generated_plugin_registrant.h
|
|
||||||
filcnaplo/linux/flutter/generated_plugins.cmake
|
|
||||||
filcnaplo/macos/Flutter/GeneratedPluginRegistrant.swift
|
|
||||||
.vscode/
|
.vscode/
|
||||||
key.properties
|
key.properties
|
||||||
|
|
||||||
|
.flutter-plugins*
|
||||||
|
1286
.idea/libraries/Dart_Packages.xml
generated
Normal file
27
.idea/libraries/Dart_SDK.xml
generated
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<component name="libraryTable">
|
||||||
|
<library name="Dart SDK">
|
||||||
|
<CLASSES>
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/async" />
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/cli" />
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/collection" />
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/convert" />
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/core" />
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/developer" />
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/ffi" />
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/html" />
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/indexed_db" />
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/io" />
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/isolate" />
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/js" />
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/js_util" />
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/math" />
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/mirrors" />
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/svg" />
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/typed_data" />
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/web_audio" />
|
||||||
|
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/web_gl" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES />
|
||||||
|
</library>
|
||||||
|
</component>
|
4
.idea/misc.xml
generated
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Android API 33, extension level 3 Platform" project-jdk-type="Android SDK" />
|
||||||
|
</project>
|
@ -12,7 +12,7 @@
|
|||||||
### Clone the project
|
### Clone the project
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone --recursive https://github.com/refilc/naplo
|
git clone https://github.com/refilc/naplo
|
||||||
cd naplo
|
cd naplo
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -2,12 +2,14 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools" package="hu.refilc.naplo">
|
xmlns:tools="http://schemas.android.com/tools" package="hu.refilc.naplo">
|
||||||
<application android:name="${applicationName}" android:label="reFilc" tools:replace="android:label" android:icon="@mipmap/ic_launcher"
|
<application android:name="${applicationName}" android:label="reFilc" tools:replace="android:label" android:icon="@mipmap/ic_launcher"
|
||||||
android:requestLegacyExternalStorage="true">
|
android:requestLegacyExternalStorage="true">
|
||||||
<activity android:exported="true" android:name=".MainActivity"
|
<activity android:exported="true" android:name="hu.refilc.naplo.MainActivity"
|
||||||
android:launchMode="singleTop" android:theme="@style/LaunchTheme"
|
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:windowSoftInputMode="adjustResize"
|
android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize"
|
||||||
android:showWhenLocked="true"
|
android:showWhenLocked="true"
|
||||||
android:turnScreenOn="true">
|
android:turnScreenOn="true">
|
||||||
|
<meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable"
|
||||||
|
android:resource="@drawable/launch_background" />
|
||||||
<meta-data android:name="io.flutter.embedding.android.NormalTheme"
|
<meta-data android:name="io.flutter.embedding.android.NormalTheme"
|
||||||
android:resource="@style/NormalTheme" />
|
android:resource="@style/NormalTheme" />
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@ -18,16 +20,26 @@
|
|||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<category android:name="android.intent.category.BROWSABLE" />
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
<!-- Accepts URIs that begin with https://api.filcnaplo.hu -->
|
<!-- Accepts URIs that begin with https://api.refilcapp.hu -->
|
||||||
<data
|
<data
|
||||||
android:scheme="https"
|
android:scheme="https"
|
||||||
android:host="api.filcnaplo.hu"
|
android:host="api.refilcapp.hu"
|
||||||
android:pathPrefix="/callback" />
|
android:pathPrefix="/v1/auth/callback" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter android:autoVerify="true">
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<!-- Accepts URIs that begin with https://refilc.hu -->
|
||||||
|
<data
|
||||||
|
android:scheme="https"
|
||||||
|
android:host="refilc.hu"
|
||||||
|
android:pathPrefix="/app" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<meta-data android:name="flutterEmbedding" android:value="2" />
|
<meta-data android:name="flutterEmbedding" android:value="2" />
|
||||||
|
|
||||||
<receiver android:name=".widget_timetable.WidgetTimetable"
|
<receiver android:name="hu.refilc.naplo.widget_timetable.WidgetTimetable"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
@ -43,7 +55,7 @@
|
|||||||
android:resource="@xml/home_widget_test_info" />
|
android:resource="@xml/home_widget_test_info" />
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<service android:name=".widget_timetable.WidgetTimetableService"
|
<service android:name="hu.refilc.naplo.widget_timetable.WidgetTimetableService"
|
||||||
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||||
|
|
||||||
<receiver android:name="es.antonborri.home_widget.HomeWidgetBackgroundReceiver"
|
<receiver android:name="es.antonborri.home_widget.HomeWidgetBackgroundReceiver"
|
||||||
@ -57,6 +69,8 @@
|
|||||||
android:permission="android.permission.BIND_JOB_SERVICE" android:exported="true" />
|
android:permission="android.permission.BIND_JOB_SERVICE" android:exported="true" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
<meta-data android:name="flutterEmbedding" android:value="2" />
|
||||||
|
|
||||||
<!-- Permissions -->
|
<!-- Permissions -->
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
@ -1 +0,0 @@
|
|||||||
../../../../../../../../../filcnaplo_premium/android/database
|
|
@ -1 +0,0 @@
|
|||||||
../../../../../../../../../filcnaplo_premium/android/utils
|
|
@ -1 +0,0 @@
|
|||||||
../../../../../../../../../filcnaplo_premium/android/widget_timetable
|
|
@ -1,9 +1,7 @@
|
|||||||
package hu.refilc.naplo;
|
package hu.refilc.naplo;
|
||||||
|
|
||||||
import io.flutter.embedding.android.FlutterActivity;
|
import io.flutter.embedding.android.FlutterActivity;
|
||||||
|
|
||||||
import io.flutter.embedding.engine.FlutterEngine;
|
public class MainActivity extends FlutterActivity {
|
||||||
|
|
||||||
public class MainActivity extends FlutterActivity {
|
}
|
||||||
|
|
||||||
}
|
|
@ -1,119 +1,119 @@
|
|||||||
package hu.refilc.naplo.database;
|
package hu.refilc.naplo.database;
|
||||||
|
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
import hu.refilc.naplo.database.SQLiteHelper;
|
import hu.refilc.naplo.database.SQLiteHelper;
|
||||||
|
|
||||||
public class DBManager {
|
public class DBManager {
|
||||||
private Context context;
|
private Context context;
|
||||||
private SQLiteDatabase database;
|
private SQLiteDatabase database;
|
||||||
private SQLiteHelper dbHelper;
|
private SQLiteHelper dbHelper;
|
||||||
|
|
||||||
public DBManager(Context c) {
|
public DBManager(Context c) {
|
||||||
this.context = c;
|
this.context = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DBManager open() throws SQLException {
|
public DBManager open() throws SQLException {
|
||||||
this.dbHelper = new SQLiteHelper(this.context);
|
this.dbHelper = new SQLiteHelper(this.context);
|
||||||
this.database = this.dbHelper.getWritableDatabase();
|
this.database = this.dbHelper.getWritableDatabase();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
this.dbHelper.close();
|
this.dbHelper.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cursor fetchWidget(int wid) {
|
public Cursor fetchWidget(int wid) {
|
||||||
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_WIDGETS, new String[]{SQLiteHelper._ID, SQLiteHelper.DAY_SEL}, SQLiteHelper._ID + " = " + wid, null, null, null, null);
|
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_WIDGETS, new String[]{SQLiteHelper._ID, SQLiteHelper.DAY_SEL}, SQLiteHelper._ID + " = " + wid, null, null, null, null);
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
cursor.moveToFirst();
|
cursor.moveToFirst();
|
||||||
}
|
}
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cursor fetchTimetable() {
|
public Cursor fetchTimetable() {
|
||||||
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_USER_DATA, new String[]{SQLiteHelper.TIMETABLE}, null, null, null, null, null);
|
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_USER_DATA, new String[]{SQLiteHelper.TIMETABLE}, null, null, null, null, null);
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
cursor.moveToFirst();
|
cursor.moveToFirst();
|
||||||
}
|
}
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cursor fetchLastUser() {
|
public Cursor fetchLastUser() {
|
||||||
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_SETTINGS, new String[]{SQLiteHelper.LAST_ACCOUNT_ID}, null, null, null, null, null);
|
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_SETTINGS, new String[]{SQLiteHelper.LAST_ACCOUNT_ID}, null, null, null, null, null);
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
cursor.moveToFirst();
|
cursor.moveToFirst();
|
||||||
}
|
}
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cursor fetchTheme() {
|
public Cursor fetchTheme() {
|
||||||
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_SETTINGS, new String[]{SQLiteHelper.THEME, SQLiteHelper.ACCENT_COLOR}, null, null, null, null, null);
|
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_SETTINGS, new String[]{SQLiteHelper.THEME, SQLiteHelper.ACCENT_COLOR}, null, null, null, null, null);
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
cursor.moveToFirst();
|
cursor.moveToFirst();
|
||||||
}
|
}
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cursor fetchPremiumToken() {
|
public Cursor fetchPremiumToken() {
|
||||||
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_SETTINGS, new String[]{SQLiteHelper.PREMIUM_TOKEN}, null, null, null, null, null);
|
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_SETTINGS, new String[]{SQLiteHelper.PREMIUM_TOKEN}, null, null, null, null, null);
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
cursor.moveToFirst();
|
cursor.moveToFirst();
|
||||||
}
|
}
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cursor fetchPremiumScopes() {
|
public Cursor fetchPremiumScopes() {
|
||||||
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_SETTINGS, new String[]{SQLiteHelper.PREMIUM_SCOPES}, null, null, null, null, null);
|
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_SETTINGS, new String[]{SQLiteHelper.PREMIUM_SCOPES}, null, null, null, null, null);
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
cursor.moveToFirst();
|
cursor.moveToFirst();
|
||||||
}
|
}
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cursor fetchLocale() {
|
public Cursor fetchLocale() {
|
||||||
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_SETTINGS, new String[]{SQLiteHelper.LOCALE}, null, null, null, null, null);
|
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_SETTINGS, new String[]{SQLiteHelper.LOCALE}, null, null, null, null, null);
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
cursor.moveToFirst();
|
cursor.moveToFirst();
|
||||||
}
|
}
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteWidget(int _id) {
|
public void deleteWidget(int _id) {
|
||||||
this.database.delete(SQLiteHelper.TABLE_NAME_WIDGETS, "_id=" + _id, null);
|
this.database.delete(SQLiteHelper.TABLE_NAME_WIDGETS, "_id=" + _id, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*public void changeSettings(int _id, Map<String, String> map) {
|
/*public void changeSettings(int _id, Map<String, String> map) {
|
||||||
ContentValues con = new ContentValues();
|
ContentValues con = new ContentValues();
|
||||||
for(Map.Entry<String, String> e: map.entrySet()){
|
for(Map.Entry<String, String> e: map.entrySet()){
|
||||||
con.put(e.getKey(), e.getValue());
|
con.put(e.getKey(), e.getValue());
|
||||||
}
|
}
|
||||||
this.database.update(SQLiteHelper.TABLE_NAME_WIDGETS, con, "_id = " + _id, null);
|
this.database.update(SQLiteHelper.TABLE_NAME_WIDGETS, con, "_id = " + _id, null);
|
||||||
}
|
}
|
||||||
public void insertSettings(int _id, Map<String, String> map) {
|
public void insertSettings(int _id, Map<String, String> map) {
|
||||||
ContentValues con = new ContentValues();
|
ContentValues con = new ContentValues();
|
||||||
for(Map.Entry<String, String> e: map.entrySet()){
|
for(Map.Entry<String, String> e: map.entrySet()){
|
||||||
con.put(e.getKey(), e.getValue());
|
con.put(e.getKey(), e.getValue());
|
||||||
//Log.d("Settings added", e.getKey() + " - " + e.getValue());
|
//Log.d("Settings added", e.getKey() + " - " + e.getValue());
|
||||||
}
|
}
|
||||||
this.database.insert(SQLiteHelper.TABLE_NAME_WIDGETS, null, con);
|
this.database.insert(SQLiteHelper.TABLE_NAME_WIDGETS, null, con);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
public void insertSelDay(int _id, int day_sel) {
|
public void insertSelDay(int _id, int day_sel) {
|
||||||
ContentValues con = new ContentValues();
|
ContentValues con = new ContentValues();
|
||||||
con.put(SQLiteHelper._ID, _id);
|
con.put(SQLiteHelper._ID, _id);
|
||||||
con.put(SQLiteHelper.DAY_SEL, day_sel);
|
con.put(SQLiteHelper.DAY_SEL, day_sel);
|
||||||
this.database.insert(SQLiteHelper.TABLE_NAME_WIDGETS, null, con);
|
this.database.insert(SQLiteHelper.TABLE_NAME_WIDGETS, null, con);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int update(int _id, int day_sel) {
|
public int update(int _id, int day_sel) {
|
||||||
ContentValues con = new ContentValues();
|
ContentValues con = new ContentValues();
|
||||||
con.put(SQLiteHelper.DAY_SEL, day_sel);
|
con.put(SQLiteHelper.DAY_SEL, day_sel);
|
||||||
return this.database.update(SQLiteHelper.TABLE_NAME_WIDGETS, con, SQLiteHelper._ID + " = " + _id, null);
|
return this.database.update(SQLiteHelper.TABLE_NAME_WIDGETS, con, SQLiteHelper._ID + " = " + _id, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,36 +1,36 @@
|
|||||||
package hu.refilc.naplo.database;
|
package hu.refilc.naplo.database;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
|
||||||
public class SQLiteHelper extends SQLiteOpenHelper {
|
public class SQLiteHelper extends SQLiteOpenHelper {
|
||||||
private static final String CREATE_TABLE_WIDGET = " create table widgets ( _id INTEGER NOT NULL, day_sel INTEGER NOT NULL);";
|
private static final String CREATE_TABLE_WIDGET = " create table widgets ( _id INTEGER NOT NULL, day_sel INTEGER NOT NULL);";
|
||||||
private static final String DB_NAME = "app.db";
|
private static final String DB_NAME = "app.db";
|
||||||
private static final int DB_VERSION = 1;
|
private static final int DB_VERSION = 1;
|
||||||
public static final String _ID = "_id";
|
public static final String _ID = "_id";
|
||||||
public static final String DAY_SEL = "day_sel";
|
public static final String DAY_SEL = "day_sel";
|
||||||
public static final String TIMETABLE = "timetable";
|
public static final String TIMETABLE = "timetable";
|
||||||
public static final String LAST_ACCOUNT_ID = "last_account_id";
|
public static final String LAST_ACCOUNT_ID = "last_account_id";
|
||||||
public static final String THEME = "theme";
|
public static final String THEME = "theme";
|
||||||
public static final String PREMIUM_TOKEN = "premium_token";
|
public static final String PREMIUM_TOKEN = "premium_token";
|
||||||
public static final String PREMIUM_SCOPES = "premium_scopes";
|
public static final String PREMIUM_SCOPES = "premium_scopes";
|
||||||
public static final String LOCALE = "language";
|
public static final String LOCALE = "language";
|
||||||
public static final String ACCENT_COLOR = "accent_color";
|
public static final String ACCENT_COLOR = "accent_color";
|
||||||
public static final String TABLE_NAME_WIDGETS = "widgets";
|
public static final String TABLE_NAME_WIDGETS = "widgets";
|
||||||
public static final String TABLE_NAME_USER_DATA = "user_data";
|
public static final String TABLE_NAME_USER_DATA = "user_data";
|
||||||
public static final String TABLE_NAME_SETTINGS = "settings";
|
public static final String TABLE_NAME_SETTINGS = "settings";
|
||||||
|
|
||||||
public SQLiteHelper(Context context) {
|
public SQLiteHelper(Context context) {
|
||||||
super(context, DB_NAME, null, 7);
|
super(context, DB_NAME, null, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onCreate(SQLiteDatabase db) {
|
public void onCreate(SQLiteDatabase db) {
|
||||||
db.execSQL(CREATE_TABLE_WIDGET);
|
db.execSQL(CREATE_TABLE_WIDGET);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
db.execSQL("DROP TABLE IF EXISTS widgets");
|
db.execSQL("DROP TABLE IF EXISTS widgets");
|
||||||
onCreate(db);
|
onCreate(db);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,36 +1,36 @@
|
|||||||
package hu.refilc.naplo.utils;
|
package hu.refilc.naplo.utils;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.NetworkInfo;
|
import android.net.NetworkInfo;
|
||||||
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
public class Utils {
|
public class Utils {
|
||||||
public static boolean hasNetwork(Context context) {
|
public static boolean hasNetwork(Context context) {
|
||||||
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
NetworkInfo netInfo = cm.getActiveNetworkInfo();
|
NetworkInfo netInfo = cm.getActiveNetworkInfo();
|
||||||
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
|
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Date getWeekStartDate() {
|
public static Date getWeekStartDate() {
|
||||||
Calendar calendar = Calendar.getInstance();
|
Calendar calendar = Calendar.getInstance();
|
||||||
while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
|
while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
|
||||||
calendar.add(Calendar.DATE, -1);
|
calendar.add(Calendar.DATE, -1);
|
||||||
}
|
}
|
||||||
return calendar.getTime();
|
return calendar.getTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Date getWeekEndDate() {
|
public static Date getWeekEndDate() {
|
||||||
Calendar calendar = Calendar.getInstance();
|
Calendar calendar = Calendar.getInstance();
|
||||||
while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
|
while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
|
||||||
calendar.add(Calendar.DATE, 1);
|
calendar.add(Calendar.DATE, 1);
|
||||||
}
|
}
|
||||||
calendar.add(Calendar.DATE, -1);
|
calendar.add(Calendar.DATE, -1);
|
||||||
return calendar.getTime();
|
return calendar.getTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,65 +1,65 @@
|
|||||||
package hu.refilc.naplo.utils;
|
package hu.refilc.naplo.utils;
|
||||||
|
|
||||||
import java.time.DayOfWeek;
|
import java.time.DayOfWeek;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
|
||||||
public class Week {
|
public class Week {
|
||||||
private final LocalDate start;
|
private final LocalDate start;
|
||||||
private final LocalDate end;
|
private final LocalDate end;
|
||||||
|
|
||||||
private Week(LocalDate start, LocalDate end) {
|
private Week(LocalDate start, LocalDate end) {
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Week current() {
|
public static Week current() {
|
||||||
return fromDate(LocalDate.now());
|
return fromDate(LocalDate.now());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Week fromId(int id) {
|
public static Week fromId(int id) {
|
||||||
LocalDate _now = getYearStart().plusDays(id * 7L);
|
LocalDate _now = getYearStart().plusDays(id * 7L);
|
||||||
return new Week(_now.minusDays(_now.getDayOfWeek().getValue() - 1), _now.plusDays(7 - _now.getDayOfWeek().getValue()));
|
return new Week(_now.minusDays(_now.getDayOfWeek().getValue() - 1), _now.plusDays(7 - _now.getDayOfWeek().getValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Week fromDate(LocalDate date) {
|
public static Week fromDate(LocalDate date) {
|
||||||
|
|
||||||
return new Week(date.minusDays(date.getDayOfWeek().getValue() - 1), date.plusDays(7 - date.getDayOfWeek().getValue()));
|
return new Week(date.minusDays(date.getDayOfWeek().getValue() - 1), date.plusDays(7 - date.getDayOfWeek().getValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Week next() {
|
public Week next() {
|
||||||
return Week.fromDate(start.plusDays(8));
|
return Week.fromDate(start.plusDays(8));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int id() {
|
public int id() {
|
||||||
return (int) Math.ceil(Duration.between(getYearStart().atStartOfDay(), start.atStartOfDay()).toDays() / 7f);
|
return (int) Math.ceil(Duration.between(getYearStart().atStartOfDay(), start.atStartOfDay()).toDays() / 7f);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LocalDate getYearStart() {
|
private static LocalDate getYearStart() {
|
||||||
LocalDate now = LocalDate.now();
|
LocalDate now = LocalDate.now();
|
||||||
LocalDate start = getYearStart(now.getYear());
|
LocalDate start = getYearStart(now.getYear());
|
||||||
return start.isBefore(now) ? start : getYearStart(now.getYear() -1);
|
return start.isBefore(now) ? start : getYearStart(now.getYear() -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LocalDate getYearStart(int year) {
|
private static LocalDate getYearStart(int year) {
|
||||||
LocalDate time = LocalDate.of(year, 9, 1);
|
LocalDate time = LocalDate.of(year, 9, 1);
|
||||||
if (time.getDayOfWeek() == DayOfWeek.SATURDAY)
|
if (time.getDayOfWeek() == DayOfWeek.SATURDAY)
|
||||||
return time.plusDays(2);
|
return time.plusDays(2);
|
||||||
else if (time.getDayOfWeek() == DayOfWeek.SUNDAY)
|
else if (time.getDayOfWeek() == DayOfWeek.SUNDAY)
|
||||||
return time.plusDays(1);
|
return time.plusDays(1);
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
Week week = (Week) o;
|
Week week = (Week) o;
|
||||||
return this.id() == week.id();
|
return this.id() == week.id();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return id();
|
return id();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,397 +1,397 @@
|
|||||||
package hu.refilc.naplo.widget_timetable;
|
package hu.refilc.naplo.widget_timetable;
|
||||||
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.appwidget.AppWidgetManager;
|
import android.appwidget.AppWidgetManager;
|
||||||
import android.appwidget.AppWidgetProvider;
|
import android.appwidget.AppWidgetProvider;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.RemoteViews;
|
import android.widget.RemoteViews;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.time.DayOfWeek;
|
import java.time.DayOfWeek;
|
||||||
import java.time.format.TextStyle;
|
import java.time.format.TextStyle;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import hu.refilc.naplo.database.DBManager;
|
import hu.refilc.naplo.database.DBManager;
|
||||||
import hu.refilc.naplo.MainActivity;
|
import hu.refilc.naplo.MainActivity;
|
||||||
import hu.refilc.naplo.R;
|
import hu.refilc.naplo.R;
|
||||||
|
|
||||||
import hu.refilc.naplo.utils.Week;
|
import hu.refilc.naplo.utils.Week;
|
||||||
|
|
||||||
import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
|
import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
|
||||||
|
|
||||||
import es.antonborri.home_widget.HomeWidgetBackgroundIntent;
|
import es.antonborri.home_widget.HomeWidgetBackgroundIntent;
|
||||||
import es.antonborri.home_widget.HomeWidgetLaunchIntent;
|
import es.antonborri.home_widget.HomeWidgetLaunchIntent;
|
||||||
import es.antonborri.home_widget.HomeWidgetProvider;
|
import es.antonborri.home_widget.HomeWidgetProvider;
|
||||||
|
|
||||||
public class WidgetTimetable extends HomeWidgetProvider {
|
public class WidgetTimetable extends HomeWidgetProvider {
|
||||||
|
|
||||||
private static final String ACTION_WIDGET_CLICK_NAV_LEFT = "list_widget.ACTION_WIDGET_CLICK_NAV_LEFT";
|
private static final String ACTION_WIDGET_CLICK_NAV_LEFT = "list_widget.ACTION_WIDGET_CLICK_NAV_LEFT";
|
||||||
private static final String ACTION_WIDGET_CLICK_NAV_RIGHT = "list_widget.ACTION_WIDGET_CLICK_NAV_RIGHT";
|
private static final String ACTION_WIDGET_CLICK_NAV_RIGHT = "list_widget.ACTION_WIDGET_CLICK_NAV_RIGHT";
|
||||||
private static final String ACTION_WIDGET_CLICK_NAV_TODAY = "list_widget.ACTION_WIDGET_CLICK_NAV_TODAY";
|
private static final String ACTION_WIDGET_CLICK_NAV_TODAY = "list_widget.ACTION_WIDGET_CLICK_NAV_TODAY";
|
||||||
private static final String ACTION_WIDGET_CLICK_NAV_REFRESH = "list_widget.ACTION_WIDGET_CLICK_NAV_REFRESH";
|
private static final String ACTION_WIDGET_CLICK_NAV_REFRESH = "list_widget.ACTION_WIDGET_CLICK_NAV_REFRESH";
|
||||||
private static final String ACTION_WIDGET_CLICK_BUY_PREMIUM = "list_widget.ACTION_WIDGET_CLICK_BUY_PREMIUM";
|
private static final String ACTION_WIDGET_CLICK_BUY_PREMIUM = "list_widget.ACTION_WIDGET_CLICK_BUY_PREMIUM";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds, SharedPreferences widgetData) {
|
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds, SharedPreferences widgetData) {
|
||||||
for (int i = 0; i < appWidgetIds.length; i++) {
|
for (int i = 0; i < appWidgetIds.length; i++) {
|
||||||
RemoteViews views = generateView(context, appWidgetIds[i]);
|
RemoteViews views = generateView(context, appWidgetIds[i]);
|
||||||
|
|
||||||
if(premiumEnabled(context) && userLoggedIn(context)) {
|
if(premiumEnabled(context) && userLoggedIn(context)) {
|
||||||
int rday = selectDay(context, appWidgetIds[i], 0, true);
|
int rday = selectDay(context, appWidgetIds[i], 0, true);
|
||||||
views.setTextViewText(R.id.nav_current, convertDayOfWeek(context, rday));
|
views.setTextViewText(R.id.nav_current, convertDayOfWeek(context, rday));
|
||||||
}
|
}
|
||||||
|
|
||||||
pushUpdate(context, views, appWidgetIds[i]);
|
pushUpdate(context, views, appWidgetIds[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void pushUpdate(Context context, RemoteViews remoteViews, int appWidgetSingleId) {
|
public static void pushUpdate(Context context, RemoteViews remoteViews, int appWidgetSingleId) {
|
||||||
AppWidgetManager manager = AppWidgetManager.getInstance(context);
|
AppWidgetManager manager = AppWidgetManager.getInstance(context);
|
||||||
|
|
||||||
manager.updateAppWidget(appWidgetSingleId, remoteViews);
|
manager.updateAppWidget(appWidgetSingleId, remoteViews);
|
||||||
manager.notifyAppWidgetViewDataChanged(appWidgetSingleId, R.id.widget_list);
|
manager.notifyAppWidgetViewDataChanged(appWidgetSingleId, R.id.widget_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RemoteViews generateView(Context context, int appId) {
|
public static RemoteViews generateView(Context context, int appId) {
|
||||||
Intent serviceIntent = new Intent(context, WidgetTimetableService.class);
|
Intent serviceIntent = new Intent(context, WidgetTimetableService.class);
|
||||||
serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appId);
|
serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appId);
|
||||||
serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)));
|
serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)));
|
||||||
|
|
||||||
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_timetable);
|
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_timetable);
|
||||||
|
|
||||||
views.setViewVisibility(R.id.need_premium, View.GONE);
|
views.setViewVisibility(R.id.need_premium, View.GONE);
|
||||||
views.setViewVisibility(R.id.need_login, View.GONE);
|
views.setViewVisibility(R.id.need_login, View.GONE);
|
||||||
views.setViewVisibility(R.id.tt_grid_cont, View.GONE);
|
views.setViewVisibility(R.id.tt_grid_cont, View.GONE);
|
||||||
|
|
||||||
if(!userLoggedIn(context)) {
|
if(!userLoggedIn(context)) {
|
||||||
views.setViewVisibility(R.id.need_login, View.VISIBLE);
|
views.setViewVisibility(R.id.need_login, View.VISIBLE);
|
||||||
views.setOnClickPendingIntent(R.id.open_login, makePending(context, ACTION_WIDGET_CLICK_BUY_PREMIUM, appId));
|
views.setOnClickPendingIntent(R.id.open_login, makePending(context, ACTION_WIDGET_CLICK_BUY_PREMIUM, appId));
|
||||||
} else if(premiumEnabled(context)) {
|
} else if(premiumEnabled(context)) {
|
||||||
views.setViewVisibility(R.id.tt_grid_cont, View.VISIBLE);
|
views.setViewVisibility(R.id.tt_grid_cont, View.VISIBLE);
|
||||||
views.setOnClickPendingIntent(R.id.nav_to_left, makePending(context, ACTION_WIDGET_CLICK_NAV_LEFT, appId));
|
views.setOnClickPendingIntent(R.id.nav_to_left, makePending(context, ACTION_WIDGET_CLICK_NAV_LEFT, appId));
|
||||||
views.setOnClickPendingIntent(R.id.nav_to_right, makePending(context, ACTION_WIDGET_CLICK_NAV_RIGHT, appId));
|
views.setOnClickPendingIntent(R.id.nav_to_right, makePending(context, ACTION_WIDGET_CLICK_NAV_RIGHT, appId));
|
||||||
views.setOnClickPendingIntent(R.id.nav_current, makePending(context, ACTION_WIDGET_CLICK_NAV_TODAY, appId));
|
views.setOnClickPendingIntent(R.id.nav_current, makePending(context, ACTION_WIDGET_CLICK_NAV_TODAY, appId));
|
||||||
views.setOnClickPendingIntent(R.id.nav_refresh, makePending(context, ACTION_WIDGET_CLICK_NAV_REFRESH, appId));
|
views.setOnClickPendingIntent(R.id.nav_refresh, makePending(context, ACTION_WIDGET_CLICK_NAV_REFRESH, appId));
|
||||||
views.setRemoteAdapter(R.id.widget_list, serviceIntent);
|
views.setRemoteAdapter(R.id.widget_list, serviceIntent);
|
||||||
views.setEmptyView(R.id.widget_list, R.id.empty_view);
|
views.setEmptyView(R.id.widget_list, R.id.empty_view);
|
||||||
} else {
|
} else {
|
||||||
views.setViewVisibility(R.id.need_premium, View.VISIBLE);
|
views.setViewVisibility(R.id.need_premium, View.VISIBLE);
|
||||||
views.setOnClickPendingIntent(R.id.buy_premium, makePending(context, ACTION_WIDGET_CLICK_BUY_PREMIUM, appId));
|
views.setOnClickPendingIntent(R.id.buy_premium, makePending(context, ACTION_WIDGET_CLICK_BUY_PREMIUM, appId));
|
||||||
}
|
}
|
||||||
|
|
||||||
return views;
|
return views;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PendingIntent makePending(Context context, String action, int appWidgetId) {
|
static PendingIntent makePending(Context context, String action, int appWidgetId) {
|
||||||
Intent activebtnnext = new Intent(context, WidgetTimetable.class);
|
Intent activebtnnext = new Intent(context, WidgetTimetable.class);
|
||||||
activebtnnext.setAction(action);
|
activebtnnext.setAction(action);
|
||||||
activebtnnext.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
|
activebtnnext.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
|
||||||
return PendingIntent.getBroadcast(context, appWidgetId, activebtnnext , PendingIntent.FLAG_IMMUTABLE);
|
return PendingIntent.getBroadcast(context, appWidgetId, activebtnnext , PendingIntent.FLAG_IMMUTABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
super.onReceive(context, intent);
|
super.onReceive(context, intent);
|
||||||
|
|
||||||
if(intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
|
if(intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
|
||||||
int appId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
|
int appId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
|
||||||
RemoteViews views = generateView(context, appId);
|
RemoteViews views = generateView(context, appId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(premiumEnabled(context) && userLoggedIn(context)) {
|
if(premiumEnabled(context) && userLoggedIn(context)) {
|
||||||
if (intent.getAction().equals(ACTION_WIDGET_CLICK_NAV_LEFT)) {
|
if (intent.getAction().equals(ACTION_WIDGET_CLICK_NAV_LEFT)) {
|
||||||
int rday = selectDay(context, appId, -1, false);
|
int rday = selectDay(context, appId, -1, false);
|
||||||
views.setTextViewText(R.id.nav_current, convertDayOfWeek(context, rday));
|
views.setTextViewText(R.id.nav_current, convertDayOfWeek(context, rday));
|
||||||
|
|
||||||
pushUpdate(context, views, appId);
|
pushUpdate(context, views, appId);
|
||||||
} else if (intent.getAction().equals(ACTION_WIDGET_CLICK_NAV_RIGHT)) {
|
} else if (intent.getAction().equals(ACTION_WIDGET_CLICK_NAV_RIGHT)) {
|
||||||
int rday = selectDay(context, appId, 1, false);
|
int rday = selectDay(context, appId, 1, false);
|
||||||
views.setTextViewText(R.id.nav_current, convertDayOfWeek(context, rday));
|
views.setTextViewText(R.id.nav_current, convertDayOfWeek(context, rday));
|
||||||
|
|
||||||
pushUpdate(context, views, appId);
|
pushUpdate(context, views, appId);
|
||||||
} else if (intent.getAction().equals(ACTION_WIDGET_CLICK_NAV_TODAY)) {
|
} else if (intent.getAction().equals(ACTION_WIDGET_CLICK_NAV_TODAY)) {
|
||||||
int rday = getToday(context);
|
int rday = getToday(context);
|
||||||
setSelectedDay(context, appId, rday);
|
setSelectedDay(context, appId, rday);
|
||||||
|
|
||||||
views.setTextViewText(R.id.nav_current, convertDayOfWeek(context, rday));
|
views.setTextViewText(R.id.nav_current, convertDayOfWeek(context, rday));
|
||||||
|
|
||||||
pushUpdate(context, views, appId);
|
pushUpdate(context, views, appId);
|
||||||
} else if (intent.getAction().equals(ACTION_WIDGET_CLICK_NAV_REFRESH)) {
|
} else if (intent.getAction().equals(ACTION_WIDGET_CLICK_NAV_REFRESH)) {
|
||||||
PendingIntent pendingIntent = HomeWidgetLaunchIntent.INSTANCE.getActivity(context, MainActivity.class, Uri.parse("timetable://refresh"));
|
PendingIntent pendingIntent = HomeWidgetLaunchIntent.INSTANCE.getActivity(context, MainActivity.class, Uri.parse("timetable://refresh"));
|
||||||
pendingIntent.send();
|
pendingIntent.send();
|
||||||
} else if (intent.getAction().equals("android.appwidget.action.APPWIDGET_DELETED")) {
|
} else if (intent.getAction().equals("android.appwidget.action.APPWIDGET_DELETED")) {
|
||||||
DBManager dbManager = new DBManager(context.getApplicationContext());
|
DBManager dbManager = new DBManager(context.getApplicationContext());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dbManager.open();
|
dbManager.open();
|
||||||
dbManager.deleteWidget(appId);
|
dbManager.deleteWidget(appId);
|
||||||
dbManager.close();
|
dbManager.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(intent.getAction().equals(ACTION_WIDGET_CLICK_BUY_PREMIUM)) {
|
if(intent.getAction().equals(ACTION_WIDGET_CLICK_BUY_PREMIUM)) {
|
||||||
PendingIntent pendingIntent = HomeWidgetLaunchIntent.INSTANCE.getActivity(context, MainActivity.class, Uri.parse("settings://premium"));
|
PendingIntent pendingIntent = HomeWidgetLaunchIntent.INSTANCE.getActivity(context, MainActivity.class, Uri.parse("settings://premium"));
|
||||||
pendingIntent.send();
|
pendingIntent.send();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String convertDayOfWeek(Context context, int rday) {
|
public static String convertDayOfWeek(Context context, int rday) {
|
||||||
|
|
||||||
/*if(rday == -1) return DayOfWeek.of(1).getDisplayName(TextStyle.FULL, new Locale("hu", "HU"));
|
/*if(rday == -1) return DayOfWeek.of(1).getDisplayName(TextStyle.FULL, new Locale("hu", "HU"));
|
||||||
|
|
||||||
String dayOfWeek = DayOfWeek.of(rday + 1).getDisplayName(TextStyle.FULL, new Locale("hu", "HU"));*/
|
String dayOfWeek = DayOfWeek.of(rday + 1).getDisplayName(TextStyle.FULL, new Locale("hu", "HU"));*/
|
||||||
|
|
||||||
String dayOfWeek = "Unknown";
|
String dayOfWeek = "Unknown";
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
Locale loc = getLocale(context);
|
Locale loc = getLocale(context);
|
||||||
|
|
||||||
if (rday == -1)
|
if (rday == -1)
|
||||||
return DayOfWeek.of(1).getDisplayName(TextStyle.FULL, loc);
|
return DayOfWeek.of(1).getDisplayName(TextStyle.FULL, loc);
|
||||||
|
|
||||||
dayOfWeek = DayOfWeek.of(rday + 1).getDisplayName(TextStyle.FULL, loc);
|
dayOfWeek = DayOfWeek.of(rday + 1).getDisplayName(TextStyle.FULL, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dayOfWeek.substring(0, 1).toUpperCase() + dayOfWeek.substring(1).toLowerCase();
|
return dayOfWeek.substring(0, 1).toUpperCase() + dayOfWeek.substring(1).toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setSelectedDay(Context context, int wid, int day) {
|
public static void setSelectedDay(Context context, int wid, int day) {
|
||||||
DBManager dbManager = new DBManager(context.getApplicationContext());
|
DBManager dbManager = new DBManager(context.getApplicationContext());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dbManager.open();
|
dbManager.open();
|
||||||
dbManager.update(wid, day);
|
dbManager.update(wid, day);
|
||||||
dbManager.close();
|
dbManager.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getToday(Context context) {
|
public static int getToday(Context context) {
|
||||||
int rday = new DateTime().getDayOfWeek() - 1;
|
int rday = new DateTime().getDayOfWeek() - 1;
|
||||||
List<JSONArray> s = genJsonDays(context);
|
List<JSONArray> s = genJsonDays(context);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(checkIsAfter(s, rday)) rday += 1;
|
if(checkIsAfter(s, rday)) rday += 1;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return retDay(rday, s.size());
|
return retDay(rday, s.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int selectDay(Context context, int wid, int add, Boolean afterSubjects) {
|
public static int selectDay(Context context, int wid, int add, Boolean afterSubjects) {
|
||||||
DBManager dbManager = new DBManager(context.getApplicationContext());
|
DBManager dbManager = new DBManager(context.getApplicationContext());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dbManager.open();
|
dbManager.open();
|
||||||
Cursor cursor = dbManager.fetchWidget(wid);
|
Cursor cursor = dbManager.fetchWidget(wid);
|
||||||
|
|
||||||
List<JSONArray> s = genJsonDays(context);
|
List<JSONArray> s = genJsonDays(context);
|
||||||
int retday = new DateTime().getDayOfWeek() - 1;
|
int retday = new DateTime().getDayOfWeek() - 1;
|
||||||
|
|
||||||
if(cursor.getCount() != 0) retday = retDay(cursor.getInt(1) + add, s.size());
|
if(cursor.getCount() != 0) retday = retDay(cursor.getInt(1) + add, s.size());
|
||||||
|
|
||||||
if(afterSubjects) if(checkIsAfter(s, retday)) retday += 1;
|
if(afterSubjects) if(checkIsAfter(s, retday)) retday += 1;
|
||||||
retday = retDay(retday, s.size());
|
retday = retDay(retday, s.size());
|
||||||
|
|
||||||
if(cursor.getCount() == 0) dbManager.insertSelDay(wid, retday);
|
if(cursor.getCount() == 0) dbManager.insertSelDay(wid, retday);
|
||||||
else dbManager.update(wid, retday);
|
else dbManager.update(wid, retday);
|
||||||
|
|
||||||
dbManager.close();
|
dbManager.close();
|
||||||
|
|
||||||
return retday;
|
return retday;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Boolean checkIsAfter(List<JSONArray> s, int retday) throws Exception {
|
public static Boolean checkIsAfter(List<JSONArray> s, int retday) throws Exception {
|
||||||
retday = retDay(retday, s.size());
|
retday = retDay(retday, s.size());
|
||||||
|
|
||||||
String vegIdopont = s.get(retday).getJSONObject(s.get(retday).length() - 1).getString("VegIdopont");
|
String vegIdopont = s.get(retday).getJSONObject(s.get(retday).length() - 1).getString("VegIdopont");
|
||||||
|
|
||||||
return new DateTime().isAfter(new DateTime(vegIdopont));
|
return new DateTime().isAfter(new DateTime(vegIdopont));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int retDay(int retday, int size) {
|
public static int retDay(int retday, int size) {
|
||||||
if (retday < 0) retday = size - 1;
|
if (retday < 0) retday = size - 1;
|
||||||
else if (retday > size - 1) retday = 0;
|
else if (retday > size - 1) retday = 0;
|
||||||
|
|
||||||
return retday;
|
return retday;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<JSONArray> genJsonDays(Context context) {
|
public static List<JSONArray> genJsonDays(Context context) {
|
||||||
List<JSONArray> gen_days = new ArrayList<>();
|
List<JSONArray> gen_days = new ArrayList<>();
|
||||||
|
|
||||||
DBManager dbManager = new DBManager(context.getApplicationContext());
|
DBManager dbManager = new DBManager(context.getApplicationContext());
|
||||||
try {
|
try {
|
||||||
dbManager.open();
|
dbManager.open();
|
||||||
Cursor ct = dbManager.fetchTimetable();
|
Cursor ct = dbManager.fetchTimetable();
|
||||||
dbManager.close();
|
dbManager.close();
|
||||||
|
|
||||||
if(ct.getCount() == 0) {
|
if(ct.getCount() == 0) {
|
||||||
return gen_days;
|
return gen_days;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject fecthtt = new JSONObject(ct.getString(0));
|
JSONObject fecthtt = new JSONObject(ct.getString(0));
|
||||||
|
|
||||||
JSONArray dayArray = new JSONArray();
|
JSONArray dayArray = new JSONArray();
|
||||||
String currday = "";
|
String currday = "";
|
||||||
|
|
||||||
String currweek = String.valueOf(Week.current().id());
|
String currweek = String.valueOf(Week.current().id());
|
||||||
|
|
||||||
JSONArray week = fecthtt.getJSONArray(currweek);
|
JSONArray week = fecthtt.getJSONArray(currweek);
|
||||||
|
|
||||||
for (int i=0; i < week.length(); i++)
|
for (int i=0; i < week.length(); i++)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if(i == 0) currday = week.getJSONObject(0).getString("Datum");
|
if(i == 0) currday = week.getJSONObject(0).getString("Datum");
|
||||||
JSONObject oraObj = week.getJSONObject(i);
|
JSONObject oraObj = week.getJSONObject(i);
|
||||||
|
|
||||||
if(!currday.equals(oraObj.getString("Datum"))) {
|
if(!currday.equals(oraObj.getString("Datum"))) {
|
||||||
gen_days.add(dayArray);
|
gen_days.add(dayArray);
|
||||||
currday = week.getJSONObject(i).getString("Datum");
|
currday = week.getJSONObject(i).getString("Datum");
|
||||||
dayArray = new JSONArray();
|
dayArray = new JSONArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
dayArray.put(oraObj);
|
dayArray.put(oraObj);
|
||||||
if(i == week.length() - 1) {
|
if(i == week.length() - 1) {
|
||||||
gen_days.add(dayArray);
|
gen_days.add(dayArray);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
Collections.sort(gen_days, new Comparator<JSONArray>() {
|
Collections.sort(gen_days, new Comparator<JSONArray>() {
|
||||||
|
|
||||||
public int compare(JSONArray a, JSONArray b) {
|
public int compare(JSONArray a, JSONArray b) {
|
||||||
long valA = 0;
|
long valA = 0;
|
||||||
long valB = 0;
|
long valB = 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
valA = (long) new DateTime( a.getJSONObject(0).getString("Datum")).getMillis();
|
valA = (long) new DateTime( a.getJSONObject(0).getString("Datum")).getMillis();
|
||||||
valB = (long) new DateTime( b.getJSONObject(0).getString("Datum")).getMillis();
|
valB = (long) new DateTime( b.getJSONObject(0).getString("Datum")).getMillis();
|
||||||
}
|
}
|
||||||
catch (JSONException ignored) {
|
catch (JSONException ignored) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (int) (valA - valB);
|
return (int) (valA - valB);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return gen_days;
|
return gen_days;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String zeroPad(int value, int padding){
|
public static String zeroPad(int value, int padding){
|
||||||
StringBuilder b = new StringBuilder();
|
StringBuilder b = new StringBuilder();
|
||||||
b.append(value);
|
b.append(value);
|
||||||
while(b.length() < padding){
|
while(b.length() < padding){
|
||||||
b.insert(0,"0");
|
b.insert(0,"0");
|
||||||
}
|
}
|
||||||
return b.toString();
|
return b.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Locale getLocale(Context context) {
|
public static Locale getLocale(Context context) {
|
||||||
DBManager dbManager = new DBManager(context.getApplicationContext());
|
DBManager dbManager = new DBManager(context.getApplicationContext());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dbManager.open();
|
dbManager.open();
|
||||||
String loc = dbManager.fetchLocale().getString(0);
|
String loc = dbManager.fetchLocale().getString(0);
|
||||||
dbManager.close();
|
dbManager.close();
|
||||||
|
|
||||||
if(loc.equals("hu") || loc.equals("de")) {
|
if(loc.equals("hu") || loc.equals("de")) {
|
||||||
return new Locale(loc, loc.toUpperCase());
|
return new Locale(loc, loc.toUpperCase());
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Locale("en", "GB");
|
return new Locale("en", "GB");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean premiumEnabled(Context context) {
|
public static boolean premiumEnabled(Context context) {
|
||||||
DBManager dbManager = new DBManager(context.getApplicationContext());
|
DBManager dbManager = new DBManager(context.getApplicationContext());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dbManager.open();
|
dbManager.open();
|
||||||
String premium_token = dbManager.fetchPremiumToken().getString(0);
|
String premium_token = dbManager.fetchPremiumToken().getString(0);
|
||||||
String premium_scopes_raw = dbManager.fetchPremiumScopes().getString(0);
|
String premium_scopes_raw = dbManager.fetchPremiumScopes().getString(0);
|
||||||
dbManager.close();
|
dbManager.close();
|
||||||
|
|
||||||
JSONArray arr = new JSONArray(premium_scopes_raw);
|
JSONArray arr = new JSONArray(premium_scopes_raw);
|
||||||
List<String> premium_scopes = new ArrayList<>();
|
List<String> premium_scopes = new ArrayList<>();
|
||||||
for(int i = 0; i < arr.length(); i++){
|
for(int i = 0; i < arr.length(); i++){
|
||||||
String scope = arr.getString(i);
|
String scope = arr.getString(i);
|
||||||
premium_scopes.add(scope.substring(scope.lastIndexOf('.') + 1));
|
premium_scopes.add(scope.substring(scope.lastIndexOf('.') + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!premium_token.equals("") && (premium_scopes.contains("*") || premium_scopes.contains("TIMETALBE_WIDGET"))) {
|
if(!premium_token.equals("") && (premium_scopes.contains("*") || premium_scopes.contains("TIMETALBE_WIDGET"))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean userLoggedIn(Context context) {
|
public static boolean userLoggedIn(Context context) {
|
||||||
return !lastUserId(context).equals("");
|
return !lastUserId(context).equals("");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String lastUserId(Context context) {
|
public static String lastUserId(Context context) {
|
||||||
DBManager dbManager = new DBManager(context.getApplicationContext());
|
DBManager dbManager = new DBManager(context.getApplicationContext());
|
||||||
try {
|
try {
|
||||||
dbManager.open();
|
dbManager.open();
|
||||||
Cursor cursor = dbManager.fetchLastUser();
|
Cursor cursor = dbManager.fetchLastUser();
|
||||||
dbManager.close();
|
dbManager.close();
|
||||||
|
|
||||||
if(cursor != null && !cursor.getString(0).equals("")) {
|
if(cursor != null && !cursor.getString(0).equals("")) {
|
||||||
String last_user = cursor.getString(0);
|
String last_user = cursor.getString(0);
|
||||||
return last_user;
|
return last_user;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnabled(Context context) {
|
public void onEnabled(Context context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisabled(Context context) {
|
public void onDisabled(Context context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,354 +1,354 @@
|
|||||||
package hu.refilc.naplo.widget_timetable;
|
package hu.refilc.naplo.widget_timetable;
|
||||||
|
|
||||||
import android.appwidget.AppWidgetManager;
|
import android.appwidget.AppWidgetManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.RemoteViews;
|
import android.widget.RemoteViews;
|
||||||
import android.widget.RemoteViewsService;
|
import android.widget.RemoteViewsService;
|
||||||
|
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import hu.refilc.naplo.database.DBManager;
|
import hu.refilc.naplo.database.DBManager;
|
||||||
import hu.refilc.naplo.R;
|
import hu.refilc.naplo.R;
|
||||||
|
|
||||||
public class WidgetTimetableDataProvider implements RemoteViewsService.RemoteViewsFactory {
|
public class WidgetTimetableDataProvider implements RemoteViewsService.RemoteViewsFactory {
|
||||||
|
|
||||||
private Context context;
|
private Context context;
|
||||||
private int appWidgetId;
|
private int appWidgetId;
|
||||||
|
|
||||||
private int rday = 0;
|
private int rday = 0;
|
||||||
|
|
||||||
private int theme;
|
private int theme;
|
||||||
|
|
||||||
private Integer[] colorValues;
|
private Integer[] colorValues;
|
||||||
|
|
||||||
List<Lesson> day_subjects = new ArrayList<>();
|
List<Lesson> day_subjects = new ArrayList<>();
|
||||||
List<Integer> lessonIndexes = new ArrayList<>();
|
List<Integer> lessonIndexes = new ArrayList<>();
|
||||||
|
|
||||||
Item witem;
|
Item witem;
|
||||||
|
|
||||||
/* Default values */
|
/* Default values */
|
||||||
|
|
||||||
static class Item {
|
static class Item {
|
||||||
int Layout;
|
int Layout;
|
||||||
|
|
||||||
int NumVisibility;
|
int NumVisibility;
|
||||||
int NameVisibility;
|
int NameVisibility;
|
||||||
int NameNodescVisibility;
|
int NameNodescVisibility;
|
||||||
int DescVisibility;
|
int DescVisibility;
|
||||||
int RoomVisibility;
|
int RoomVisibility;
|
||||||
int TimeVisibility;
|
int TimeVisibility;
|
||||||
|
|
||||||
int NumColor;
|
int NumColor;
|
||||||
int NameColor;
|
int NameColor;
|
||||||
int NameNodescColor;
|
int NameNodescColor;
|
||||||
int DescColor;
|
int DescColor;
|
||||||
|
|
||||||
Integer[] NameNodescPadding = {0, 0, 0, 0};
|
Integer[] NameNodescPadding = {0, 0, 0, 0};
|
||||||
|
|
||||||
public Item(int Layout, int NumVisibility,int NameVisibility,int NameNodescVisibility,int DescVisibility,int RoomVisibility,int TimeVisibility,int NumColor,int NameColor,int NameNodescColor,int DescColor) {
|
public Item(int Layout, int NumVisibility,int NameVisibility,int NameNodescVisibility,int DescVisibility,int RoomVisibility,int TimeVisibility,int NumColor,int NameColor,int NameNodescColor,int DescColor) {
|
||||||
this.Layout = Layout;
|
this.Layout = Layout;
|
||||||
this.NumVisibility = NumVisibility;
|
this.NumVisibility = NumVisibility;
|
||||||
this.NameVisibility = NameVisibility;
|
this.NameVisibility = NameVisibility;
|
||||||
this.NameNodescVisibility = NameNodescVisibility;
|
this.NameNodescVisibility = NameNodescVisibility;
|
||||||
this.DescVisibility = DescVisibility;
|
this.DescVisibility = DescVisibility;
|
||||||
this.RoomVisibility = RoomVisibility;
|
this.RoomVisibility = RoomVisibility;
|
||||||
this.TimeVisibility = TimeVisibility;
|
this.TimeVisibility = TimeVisibility;
|
||||||
|
|
||||||
this.NumColor = NumColor;
|
this.NumColor = NumColor;
|
||||||
this.NameColor = NameColor;
|
this.NameColor = NameColor;
|
||||||
this.NameNodescColor = NameNodescColor;
|
this.NameNodescColor = NameNodescColor;
|
||||||
this.DescColor = DescColor;
|
this.DescColor = DescColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Lesson {
|
static class Lesson {
|
||||||
String status;
|
String status;
|
||||||
String lessonIndex;
|
String lessonIndex;
|
||||||
String lessonName;
|
String lessonName;
|
||||||
String lessonTopic;
|
String lessonTopic;
|
||||||
String lessonRoom;
|
String lessonRoom;
|
||||||
long lessonStart;
|
long lessonStart;
|
||||||
long lessonEnd;
|
long lessonEnd;
|
||||||
String substituteTeacher;
|
String substituteTeacher;
|
||||||
|
|
||||||
public Lesson(String status, String lessonIndex,String lessonName,String lessonTopic, String lessonRoom,long lessonStart,long lessonEnd,String substituteTeacher) {
|
public Lesson(String status, String lessonIndex,String lessonName,String lessonTopic, String lessonRoom,long lessonStart,long lessonEnd,String substituteTeacher) {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
this.lessonIndex = lessonIndex;
|
this.lessonIndex = lessonIndex;
|
||||||
this.lessonName = lessonName;
|
this.lessonName = lessonName;
|
||||||
this.lessonTopic = lessonTopic;
|
this.lessonTopic = lessonTopic;
|
||||||
this.lessonRoom = lessonRoom;
|
this.lessonRoom = lessonRoom;
|
||||||
this.lessonStart = lessonStart;
|
this.lessonStart = lessonStart;
|
||||||
this.lessonEnd = lessonEnd;
|
this.lessonEnd = lessonEnd;
|
||||||
this.substituteTeacher = substituteTeacher;
|
this.substituteTeacher = substituteTeacher;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer[] itemNameNodescPadding = {0, 0, 0, 0};
|
Integer[] itemNameNodescPadding = {0, 0, 0, 0};
|
||||||
|
|
||||||
public WidgetTimetableDataProvider(Context context, Intent intent) {
|
public WidgetTimetableDataProvider(Context context, Intent intent) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
|
this.appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
|
||||||
|
|
||||||
this.theme = getThemeAccent(context);
|
this.theme = getThemeAccent(context);
|
||||||
|
|
||||||
this.colorValues = new Integer[]{R.color.filc,
|
this.colorValues = new Integer[]{R.color.filc,
|
||||||
R.color.blue_shade300,
|
R.color.blue_shade300,
|
||||||
R.color.green_shade300,
|
R.color.green_shade300,
|
||||||
R.color.lime_shade300,
|
R.color.lime_shade300,
|
||||||
R.color.yellow_shade300,
|
R.color.yellow_shade300,
|
||||||
R.color.orange_shade300,
|
R.color.orange_shade300,
|
||||||
R.color.red_shade300,
|
R.color.red_shade300,
|
||||||
R.color.pink_shade300,
|
R.color.pink_shade300,
|
||||||
R.color.purple_shade300};
|
R.color.purple_shade300};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
initData();
|
initData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDataSetChanged() {
|
public void onDataSetChanged() {
|
||||||
initData();
|
initData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCount() {
|
public int getCount() {
|
||||||
|
|
||||||
return day_subjects.size();
|
return day_subjects.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLayout(final RemoteViews view) {
|
public void setLayout(final RemoteViews view) {
|
||||||
/* Visibilities */
|
/* Visibilities */
|
||||||
view.setViewVisibility(R.id.tt_item_num, witem.NumVisibility);
|
view.setViewVisibility(R.id.tt_item_num, witem.NumVisibility);
|
||||||
view.setViewVisibility(R.id.tt_item_name, witem.NameVisibility);
|
view.setViewVisibility(R.id.tt_item_name, witem.NameVisibility);
|
||||||
view.setViewVisibility(R.id.tt_item_name_nodesc, witem.NameNodescVisibility);
|
view.setViewVisibility(R.id.tt_item_name_nodesc, witem.NameNodescVisibility);
|
||||||
view.setViewVisibility(R.id.tt_item_desc, witem.DescVisibility);
|
view.setViewVisibility(R.id.tt_item_desc, witem.DescVisibility);
|
||||||
view.setViewVisibility(R.id.tt_item_room, witem.RoomVisibility);
|
view.setViewVisibility(R.id.tt_item_room, witem.RoomVisibility);
|
||||||
view.setViewVisibility(R.id.tt_item_time, witem.TimeVisibility);
|
view.setViewVisibility(R.id.tt_item_time, witem.TimeVisibility);
|
||||||
|
|
||||||
/* backgroundResources */
|
/* backgroundResources */
|
||||||
view.setInt(R.id.main_lay, "setBackgroundResource", witem.Layout);
|
view.setInt(R.id.main_lay, "setBackgroundResource", witem.Layout);
|
||||||
|
|
||||||
/* Paddings */
|
/* Paddings */
|
||||||
view.setViewPadding(R.id.tt_item_name_nodesc, witem.NameNodescPadding[0], witem.NameNodescPadding[1], witem.NameNodescPadding[2], witem.NameNodescPadding[3]);
|
view.setViewPadding(R.id.tt_item_name_nodesc, witem.NameNodescPadding[0], witem.NameNodescPadding[1], witem.NameNodescPadding[2], witem.NameNodescPadding[3]);
|
||||||
|
|
||||||
/* Text Colors */
|
/* Text Colors */
|
||||||
view.setInt(R.id.tt_item_num, "setTextColor", getColor(context, witem.NumColor));
|
view.setInt(R.id.tt_item_num, "setTextColor", getColor(context, witem.NumColor));
|
||||||
view.setInt(R.id.tt_item_name, "setTextColor", getColor(context, witem.NameColor));
|
view.setInt(R.id.tt_item_name, "setTextColor", getColor(context, witem.NameColor));
|
||||||
view.setInt(R.id.tt_item_name_nodesc, "setTextColor", getColor(context, witem.NameNodescColor));
|
view.setInt(R.id.tt_item_name_nodesc, "setTextColor", getColor(context, witem.NameNodescColor));
|
||||||
view.setInt(R.id.tt_item_desc, "setTextColor", getColor(context, witem.DescColor));
|
view.setInt(R.id.tt_item_desc, "setTextColor", getColor(context, witem.DescColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getColor(Context context, int color) {
|
public int getColor(Context context, int color) {
|
||||||
return context.getResources().getColor(color);
|
return context.getResources().getColor(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RemoteViews getViewAt(int position) {
|
public RemoteViews getViewAt(int position) {
|
||||||
RemoteViews view = new RemoteViews(context.getPackageName(), R.layout.timetable_item);
|
RemoteViews view = new RemoteViews(context.getPackageName(), R.layout.timetable_item);
|
||||||
|
|
||||||
witem = defaultItem(theme);
|
witem = defaultItem(theme);
|
||||||
|
|
||||||
Lesson curr_subject = day_subjects.get(position);
|
Lesson curr_subject = day_subjects.get(position);
|
||||||
|
|
||||||
if (curr_subject.status.equals("empty")) {
|
if (curr_subject.status.equals("empty")) {
|
||||||
witem.NumColor = R.color.text_miss_num;
|
witem.NumColor = R.color.text_miss_num;
|
||||||
|
|
||||||
witem.TimeVisibility = View.GONE;
|
witem.TimeVisibility = View.GONE;
|
||||||
witem.RoomVisibility = View.GONE;
|
witem.RoomVisibility = View.GONE;
|
||||||
|
|
||||||
witem.NameNodescColor = R.color.text_miss;
|
witem.NameNodescColor = R.color.text_miss;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!curr_subject.substituteTeacher.equals("null")) {
|
if (!curr_subject.substituteTeacher.equals("null")) {
|
||||||
witem.NumColor = R.color.yellow;
|
witem.NumColor = R.color.yellow;
|
||||||
witem.Layout = R.drawable.card_layout_tile_helyetesitett;
|
witem.Layout = R.drawable.card_layout_tile_helyetesitett;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curr_subject.status.equals("Elmaradt")) {
|
if (curr_subject.status.equals("Elmaradt")) {
|
||||||
witem.NumColor = R.color.red;
|
witem.NumColor = R.color.red;
|
||||||
witem.Layout = R.drawable.card_layout_tile_elmarad;
|
witem.Layout = R.drawable.card_layout_tile_elmarad;
|
||||||
} else if (curr_subject.status.equals("TanevRendjeEsemeny")) {
|
} else if (curr_subject.status.equals("TanevRendjeEsemeny")) {
|
||||||
witem.NumVisibility = View.GONE;
|
witem.NumVisibility = View.GONE;
|
||||||
witem.TimeVisibility = View.GONE;
|
witem.TimeVisibility = View.GONE;
|
||||||
witem.RoomVisibility = View.GONE;
|
witem.RoomVisibility = View.GONE;
|
||||||
|
|
||||||
witem.NameNodescPadding[0] = 50;
|
witem.NameNodescPadding[0] = 50;
|
||||||
witem.NameNodescPadding[2] = 50;
|
witem.NameNodescPadding[2] = 50;
|
||||||
|
|
||||||
witem.NameNodescColor = R.color.text_miss;
|
witem.NameNodescColor = R.color.text_miss;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curr_subject.lessonTopic.equals("null")) {
|
if (curr_subject.lessonTopic.equals("null")) {
|
||||||
witem.DescVisibility = View.GONE;
|
witem.DescVisibility = View.GONE;
|
||||||
witem.NameVisibility = View.GONE;
|
witem.NameVisibility = View.GONE;
|
||||||
|
|
||||||
witem.NameNodescVisibility = View.VISIBLE;
|
witem.NameNodescVisibility = View.VISIBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
setLayout(view);
|
setLayout(view);
|
||||||
|
|
||||||
String lessonIndexTrailing = curr_subject.lessonIndex.equals("+") ? "" : ".";
|
String lessonIndexTrailing = curr_subject.lessonIndex.equals("+") ? "" : ".";
|
||||||
|
|
||||||
view.setTextViewText(R.id.tt_item_num, curr_subject.lessonIndex + lessonIndexTrailing);
|
view.setTextViewText(R.id.tt_item_num, curr_subject.lessonIndex + lessonIndexTrailing);
|
||||||
view.setTextViewText(R.id.tt_item_name, curr_subject.lessonName);
|
view.setTextViewText(R.id.tt_item_name, curr_subject.lessonName);
|
||||||
view.setTextViewText(R.id.tt_item_name_nodesc, curr_subject.lessonName);
|
view.setTextViewText(R.id.tt_item_name_nodesc, curr_subject.lessonName);
|
||||||
view.setTextViewText(R.id.tt_item_desc, curr_subject.lessonTopic);
|
view.setTextViewText(R.id.tt_item_desc, curr_subject.lessonTopic);
|
||||||
view.setTextViewText(R.id.tt_item_room, curr_subject.lessonRoom);
|
view.setTextViewText(R.id.tt_item_room, curr_subject.lessonRoom);
|
||||||
if(curr_subject.lessonStart != 0 && curr_subject.lessonEnd != 0)
|
if(curr_subject.lessonStart != 0 && curr_subject.lessonEnd != 0)
|
||||||
view.setTextViewText(R.id.tt_item_time, WidgetTimetable.zeroPad(new DateTime(curr_subject.lessonStart).getHourOfDay(), 2) + ":" + WidgetTimetable.zeroPad(new DateTime(curr_subject.lessonStart).getMinuteOfHour(), 2) +
|
view.setTextViewText(R.id.tt_item_time, WidgetTimetable.zeroPad(new DateTime(curr_subject.lessonStart).getHourOfDay(), 2) + ":" + WidgetTimetable.zeroPad(new DateTime(curr_subject.lessonStart).getMinuteOfHour(), 2) +
|
||||||
"\n" + WidgetTimetable.zeroPad(new DateTime(curr_subject.lessonEnd).getHourOfDay(), 2) + ":" + WidgetTimetable.zeroPad(new DateTime(curr_subject.lessonEnd).getMinuteOfHour(),2));
|
"\n" + WidgetTimetable.zeroPad(new DateTime(curr_subject.lessonEnd).getHourOfDay(), 2) + ":" + WidgetTimetable.zeroPad(new DateTime(curr_subject.lessonEnd).getMinuteOfHour(),2));
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RemoteViews getLoadingView() {
|
public RemoteViews getLoadingView() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getViewTypeCount() {
|
public int getViewTypeCount() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getItemId(int position) {
|
public long getItemId(int position) {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasStableIds() {
|
public boolean hasStableIds() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initData() {
|
private void initData() {
|
||||||
|
|
||||||
theme = getThemeAccent(context);
|
theme = getThemeAccent(context);
|
||||||
|
|
||||||
rday = WidgetTimetable.selectDay(context, appWidgetId, 0, false);
|
rday = WidgetTimetable.selectDay(context, appWidgetId, 0, false);
|
||||||
|
|
||||||
day_subjects.clear();
|
day_subjects.clear();
|
||||||
lessonIndexes.clear();
|
lessonIndexes.clear();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<JSONArray> arr = WidgetTimetable.genJsonDays(context);
|
List<JSONArray> arr = WidgetTimetable.genJsonDays(context);
|
||||||
|
|
||||||
if(arr.isEmpty()) {
|
if(arr.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
JSONArray arr_lessons = WidgetTimetable.genJsonDays(context).get(rday);
|
JSONArray arr_lessons = WidgetTimetable.genJsonDays(context).get(rday);
|
||||||
|
|
||||||
for (int i = 0; i < arr_lessons.length(); i++) {
|
for (int i = 0; i < arr_lessons.length(); i++) {
|
||||||
JSONObject obj_lessons = arr_lessons.getJSONObject(i);
|
JSONObject obj_lessons = arr_lessons.getJSONObject(i);
|
||||||
|
|
||||||
day_subjects.add(jsonToLesson(obj_lessons));
|
day_subjects.add(jsonToLesson(obj_lessons));
|
||||||
}
|
}
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(day_subjects.size() > 0) {
|
if(day_subjects.size() > 0) {
|
||||||
Collections.sort(day_subjects, new Comparator<Lesson>() {
|
Collections.sort(day_subjects, new Comparator<Lesson>() {
|
||||||
public int compare(Lesson o1, Lesson o2) {
|
public int compare(Lesson o1, Lesson o2) {
|
||||||
return new DateTime(o1.lessonStart).compareTo(new DateTime(o2.lessonStart));
|
return new DateTime(o1.lessonStart).compareTo(new DateTime(o2.lessonStart));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
for (int i = 0; i < day_subjects.size(); i++) {
|
for (int i = 0; i < day_subjects.size(); i++) {
|
||||||
if(!day_subjects.get(i).lessonIndex.equals("+")) {
|
if(!day_subjects.get(i).lessonIndex.equals("+")) {
|
||||||
lessonIndexes.add(Integer.valueOf(day_subjects.get(i).lessonIndex));
|
lessonIndexes.add(Integer.valueOf(day_subjects.get(i).lessonIndex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lessonIndexes.size() > 0) {
|
if(lessonIndexes.size() > 0) {
|
||||||
|
|
||||||
int lessonsChecked = Collections.min(lessonIndexes);
|
int lessonsChecked = Collections.min(lessonIndexes);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
while(lessonsChecked < Collections.max(lessonIndexes)) {
|
while(lessonsChecked < Collections.max(lessonIndexes)) {
|
||||||
if(!lessonIndexes.contains(lessonsChecked)) {
|
if(!lessonIndexes.contains(lessonsChecked)) {
|
||||||
day_subjects.add(i, emptyLesson(lessonsChecked));
|
day_subjects.add(i, emptyLesson(lessonsChecked));
|
||||||
}
|
}
|
||||||
lessonsChecked++;
|
lessonsChecked++;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Integer getThemeAccent(Context context) {
|
public static Integer getThemeAccent(Context context) {
|
||||||
DBManager dbManager = new DBManager(context.getApplicationContext());
|
DBManager dbManager = new DBManager(context.getApplicationContext());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dbManager.open();
|
dbManager.open();
|
||||||
Cursor cursor = dbManager.fetchTheme();
|
Cursor cursor = dbManager.fetchTheme();
|
||||||
dbManager.close();
|
dbManager.close();
|
||||||
|
|
||||||
return cursor.getInt(1);
|
return cursor.getInt(1);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Item defaultItem(int theme) {
|
public Item defaultItem(int theme) {
|
||||||
return new Item(
|
return new Item(
|
||||||
R.drawable.card_layout_tile,
|
R.drawable.card_layout_tile,
|
||||||
View.VISIBLE,
|
View.VISIBLE,
|
||||||
View.VISIBLE,
|
View.VISIBLE,
|
||||||
View.INVISIBLE,
|
View.INVISIBLE,
|
||||||
View.VISIBLE,
|
View.VISIBLE,
|
||||||
View.VISIBLE,
|
View.VISIBLE,
|
||||||
View.VISIBLE,
|
View.VISIBLE,
|
||||||
colorValues[theme >= colorValues.length ? 0 : theme],
|
colorValues[theme >= colorValues.length ? 0 : theme],
|
||||||
R.color.text,
|
R.color.text,
|
||||||
R.color.text,
|
R.color.text,
|
||||||
R.color.text_desc
|
R.color.text_desc
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Lesson emptyLesson(int lessonIndex) {
|
public Lesson emptyLesson(int lessonIndex) {
|
||||||
return new Lesson("empty", String.valueOf(lessonIndex), "Lyukasóra", "null", "null", 0, 0, "null");
|
return new Lesson("empty", String.valueOf(lessonIndex), "Lyukasóra", "null", "null", 0, 0, "null");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Lesson jsonToLesson(JSONObject json) {
|
public Lesson jsonToLesson(JSONObject json) {
|
||||||
try {
|
try {
|
||||||
return new Lesson(
|
return new Lesson(
|
||||||
json.getJSONObject("Allapot").getString("Nev"),
|
json.getJSONObject("Allapot").getString("Nev"),
|
||||||
!json.getString("Oraszam").equals("null") ? json.getString("Oraszam") : "+",
|
!json.getString("Oraszam").equals("null") ? json.getString("Oraszam") : "+",
|
||||||
json.getString("Nev"),
|
json.getString("Nev"),
|
||||||
json.getString("Tema"),
|
json.getString("Tema"),
|
||||||
json.getString("TeremNeve"),
|
json.getString("TeremNeve"),
|
||||||
new DateTime(json.getString("KezdetIdopont")).getMillis(),
|
new DateTime(json.getString("KezdetIdopont")).getMillis(),
|
||||||
new DateTime(json.getString("VegIdopont")).getMillis(),
|
new DateTime(json.getString("VegIdopont")).getMillis(),
|
||||||
json.getString("HelyettesTanarNeve")
|
json.getString("HelyettesTanarNeve")
|
||||||
);
|
);
|
||||||
}catch (Exception e) {
|
}catch (Exception e) {
|
||||||
Log.d("Filc", "exception: " + e);
|
Log.d("Filc", "exception: " + e);
|
||||||
};
|
};
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,12 +1,12 @@
|
|||||||
package hu.refilc.naplo.widget_timetable;
|
package hu.refilc.naplo.widget_timetable;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.widget.RemoteViewsService;
|
import android.widget.RemoteViewsService;
|
||||||
|
|
||||||
public class WidgetTimetableService extends RemoteViewsService {
|
public class WidgetTimetableService extends RemoteViewsService {
|
||||||
@Override
|
@Override
|
||||||
public RemoteViewsFactory onGetViewFactory(Intent intent) {
|
public RemoteViewsFactory onGetViewFactory(Intent intent) {
|
||||||
return new WidgetTimetableDataProvider(getApplicationContext(), intent);
|
return new WidgetTimetableDataProvider(getApplicationContext(), intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
Before Width: | Height: | Size: 1.4 KiB |
@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item>
|
|
||||||
<shape>
|
|
||||||
<gradient
|
|
||||||
android:startColor="#123323"
|
|
||||||
android:endColor="#20AC9B"
|
|
||||||
android:angle="135" />
|
|
||||||
</shape>
|
|
||||||
</item>
|
|
||||||
</selector>
|
|
@ -1,7 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:drawable="@drawable/launch_gradient_background" />
|
|
||||||
<item>
|
|
||||||
<bitmap android:gravity="center" android:src="@mipmap/ic_splash"/>
|
|
||||||
</item>
|
|
||||||
</layer-list>
|
|
@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item>
|
|
||||||
<shape>
|
|
||||||
<gradient
|
|
||||||
android:startColor="#123323"
|
|
||||||
android:endColor="#20AC9B"
|
|
||||||
android:angle="135" />
|
|
||||||
</shape>
|
|
||||||
</item>
|
|
||||||
</selector>
|
|
@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item>
|
|
||||||
<shape>
|
|
||||||
<gradient
|
|
||||||
android:startColor="#123323"
|
|
||||||
android:endColor="#20AC9B"
|
|
||||||
android:angle="135" />
|
|
||||||
</shape>
|
|
||||||
</item>
|
|
||||||
</selector>
|
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:id="@+id/main_lay"
|
android:id="@+id/main_lay"
|
||||||
android:layout_height="50dp"
|
android:layout_height="50dp"
|
||||||
@ -15,12 +16,14 @@
|
|||||||
android:id="@+id/tt_item_num"
|
android:id="@+id/tt_item_num"
|
||||||
android:layout_width="50dp"
|
android:layout_width="50dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:fontFamily="@font/montserrat_medium"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="1."
|
||||||
|
android:textColor="@color/filc"
|
||||||
|
android:textColorLink="#ff3D7BF4"
|
||||||
android:textSize="30sp"
|
android:textSize="30sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:fontFamily="@font/montserrat_medium"
|
tools:ignore="HardcodedText" />
|
||||||
android:text="1."
|
|
||||||
android:gravity="center"
|
|
||||||
android:textColor="@color/filc"></TextView>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tt_item_name"
|
android:id="@+id/tt_item_name"
|
||||||
@ -33,10 +36,11 @@
|
|||||||
android:text="Óra neve"
|
android:text="Óra neve"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:layout_toLeftOf="@id/tt_item_room"
|
android:layout_toStartOf="@id/tt_item_room"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:layout_toRightOf="@id/tt_item_num"
|
android:layout_toEndOf="@id/tt_item_num"
|
||||||
android:textColor="@color/text"></TextView>
|
android:textColor="@color/text"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tt_item_name_nodesc"
|
android:id="@+id/tt_item_name_nodesc"
|
||||||
@ -47,13 +51,14 @@
|
|||||||
android:fontFamily="@font/montserrat_medium"
|
android:fontFamily="@font/montserrat_medium"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:layout_marginTop="2.5dp"
|
android:layout_marginTop="2.5dp"
|
||||||
android:layout_toLeftOf="@id/tt_item_room"
|
android:layout_toStartOf="@id/tt_item_room"
|
||||||
android:text="Óra neve"
|
android:text="Óra neve"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:layout_toRightOf="@id/tt_item_num"
|
android:layout_toEndOf="@id/tt_item_num"
|
||||||
android:textColor="@color/text"></TextView>
|
android:textColor="@color/text"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tt_item_desc"
|
android:id="@+id/tt_item_desc"
|
||||||
@ -67,10 +72,11 @@
|
|||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:layout_toRightOf="@id/tt_item_num"
|
android:layout_toEndOf="@id/tt_item_num"
|
||||||
android:layout_toLeftOf="@id/tt_item_room"
|
android:layout_toStartOf="@id/tt_item_room"
|
||||||
android:layout_below="@id/tt_item_name"
|
android:layout_below="@id/tt_item_name"
|
||||||
android:textColor="@color/text_desc"></TextView>
|
android:textColor="@color/text_desc"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tt_item_room"
|
android:id="@+id/tt_item_room"
|
||||||
@ -84,8 +90,9 @@
|
|||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="2"
|
android:maxLines="2"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:layout_toLeftOf="@id/tt_item_time"
|
android:layout_toStartOf="@id/tt_item_time"
|
||||||
android:textColor="@color/text_desc"></TextView>
|
android:textColor="@color/text_desc"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tt_item_time"
|
android:id="@+id/tt_item_time"
|
||||||
@ -95,11 +102,12 @@
|
|||||||
android:textFontWeight="500"
|
android:textFontWeight="500"
|
||||||
android:fontFamily="@font/montserrat_medium"
|
android:fontFamily="@font/montserrat_medium"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:layout_marginLeft="2dp"
|
android:layout_marginStart="2dp"
|
||||||
android:layout_marginTop="-2dp"
|
android:layout_marginTop="-2dp"
|
||||||
android:text="8:30\n9:10"
|
android:text="8:30\n9:10"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:textColor="@color/white"></TextView>
|
android:textColor="@color/white"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
@ -19,10 +19,12 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="Empty"
|
android:text="Üres / Empty"
|
||||||
|
android:background="@drawable/widget_card_bottom_dark"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<ListView
|
<ListView
|
||||||
android:id="@+id/widget_list"
|
android:id="@+id/widget_list"
|
||||||
@ -43,57 +45,63 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="45dp"
|
android:layout_height="45dp"
|
||||||
android:background="@drawable/widget_card_top_dark">
|
android:background="@drawable/widget_card_top_dark">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/nav_refresh"
|
android:id="@+id/nav_refresh"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:layout_toStartOf="@id/nav_to_left"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:foreground="?android:attr/selectableItemBackground"
|
android:foreground="?android:attr/selectableItemBackground"
|
||||||
|
android:padding="10dp"
|
||||||
android:src="@drawable/ic_refresh_cw"
|
android:src="@drawable/ic_refresh_cw"
|
||||||
android:layout_toLeftOf="@id/nav_to_left"
|
|
||||||
android:tint="@color/text_desc"
|
android:tint="@color/text_desc"
|
||||||
tools:ignore="UseAppTint"
|
tools:ignore="UseAppTint"
|
||||||
android:padding="10dp" />
|
android:focusable="true" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/nav_to_left"
|
android:id="@+id/nav_to_left"
|
||||||
android:layout_width="50dp"
|
android:layout_width="45dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:layout_toStartOf="@id/nav_to_right"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:foreground="?android:attr/selectableItemBackground"
|
android:foreground="?android:attr/selectableItemBackground"
|
||||||
|
android:padding="10dp"
|
||||||
android:src="@drawable/ic_chevron_left"
|
android:src="@drawable/ic_chevron_left"
|
||||||
android:layout_toLeftOf="@id/nav_to_right"
|
|
||||||
android:tint="@color/text_desc"
|
android:tint="@color/text_desc"
|
||||||
tools:ignore="UseAppTint"
|
tools:ignore="UseAppTint"
|
||||||
android:padding="10dp" />
|
android:focusable="true" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/nav_to_right"
|
android:id="@+id/nav_to_right"
|
||||||
android:layout_width="50dp"
|
android:layout_width="45dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_marginEnd="5dp"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:foreground="?android:attr/selectableItemBackground"
|
android:foreground="?android:attr/selectableItemBackground"
|
||||||
|
android:padding="10dp"
|
||||||
android:src="@drawable/ic_chevron_right"
|
android:src="@drawable/ic_chevron_right"
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_marginRight="5dp"
|
|
||||||
android:tint="@color/text_desc"
|
android:tint="@color/text_desc"
|
||||||
tools:ignore="UseAppTint"
|
tools:ignore="UseAppTint"
|
||||||
android:padding="10dp" />
|
android:focusable="true" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/nav_current"
|
android:id="@+id/nav_current"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_marginLeft="20sp"
|
android:layout_marginStart="15sp"
|
||||||
android:layout_toLeftOf="@id/nav_refresh"
|
android:layout_marginTop="2sp"
|
||||||
|
android:layout_toStartOf="@id/nav_refresh"
|
||||||
android:fontFamily="@font/montserrat_medium"
|
android:fontFamily="@font/montserrat_medium"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:text="Timetable"
|
android:text="Órarend"
|
||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:textSize="24sp"
|
android:textSize="22sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
@ -131,8 +139,9 @@
|
|||||||
android:text="A widget használatához, bejelentkezés szükséges."
|
android:text="A widget használatához, bejelentkezés szükséges."
|
||||||
android:textColor="@color/black"
|
android:textColor="@color/black"
|
||||||
android:paddingTop="10dp"
|
android:paddingTop="10dp"
|
||||||
android:textSize="17dp"
|
android:textSize="17sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/open_login"
|
android:id="@+id/open_login"
|
||||||
@ -145,8 +154,9 @@
|
|||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:fontFamily="@font/montserrat_medium"
|
android:fontFamily="@font/montserrat_medium"
|
||||||
android:textSize="16dp"
|
android:textSize="16sp"
|
||||||
android:textStyle="bold"/>
|
android:textStyle="bold"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
@ -185,8 +195,9 @@
|
|||||||
android:text="Órák a kezdőképernyőd kényelméből."
|
android:text="Órák a kezdőképernyőd kényelméből."
|
||||||
android:textColor="@color/black"
|
android:textColor="@color/black"
|
||||||
android:paddingTop="10dp"
|
android:paddingTop="10dp"
|
||||||
android:textSize="16dp"
|
android:textSize="16sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@ -197,7 +208,8 @@
|
|||||||
android:textColor="@color/black"
|
android:textColor="@color/black"
|
||||||
android:layout_marginTop="0dp"
|
android:layout_marginTop="0dp"
|
||||||
android:layout_marginHorizontal="15dp"
|
android:layout_marginHorizontal="15dp"
|
||||||
android:textSize="14dp" />
|
android:textSize="14sp"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/buy_premium"
|
android:id="@+id/buy_premium"
|
||||||
@ -211,8 +223,9 @@
|
|||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:textColor="#ff691A9B"
|
android:textColor="#ff691A9B"
|
||||||
android:fontFamily="@font/montserrat_medium"
|
android:fontFamily="@font/montserrat_medium"
|
||||||
android:textSize="16dp"
|
android:textSize="16sp"
|
||||||
android:textStyle="bold"/>
|
android:textStyle="bold"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 11 KiB |
@ -1,12 +0,0 @@
|
|||||||
<resources>
|
|
||||||
|
|
||||||
<style name="Widget.Android.AppWidget.Container" parent="android:Widget">
|
|
||||||
<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>
|
|
||||||
</style>
|
|
||||||
</resources>
|
|
@ -27,7 +27,7 @@
|
|||||||
<color name="yellow_light">#ffFFCC00</color>
|
<color name="yellow_light">#ffFFCC00</color>
|
||||||
<color name="light_yellow_light">#40FFD60A</color>
|
<color name="light_yellow_light">#40FFD60A</color>
|
||||||
<color name="green_light">#ff34C759</color>
|
<color name="green_light">#ff34C759</color>
|
||||||
<color name="filc_light">#ff247665</color>
|
<color name="filc_light">#ff3D7BF4</color>
|
||||||
<color name="teal_light">#ff5AC8FA</color>
|
<color name="teal_light">#ff5AC8FA</color>
|
||||||
<color name="blue_light">#ff007AFF</color>
|
<color name="blue_light">#ff007AFF</color>
|
||||||
<color name="indigo_light">#ff5856D6</color>
|
<color name="indigo_light">#ff5856D6</color>
|
||||||
@ -49,7 +49,7 @@
|
|||||||
<color name="yellow">#ffFFD60A</color>
|
<color name="yellow">#ffFFD60A</color>
|
||||||
<color name="light_yellow">#40FFD60A</color>
|
<color name="light_yellow">#40FFD60A</color>
|
||||||
<color name="green">#ff32D74B</color>
|
<color name="green">#ff32D74B</color>
|
||||||
<color name="filc">#ff29826F</color>
|
<color name="filc">#ff3D7BF4</color>
|
||||||
<color name="teal">#ff64D2FF</color>
|
<color name="teal">#ff64D2FF</color>
|
||||||
<color name="blue">#ff0A84FF</color>
|
<color name="blue">#ff0A84FF</color>
|
||||||
<color name="indigo">#ff5E5CE6</color>
|
<color name="indigo">#ff5E5CE6</color>
|
||||||
|
BIN
filcnaplo/assets/images/static_confetti.png
Normal file
After Width: | Height: | Size: 126 KiB |
BIN
filcnaplo/assets/images/subject_covers/math_light.png
Normal file
After Width: | Height: | Size: 19 KiB |
@ -1,237 +0,0 @@
|
|||||||
PODS:
|
|
||||||
- app_group_directory (1.0.0):
|
|
||||||
- Flutter
|
|
||||||
- background_fetch (1.1.6):
|
|
||||||
- Flutter
|
|
||||||
- connectivity_plus (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- ReachabilitySwift
|
|
||||||
- DKImagePickerController/Core (4.3.4):
|
|
||||||
- DKImagePickerController/ImageDataManager
|
|
||||||
- DKImagePickerController/Resource
|
|
||||||
- DKImagePickerController/ImageDataManager (4.3.4)
|
|
||||||
- DKImagePickerController/PhotoGallery (4.3.4):
|
|
||||||
- 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)
|
|
||||||
- SDWebImage
|
|
||||||
- SwiftyGif
|
|
||||||
- DKPhotoGallery/Core (0.0.17):
|
|
||||||
- DKPhotoGallery/Model
|
|
||||||
- DKPhotoGallery/Preview
|
|
||||||
- SDWebImage
|
|
||||||
- SwiftyGif
|
|
||||||
- DKPhotoGallery/Model (0.0.17):
|
|
||||||
- SDWebImage
|
|
||||||
- SwiftyGif
|
|
||||||
- DKPhotoGallery/Preview (0.0.17):
|
|
||||||
- DKPhotoGallery/Model
|
|
||||||
- DKPhotoGallery/Resource
|
|
||||||
- SDWebImage
|
|
||||||
- SwiftyGif
|
|
||||||
- DKPhotoGallery/Resource (0.0.17):
|
|
||||||
- SDWebImage
|
|
||||||
- SwiftyGif
|
|
||||||
- file_picker (0.0.1):
|
|
||||||
- DKImagePickerController/PhotoGallery
|
|
||||||
- Flutter
|
|
||||||
- Flutter (1.0.0)
|
|
||||||
- flutter_custom_tabs (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- flutter_image_compress (1.0.0):
|
|
||||||
- Flutter
|
|
||||||
- Mantle
|
|
||||||
- SDWebImage
|
|
||||||
- SDWebImageWebPCoder
|
|
||||||
- flutter_local_notifications (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- flutter_native_image (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- flutter_native_splash (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- FMDB (2.7.5):
|
|
||||||
- FMDB/standard (= 2.7.5)
|
|
||||||
- FMDB/standard (2.7.5)
|
|
||||||
- home_widget (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- image_picker_ios (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- libwebp (1.2.4):
|
|
||||||
- libwebp/demux (= 1.2.4)
|
|
||||||
- libwebp/mux (= 1.2.4)
|
|
||||||
- libwebp/webp (= 1.2.4)
|
|
||||||
- libwebp/demux (1.2.4):
|
|
||||||
- libwebp/webp
|
|
||||||
- libwebp/mux (1.2.4):
|
|
||||||
- libwebp/demux
|
|
||||||
- libwebp/webp (1.2.4)
|
|
||||||
- live_activities (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- Mantle (2.2.0):
|
|
||||||
- Mantle/extobjc (= 2.2.0)
|
|
||||||
- Mantle/extobjc (2.2.0)
|
|
||||||
- open_file (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- package_info_plus (0.4.5):
|
|
||||||
- Flutter
|
|
||||||
- path_provider_foundation (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- FlutterMacOS
|
|
||||||
- permission_handler_apple (9.0.4):
|
|
||||||
- Flutter
|
|
||||||
- quick_actions_ios (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- ReachabilitySwift (5.0.0)
|
|
||||||
- SDWebImage (5.13.2):
|
|
||||||
- SDWebImage/Core (= 5.13.2)
|
|
||||||
- SDWebImage/Core (5.13.2)
|
|
||||||
- SDWebImageWebPCoder (0.9.1):
|
|
||||||
- libwebp (~> 1.0)
|
|
||||||
- SDWebImage/Core (~> 5.13)
|
|
||||||
- share_plus (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- sqflite (0.0.3):
|
|
||||||
- Flutter
|
|
||||||
- FMDB (>= 2.7.5)
|
|
||||||
- SwiftyGif (5.4.3)
|
|
||||||
- uni_links (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- url_launcher_ios (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- workmanager (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
|
|
||||||
DEPENDENCIES:
|
|
||||||
- app_group_directory (from `.symlinks/plugins/app_group_directory/ios`)
|
|
||||||
- background_fetch (from `.symlinks/plugins/background_fetch/ios`)
|
|
||||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
|
||||||
- DKImagePickerController/PhotoGallery (from `https://github.com/zhangao0086/DKImagePickerController.git`)
|
|
||||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
|
||||||
- Flutter (from `Flutter`)
|
|
||||||
- flutter_custom_tabs (from `.symlinks/plugins/flutter_custom_tabs/ios`)
|
|
||||||
- flutter_image_compress (from `.symlinks/plugins/flutter_image_compress/ios`)
|
|
||||||
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
|
||||||
- flutter_native_image (from `.symlinks/plugins/flutter_native_image/ios`)
|
|
||||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
|
||||||
- home_widget (from `.symlinks/plugins/home_widget/ios`)
|
|
||||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
|
||||||
- live_activities (from `.symlinks/plugins/live_activities/ios`)
|
|
||||||
- open_file (from `.symlinks/plugins/open_file/ios`)
|
|
||||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
|
||||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
|
||||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
|
||||||
- quick_actions_ios (from `.symlinks/plugins/quick_actions_ios/ios`)
|
|
||||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
|
||||||
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
|
||||||
- uni_links (from `.symlinks/plugins/uni_links/ios`)
|
|
||||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
|
||||||
- workmanager (from `.symlinks/plugins/workmanager/ios`)
|
|
||||||
|
|
||||||
SPEC REPOS:
|
|
||||||
trunk:
|
|
||||||
- DKPhotoGallery
|
|
||||||
- FMDB
|
|
||||||
- libwebp
|
|
||||||
- Mantle
|
|
||||||
- ReachabilitySwift
|
|
||||||
- SDWebImage
|
|
||||||
- SDWebImageWebPCoder
|
|
||||||
- SwiftyGif
|
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
|
||||||
app_group_directory:
|
|
||||||
:path: ".symlinks/plugins/app_group_directory/ios"
|
|
||||||
background_fetch:
|
|
||||||
:path: ".symlinks/plugins/background_fetch/ios"
|
|
||||||
connectivity_plus:
|
|
||||||
:path: ".symlinks/plugins/connectivity_plus/ios"
|
|
||||||
DKImagePickerController:
|
|
||||||
:git: https://github.com/zhangao0086/DKImagePickerController.git
|
|
||||||
file_picker:
|
|
||||||
:path: ".symlinks/plugins/file_picker/ios"
|
|
||||||
Flutter:
|
|
||||||
:path: Flutter
|
|
||||||
flutter_custom_tabs:
|
|
||||||
:path: ".symlinks/plugins/flutter_custom_tabs/ios"
|
|
||||||
flutter_image_compress:
|
|
||||||
:path: ".symlinks/plugins/flutter_image_compress/ios"
|
|
||||||
flutter_local_notifications:
|
|
||||||
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
|
||||||
flutter_native_image:
|
|
||||||
:path: ".symlinks/plugins/flutter_native_image/ios"
|
|
||||||
flutter_native_splash:
|
|
||||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
|
||||||
home_widget:
|
|
||||||
:path: ".symlinks/plugins/home_widget/ios"
|
|
||||||
image_picker_ios:
|
|
||||||
:path: ".symlinks/plugins/image_picker_ios/ios"
|
|
||||||
live_activities:
|
|
||||||
:path: ".symlinks/plugins/live_activities/ios"
|
|
||||||
open_file:
|
|
||||||
:path: ".symlinks/plugins/open_file/ios"
|
|
||||||
package_info_plus:
|
|
||||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
|
||||||
path_provider_foundation:
|
|
||||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
|
||||||
permission_handler_apple:
|
|
||||||
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
|
||||||
quick_actions_ios:
|
|
||||||
:path: ".symlinks/plugins/quick_actions_ios/ios"
|
|
||||||
share_plus:
|
|
||||||
:path: ".symlinks/plugins/share_plus/ios"
|
|
||||||
sqflite:
|
|
||||||
:path: ".symlinks/plugins/sqflite/ios"
|
|
||||||
uni_links:
|
|
||||||
:path: ".symlinks/plugins/uni_links/ios"
|
|
||||||
url_launcher_ios:
|
|
||||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
|
||||||
workmanager:
|
|
||||||
:path: ".symlinks/plugins/workmanager/ios"
|
|
||||||
|
|
||||||
CHECKOUT OPTIONS:
|
|
||||||
DKImagePickerController:
|
|
||||||
:commit: a727e44718a67e300089174e5591166045815ba4
|
|
||||||
:git: https://github.com/zhangao0086/DKImagePickerController.git
|
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
|
||||||
app_group_directory: 7bf9f8f9819ead554de29da7c25fb7a680d6a9a0
|
|
||||||
background_fetch: bc9b44b0bf8b434e282a2ac9be8662800a0296ed
|
|
||||||
connectivity_plus: 07c49e96d7fc92bc9920617b83238c4d178b446a
|
|
||||||
DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
|
|
||||||
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
|
|
||||||
file_picker: ce3938a0df3cc1ef404671531facef740d03f920
|
|
||||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
|
||||||
flutter_custom_tabs: 7a10a08686955cb748e5d26e0ae586d30689bf89
|
|
||||||
flutter_image_compress: 5a5e9aee05b6553048b8df1c3bc456d0afaac433
|
|
||||||
flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
|
|
||||||
flutter_native_image: 9c0b7451838484458e5b0fae007b86a4c2d4bdfe
|
|
||||||
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
|
|
||||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
|
||||||
home_widget: 2829415127ee92e876f816cbbe44c0b6601b8a37
|
|
||||||
image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5
|
|
||||||
libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef
|
|
||||||
live_activities: 9ff56a06a2d43ecd68f56deeed13b18a8304789c
|
|
||||||
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
|
|
||||||
open_file: 02eb5cb6b21264bd3a696876f5afbfb7ca4f4b7d
|
|
||||||
package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7
|
|
||||||
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
|
|
||||||
permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
|
|
||||||
quick_actions_ios: 9e80dcfadfbc5d47d9cf8f47bcf428b11cf383d4
|
|
||||||
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
|
||||||
SDWebImage: 72f86271a6f3139cc7e4a89220946489d4b9a866
|
|
||||||
SDWebImageWebPCoder: 18503de6621dd2c420d680e33d46bf8e1d5169b0
|
|
||||||
share_plus: 599aa54e4ea31d4b4c0e9c911bcc26c55e791028
|
|
||||||
sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a
|
|
||||||
SwiftyGif: 6c3eafd0ce693cad58bb63d2b2fb9bacb8552780
|
|
||||||
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
|
|
||||||
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
|
|
||||||
workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6
|
|
||||||
|
|
||||||
PODFILE CHECKSUM: efe5e2e257c61a1c3d5be693ef1a8ea1c4b81d8f
|
|
||||||
|
|
||||||
COCOAPODS: 1.12.1
|
|
@ -198,9 +198,9 @@
|
|||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 3127F79F28EAEDE300C2EFB3 /* Build configuration list for PBXNativeTarget "livecard" */;
|
buildConfigurationList = 3127F79F28EAEDE300C2EFB3 /* Build configuration list for PBXNativeTarget "livecard" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
|
3127F78A28EAEDE200C2EFB3 /* Resources */,
|
||||||
3127F78828EAEDE200C2EFB3 /* Sources */,
|
3127F78828EAEDE200C2EFB3 /* Sources */,
|
||||||
3127F78928EAEDE200C2EFB3 /* Frameworks */,
|
3127F78928EAEDE200C2EFB3 /* Frameworks */,
|
||||||
3127F78A28EAEDE200C2EFB3 /* Resources */,
|
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@ -299,7 +299,7 @@
|
|||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
alwaysOutOfDate = 1;
|
alwaysOutOfDate = 1;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 12;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
@ -310,11 +310,11 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n";
|
||||||
};
|
};
|
||||||
71459C0EB905E05018E3D78F /* [CP] Embed Pods Frameworks */ = {
|
71459C0EB905E05018E3D78F /* [CP] Embed Pods Frameworks */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 12;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
@ -364,7 +364,7 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
|
||||||
};
|
};
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>aps-environment</key>
|
||||||
|
<string>development</string>
|
||||||
<key>com.apple.security.application-groups</key>
|
<key>com.apple.security.application-groups</key>
|
||||||
<array>
|
<array>
|
||||||
<string>group.refilcnaplo.livecard</string>
|
<string>group.refilcnaplo.livecard</string>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class LessonData {
|
class LessonData {
|
||||||
|
var color: String
|
||||||
var icon: String
|
var icon: String
|
||||||
var index: String
|
var index: String
|
||||||
var title: String
|
var title: String
|
||||||
@ -15,6 +16,7 @@ class LessonData {
|
|||||||
init?() {
|
init?() {
|
||||||
let sharedDefault = UserDefaults(suiteName: "group.refilc.livecard")!
|
let sharedDefault = UserDefaults(suiteName: "group.refilc.livecard")!
|
||||||
|
|
||||||
|
self.color = sharedDefault.string(forKey: "color")!
|
||||||
self.icon = sharedDefault.string(forKey: "icon")!
|
self.icon = sharedDefault.string(forKey: "icon")!
|
||||||
self.index = sharedDefault.string(forKey: "index")!
|
self.index = sharedDefault.string(forKey: "index")!
|
||||||
self.title = sharedDefault.string(forKey: "title")!
|
self.title = sharedDefault.string(forKey: "title")!
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>aps-environment</key>
|
||||||
|
<string>development</string>
|
||||||
<key>com.apple.security.application-groups</key>
|
<key>com.apple.security.application-groups</key>
|
||||||
<array>
|
<array>
|
||||||
<string>group.refilcnaplo.livecard</string>
|
<string>group.refilcnaplo.livecard</string>
|
||||||
|
@ -11,6 +11,33 @@ struct Widgets: WidgetBundle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Color Converter
|
||||||
|
extension Color {
|
||||||
|
init(hex: String, alpha: Double = 1.0) {
|
||||||
|
var hexValue = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
|
||||||
|
|
||||||
|
if hexValue.hasPrefix("#") {
|
||||||
|
hexValue.remove(at: hexValue.startIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
var rgbValue: UInt64 = 0
|
||||||
|
Scanner(string: hexValue).scanHexInt64(&rgbValue)
|
||||||
|
|
||||||
|
let red = Double((rgbValue & 0xFF0000) >> 16) / 255.0
|
||||||
|
let green = Double((rgbValue & 0x00FF00) >> 8) / 255.0
|
||||||
|
let blue = Double(rgbValue & 0x0000FF) / 255.0
|
||||||
|
|
||||||
|
self.init(
|
||||||
|
.sRGB,
|
||||||
|
red: red,
|
||||||
|
green: green,
|
||||||
|
blue: blue,
|
||||||
|
opacity: alpha
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// We need to redefined live activities pipe
|
// We need to redefined live activities pipe
|
||||||
struct LiveActivitiesAppAttributes: ActivityAttributes, Identifiable {
|
struct LiveActivitiesAppAttributes: ActivityAttributes, Identifiable {
|
||||||
public struct ContentState: Codable, Hashable { }
|
public struct ContentState: Codable, Hashable { }
|
||||||
@ -68,6 +95,11 @@ struct LockScreenLiveActivityView: View {
|
|||||||
.monospacedDigit()
|
.monospacedDigit()
|
||||||
.padding(.trailing, CGFloat(24))
|
.padding(.trailing, CGFloat(24))
|
||||||
}
|
}
|
||||||
|
.activityBackgroundTint(
|
||||||
|
lesson!.color == "#676767"
|
||||||
|
? nil
|
||||||
|
: Color(hex: lesson!.color)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +176,11 @@ struct LiveCardWidget: Widget {
|
|||||||
.font(.system(size: CGFloat(10)))
|
.font(.system(size: CGFloat(10)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.keylineTint(.accentColor)
|
.keylineTint(
|
||||||
|
lesson!.color == "#676767"
|
||||||
|
? nil
|
||||||
|
: Color(hex: lesson!.color)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,27 +47,28 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
required SettingsProvider settings,
|
required SettingsProvider settings,
|
||||||
}) : _timetable = timetable,
|
}) : _timetable = timetable,
|
||||||
_settings = settings {
|
_settings = settings {
|
||||||
// Check if live card is enabled .areActivitiesEnabled()
|
if (Platform.isIOS) {
|
||||||
_liveActivitiesPlugin.areActivitiesEnabled().then((value) {
|
_liveActivitiesPlugin.areActivitiesEnabled().then((value) {
|
||||||
// Console log
|
// Console log
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
print("Live card enabled: $value");
|
print("Live card enabled: $value");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
_liveActivitiesPlugin.init(appGroupId: "group.refilc.livecard");
|
_liveActivitiesPlugin.init(appGroupId: "group.refilc.livecard");
|
||||||
|
|
||||||
_liveActivitiesPlugin.getAllActivitiesIds().then((value) {
|
_liveActivitiesPlugin.getAllActivitiesIds().then((value) {
|
||||||
_latestActivityId = value.isNotEmpty ? value.first : null;
|
_latestActivityId = value.isNotEmpty ? value.first : null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) => update());
|
_timer = Timer.periodic(const Duration(seconds: 1), (timer) => update());
|
||||||
_delay = settings.bellDelayEnabled
|
_delay = settings.bellDelayEnabled
|
||||||
? Duration(seconds: settings.bellDelay)
|
? Duration(seconds: settings.bellDelay)
|
||||||
: Duration.zero;
|
: Duration.zero;
|
||||||
update();
|
update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -87,6 +88,7 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
// Debugging
|
// Debugging
|
||||||
static DateTime _now() {
|
static DateTime _now() {
|
||||||
|
// return DateTime(2023, 8, 31, 8, 0);
|
||||||
return DateTime.now();
|
return DateTime.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +112,8 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
switch (currentState) {
|
switch (currentState) {
|
||||||
case LiveCardState.duringLesson:
|
case LiveCardState.duringLesson:
|
||||||
return {
|
return {
|
||||||
|
"color":
|
||||||
|
'#${_settings.liveActivityColor.toString().substring(10, 16)}',
|
||||||
"icon": currentLesson != null
|
"icon": currentLesson != null
|
||||||
? SubjectIcon.resolveName(subject: currentLesson?.subject)
|
? SubjectIcon.resolveName(subject: currentLesson?.subject)
|
||||||
: "book",
|
: "book",
|
||||||
@ -142,6 +146,8 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
final diff = getFloorDifference();
|
final diff = getFloorDifference();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
"color":
|
||||||
|
'#${_settings.liveActivityColor.toString().substring(10, 16)}',
|
||||||
"icon": iconFloorMap[diff] ?? "cup.and.saucer",
|
"icon": iconFloorMap[diff] ?? "cup.and.saucer",
|
||||||
"title": "Szünet",
|
"title": "Szünet",
|
||||||
"description": "go $diff".i18n.fill([
|
"description": "go $diff".i18n.fill([
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:filcnaplo/api/client.dart';
|
import 'package:filcnaplo/api/client.dart';
|
||||||
import 'package:filcnaplo/models/news.dart';
|
import 'package:filcnaplo/models/news.dart';
|
||||||
import 'package:filcnaplo/models/settings.dart';
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
@ -11,7 +8,7 @@ import 'package:provider/provider.dart';
|
|||||||
class NewsProvider extends ChangeNotifier {
|
class NewsProvider extends ChangeNotifier {
|
||||||
// Private
|
// Private
|
||||||
late List<News> _news;
|
late List<News> _news;
|
||||||
late int _state;
|
//late int _state;
|
||||||
late int _fresh;
|
late int _fresh;
|
||||||
bool show = false;
|
bool show = false;
|
||||||
late BuildContext _context;
|
late BuildContext _context;
|
||||||
@ -30,56 +27,83 @@ class NewsProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
Future<void> restore() async {
|
Future<void> restore() async {
|
||||||
// Load news state from the database
|
// Load news state from the database
|
||||||
var state_ = Provider.of<SettingsProvider>(_context, listen: false).newsState;
|
var seen_ = Provider.of<SettingsProvider>(_context, listen: false).seenNews;
|
||||||
|
|
||||||
if (state_ == -1) {
|
if (seen_.isEmpty) {
|
||||||
var news_ = await FilcAPI.getNews();
|
var news_ = await FilcAPI.getNews();
|
||||||
if (news_ != null) {
|
if (news_ != null) {
|
||||||
state_ = news_.length;
|
|
||||||
_news = news_;
|
_news = news_;
|
||||||
|
show = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_state = state_;
|
//_state = seen_;
|
||||||
Provider.of<SettingsProvider>(_context, listen: false).update(newsState: _state);
|
// Provider.of<SettingsProvider>(_context, listen: false)
|
||||||
|
// .update(seenNewsId: news_.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> fetch() async {
|
Future<void> fetch() async {
|
||||||
var news_ = await FilcAPI.getNews();
|
var news_ = await FilcAPI.getNews();
|
||||||
if (news_ == null) return;
|
if (news_ == null) return;
|
||||||
|
|
||||||
|
show = false;
|
||||||
|
|
||||||
_news = news_;
|
_news = news_;
|
||||||
_fresh = news_.length - _state;
|
|
||||||
|
|
||||||
if (_fresh < 0) {
|
for (var news in news_) {
|
||||||
_state = news_.length;
|
if (news.expireDate.isAfter(DateTime.now()) &&
|
||||||
Provider.of<SettingsProvider>(_context, listen: false).update(newsState: _state);
|
Provider.of<SettingsProvider>(_context, listen: false)
|
||||||
|
.seenNews
|
||||||
|
.contains(news.id) ==
|
||||||
|
false) {
|
||||||
|
show = true;
|
||||||
|
Provider.of<SettingsProvider>(_context, listen: false)
|
||||||
|
.update(seenNewsId: news.id);
|
||||||
|
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// print(news_.length);
|
||||||
|
// print(_state);
|
||||||
|
|
||||||
_fresh = max(_fresh, 0);
|
// _news = news_;
|
||||||
|
// _fresh = news_.length - _state;
|
||||||
|
|
||||||
if (_fresh > 0) {
|
// if (_fresh < 0) {
|
||||||
show = true;
|
// _state = news_.length;
|
||||||
notifyListeners();
|
// Provider.of<SettingsProvider>(_context, listen: false)
|
||||||
}
|
// .update(newsState: _state);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// _fresh = max(_fresh, 0);
|
||||||
|
|
||||||
|
// if (_fresh > 0) {
|
||||||
|
// show = true;
|
||||||
|
// notifyListeners();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// print(_fresh);
|
||||||
|
// print(_state);
|
||||||
|
// print(show);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lock() => show = false;
|
void lock() => show = false;
|
||||||
|
|
||||||
void release() {
|
void release() {
|
||||||
if (_fresh == 0) return;
|
// if (_fresh == 0) return;
|
||||||
|
|
||||||
_fresh--;
|
// _fresh--;
|
||||||
_state++;
|
// //_state++;
|
||||||
|
|
||||||
Provider.of<SettingsProvider>(_context, listen: false).update(newsState: _state);
|
// // Provider.of<SettingsProvider>(_context, listen: false)
|
||||||
|
// // .update(seenNewsId: _state);
|
||||||
|
|
||||||
if (_fresh > 0) {
|
// if (_fresh > 0) {
|
||||||
show = true;
|
// show = true;
|
||||||
} else {
|
// } else {
|
||||||
show = false;
|
// show = false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
notifyListeners();
|
// notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import 'package:filcnaplo/theme/observer.dart';
|
|||||||
import 'package:filcnaplo/theme/theme.dart';
|
import 'package:filcnaplo/theme/theme.dart';
|
||||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
||||||
|
import 'package:filcnaplo_premium/providers/goal_provider.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -89,6 +90,7 @@ class App extends StatelessWidget {
|
|||||||
|
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
providers: [
|
providers: [
|
||||||
|
// refilc providers
|
||||||
ChangeNotifierProvider<PremiumProvider>(create: (_) => premium),
|
ChangeNotifierProvider<PremiumProvider>(create: (_) => premium),
|
||||||
ChangeNotifierProvider<SettingsProvider>(create: (_) => settings),
|
ChangeNotifierProvider<SettingsProvider>(create: (_) => settings),
|
||||||
ChangeNotifierProvider<UserProvider>(create: (_) => user),
|
ChangeNotifierProvider<UserProvider>(create: (_) => user),
|
||||||
@ -103,7 +105,7 @@ class App extends StatelessWidget {
|
|||||||
ChangeNotifierProvider<UpdateProvider>(
|
ChangeNotifierProvider<UpdateProvider>(
|
||||||
create: (context) => UpdateProvider(context: context)),
|
create: (context) => UpdateProvider(context: context)),
|
||||||
|
|
||||||
// User data providers
|
// user data (kreten) providers
|
||||||
ChangeNotifierProvider<GradeProvider>(
|
ChangeNotifierProvider<GradeProvider>(
|
||||||
create: (_) => GradeProvider(
|
create: (_) => GradeProvider(
|
||||||
settings: settings,
|
settings: settings,
|
||||||
@ -114,7 +116,8 @@ class App extends StatelessWidget {
|
|||||||
ChangeNotifierProvider<ExamProvider>(
|
ChangeNotifierProvider<ExamProvider>(
|
||||||
create: (context) => ExamProvider(context: context)),
|
create: (context) => ExamProvider(context: context)),
|
||||||
ChangeNotifierProvider<HomeworkProvider>(
|
ChangeNotifierProvider<HomeworkProvider>(
|
||||||
create: (context) => HomeworkProvider(context: context)),
|
create: (context) =>
|
||||||
|
HomeworkProvider(context: context, database: database)),
|
||||||
ChangeNotifierProvider<MessageProvider>(
|
ChangeNotifierProvider<MessageProvider>(
|
||||||
create: (context) => MessageProvider(context: context)),
|
create: (context) => MessageProvider(context: context)),
|
||||||
ChangeNotifierProvider<NoteProvider>(
|
ChangeNotifierProvider<NoteProvider>(
|
||||||
@ -124,6 +127,7 @@ class App extends StatelessWidget {
|
|||||||
ChangeNotifierProvider<AbsenceProvider>(
|
ChangeNotifierProvider<AbsenceProvider>(
|
||||||
create: (context) => AbsenceProvider(context: context)),
|
create: (context) => AbsenceProvider(context: context)),
|
||||||
|
|
||||||
|
// other providers
|
||||||
ChangeNotifierProvider<GradeCalculatorProvider>(
|
ChangeNotifierProvider<GradeCalculatorProvider>(
|
||||||
create: (_) => GradeCalculatorProvider(
|
create: (_) => GradeCalculatorProvider(
|
||||||
settings: settings,
|
settings: settings,
|
||||||
@ -132,7 +136,9 @@ class App extends StatelessWidget {
|
|||||||
kreta: kreta)),
|
kreta: kreta)),
|
||||||
ChangeNotifierProvider<LiveCardProvider>(
|
ChangeNotifierProvider<LiveCardProvider>(
|
||||||
create: (context) =>
|
create: (context) =>
|
||||||
LiveCardProvider(timetable: timetable, settings: settings))
|
LiveCardProvider(timetable: timetable, settings: settings)),
|
||||||
|
ChangeNotifierProvider<GoalProvider>(
|
||||||
|
create: (context) => GoalProvider(database: database, user: user)),
|
||||||
],
|
],
|
||||||
child: Consumer<ThemeModeObserver>(
|
child: Consumer<ThemeModeObserver>(
|
||||||
builder: (context, themeMode, child) {
|
builder: (context, themeMode, child) {
|
||||||
|
@ -12,20 +12,27 @@ import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';
|
|||||||
|
|
||||||
const settingsDB = DatabaseStruct("settings", {
|
const settingsDB = DatabaseStruct("settings", {
|
||||||
"language": String, "start_page": int, "rounding": int, "theme": int,
|
"language": String, "start_page": int, "rounding": int, "theme": int,
|
||||||
"accent_color": int, "news": int, "news_state": int, "developer_mode": int,
|
"accent_color": int, "news": int, "seen_news": String,
|
||||||
|
"developer_mode": int,
|
||||||
"update_channel": int, "config": String, "custom_accent_color": int,
|
"update_channel": int, "config": String, "custom_accent_color": int,
|
||||||
"custom_background_color": int, "custom_highlight_color": int, // general
|
"custom_background_color": int, "custom_highlight_color": int, // general
|
||||||
"grade_color1": int, "grade_color2": int, "grade_color3": int,
|
"grade_color1": int, "grade_color2": int, "grade_color3": int,
|
||||||
"grade_color4": int, "grade_color5": int, // grade colors
|
"grade_color4": int, "grade_color5": int, // grade colors
|
||||||
"vibration_strength": int, "ab_weeks": int, "swap_ab_weeks": int,
|
"vibration_strength": int, "ab_weeks": int, "swap_ab_weeks": int,
|
||||||
"notifications": int, "notifications_bitfield": int,
|
"notifications": int, "notifications_bitfield": int,
|
||||||
"notification_poll_interval": int, // notifications
|
"notification_poll_interval": int,
|
||||||
|
"notifications_grades": int,
|
||||||
|
"notifications_absences": int,
|
||||||
|
"notifications_messages": int,
|
||||||
|
"notifications_lessons": int, // notifications
|
||||||
"x_filc_id": String, "graph_class_avg": int, "presentation_mode": int,
|
"x_filc_id": String, "graph_class_avg": int, "presentation_mode": int,
|
||||||
"bell_delay": int, "bell_delay_enabled": int,
|
"bell_delay": int, "bell_delay_enabled": int,
|
||||||
"grade_opening_fun": int, "icon_pack": String, "premium_scopes": String,
|
"grade_opening_fun": int, "icon_pack": String, "premium_scopes": String,
|
||||||
"premium_token": String, "premium_login": String,
|
"premium_token": String, "premium_login": String,
|
||||||
"last_account_id": String, "renamed_subjects_enabled": int,
|
"last_account_id": String, "renamed_subjects_enabled": int,
|
||||||
"renamed_subjects_italics": int,
|
"renamed_subjects_italics": int, "renamed_teachers_enabled": int,
|
||||||
|
"renamed_teachers_italics": int,
|
||||||
|
"live_activity_color": String,
|
||||||
});
|
});
|
||||||
// DON'T FORGET TO UPDATE DEFAULT VALUES IN `initDB` MIGRATION OR ELSE PARENTS WILL COMPLAIN ABOUT THEIR CHILDREN MISSING
|
// DON'T FORGET TO UPDATE DEFAULT VALUES IN `initDB` MIGRATION OR ELSE PARENTS WILL COMPLAIN ABOUT THEIR CHILDREN MISSING
|
||||||
// YOU'VE BEEN WARNED!!!
|
// YOU'VE BEEN WARNED!!!
|
||||||
@ -40,8 +47,15 @@ const userDataDB = DatabaseStruct("user_data", {
|
|||||||
"events": String, "absences": String, "group_averages": String,
|
"events": String, "absences": String, "group_averages": String,
|
||||||
// renamed subjects // non kreta data
|
// renamed subjects // non kreta data
|
||||||
"renamed_subjects": String,
|
"renamed_subjects": String,
|
||||||
|
// renamed teachers // non kreta data
|
||||||
|
"renamed_teachers": String,
|
||||||
// "subject_lesson_count": String, // non kreta data
|
// "subject_lesson_count": String, // non kreta data
|
||||||
"last_seen_grade": int,
|
"last_seen_grade": int,
|
||||||
|
// goal planning // non kreta data
|
||||||
|
"goal_plans": String,
|
||||||
|
"goal_averages": String,
|
||||||
|
"goal_befores": String,
|
||||||
|
"goal_pin_dates": String,
|
||||||
});
|
});
|
||||||
|
|
||||||
Future<void> createTable(Database db, DatabaseStruct struct) =>
|
Future<void> createTable(Database db, DatabaseStruct struct) =>
|
||||||
@ -89,8 +103,15 @@ Future<Database> initDB(DatabaseProvider database) async {
|
|||||||
"group_averages": "[]",
|
"group_averages": "[]",
|
||||||
// renamed subjects // non kreta data
|
// renamed subjects // non kreta data
|
||||||
"renamed_subjects": "{}",
|
"renamed_subjects": "{}",
|
||||||
|
// renamed teachers // non kreta data
|
||||||
|
"renamed_teachers": "{}",
|
||||||
// "subject_lesson_count": "{}", // non kreta data
|
// "subject_lesson_count": "{}", // non kreta data
|
||||||
"last_seen_grade": 0,
|
"last_seen_grade": 0,
|
||||||
|
// goal planning // non kreta data
|
||||||
|
"goal_plans": "{}",
|
||||||
|
"goal_averages": "{}",
|
||||||
|
"goal_befores": "{}",
|
||||||
|
"goal_pin_dates": "{}",
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
print("ERROR: migrateDB: $error");
|
print("ERROR: migrateDB: $error");
|
||||||
|
@ -26,7 +26,8 @@ class DatabaseQuery {
|
|||||||
|
|
||||||
Future<SettingsProvider> getSettings(DatabaseProvider database) async {
|
Future<SettingsProvider> getSettings(DatabaseProvider database) async {
|
||||||
Map settingsMap = (await db.query("settings")).elementAt(0);
|
Map settingsMap = (await db.query("settings")).elementAt(0);
|
||||||
SettingsProvider settings = SettingsProvider.fromMap(settingsMap, database: database);
|
SettingsProvider settings =
|
||||||
|
SettingsProvider.fromMap(settingsMap, database: database);
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +37,10 @@ class DatabaseQuery {
|
|||||||
for (var user in usersMap) {
|
for (var user in usersMap) {
|
||||||
userProvider.addUser(User.fromMap(user));
|
userProvider.addUser(User.fromMap(user));
|
||||||
}
|
}
|
||||||
if (userProvider.getUsers().map((e) => e.id).contains(settings.lastAccountId)) {
|
if (userProvider
|
||||||
|
.getUsers()
|
||||||
|
.map((e) => e.id)
|
||||||
|
.contains(settings.lastAccountId)) {
|
||||||
userProvider.setUser(settings.lastAccountId);
|
userProvider.setUser(settings.lastAccountId);
|
||||||
} else {
|
} else {
|
||||||
if (usersMap.isNotEmpty) {
|
if (usersMap.isNotEmpty) {
|
||||||
@ -54,100 +58,133 @@ class UserDatabaseQuery {
|
|||||||
final Database db;
|
final Database db;
|
||||||
|
|
||||||
Future<List<Grade>> getGrades({required String userId}) async {
|
Future<List<Grade>> getGrades({required String userId}) async {
|
||||||
List<Map> userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
List<Map> userData =
|
||||||
|
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
if (userData.isEmpty) return [];
|
if (userData.isEmpty) return [];
|
||||||
String? gradesJson = userData.elementAt(0)["grades"] as String?;
|
String? gradesJson = userData.elementAt(0)["grades"] as String?;
|
||||||
if (gradesJson == null) return [];
|
if (gradesJson == null) return [];
|
||||||
List<Grade> grades = (jsonDecode(gradesJson) as List).map((e) => Grade.fromJson(e)).toList();
|
List<Grade> grades =
|
||||||
|
(jsonDecode(gradesJson) as List).map((e) => Grade.fromJson(e)).toList();
|
||||||
return grades;
|
return grades;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<Week, List<Lesson>>> getLessons({required String userId}) async {
|
Future<Map<Week, List<Lesson>>> getLessons({required String userId}) async {
|
||||||
List<Map> userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
List<Map> userData =
|
||||||
|
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
if (userData.isEmpty) return {};
|
if (userData.isEmpty) return {};
|
||||||
String? lessonsJson = userData.elementAt(0)["timetable"] as String?;
|
String? lessonsJson = userData.elementAt(0)["timetable"] as String?;
|
||||||
if (lessonsJson == null) return {};
|
if (lessonsJson == null) return {};
|
||||||
if (jsonDecode(lessonsJson) is List) return {};
|
if (jsonDecode(lessonsJson) is List) return {};
|
||||||
Map<Week, List<Lesson>> lessons = (jsonDecode(lessonsJson) as Map).cast<String, List>().map((key, value) {
|
Map<Week, List<Lesson>> lessons =
|
||||||
return MapEntry(Week.fromId(int.parse(key)), value.cast<Map<String, Object?>>().map((e) => Lesson.fromJson(e)).toList());
|
(jsonDecode(lessonsJson) as Map).cast<String, List>().map((key, value) {
|
||||||
|
return MapEntry(
|
||||||
|
Week.fromId(int.parse(key)),
|
||||||
|
value
|
||||||
|
.cast<Map<String, Object?>>()
|
||||||
|
.map((e) => Lesson.fromJson(e))
|
||||||
|
.toList());
|
||||||
}).cast();
|
}).cast();
|
||||||
return lessons;
|
return lessons;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Exam>> getExams({required String userId}) async {
|
Future<List<Exam>> getExams({required String userId}) async {
|
||||||
List<Map> userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
List<Map> userData =
|
||||||
|
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
if (userData.isEmpty) return [];
|
if (userData.isEmpty) return [];
|
||||||
String? examsJson = userData.elementAt(0)["exams"] as String?;
|
String? examsJson = userData.elementAt(0)["exams"] as String?;
|
||||||
if (examsJson == null) return [];
|
if (examsJson == null) return [];
|
||||||
List<Exam> exams = (jsonDecode(examsJson) as List).map((e) => Exam.fromJson(e)).toList();
|
List<Exam> exams =
|
||||||
|
(jsonDecode(examsJson) as List).map((e) => Exam.fromJson(e)).toList();
|
||||||
return exams;
|
return exams;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Homework>> getHomework({required String userId}) async {
|
Future<List<Homework>> getHomework({required String userId}) async {
|
||||||
List<Map> userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
List<Map> userData =
|
||||||
|
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
if (userData.isEmpty) return [];
|
if (userData.isEmpty) return [];
|
||||||
String? homeworkJson = userData.elementAt(0)["homework"] as String?;
|
String? homeworkJson = userData.elementAt(0)["homework"] as String?;
|
||||||
if (homeworkJson == null) return [];
|
if (homeworkJson == null) return [];
|
||||||
List<Homework> homework = (jsonDecode(homeworkJson) as List).map((e) => Homework.fromJson(e)).toList();
|
List<Homework> homework = (jsonDecode(homeworkJson) as List)
|
||||||
|
.map((e) => Homework.fromJson(e))
|
||||||
|
.toList();
|
||||||
return homework;
|
return homework;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Message>> getMessages({required String userId}) async {
|
Future<List<Message>> getMessages({required String userId}) async {
|
||||||
List<Map> userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
List<Map> userData =
|
||||||
|
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
if (userData.isEmpty) return [];
|
if (userData.isEmpty) return [];
|
||||||
String? messagesJson = userData.elementAt(0)["messages"] as String?;
|
String? messagesJson = userData.elementAt(0)["messages"] as String?;
|
||||||
if (messagesJson == null) return [];
|
if (messagesJson == null) return [];
|
||||||
List<Message> messages = (jsonDecode(messagesJson) as List).map((e) => Message.fromJson(e)).toList();
|
List<Message> messages = (jsonDecode(messagesJson) as List)
|
||||||
|
.map((e) => Message.fromJson(e))
|
||||||
|
.toList();
|
||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Note>> getNotes({required String userId}) async {
|
Future<List<Note>> getNotes({required String userId}) async {
|
||||||
List<Map> userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
List<Map> userData =
|
||||||
|
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
if (userData.isEmpty) return [];
|
if (userData.isEmpty) return [];
|
||||||
String? notesJson = userData.elementAt(0)["notes"] as String?;
|
String? notesJson = userData.elementAt(0)["notes"] as String?;
|
||||||
if (notesJson == null) return [];
|
if (notesJson == null) return [];
|
||||||
List<Note> notes = (jsonDecode(notesJson) as List).map((e) => Note.fromJson(e)).toList();
|
List<Note> notes =
|
||||||
|
(jsonDecode(notesJson) as List).map((e) => Note.fromJson(e)).toList();
|
||||||
return notes;
|
return notes;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Event>> getEvents({required String userId}) async {
|
Future<List<Event>> getEvents({required String userId}) async {
|
||||||
List<Map> userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
List<Map> userData =
|
||||||
|
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
if (userData.isEmpty) return [];
|
if (userData.isEmpty) return [];
|
||||||
String? eventsJson = userData.elementAt(0)["events"] as String?;
|
String? eventsJson = userData.elementAt(0)["events"] as String?;
|
||||||
if (eventsJson == null) return [];
|
if (eventsJson == null) return [];
|
||||||
List<Event> events = (jsonDecode(eventsJson) as List).map((e) => Event.fromJson(e)).toList();
|
List<Event> events =
|
||||||
|
(jsonDecode(eventsJson) as List).map((e) => Event.fromJson(e)).toList();
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Absence>> getAbsences({required String userId}) async {
|
Future<List<Absence>> getAbsences({required String userId}) async {
|
||||||
List<Map> userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
List<Map> userData =
|
||||||
|
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
if (userData.isEmpty) return [];
|
if (userData.isEmpty) return [];
|
||||||
String? absencesJson = userData.elementAt(0)["absences"] as String?;
|
String? absencesJson = userData.elementAt(0)["absences"] as String?;
|
||||||
if (absencesJson == null) return [];
|
if (absencesJson == null) return [];
|
||||||
List<Absence> absences = (jsonDecode(absencesJson) as List).map((e) => Absence.fromJson(e)).toList();
|
List<Absence> absences = (jsonDecode(absencesJson) as List)
|
||||||
|
.map((e) => Absence.fromJson(e))
|
||||||
|
.toList();
|
||||||
return absences;
|
return absences;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<GroupAverage>> getGroupAverages({required String userId}) async {
|
Future<List<GroupAverage>> getGroupAverages({required String userId}) async {
|
||||||
List<Map> userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
List<Map> userData =
|
||||||
|
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
if (userData.isEmpty) return [];
|
if (userData.isEmpty) return [];
|
||||||
String? groupAveragesJson = userData.elementAt(0)["group_averages"] as String?;
|
String? groupAveragesJson =
|
||||||
|
userData.elementAt(0)["group_averages"] as String?;
|
||||||
if (groupAveragesJson == null) return [];
|
if (groupAveragesJson == null) return [];
|
||||||
List<GroupAverage> groupAverages = (jsonDecode(groupAveragesJson) as List).map((e) => GroupAverage.fromJson(e)).toList();
|
List<GroupAverage> groupAverages = (jsonDecode(groupAveragesJson) as List)
|
||||||
|
.map((e) => GroupAverage.fromJson(e))
|
||||||
|
.toList();
|
||||||
return groupAverages;
|
return groupAverages;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<SubjectLessonCount> getSubjectLessonCount({required String userId}) async {
|
Future<SubjectLessonCount> getSubjectLessonCount(
|
||||||
List<Map> userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
{required String userId}) async {
|
||||||
|
List<Map> userData =
|
||||||
|
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
if (userData.isEmpty) return SubjectLessonCount.fromMap({});
|
if (userData.isEmpty) return SubjectLessonCount.fromMap({});
|
||||||
String? lessonCountJson = userData.elementAt(0)["subject_lesson_count"] as String?;
|
String? lessonCountJson =
|
||||||
|
userData.elementAt(0)["subject_lesson_count"] as String?;
|
||||||
if (lessonCountJson == null) return SubjectLessonCount.fromMap({});
|
if (lessonCountJson == null) return SubjectLessonCount.fromMap({});
|
||||||
SubjectLessonCount lessonCount = SubjectLessonCount.fromMap(jsonDecode(lessonCountJson) as Map);
|
SubjectLessonCount lessonCount =
|
||||||
|
SubjectLessonCount.fromMap(jsonDecode(lessonCountJson) as Map);
|
||||||
return lessonCount;
|
return lessonCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<DateTime> lastSeenGrade({required String userId}) async {
|
Future<DateTime> lastSeenGrade({required String userId}) async {
|
||||||
List<Map> userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
List<Map> userData =
|
||||||
|
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
if (userData.isEmpty) return DateTime(0);
|
if (userData.isEmpty) return DateTime(0);
|
||||||
int? lastSeenDate = userData.elementAt(0)["last_seen_grade"] as int?;
|
int? lastSeenDate = userData.elementAt(0)["last_seen_grade"] as int?;
|
||||||
if (lastSeenDate == null) return DateTime(0);
|
if (lastSeenDate == null) return DateTime(0);
|
||||||
@ -155,11 +192,71 @@ class UserDatabaseQuery {
|
|||||||
return lastSeen;
|
return lastSeen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// renamed things
|
||||||
Future<Map<String, String>> renamedSubjects({required String userId}) async {
|
Future<Map<String, String>> renamedSubjects({required String userId}) async {
|
||||||
List<Map> userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
List<Map> userData =
|
||||||
|
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
if (userData.isEmpty) return {};
|
if (userData.isEmpty) return {};
|
||||||
String? renamedSubjectsJson = userData.elementAt(0)["renamed_subjects"] as String?;
|
String? renamedSubjectsJson =
|
||||||
|
userData.elementAt(0)["renamed_subjects"] as String?;
|
||||||
if (renamedSubjectsJson == null) return {};
|
if (renamedSubjectsJson == null) return {};
|
||||||
return (jsonDecode(renamedSubjectsJson) as Map).map((key, value) => MapEntry(key.toString(), value.toString()));
|
return (jsonDecode(renamedSubjectsJson) as Map)
|
||||||
|
.map((key, value) => MapEntry(key.toString(), value.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Map<String, String>> renamedTeachers({required String userId}) async {
|
||||||
|
List<Map> userData =
|
||||||
|
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
|
if (userData.isEmpty) return {};
|
||||||
|
String? renamedTeachersJson =
|
||||||
|
userData.elementAt(0)["renamed_teachers"] as String?;
|
||||||
|
if (renamedTeachersJson == null) return {};
|
||||||
|
return (jsonDecode(renamedTeachersJson) as Map)
|
||||||
|
.map((key, value) => MapEntry(key.toString(), value.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// goal planner
|
||||||
|
Future<Map<String, String>> subjectGoalPlans({required String userId}) async {
|
||||||
|
List<Map> userData =
|
||||||
|
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
|
if (userData.isEmpty) return {};
|
||||||
|
String? goalPlansJson = userData.elementAt(0)["goal_plans"] as String?;
|
||||||
|
if (goalPlansJson == null) return {};
|
||||||
|
return (jsonDecode(goalPlansJson) as Map)
|
||||||
|
.map((key, value) => MapEntry(key.toString(), value.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Map<String, String>> subjectGoalAverages(
|
||||||
|
{required String userId}) async {
|
||||||
|
List<Map> userData =
|
||||||
|
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
|
if (userData.isEmpty) return {};
|
||||||
|
String? goalAvgsJson = userData.elementAt(0)["goal_averages"] as String?;
|
||||||
|
if (goalAvgsJson == null) return {};
|
||||||
|
return (jsonDecode(goalAvgsJson) as Map)
|
||||||
|
.map((key, value) => MapEntry(key.toString(), value.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Map<String, String>> subjectGoalBefores(
|
||||||
|
{required String userId}) async {
|
||||||
|
List<Map> userData =
|
||||||
|
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
|
if (userData.isEmpty) return {};
|
||||||
|
String? goalBeforesJson = userData.elementAt(0)["goal_befores"] as String?;
|
||||||
|
if (goalBeforesJson == null) return {};
|
||||||
|
return (jsonDecode(goalBeforesJson) as Map)
|
||||||
|
.map((key, value) => MapEntry(key.toString(), value.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Map<String, String>> subjectGoalPinDates(
|
||||||
|
{required String userId}) async {
|
||||||
|
List<Map> userData =
|
||||||
|
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||||
|
if (userData.isEmpty) return {};
|
||||||
|
String? goalPinDatesJson =
|
||||||
|
userData.elementAt(0)["goal_pin_dates"] as String?;
|
||||||
|
if (goalPinDatesJson == null) return {};
|
||||||
|
return (jsonDecode(goalPinDatesJson) as Map)
|
||||||
|
.map((key, value) => MapEntry(key.toString(), value.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,11 @@ class DatabaseStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> storeUser(User user) async {
|
Future<void> storeUser(User user) async {
|
||||||
List userRes = await db.query("users", where: "id = ?", whereArgs: [user.id]);
|
List userRes =
|
||||||
|
await db.query("users", where: "id = ?", whereArgs: [user.id]);
|
||||||
if (userRes.isNotEmpty) {
|
if (userRes.isNotEmpty) {
|
||||||
await db.update("users", user.toMap(), where: "id = ?", whereArgs: [user.id]);
|
await db
|
||||||
|
.update("users", user.toMap(), where: "id = ?", whereArgs: [user.id]);
|
||||||
} else {
|
} else {
|
||||||
await db.insert("users", user.toMap());
|
await db.insert("users", user.toMap());
|
||||||
await db.insert("user_data", {"id": user.id});
|
await db.insert("user_data", {"id": user.id});
|
||||||
@ -49,64 +51,123 @@ class UserDatabaseStore {
|
|||||||
|
|
||||||
Future<void> storeGrades(List<Grade> grades, {required String userId}) async {
|
Future<void> storeGrades(List<Grade> grades, {required String userId}) async {
|
||||||
String gradesJson = jsonEncode(grades.map((e) => e.json).toList());
|
String gradesJson = jsonEncode(grades.map((e) => e.json).toList());
|
||||||
await db.update("user_data", {"grades": gradesJson}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"grades": gradesJson},
|
||||||
|
where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> storeLessons(Map<Week, List<Lesson>?> lessons, {required String userId}) async {
|
Future<void> storeLessons(Map<Week, List<Lesson>?> lessons,
|
||||||
|
{required String userId}) async {
|
||||||
final map = lessons.map<String, List<Map<String, Object?>>>(
|
final map = lessons.map<String, List<Map<String, Object?>>>(
|
||||||
(k, v) => MapEntry(k.id.toString(), v!.where((e) => e.json != null).map((e) => e.json!).toList().cast()),
|
(k, v) => MapEntry(k.id.toString(),
|
||||||
|
v!.where((e) => e.json != null).map((e) => e.json!).toList().cast()),
|
||||||
);
|
);
|
||||||
String lessonsJson = jsonEncode(map);
|
String lessonsJson = jsonEncode(map);
|
||||||
await db.update("user_data", {"timetable": lessonsJson}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"timetable": lessonsJson},
|
||||||
|
where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> storeExams(List<Exam> exams, {required String userId}) async {
|
Future<void> storeExams(List<Exam> exams, {required String userId}) async {
|
||||||
String examsJson = jsonEncode(exams.map((e) => e.json).toList());
|
String examsJson = jsonEncode(exams.map((e) => e.json).toList());
|
||||||
await db.update("user_data", {"exams": examsJson}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"exams": examsJson},
|
||||||
|
where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> storeHomework(List<Homework> homework, {required String userId}) async {
|
Future<void> storeHomework(List<Homework> homework,
|
||||||
|
{required String userId}) async {
|
||||||
String homeworkJson = jsonEncode(homework.map((e) => e.json).toList());
|
String homeworkJson = jsonEncode(homework.map((e) => e.json).toList());
|
||||||
await db.update("user_data", {"homework": homeworkJson}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"homework": homeworkJson},
|
||||||
|
where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> storeMessages(List<Message> messages, {required String userId}) async {
|
Future<void> storeMessages(List<Message> messages,
|
||||||
|
{required String userId}) async {
|
||||||
String messagesJson = jsonEncode(messages.map((e) => e.json).toList());
|
String messagesJson = jsonEncode(messages.map((e) => e.json).toList());
|
||||||
await db.update("user_data", {"messages": messagesJson}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"messages": messagesJson},
|
||||||
|
where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> storeNotes(List<Note> notes, {required String userId}) async {
|
Future<void> storeNotes(List<Note> notes, {required String userId}) async {
|
||||||
String notesJson = jsonEncode(notes.map((e) => e.json).toList());
|
String notesJson = jsonEncode(notes.map((e) => e.json).toList());
|
||||||
await db.update("user_data", {"notes": notesJson}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"notes": notesJson},
|
||||||
|
where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> storeEvents(List<Event> events, {required String userId}) async {
|
Future<void> storeEvents(List<Event> events, {required String userId}) async {
|
||||||
String eventsJson = jsonEncode(events.map((e) => e.json).toList());
|
String eventsJson = jsonEncode(events.map((e) => e.json).toList());
|
||||||
await db.update("user_data", {"events": eventsJson}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"events": eventsJson},
|
||||||
|
where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> storeAbsences(List<Absence> absences, {required String userId}) async {
|
Future<void> storeAbsences(List<Absence> absences,
|
||||||
|
{required String userId}) async {
|
||||||
String absencesJson = jsonEncode(absences.map((e) => e.json).toList());
|
String absencesJson = jsonEncode(absences.map((e) => e.json).toList());
|
||||||
await db.update("user_data", {"absences": absencesJson}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"absences": absencesJson},
|
||||||
|
where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> storeGroupAverages(List<GroupAverage> groupAverages, {required String userId}) async {
|
Future<void> storeGroupAverages(List<GroupAverage> groupAverages,
|
||||||
String groupAveragesJson = jsonEncode(groupAverages.map((e) => e.json).toList());
|
{required String userId}) async {
|
||||||
await db.update("user_data", {"group_averages": groupAveragesJson}, where: "id = ?", whereArgs: [userId]);
|
String groupAveragesJson =
|
||||||
|
jsonEncode(groupAverages.map((e) => e.json).toList());
|
||||||
|
await db.update("user_data", {"group_averages": groupAveragesJson},
|
||||||
|
where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> storeSubjectLessonCount(SubjectLessonCount lessonCount, {required String userId}) async {
|
Future<void> storeSubjectLessonCount(SubjectLessonCount lessonCount,
|
||||||
|
{required String userId}) async {
|
||||||
String lessonCountJson = jsonEncode(lessonCount.toMap());
|
String lessonCountJson = jsonEncode(lessonCount.toMap());
|
||||||
await db.update("user_data", {"subject_lesson_count": lessonCountJson}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"subject_lesson_count": lessonCountJson},
|
||||||
|
where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> storeLastSeenGrade(DateTime date, {required String userId}) async {
|
Future<void> storeLastSeenGrade(DateTime date,
|
||||||
|
{required String userId}) async {
|
||||||
int lastSeenDate = date.millisecondsSinceEpoch;
|
int lastSeenDate = date.millisecondsSinceEpoch;
|
||||||
await db.update("user_data", {"last_seen_grade": lastSeenDate}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"last_seen_grade": lastSeenDate},
|
||||||
|
where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> storeRenamedSubjects(Map<String, String> subjects, {required String userId}) async {
|
// renamed things
|
||||||
|
Future<void> storeRenamedSubjects(Map<String, String> subjects,
|
||||||
|
{required String userId}) async {
|
||||||
String renamedSubjectsJson = jsonEncode(subjects);
|
String renamedSubjectsJson = jsonEncode(subjects);
|
||||||
await db.update("user_data", {"renamed_subjects": renamedSubjectsJson}, where: "id = ?", whereArgs: [userId]);
|
await db.update("user_data", {"renamed_subjects": renamedSubjectsJson},
|
||||||
|
where: "id = ?", whereArgs: [userId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> storeRenamedTeachers(Map<String, String> teachers,
|
||||||
|
{required String userId}) async {
|
||||||
|
String renamedTeachersJson = jsonEncode(teachers);
|
||||||
|
await db.update("user_data", {"renamed_teachers": renamedTeachersJson},
|
||||||
|
where: "id = ?", whereArgs: [userId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// goal planner
|
||||||
|
Future<void> storeSubjectGoalPlans(Map<String, String> plans,
|
||||||
|
{required String userId}) async {
|
||||||
|
String goalPlansJson = jsonEncode(plans);
|
||||||
|
await db.update("user_data", {"goal_plans": goalPlansJson},
|
||||||
|
where: "id = ?", whereArgs: [userId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> storeSubjectGoalAverages(Map<String, String> avgs,
|
||||||
|
{required String userId}) async {
|
||||||
|
String goalAvgsJson = jsonEncode(avgs);
|
||||||
|
await db.update("user_data", {"goal_averages": goalAvgsJson},
|
||||||
|
where: "id = ?", whereArgs: [userId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> storeSubjectGoalBefores(Map<String, String> befores,
|
||||||
|
{required String userId}) async {
|
||||||
|
String goalBeforesJson = jsonEncode(befores);
|
||||||
|
await db.update("user_data", {"goal_befores": goalBeforesJson},
|
||||||
|
where: "id = ?", whereArgs: [userId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> storeSubjectGoalPinDates(Map<String, String> dates,
|
||||||
|
{required String userId}) async {
|
||||||
|
String goalPinDatesJson = jsonEncode(dates);
|
||||||
|
await db.update("user_data", {"goal_pin_dates": goalPinDatesJson},
|
||||||
|
where: "id = ?", whereArgs: [userId]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,76 +1,601 @@
|
|||||||
import 'dart:math';
|
|
||||||
import 'dart:ui';
|
|
||||||
|
|
||||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||||
import 'package:filcnaplo/api/providers/status_provider.dart';
|
import 'package:filcnaplo/api/providers/status_provider.dart';
|
||||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||||
import 'package:filcnaplo/models/settings.dart';
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
import 'package:filcnaplo/helpers/notification_helper.i18n.dart';
|
import 'package:filcnaplo/helpers/notification_helper.i18n.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/absence.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/lesson.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/week.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
||||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
|
||||||
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart'
|
||||||
|
hide Message;
|
||||||
|
import 'package:i18n_extension/i18n_widget.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/message.dart';
|
||||||
|
|
||||||
class NotificationsHelper {
|
class NotificationsHelper {
|
||||||
|
late DatabaseProvider database;
|
||||||
|
late SettingsProvider settingsProvider;
|
||||||
|
late UserProvider userProvider;
|
||||||
|
late KretaClient kretaClient;
|
||||||
|
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
|
||||||
|
FlutterLocalNotificationsPlugin();
|
||||||
|
|
||||||
|
List<T> combineLists<T, K>(
|
||||||
|
List<T> list1,
|
||||||
|
List<T> list2,
|
||||||
|
K Function(T) keyExtractor,
|
||||||
|
) {
|
||||||
|
Set<K> uniqueKeys = <K>{};
|
||||||
|
List<T> combinedList = [];
|
||||||
|
|
||||||
|
for (T item in list1) {
|
||||||
|
K key = keyExtractor(item);
|
||||||
|
if (!uniqueKeys.contains(key)) {
|
||||||
|
uniqueKeys.add(key);
|
||||||
|
combinedList.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (T item in list2) {
|
||||||
|
K key = keyExtractor(item);
|
||||||
|
if (!uniqueKeys.contains(key)) {
|
||||||
|
uniqueKeys.add(key);
|
||||||
|
combinedList.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return combinedList;
|
||||||
|
}
|
||||||
|
|
||||||
|
String dayTitle(DateTime date) {
|
||||||
|
try {
|
||||||
|
return DateFormat("EEEE", I18n.locale.languageCode).format(date);
|
||||||
|
} catch (e) {
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@pragma('vm:entry-point')
|
@pragma('vm:entry-point')
|
||||||
void backgroundJob() async {
|
void backgroundJob() async {
|
||||||
// initialize providers
|
// initialize providers
|
||||||
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
|
database = DatabaseProvider();
|
||||||
FlutterLocalNotificationsPlugin();
|
|
||||||
DatabaseProvider database = DatabaseProvider();
|
|
||||||
await database.init();
|
await database.init();
|
||||||
SettingsProvider settingsProvider =
|
settingsProvider = await database.query.getSettings(database);
|
||||||
await database.query.getSettings(database);
|
userProvider = await database.query.getUsers(settingsProvider);
|
||||||
UserProvider userProvider = await database.query.getUsers(settingsProvider);
|
|
||||||
|
|
||||||
if (userProvider.id != null && settingsProvider.notificationsEnabled) {
|
if (userProvider.id != null && settingsProvider.notificationsEnabled) {
|
||||||
// refresh grades
|
// refresh kreta login
|
||||||
final status = StatusProvider();
|
final status = StatusProvider();
|
||||||
final kretaClient = KretaClient(
|
kretaClient = KretaClient(
|
||||||
user: userProvider, settings: settingsProvider, status: status);
|
user: userProvider, settings: settingsProvider, status: status);
|
||||||
kretaClient.refreshLogin();
|
kretaClient.refreshLogin();
|
||||||
GradeProvider gradeProvider = GradeProvider(
|
if (settingsProvider.notificationsGradesEnabled) gradeNotification();
|
||||||
settings: settingsProvider,
|
if (settingsProvider.notificationsAbsencesEnabled) absenceNotification();
|
||||||
user: userProvider,
|
if (settingsProvider.notificationsMessagesEnabled) messageNotification();
|
||||||
database: database,
|
if (settingsProvider.notificationsLessonsEnabled) lessonNotification();
|
||||||
kreta: kretaClient);
|
}
|
||||||
gradeProvider.fetch();
|
}
|
||||||
List<Grade> grades =
|
|
||||||
await database.userQuery.getGrades(userId: userProvider.id ?? "");
|
|
||||||
DateTime lastSeenGrade =
|
|
||||||
await database.userQuery.lastSeenGrade(userId: userProvider.id ?? "");
|
|
||||||
|
|
||||||
// loop through grades and see which hasn't been seen yet
|
void gradeNotification() async {
|
||||||
for (Grade grade in grades) {
|
// fetch grades
|
||||||
|
GradeProvider gradeProvider = GradeProvider(
|
||||||
|
settings: settingsProvider,
|
||||||
|
user: userProvider,
|
||||||
|
database: database,
|
||||||
|
kreta: kretaClient);
|
||||||
|
gradeProvider.fetch();
|
||||||
|
List<Grade> grades =
|
||||||
|
await database.userQuery.getGrades(userId: userProvider.id ?? "");
|
||||||
|
DateTime lastSeenGrade =
|
||||||
|
await database.userQuery.lastSeenGrade(userId: userProvider.id ?? "");
|
||||||
|
|
||||||
|
// loop through grades and see which hasn't been seen yet
|
||||||
|
for (Grade grade in grades) {
|
||||||
|
// if grade is not a normal grade (1-5), don't show it
|
||||||
|
if ([1, 2, 3, 4, 5].contains(grade.value.value)) {
|
||||||
// if the grade was added over a week ago, don't show it to avoid notification spam
|
// if the grade was added over a week ago, don't show it to avoid notification spam
|
||||||
if (grade.seenDate.isAfter(lastSeenGrade) &&
|
if (grade.seenDate.isAfter(lastSeenGrade) &&
|
||||||
grade.date.difference(DateTime.now()).inDays * -1 < 7) {
|
grade.date.difference(DateTime.now()).inDays * -1 < 7) {
|
||||||
// send notificiation about new grade
|
// send notificiation about new grade
|
||||||
const AndroidNotificationDetails androidNotificationDetails =
|
AndroidNotificationDetails androidNotificationDetails =
|
||||||
AndroidNotificationDetails('GRADES', 'Jegyek',
|
AndroidNotificationDetails(
|
||||||
channelDescription: 'Értesítés jegyek beírásakor',
|
'GRADES',
|
||||||
importance: Importance.max,
|
'Jegyek',
|
||||||
priority: Priority.max,
|
channelDescription: 'Értesítés jegyek beírásakor',
|
||||||
color: Color(0xFF3D7BF4),
|
importance: Importance.max,
|
||||||
ticker: 'Jegyek');
|
priority: Priority.max,
|
||||||
const NotificationDetails notificationDetails =
|
color: settingsProvider.customAccentColor,
|
||||||
|
ticker: 'Jegyek',
|
||||||
|
);
|
||||||
|
NotificationDetails notificationDetails =
|
||||||
NotificationDetails(android: androidNotificationDetails);
|
NotificationDetails(android: androidNotificationDetails);
|
||||||
await flutterLocalNotificationsPlugin.show(
|
if (userProvider.getUsers().length == 1) {
|
||||||
// probably shouldn't use a random int
|
await flutterLocalNotificationsPlugin.show(
|
||||||
Random().nextInt(432234 * 2),
|
grade.id.hashCode,
|
||||||
"title".i18n,
|
"title_grade".i18n,
|
||||||
"body".i18n.fill([
|
"body_grade".i18n.fill(
|
||||||
grade.value.value.toString(),
|
[
|
||||||
grade.subject.isRenamed &&
|
grade.value.value.toString(),
|
||||||
settingsProvider.renamedSubjectsEnabled
|
grade.subject.isRenamed &&
|
||||||
? grade.subject.renamedTo!
|
settingsProvider.renamedSubjectsEnabled
|
||||||
: grade.subject.name
|
? grade.subject.renamedTo!
|
||||||
]),
|
: grade.subject.name
|
||||||
notificationDetails);
|
],
|
||||||
|
),
|
||||||
|
notificationDetails,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// multiple users are added, also display student name
|
||||||
|
await flutterLocalNotificationsPlugin.show(
|
||||||
|
grade.id.hashCode,
|
||||||
|
"title_grade".i18n,
|
||||||
|
"body_grade_multiuser".i18n.fill(
|
||||||
|
[
|
||||||
|
userProvider.displayName!,
|
||||||
|
grade.value.value.toString(),
|
||||||
|
grade.subject.isRenamed &&
|
||||||
|
settingsProvider.renamedSubjectsEnabled
|
||||||
|
? grade.subject.renamedTo!
|
||||||
|
: grade.subject.name
|
||||||
|
],
|
||||||
|
),
|
||||||
|
notificationDetails,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// set grade seen status
|
}
|
||||||
gradeProvider.seenAll();
|
// set grade seen status
|
||||||
|
gradeProvider.seenAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void absenceNotification() async {
|
||||||
|
// get absences from api
|
||||||
|
List? absenceJson = await kretaClient
|
||||||
|
.getAPI(KretaAPI.absences(userProvider.instituteCode ?? ""));
|
||||||
|
List<Absence> storedAbsences =
|
||||||
|
await database.userQuery.getAbsences(userId: userProvider.id!);
|
||||||
|
if (absenceJson == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// format api absences to correct format while preserving isSeen value
|
||||||
|
List<Absence> absences = absenceJson.map((e) {
|
||||||
|
Absence apiAbsence = Absence.fromJson(e);
|
||||||
|
Absence storedAbsence = storedAbsences.firstWhere(
|
||||||
|
(stored) => stored.id == apiAbsence.id,
|
||||||
|
orElse: () => apiAbsence);
|
||||||
|
apiAbsence.isSeen = storedAbsence.isSeen;
|
||||||
|
return apiAbsence;
|
||||||
|
}).toList();
|
||||||
|
List<Absence> modifiedAbsences = [];
|
||||||
|
if (absences != storedAbsences) {
|
||||||
|
// remove absences that are not new
|
||||||
|
absences.removeWhere((element) => storedAbsences.contains(element));
|
||||||
|
for (Absence absence in absences) {
|
||||||
|
if (!absence.isSeen) {
|
||||||
|
absence.isSeen = true;
|
||||||
|
modifiedAbsences.add(absence);
|
||||||
|
AndroidNotificationDetails androidNotificationDetails =
|
||||||
|
AndroidNotificationDetails(
|
||||||
|
'ABSENCES',
|
||||||
|
'Hiányzások',
|
||||||
|
channelDescription: 'Értesítés hiányzások beírásakor',
|
||||||
|
importance: Importance.max,
|
||||||
|
priority: Priority.max,
|
||||||
|
color: settingsProvider.customAccentColor,
|
||||||
|
ticker: 'Hiányzások',
|
||||||
|
);
|
||||||
|
NotificationDetails notificationDetails =
|
||||||
|
NotificationDetails(android: androidNotificationDetails);
|
||||||
|
if (userProvider.getUsers().length == 1) {
|
||||||
|
await flutterLocalNotificationsPlugin.show(
|
||||||
|
absence.id.hashCode,
|
||||||
|
"title_absence".i18n,
|
||||||
|
"body_absence".i18n.fill(
|
||||||
|
[
|
||||||
|
DateFormat("yyyy-MM-dd").format(absence.date),
|
||||||
|
absence.subject.isRenamed &&
|
||||||
|
settingsProvider.renamedSubjectsEnabled
|
||||||
|
? absence.subject.renamedTo!
|
||||||
|
: absence.subject.name
|
||||||
|
],
|
||||||
|
),
|
||||||
|
notificationDetails,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
await flutterLocalNotificationsPlugin.show(
|
||||||
|
absence.id.hashCode,
|
||||||
|
"title_absence".i18n,
|
||||||
|
"body_absence_multiuser".i18n.fill(
|
||||||
|
[
|
||||||
|
userProvider.displayName!,
|
||||||
|
DateFormat("yyyy-MM-dd").format(absence.date),
|
||||||
|
absence.subject.isRenamed &&
|
||||||
|
settingsProvider.renamedSubjectsEnabled
|
||||||
|
? absence.subject.renamedTo!
|
||||||
|
: absence.subject.name
|
||||||
|
],
|
||||||
|
),
|
||||||
|
notificationDetails,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// combine modified absences and storedabsences list and save them to the database
|
||||||
|
List<Absence> combinedAbsences = combineLists(
|
||||||
|
modifiedAbsences,
|
||||||
|
storedAbsences,
|
||||||
|
(Absence absence) => absence.id,
|
||||||
|
);
|
||||||
|
await database.userStore
|
||||||
|
.storeAbsences(combinedAbsences, userId: userProvider.id!);
|
||||||
|
}
|
||||||
|
|
||||||
|
void messageNotification() async {
|
||||||
|
// get messages from api
|
||||||
|
List? messageJson =
|
||||||
|
await kretaClient.getAPI(KretaAPI.messages("beerkezett"));
|
||||||
|
List<Message> storedmessages =
|
||||||
|
await database.userQuery.getMessages(userId: userProvider.id!);
|
||||||
|
if (messageJson == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// format api messages to correct format while preserving isSeen value
|
||||||
|
// Parse messages
|
||||||
|
List<Message> messages = [];
|
||||||
|
await Future.wait(List.generate(messageJson.length, (index) {
|
||||||
|
return () async {
|
||||||
|
Map message = messageJson.cast<Map>()[index];
|
||||||
|
Map? innerMessageJson = await kretaClient
|
||||||
|
.getAPI(KretaAPI.message(message["azonosito"].toString()));
|
||||||
|
if (innerMessageJson != null) {
|
||||||
|
messages.add(
|
||||||
|
Message.fromJson(innerMessageJson, forceType: MessageType.inbox));
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
}));
|
||||||
|
|
||||||
|
for (Message message in messages) {
|
||||||
|
for (Message storedMessage in storedmessages) {
|
||||||
|
if (message.id == storedMessage.id) {
|
||||||
|
message.isSeen = storedMessage.isSeen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<Message> modifiedmessages = [];
|
||||||
|
if (messages != storedmessages) {
|
||||||
|
// remove messages that are not new
|
||||||
|
messages.removeWhere((element) => storedmessages.contains(element));
|
||||||
|
for (Message message in messages) {
|
||||||
|
if (!message.isSeen) {
|
||||||
|
message.isSeen = true;
|
||||||
|
modifiedmessages.add(message);
|
||||||
|
AndroidNotificationDetails androidNotificationDetails =
|
||||||
|
AndroidNotificationDetails(
|
||||||
|
'MESSAGES',
|
||||||
|
'Üzenetek',
|
||||||
|
channelDescription: 'Értesítés kapott üzenetekkor',
|
||||||
|
importance: Importance.max,
|
||||||
|
priority: Priority.max,
|
||||||
|
color: settingsProvider.customAccentColor,
|
||||||
|
ticker: 'Üzenetek',
|
||||||
|
);
|
||||||
|
NotificationDetails notificationDetails =
|
||||||
|
NotificationDetails(android: androidNotificationDetails);
|
||||||
|
if (userProvider.getUsers().length == 1) {
|
||||||
|
await flutterLocalNotificationsPlugin.show(
|
||||||
|
message.id.hashCode,
|
||||||
|
message.author,
|
||||||
|
message.content.replaceAll(RegExp(r'<[^>]*>'), ''),
|
||||||
|
notificationDetails,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
await flutterLocalNotificationsPlugin.show(
|
||||||
|
message.id.hashCode,
|
||||||
|
"(${userProvider.displayName!}) ${message.author}",
|
||||||
|
message.content.replaceAll(RegExp(r'<[^>]*>'), ''),
|
||||||
|
notificationDetails,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// combine modified messages and storedmessages list and save them to the database
|
||||||
|
List<Message> combinedmessages = combineLists(
|
||||||
|
modifiedmessages,
|
||||||
|
storedmessages,
|
||||||
|
(Message message) => message.id,
|
||||||
|
);
|
||||||
|
await database.userStore
|
||||||
|
.storeMessages(combinedmessages, userId: userProvider.id!);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lessonNotification() async {
|
||||||
|
// get lesson from api
|
||||||
|
TimetableProvider timetableProvider = TimetableProvider(
|
||||||
|
user: userProvider, database: database, kreta: kretaClient);
|
||||||
|
List<Lesson> storedlessons =
|
||||||
|
timetableProvider.lessons[Week.current()] ?? [];
|
||||||
|
List? apilessons = timetableProvider.getWeek(Week.current()) ?? [];
|
||||||
|
for (Lesson lesson in apilessons) {
|
||||||
|
for (Lesson storedLesson in storedlessons) {
|
||||||
|
if (lesson.id == storedLesson.id) {
|
||||||
|
lesson.isSeen = storedLesson.isSeen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<Lesson> modifiedlessons = [];
|
||||||
|
if (apilessons != storedlessons) {
|
||||||
|
// remove lessons that are not new
|
||||||
|
apilessons.removeWhere((element) => storedlessons.contains(element));
|
||||||
|
for (Lesson lesson in apilessons) {
|
||||||
|
if (!lesson.isSeen && lesson.isChanged) {
|
||||||
|
lesson.isSeen = true;
|
||||||
|
modifiedlessons.add(lesson);
|
||||||
|
AndroidNotificationDetails androidNotificationDetails =
|
||||||
|
AndroidNotificationDetails(
|
||||||
|
'LESSONS',
|
||||||
|
'Órák',
|
||||||
|
channelDescription:
|
||||||
|
'Értesítés órák elmaradásáról, helyettesítésről',
|
||||||
|
importance: Importance.max,
|
||||||
|
priority: Priority.max,
|
||||||
|
color: settingsProvider.customAccentColor,
|
||||||
|
ticker: 'Órák',
|
||||||
|
);
|
||||||
|
NotificationDetails notificationDetails =
|
||||||
|
NotificationDetails(android: androidNotificationDetails);
|
||||||
|
if (userProvider.getUsers().length == 1) {
|
||||||
|
if (lesson.status?.name == "Elmaradt") {
|
||||||
|
switch (I18n.localeStr) {
|
||||||
|
case "en_en":
|
||||||
|
{
|
||||||
|
await flutterLocalNotificationsPlugin.show(
|
||||||
|
lesson.id.hashCode,
|
||||||
|
"title_lesson".i18n,
|
||||||
|
"body_lesson_canceled".i18n.fill(
|
||||||
|
[
|
||||||
|
lesson.lessonIndex,
|
||||||
|
lesson.name,
|
||||||
|
dayTitle(lesson.date)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
notificationDetails,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "hu_hu":
|
||||||
|
{
|
||||||
|
await flutterLocalNotificationsPlugin.show(
|
||||||
|
lesson.id.hashCode,
|
||||||
|
"title_lesson".i18n,
|
||||||
|
"body_lesson_canceled".i18n.fill(
|
||||||
|
[
|
||||||
|
dayTitle(lesson.date),
|
||||||
|
lesson.lessonIndex,
|
||||||
|
lesson.name
|
||||||
|
],
|
||||||
|
),
|
||||||
|
notificationDetails,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
await flutterLocalNotificationsPlugin.show(
|
||||||
|
lesson.id.hashCode,
|
||||||
|
"title_lesson".i18n,
|
||||||
|
"body_lesson_canceled".i18n.fill(
|
||||||
|
[
|
||||||
|
lesson.lessonIndex,
|
||||||
|
lesson.name,
|
||||||
|
dayTitle(lesson.date)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
notificationDetails,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (lesson.substituteTeacher?.name != "") {
|
||||||
|
switch (I18n.localeStr) {
|
||||||
|
case "en_en":
|
||||||
|
{
|
||||||
|
await flutterLocalNotificationsPlugin.show(
|
||||||
|
lesson.id.hashCode,
|
||||||
|
"title_lesson".i18n,
|
||||||
|
"body_lesson_substituted".i18n.fill(
|
||||||
|
[
|
||||||
|
lesson.lessonIndex,
|
||||||
|
lesson.name,
|
||||||
|
dayTitle(lesson.date),
|
||||||
|
lesson.substituteTeacher!.isRenamed
|
||||||
|
? lesson.substituteTeacher!.renamedTo!
|
||||||
|
: lesson.substituteTeacher!.name
|
||||||
|
],
|
||||||
|
),
|
||||||
|
notificationDetails,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "hu_hu":
|
||||||
|
{
|
||||||
|
await flutterLocalNotificationsPlugin.show(
|
||||||
|
lesson.id.hashCode,
|
||||||
|
"title_lesson".i18n,
|
||||||
|
"body_lesson_substituted".i18n.fill(
|
||||||
|
[
|
||||||
|
dayTitle(lesson.date),
|
||||||
|
lesson.lessonIndex,
|
||||||
|
lesson.name,
|
||||||
|
lesson.substituteTeacher!.isRenamed
|
||||||
|
? lesson.substituteTeacher!.renamedTo!
|
||||||
|
: lesson.substituteTeacher!.name
|
||||||
|
],
|
||||||
|
),
|
||||||
|
notificationDetails,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
await flutterLocalNotificationsPlugin.show(
|
||||||
|
lesson.id.hashCode,
|
||||||
|
"title_lesson".i18n,
|
||||||
|
"body_lesson_substituted".i18n.fill(
|
||||||
|
[
|
||||||
|
lesson.lessonIndex,
|
||||||
|
lesson.name,
|
||||||
|
dayTitle(lesson.date),
|
||||||
|
lesson.substituteTeacher!.isRenamed
|
||||||
|
? lesson.substituteTeacher!.renamedTo!
|
||||||
|
: lesson.substituteTeacher!.name
|
||||||
|
],
|
||||||
|
),
|
||||||
|
notificationDetails,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (lesson.status?.name == "Elmaradt") {
|
||||||
|
switch (I18n.localeStr) {
|
||||||
|
case "en_en":
|
||||||
|
{
|
||||||
|
await flutterLocalNotificationsPlugin.show(
|
||||||
|
lesson.id.hashCode,
|
||||||
|
"title_lesson".i18n,
|
||||||
|
"body_lesson_canceled".i18n.fill(
|
||||||
|
[
|
||||||
|
userProvider.displayName!,
|
||||||
|
lesson.lessonIndex,
|
||||||
|
lesson.name,
|
||||||
|
dayTitle(lesson.date)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
notificationDetails,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "hu_hu":
|
||||||
|
{
|
||||||
|
await flutterLocalNotificationsPlugin.show(
|
||||||
|
lesson.id.hashCode,
|
||||||
|
"title_lesson".i18n,
|
||||||
|
"body_lesson_canceled".i18n.fill(
|
||||||
|
[
|
||||||
|
userProvider.displayName!,
|
||||||
|
dayTitle(lesson.date),
|
||||||
|
lesson.lessonIndex,
|
||||||
|
lesson.name
|
||||||
|
],
|
||||||
|
),
|
||||||
|
notificationDetails,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
await flutterLocalNotificationsPlugin.show(
|
||||||
|
lesson.id.hashCode,
|
||||||
|
"title_lesson".i18n,
|
||||||
|
"body_lesson_canceled".i18n.fill(
|
||||||
|
[
|
||||||
|
userProvider.displayName!,
|
||||||
|
lesson.lessonIndex,
|
||||||
|
lesson.name,
|
||||||
|
dayTitle(lesson.date)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
notificationDetails,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (lesson.substituteTeacher?.name != "") {
|
||||||
|
switch (I18n.localeStr) {
|
||||||
|
case "en_en":
|
||||||
|
{
|
||||||
|
await flutterLocalNotificationsPlugin.show(
|
||||||
|
lesson.id.hashCode,
|
||||||
|
"title_lesson".i18n,
|
||||||
|
"body_lesson_substituted".i18n.fill(
|
||||||
|
[
|
||||||
|
userProvider.displayName!,
|
||||||
|
lesson.lessonIndex,
|
||||||
|
lesson.name,
|
||||||
|
dayTitle(lesson.date),
|
||||||
|
lesson.substituteTeacher!.isRenamed
|
||||||
|
? lesson.substituteTeacher!.renamedTo!
|
||||||
|
: lesson.substituteTeacher!.name
|
||||||
|
],
|
||||||
|
),
|
||||||
|
notificationDetails,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "hu_hu":
|
||||||
|
{
|
||||||
|
await flutterLocalNotificationsPlugin.show(
|
||||||
|
lesson.id.hashCode,
|
||||||
|
"title_lesson".i18n,
|
||||||
|
"body_lesson_substituted".i18n.fill(
|
||||||
|
[
|
||||||
|
userProvider.displayName!,
|
||||||
|
dayTitle(lesson.date),
|
||||||
|
lesson.lessonIndex,
|
||||||
|
lesson.name,
|
||||||
|
lesson.substituteTeacher!.isRenamed
|
||||||
|
? lesson.substituteTeacher!.renamedTo!
|
||||||
|
: lesson.substituteTeacher!.name
|
||||||
|
],
|
||||||
|
),
|
||||||
|
notificationDetails,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
await flutterLocalNotificationsPlugin.show(
|
||||||
|
lesson.id.hashCode,
|
||||||
|
"title_lesson".i18n,
|
||||||
|
"body_lesson_substituted".i18n.fill(
|
||||||
|
[
|
||||||
|
userProvider.displayName!,
|
||||||
|
lesson.lessonIndex,
|
||||||
|
lesson.name,
|
||||||
|
dayTitle(lesson.date),
|
||||||
|
lesson.substituteTeacher!.isRenamed
|
||||||
|
? lesson.substituteTeacher!.renamedTo!
|
||||||
|
: lesson.substituteTeacher!.name
|
||||||
|
],
|
||||||
|
),
|
||||||
|
notificationDetails,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// combine modified lesson and storedlesson list and save them to the database
|
||||||
|
List<Lesson> combinedlessons = combineLists(
|
||||||
|
modifiedlessons,
|
||||||
|
storedlessons,
|
||||||
|
(Lesson message) => message.id,
|
||||||
|
);
|
||||||
|
Map<Week, List<Lesson>> timetableLessons = timetableProvider.lessons;
|
||||||
|
timetableLessons[Week.current()] = combinedlessons;
|
||||||
|
await database.userStore
|
||||||
|
.storeLessons(timetableLessons, userId: userProvider.id!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,16 +4,43 @@ extension Localization on String {
|
|||||||
static final _t = Translations.byLocale("hu_hu") +
|
static final _t = Translations.byLocale("hu_hu") +
|
||||||
{
|
{
|
||||||
"en_en": {
|
"en_en": {
|
||||||
"title": "New grade",
|
"title_grade": "New grade",
|
||||||
"body": "You got a %s in %s"
|
"body_grade": "You got a %s in %s",
|
||||||
|
"body_grade_multiuser": "%s got a %s in %s",
|
||||||
|
"title_absence": "Absence recorded",
|
||||||
|
"body_absence": "An absence was recorded on %s for %s",
|
||||||
|
"body_absence_multiuser": "An absence was recorded for %s on %s for the subject %s",
|
||||||
|
"title_lesson": "Timetable modified",
|
||||||
|
"body_lesson_canceled": "Lesson #%s (%s) has been canceled on %s",
|
||||||
|
"body_lesson_canceled_multiuser": "(%s) Lesson #%s (%s) has been canceled on %s",
|
||||||
|
"body_lesson_substituted": "Lesson #%s (%s) on %s will be substituted by %s",
|
||||||
|
"body_lesson_substituted_multiuser": "(%s) Lesson #%s (%s) on %s will be substituted by %s"
|
||||||
},
|
},
|
||||||
"hu_hu": {
|
"hu_hu": {
|
||||||
"title": "Új jegy",
|
"title_grade": "Új jegy",
|
||||||
"body": "%s-st kaptál %s tantárgyból"
|
"body_grade": "%s-st kaptál %s tantárgyból",
|
||||||
|
"body_grade_multiuser": "%s tanuló %s-st kapott %s tantárgyból",
|
||||||
|
"title_absence": "Új hiányzás",
|
||||||
|
"body_absence": "Új hiányzást kaptál %s napon %s tantárgyból",
|
||||||
|
"body_absence_multiuser": "%s tanuló új hiányzást kapott %s napon %s tantárgyból",
|
||||||
|
"title_lesson": "Órarend szerkesztve",
|
||||||
|
"body_lesson_canceled": "%s-i %s. óra (%s) elmarad",
|
||||||
|
"body_lesson_canceled_multiuser": "(%s) %s-i %s. óra (%s) elmarad",
|
||||||
|
"body_lesson_substituted": "%s-i %s. (%s) órát %s helyettesíti",
|
||||||
|
"body_lesson_substituted_multiuser": "(%s) %s-i %s. (%s) órát %s helyettesíti"
|
||||||
},
|
},
|
||||||
"de_de": {
|
"de_de": {
|
||||||
"title": "Neue Note",
|
"title_grade": "Neue Note",
|
||||||
"body": "Du hast eine %s in %s"
|
"body_grade": "Du hast eine %s in %s",
|
||||||
|
"body_grade_multiuser": "%s hast eine %s in %s",
|
||||||
|
"title_absence": "Abwesenheit aufgezeichnet",
|
||||||
|
"body_absence": "Auf %s für %s wurde eine Abwesenheit aufgezeichnet",
|
||||||
|
"body_absence_multiuser": "Für %s wurde am %s für das Thema Mathematik eine Abwesenheit aufgezeichnet",
|
||||||
|
"title_lesson": "Fahrplan geändert",
|
||||||
|
"body_lesson_canceled": "Lektion Nr. %s (%s) wurde am %s abgesagt",
|
||||||
|
"body_lesson_canceled_multiuser": "(%s) Lektion Nr. %s (%s) wurde am %s abgesagt",
|
||||||
|
"body_lesson_substituted": "Lektion Nr. %s (%s) wird am %s durch %s ersetzt",
|
||||||
|
"body_lesson_substituted_multiuser": "(%s) Lektion Nr. %s (%s) wird am %s durch %s ersetzt"
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,30 +1,36 @@
|
|||||||
class News {
|
class News {
|
||||||
|
String id;
|
||||||
String title;
|
String title;
|
||||||
String content;
|
String content;
|
||||||
String link;
|
String link;
|
||||||
String openLabel;
|
String openLabel;
|
||||||
String platform;
|
String platform;
|
||||||
bool emergency;
|
bool emergency;
|
||||||
|
DateTime expireDate;
|
||||||
Map? json;
|
Map? json;
|
||||||
|
|
||||||
News({
|
News({
|
||||||
|
required this.id,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.content,
|
required this.content,
|
||||||
required this.link,
|
required this.link,
|
||||||
required this.openLabel,
|
required this.openLabel,
|
||||||
required this.platform,
|
required this.platform,
|
||||||
required this.emergency,
|
required this.emergency,
|
||||||
|
required this.expireDate,
|
||||||
this.json,
|
this.json,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory News.fromJson(Map json) {
|
factory News.fromJson(Map json) {
|
||||||
return News(
|
return News(
|
||||||
|
id: json["id"] ?? "",
|
||||||
title: json["title"] ?? "",
|
title: json["title"] ?? "",
|
||||||
content: json["content"] ?? "",
|
content: json["content"] ?? "",
|
||||||
link: json["link"] ?? "",
|
link: json["link"] ?? "",
|
||||||
openLabel: json["open_label"] ?? "",
|
openLabel: json["open_label"] ?? "",
|
||||||
platform: json["platform"] ?? "",
|
platform: json["platform"] ?? "",
|
||||||
emergency: json["emergency"] ?? false,
|
emergency: json["emergency"] ?? false,
|
||||||
|
expireDate: DateTime.parse(json["expire_date"] ?? ''),
|
||||||
json: json,
|
json: json,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,12 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
// zero is one, ...
|
// zero is one, ...
|
||||||
List<Color> _gradeColors;
|
List<Color> _gradeColors;
|
||||||
bool _newsEnabled;
|
bool _newsEnabled;
|
||||||
int _newsState;
|
String _seenNews;
|
||||||
bool _notificationsEnabled;
|
bool _notificationsEnabled;
|
||||||
|
bool _notificationsGradesEnabled;
|
||||||
|
bool _notificationsAbsencesEnabled;
|
||||||
|
bool _notificationsMessagesEnabled;
|
||||||
|
bool _notificationsLessonsEnabled;
|
||||||
/*
|
/*
|
||||||
notificationsBitfield values:
|
notificationsBitfield values:
|
||||||
|
|
||||||
@ -69,6 +73,9 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
String _lastAccountId;
|
String _lastAccountId;
|
||||||
bool _renamedSubjectsEnabled;
|
bool _renamedSubjectsEnabled;
|
||||||
bool _renamedSubjectsItalics;
|
bool _renamedSubjectsItalics;
|
||||||
|
bool _renamedTeachersEnabled;
|
||||||
|
bool _renamedTeachersItalics;
|
||||||
|
Color _liveActivityColor;
|
||||||
|
|
||||||
SettingsProvider({
|
SettingsProvider({
|
||||||
DatabaseProvider? database,
|
DatabaseProvider? database,
|
||||||
@ -79,8 +86,12 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
required AccentColor accentColor,
|
required AccentColor accentColor,
|
||||||
required List<Color> gradeColors,
|
required List<Color> gradeColors,
|
||||||
required bool newsEnabled,
|
required bool newsEnabled,
|
||||||
required int newsState,
|
required String seenNews,
|
||||||
required bool notificationsEnabled,
|
required bool notificationsEnabled,
|
||||||
|
required bool notificationsGradesEnabled,
|
||||||
|
required bool notificationsAbsencesEnabled,
|
||||||
|
required bool notificationsMessagesEnabled,
|
||||||
|
required bool notificationsLessonsEnabled,
|
||||||
required int notificationsBitfield,
|
required int notificationsBitfield,
|
||||||
required bool developerMode,
|
required bool developerMode,
|
||||||
required int notificationPollInterval,
|
required int notificationPollInterval,
|
||||||
@ -106,6 +117,9 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
required String lastAccountId,
|
required String lastAccountId,
|
||||||
required bool renameSubjectsEnabled,
|
required bool renameSubjectsEnabled,
|
||||||
required bool renameSubjectsItalics,
|
required bool renameSubjectsItalics,
|
||||||
|
required bool renameTeachersEnabled,
|
||||||
|
required bool renameTeachersItalics,
|
||||||
|
required Color liveActivityColor,
|
||||||
}) : _database = database,
|
}) : _database = database,
|
||||||
_language = language,
|
_language = language,
|
||||||
_startPage = startPage,
|
_startPage = startPage,
|
||||||
@ -114,8 +128,12 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
_accentColor = accentColor,
|
_accentColor = accentColor,
|
||||||
_gradeColors = gradeColors,
|
_gradeColors = gradeColors,
|
||||||
_newsEnabled = newsEnabled,
|
_newsEnabled = newsEnabled,
|
||||||
_newsState = newsState,
|
_seenNews = seenNews,
|
||||||
_notificationsEnabled = notificationsEnabled,
|
_notificationsEnabled = notificationsEnabled,
|
||||||
|
_notificationsGradesEnabled = notificationsGradesEnabled,
|
||||||
|
_notificationsAbsencesEnabled = notificationsAbsencesEnabled,
|
||||||
|
_notificationsMessagesEnabled = notificationsMessagesEnabled,
|
||||||
|
_notificationsLessonsEnabled = notificationsLessonsEnabled,
|
||||||
_notificationsBitfield = notificationsBitfield,
|
_notificationsBitfield = notificationsBitfield,
|
||||||
_developerMode = developerMode,
|
_developerMode = developerMode,
|
||||||
_notificationPollInterval = notificationPollInterval,
|
_notificationPollInterval = notificationPollInterval,
|
||||||
@ -140,7 +158,10 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
_premiumLogin = premiumLogin,
|
_premiumLogin = premiumLogin,
|
||||||
_lastAccountId = lastAccountId,
|
_lastAccountId = lastAccountId,
|
||||||
_renamedSubjectsEnabled = renameSubjectsEnabled,
|
_renamedSubjectsEnabled = renameSubjectsEnabled,
|
||||||
_renamedSubjectsItalics = renameSubjectsItalics;
|
_renamedSubjectsItalics = renameSubjectsItalics,
|
||||||
|
_renamedTeachersEnabled = renameTeachersEnabled,
|
||||||
|
_renamedTeachersItalics = renameTeachersItalics,
|
||||||
|
_liveActivityColor = liveActivityColor;
|
||||||
|
|
||||||
factory SettingsProvider.fromMap(Map map,
|
factory SettingsProvider.fromMap(Map map,
|
||||||
{required DatabaseProvider database}) {
|
{required DatabaseProvider database}) {
|
||||||
@ -167,8 +188,12 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
Color(map["grade_color5"]),
|
Color(map["grade_color5"]),
|
||||||
],
|
],
|
||||||
newsEnabled: map["news"] == 1,
|
newsEnabled: map["news"] == 1,
|
||||||
newsState: map["news_state"],
|
seenNews: map["seen_news"],
|
||||||
notificationsEnabled: map["notifications"] == 1,
|
notificationsEnabled: map["notifications"] == 1,
|
||||||
|
notificationsGradesEnabled: map["notifications_grades"] == 1,
|
||||||
|
notificationsAbsencesEnabled: map["notifications_absences"] == 1,
|
||||||
|
notificationsMessagesEnabled: map["notifications_messages"] == 1,
|
||||||
|
notificationsLessonsEnabled: map["notifications_lessons"] == 1,
|
||||||
notificationsBitfield: map["notifications_bitfield"],
|
notificationsBitfield: map["notifications_bitfield"],
|
||||||
notificationPollInterval: map["notification_poll_interval"],
|
notificationPollInterval: map["notification_poll_interval"],
|
||||||
developerMode: map["developer_mode"] == 1,
|
developerMode: map["developer_mode"] == 1,
|
||||||
@ -195,6 +220,9 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
lastAccountId: map["last_account_id"],
|
lastAccountId: map["last_account_id"],
|
||||||
renameSubjectsEnabled: map["renamed_subjects_enabled"] == 1,
|
renameSubjectsEnabled: map["renamed_subjects_enabled"] == 1,
|
||||||
renameSubjectsItalics: map["renamed_subjects_italics"] == 1,
|
renameSubjectsItalics: map["renamed_subjects_italics"] == 1,
|
||||||
|
renameTeachersEnabled: map["renamed_teachers_enabled"] == 1,
|
||||||
|
renameTeachersItalics: map["renamed_teachers_italics"] == 1,
|
||||||
|
liveActivityColor: Color(map["live_activity_color"]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,8 +234,12 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
"theme": _theme.index,
|
"theme": _theme.index,
|
||||||
"accent_color": _accentColor.index,
|
"accent_color": _accentColor.index,
|
||||||
"news": _newsEnabled ? 1 : 0,
|
"news": _newsEnabled ? 1 : 0,
|
||||||
"news_state": _newsState,
|
"seen_news": _seenNews,
|
||||||
"notifications": _notificationsEnabled ? 1 : 0,
|
"notifications": _notificationsEnabled ? 1 : 0,
|
||||||
|
"notifications_grades": _notificationsGradesEnabled ? 1 : 0,
|
||||||
|
"notifications_absences": _notificationsAbsencesEnabled ? 1 : 0,
|
||||||
|
"notifications_messages": _notificationsMessagesEnabled ? 1 : 0,
|
||||||
|
"notifications_lessons": _notificationsLessonsEnabled ? 1 : 0,
|
||||||
"notifications_bitfield": _notificationsBitfield,
|
"notifications_bitfield": _notificationsBitfield,
|
||||||
"developer_mode": _developerMode ? 1 : 0,
|
"developer_mode": _developerMode ? 1 : 0,
|
||||||
"grade_color1": _gradeColors[0].value,
|
"grade_color1": _gradeColors[0].value,
|
||||||
@ -236,7 +268,10 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
"premium_login": _premiumLogin,
|
"premium_login": _premiumLogin,
|
||||||
"last_account_id": _lastAccountId,
|
"last_account_id": _lastAccountId,
|
||||||
"renamed_subjects_enabled": _renamedSubjectsEnabled ? 1 : 0,
|
"renamed_subjects_enabled": _renamedSubjectsEnabled ? 1 : 0,
|
||||||
"renamed_subjects_italics": _renamedSubjectsItalics ? 1 : 0
|
"renamed_subjects_italics": _renamedSubjectsItalics ? 1 : 0,
|
||||||
|
"renamed_teachers_enabled": _renamedTeachersEnabled ? 1 : 0,
|
||||||
|
"renamed_teachers_italics": _renamedTeachersItalics ? 1 : 0,
|
||||||
|
"live_activity_color": _liveActivityColor.value,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,8 +291,12 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
DarkMobileAppColors().gradeFive,
|
DarkMobileAppColors().gradeFive,
|
||||||
],
|
],
|
||||||
newsEnabled: true,
|
newsEnabled: true,
|
||||||
newsState: -1,
|
seenNews: '',
|
||||||
notificationsEnabled: true,
|
notificationsEnabled: true,
|
||||||
|
notificationsGradesEnabled: true,
|
||||||
|
notificationsAbsencesEnabled: true,
|
||||||
|
notificationsMessagesEnabled: true,
|
||||||
|
notificationsLessonsEnabled: true,
|
||||||
notificationsBitfield: 255,
|
notificationsBitfield: 255,
|
||||||
developerMode: false,
|
developerMode: false,
|
||||||
notificationPollInterval: 1,
|
notificationPollInterval: 1,
|
||||||
@ -283,6 +322,9 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
lastAccountId: "",
|
lastAccountId: "",
|
||||||
renameSubjectsEnabled: false,
|
renameSubjectsEnabled: false,
|
||||||
renameSubjectsItalics: false,
|
renameSubjectsItalics: false,
|
||||||
|
renameTeachersEnabled: false,
|
||||||
|
renameTeachersItalics: false,
|
||||||
|
liveActivityColor: const Color(0xFF676767),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,8 +336,12 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
AccentColor get accentColor => _accentColor;
|
AccentColor get accentColor => _accentColor;
|
||||||
List<Color> get gradeColors => _gradeColors;
|
List<Color> get gradeColors => _gradeColors;
|
||||||
bool get newsEnabled => _newsEnabled;
|
bool get newsEnabled => _newsEnabled;
|
||||||
int get newsState => _newsState;
|
List<String> get seenNews => _seenNews.split(',');
|
||||||
bool get notificationsEnabled => _notificationsEnabled;
|
bool get notificationsEnabled => _notificationsEnabled;
|
||||||
|
bool get notificationsGradesEnabled => _notificationsGradesEnabled;
|
||||||
|
bool get notificationsAbsencesEnabled => _notificationsAbsencesEnabled;
|
||||||
|
bool get notificationsMessagesEnabled => _notificationsMessagesEnabled;
|
||||||
|
bool get notificationsLessonsEnabled => _notificationsLessonsEnabled;
|
||||||
int get notificationsBitfield => _notificationsBitfield;
|
int get notificationsBitfield => _notificationsBitfield;
|
||||||
bool get developerMode => _developerMode;
|
bool get developerMode => _developerMode;
|
||||||
int get notificationPollInterval => _notificationPollInterval;
|
int get notificationPollInterval => _notificationPollInterval;
|
||||||
@ -324,6 +370,9 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
String get lastAccountId => _lastAccountId;
|
String get lastAccountId => _lastAccountId;
|
||||||
bool get renamedSubjectsEnabled => _renamedSubjectsEnabled;
|
bool get renamedSubjectsEnabled => _renamedSubjectsEnabled;
|
||||||
bool get renamedSubjectsItalics => _renamedSubjectsItalics;
|
bool get renamedSubjectsItalics => _renamedSubjectsItalics;
|
||||||
|
bool get renamedTeachersEnabled => _renamedTeachersEnabled;
|
||||||
|
bool get renamedTeachersItalics => _renamedTeachersItalics;
|
||||||
|
Color get liveActivityColor => _liveActivityColor;
|
||||||
|
|
||||||
Future<void> update({
|
Future<void> update({
|
||||||
bool store = true,
|
bool store = true,
|
||||||
@ -334,8 +383,12 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
AccentColor? accentColor,
|
AccentColor? accentColor,
|
||||||
List<Color>? gradeColors,
|
List<Color>? gradeColors,
|
||||||
bool? newsEnabled,
|
bool? newsEnabled,
|
||||||
int? newsState,
|
String? seenNewsId,
|
||||||
bool? notificationsEnabled,
|
bool? notificationsEnabled,
|
||||||
|
bool? notificationsGradesEnabled,
|
||||||
|
bool? notificationsAbsencesEnabled,
|
||||||
|
bool? notificationsMessagesEnabled,
|
||||||
|
bool? notificationsLessonsEnabled,
|
||||||
int? notificationsBitfield,
|
int? notificationsBitfield,
|
||||||
bool? developerMode,
|
bool? developerMode,
|
||||||
int? notificationPollInterval,
|
int? notificationPollInterval,
|
||||||
@ -361,6 +414,9 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
String? lastAccountId,
|
String? lastAccountId,
|
||||||
bool? renamedSubjectsEnabled,
|
bool? renamedSubjectsEnabled,
|
||||||
bool? renamedSubjectsItalics,
|
bool? renamedSubjectsItalics,
|
||||||
|
bool? renamedTeachersEnabled,
|
||||||
|
bool? renamedTeachersItalics,
|
||||||
|
Color? liveActivityColor,
|
||||||
}) async {
|
}) async {
|
||||||
if (language != null && language != _language) _language = language;
|
if (language != null && language != _language) _language = language;
|
||||||
if (startPage != null && startPage != _startPage) _startPage = startPage;
|
if (startPage != null && startPage != _startPage) _startPage = startPage;
|
||||||
@ -375,11 +431,31 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
if (newsEnabled != null && newsEnabled != _newsEnabled) {
|
if (newsEnabled != null && newsEnabled != _newsEnabled) {
|
||||||
_newsEnabled = newsEnabled;
|
_newsEnabled = newsEnabled;
|
||||||
}
|
}
|
||||||
if (newsState != null && newsState != _newsState) _newsState = newsState;
|
if (seenNewsId != null && !_seenNews.split(',').contains(seenNewsId)) {
|
||||||
|
var tempList = _seenNews.split(',');
|
||||||
|
tempList.add(seenNewsId);
|
||||||
|
_seenNews = tempList.join(',');
|
||||||
|
}
|
||||||
if (notificationsEnabled != null &&
|
if (notificationsEnabled != null &&
|
||||||
notificationsEnabled != _notificationsEnabled) {
|
notificationsEnabled != _notificationsEnabled) {
|
||||||
_notificationsEnabled = notificationsEnabled;
|
_notificationsEnabled = notificationsEnabled;
|
||||||
}
|
}
|
||||||
|
if (notificationsGradesEnabled != null &&
|
||||||
|
notificationsGradesEnabled != _notificationsGradesEnabled) {
|
||||||
|
_notificationsGradesEnabled = notificationsGradesEnabled;
|
||||||
|
}
|
||||||
|
if (notificationsAbsencesEnabled != null &&
|
||||||
|
notificationsAbsencesEnabled != _notificationsAbsencesEnabled) {
|
||||||
|
_notificationsAbsencesEnabled = notificationsAbsencesEnabled;
|
||||||
|
}
|
||||||
|
if (notificationsMessagesEnabled != null &&
|
||||||
|
notificationsMessagesEnabled != _notificationsMessagesEnabled) {
|
||||||
|
_notificationsMessagesEnabled = notificationsMessagesEnabled;
|
||||||
|
}
|
||||||
|
if (notificationsLessonsEnabled != null &&
|
||||||
|
notificationsLessonsEnabled != _notificationsLessonsEnabled) {
|
||||||
|
_notificationsLessonsEnabled = notificationsLessonsEnabled;
|
||||||
|
}
|
||||||
if (notificationsBitfield != null &&
|
if (notificationsBitfield != null &&
|
||||||
notificationsBitfield != _notificationsBitfield) {
|
notificationsBitfield != _notificationsBitfield) {
|
||||||
_notificationsBitfield = notificationsBitfield;
|
_notificationsBitfield = notificationsBitfield;
|
||||||
@ -448,6 +524,17 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
renamedSubjectsItalics != _renamedSubjectsItalics) {
|
renamedSubjectsItalics != _renamedSubjectsItalics) {
|
||||||
_renamedSubjectsItalics = renamedSubjectsItalics;
|
_renamedSubjectsItalics = renamedSubjectsItalics;
|
||||||
}
|
}
|
||||||
|
if (renamedTeachersEnabled != null &&
|
||||||
|
renamedTeachersEnabled != _renamedTeachersEnabled) {
|
||||||
|
_renamedTeachersEnabled = renamedTeachersEnabled;
|
||||||
|
}
|
||||||
|
if (renamedTeachersItalics != null &&
|
||||||
|
renamedTeachersItalics != _renamedTeachersItalics) {
|
||||||
|
_renamedTeachersItalics = renamedTeachersItalics;
|
||||||
|
}
|
||||||
|
if (liveActivityColor != null && liveActivityColor != _liveActivityColor) {
|
||||||
|
_liveActivityColor = liveActivityColor;
|
||||||
|
}
|
||||||
if (store) await _database?.store.storeSettings(this);
|
if (store) await _database?.store.storeSettings(this);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,8 @@ import 'package:filcnaplo_mobile_ui/common/widgets/lesson/changed_lesson_tile.da
|
|||||||
import 'package:filcnaplo/utils/format.dart';
|
import 'package:filcnaplo/utils/format.dart';
|
||||||
|
|
||||||
// difference.inDays is not reliable
|
// difference.inDays is not reliable
|
||||||
bool _sameDate(DateTime a, DateTime b) => (a.year == b.year && a.month == b.month && a.day == b.day);
|
bool _sameDate(DateTime a, DateTime b) =>
|
||||||
|
(a.year == b.year && a.month == b.month && a.day == b.day);
|
||||||
|
|
||||||
List<Widget> sortDateWidgets(
|
List<Widget> sortDateWidgets(
|
||||||
BuildContext context, {
|
BuildContext context, {
|
||||||
@ -35,13 +36,16 @@ List<Widget> sortDateWidgets(
|
|||||||
if (message.conversationId != null) {
|
if (message.conversationId != null) {
|
||||||
convMessages.add(w);
|
convMessages.add(w);
|
||||||
|
|
||||||
Conversation conv = conversations.firstWhere((e) => e.id == message.conversationId, orElse: () => Conversation(id: message.conversationId!));
|
Conversation conv = conversations.firstWhere(
|
||||||
|
(e) => e.id == message.conversationId,
|
||||||
|
orElse: () => Conversation(id: message.conversationId!));
|
||||||
conv.add(message);
|
conv.add(message);
|
||||||
if (conv.messages.length == 1) conversations.add(conv);
|
if (conv.messages.length == 1) conversations.add(conv);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conversations.any((c) => c.id == message.messageId)) {
|
if (conversations.any((c) => c.id == message.messageId)) {
|
||||||
Conversation conv = conversations.firstWhere((e) => e.id == message.messageId);
|
Conversation conv =
|
||||||
|
conversations.firstWhere((e) => e.id == message.messageId);
|
||||||
convMessages.add(w);
|
convMessages.add(w);
|
||||||
conv.add(message);
|
conv.add(message);
|
||||||
}
|
}
|
||||||
@ -87,26 +91,41 @@ List<Widget> sortDateWidgets(
|
|||||||
|
|
||||||
// Group Absence Tiles
|
// Group Absence Tiles
|
||||||
List<DateWidget> absenceTileWidgets = elements.where((element) {
|
List<DateWidget> absenceTileWidgets = elements.where((element) {
|
||||||
return element.widget is AbsenceViewable && (element.widget as AbsenceViewable).absence.delay == 0;
|
return element.widget is AbsenceViewable &&
|
||||||
|
(element.widget as AbsenceViewable).absence.delay == 0;
|
||||||
}).toList();
|
}).toList();
|
||||||
List<AbsenceViewable> absenceTiles = absenceTileWidgets.map((e) => e.widget as AbsenceViewable).toList();
|
List<AbsenceViewable> absenceTiles =
|
||||||
|
absenceTileWidgets.map((e) => e.widget as AbsenceViewable).toList();
|
||||||
if (absenceTiles.length > 1) {
|
if (absenceTiles.length > 1) {
|
||||||
elements.removeWhere((element) => element.widget.runtimeType == AbsenceViewable && (element.widget as AbsenceViewable).absence.delay == 0);
|
elements.removeWhere((element) =>
|
||||||
|
element.widget.runtimeType == AbsenceViewable &&
|
||||||
|
(element.widget as AbsenceViewable).absence.delay == 0);
|
||||||
if (elements.isEmpty) {
|
if (elements.isEmpty) {
|
||||||
cst = false;
|
cst = false;
|
||||||
}
|
}
|
||||||
elements.add(DateWidget(
|
elements.add(
|
||||||
widget: AbsenceGroupTile(absenceTiles, showDate: !cst),
|
DateWidget(
|
||||||
date: absenceTileWidgets.first.date,
|
widget: AbsenceGroupTile(
|
||||||
key: "${absenceTileWidgets.first.date.millisecondsSinceEpoch}-absence-group"));
|
absenceTiles,
|
||||||
|
showDate: !cst,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 6.0),
|
||||||
|
),
|
||||||
|
date: absenceTileWidgets.first.date,
|
||||||
|
key:
|
||||||
|
"${absenceTileWidgets.first.date.millisecondsSinceEpoch}-absence-group"),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bring Lesson Tiles to front & sort by index asc
|
// Bring Lesson Tiles to front & sort by index asc
|
||||||
List<DateWidget> lessonTiles = elements.where((element) {
|
List<DateWidget> lessonTiles = elements.where((element) {
|
||||||
return element.widget.runtimeType == ChangedLessonTile;
|
return element.widget.runtimeType == ChangedLessonTile;
|
||||||
}).toList();
|
}).toList();
|
||||||
lessonTiles.sort((a, b) => (a.widget as ChangedLessonTile).lesson.lessonIndex.compareTo((b.widget as ChangedLessonTile).lesson.lessonIndex));
|
lessonTiles.sort((a, b) => (a.widget as ChangedLessonTile)
|
||||||
elements.removeWhere((element) => element.widget.runtimeType == ChangedLessonTile);
|
.lesson
|
||||||
|
.lessonIndex
|
||||||
|
.compareTo((b.widget as ChangedLessonTile).lesson.lessonIndex));
|
||||||
|
elements.removeWhere(
|
||||||
|
(element) => element.widget.runtimeType == ChangedLessonTile);
|
||||||
elements.insertAll(0, lessonTiles);
|
elements.insertAll(0, lessonTiles);
|
||||||
|
|
||||||
final date = (elements + absenceTileWidgets).first.date;
|
final date = (elements + absenceTileWidgets).first.date;
|
||||||
@ -122,7 +141,8 @@ List<Widget> sortDateWidgets(
|
|||||||
spawnIsolate: false,
|
spawnIsolate: false,
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
itemBuilder: (context, animation, item, index) => filterItemBuilder(context, animation, item.widget, index),
|
itemBuilder: (context, animation, item, index) =>
|
||||||
|
filterItemBuilder(context, animation, item.widget, index),
|
||||||
items: elements,
|
items: elements,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -131,9 +151,12 @@ List<Widget> sortDateWidgets(
|
|||||||
}
|
}
|
||||||
|
|
||||||
final nh = DateTime.now();
|
final nh = DateTime.now();
|
||||||
final now = DateTime(nh.year, nh.month, nh.day).subtract(const Duration(seconds: 1));
|
final now =
|
||||||
|
DateTime(nh.year, nh.month, nh.day).subtract(const Duration(seconds: 1));
|
||||||
|
|
||||||
if (showDivider && items.any((i) => i.date.isBefore(now)) && items.any((i) => i.date.isAfter(now))) {
|
if (showDivider &&
|
||||||
|
items.any((i) => i.date.isBefore(now)) &&
|
||||||
|
items.any((i) => i.date.isAfter(now))) {
|
||||||
items.add(
|
items.add(
|
||||||
DateWidget(
|
DateWidget(
|
||||||
date: now,
|
date: now,
|
||||||
@ -153,7 +176,9 @@ List<Widget> sortDateWidgets(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sort future dates asc, past dates desc
|
// Sort future dates asc, past dates desc
|
||||||
items.sort((a, b) => (a.date.isAfter(now) && b.date.isAfter(now) ? 1 : -1) * a.date.compareTo(b.date));
|
items.sort((a, b) =>
|
||||||
|
(a.date.isAfter(now) && b.date.isAfter(now) ? 1 : -1) *
|
||||||
|
a.date.compareTo(b.date));
|
||||||
|
|
||||||
return items.map((e) => e.widget).toList();
|
return items.map((e) => e.widget).toList();
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,9 @@ Future<List<DateWidget>> getFilterWidgets(FilterType activeData,
|
|||||||
|
|
||||||
// Grades
|
// Grades
|
||||||
case FilterType.grades:
|
case FilterType.grades:
|
||||||
gradeProvider.seenAll();
|
if(!settingsProvider.gradeOpeningFun) {
|
||||||
|
gradeProvider.seenAll();
|
||||||
|
}
|
||||||
items = grade_filter.getWidgets(
|
items = grade_filter.getWidgets(
|
||||||
gradeProvider.grades, gradeProvider.lastSeenDate);
|
gradeProvider.grades, gradeProvider.lastSeenDate);
|
||||||
if (settingsProvider.gradeOpeningFun) {
|
if (settingsProvider.gradeOpeningFun) {
|
||||||
|
@ -192,6 +192,7 @@ class GradeValueWidget extends StatelessWidget {
|
|||||||
this.outline = false,
|
this.outline = false,
|
||||||
this.complemented = false,
|
this.complemented = false,
|
||||||
this.nocolor = false,
|
this.nocolor = false,
|
||||||
|
this.color,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final GradeValue value;
|
final GradeValue value;
|
||||||
@ -202,6 +203,7 @@ class GradeValueWidget extends StatelessWidget {
|
|||||||
final bool outline;
|
final bool outline;
|
||||||
final bool complemented;
|
final bool complemented;
|
||||||
final bool nocolor;
|
final bool nocolor;
|
||||||
|
final Color? color;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -209,7 +211,7 @@ class GradeValueWidget extends StatelessWidget {
|
|||||||
bool isSubjectView = SubjectGradesContainer.of(context) != null;
|
bool isSubjectView = SubjectGradesContainer.of(context) != null;
|
||||||
|
|
||||||
Color color =
|
Color color =
|
||||||
gradeColor(context: context, value: value.value, nocolor: nocolor);
|
this.color ?? gradeColor(context: context, value: value.value, nocolor: nocolor);
|
||||||
Widget valueText;
|
Widget valueText;
|
||||||
final percentage = value.percentage;
|
final percentage = value.percentage;
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ class LessonTile extends StatelessWidget {
|
|||||||
bool fill = false;
|
bool fill = false;
|
||||||
bool fillLeading = false;
|
bool fillLeading = false;
|
||||||
String lessonIndexTrailing = "";
|
String lessonIndexTrailing = "";
|
||||||
|
|
||||||
SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
|
SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
|
||||||
|
|
||||||
// Only put a trailing . if its a digit
|
// Only put a trailing . if its a digit
|
||||||
@ -44,7 +44,7 @@ class LessonTile extends StatelessWidget {
|
|||||||
fillLeading = true;
|
fillLeading = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lesson.substituteTeacher != "") {
|
if (lesson.substituteTeacher?.name != "") {
|
||||||
fill = true;
|
fill = true;
|
||||||
accent = AppColors.of(context).yellow;
|
accent = AppColors.of(context).yellow;
|
||||||
}
|
}
|
||||||
@ -113,7 +113,7 @@ class LessonTile extends StatelessWidget {
|
|||||||
if (lesson.isChanged) {
|
if (lesson.isChanged) {
|
||||||
if (lesson.status?.name == "Elmaradt") {
|
if (lesson.status?.name == "Elmaradt") {
|
||||||
description = 'cancelled'.i18n;
|
description = 'cancelled'.i18n;
|
||||||
} else if (lesson.substituteTeacher != "") {
|
} else if (lesson.substituteTeacher?.name != "") {
|
||||||
description = 'substitution'.i18n;
|
description = 'substitution'.i18n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,8 +161,10 @@ class LessonTile extends StatelessWidget {
|
|||||||
color: AppColors.of(context)
|
color: AppColors.of(context)
|
||||||
.text
|
.text
|
||||||
.withOpacity(!lesson.isEmpty ? 1.0 : 0.5),
|
.withOpacity(!lesson.isEmpty ? 1.0 : 0.5),
|
||||||
fontStyle:
|
fontStyle: lesson.subject.isRenamed &&
|
||||||
lesson.subject.isRenamed && settingsProvider.renamedSubjectsItalics ? FontStyle.italic : null),
|
settingsProvider.renamedSubjectsItalics
|
||||||
|
? FontStyle.italic
|
||||||
|
: null),
|
||||||
),
|
),
|
||||||
subtitle: description != ""
|
subtitle: description != ""
|
||||||
? Text(
|
? Text(
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
//
|
|
||||||
// Generated file. Do not edit.
|
|
||||||
//
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
|
||||||
|
|
||||||
#include <dynamic_color/dynamic_color_plugin.h>
|
|
||||||
#include <flutter_acrylic/flutter_acrylic_plugin.h>
|
|
||||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
|
||||||
g_autoptr(FlPluginRegistrar) dynamic_color_registrar =
|
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin");
|
|
||||||
dynamic_color_plugin_register_with_registrar(dynamic_color_registrar);
|
|
||||||
g_autoptr(FlPluginRegistrar) flutter_acrylic_registrar =
|
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterAcrylicPlugin");
|
|
||||||
flutter_acrylic_plugin_register_with_registrar(flutter_acrylic_registrar);
|
|
||||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
|
||||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
//
|
|
||||||
// Generated file. Do not edit.
|
|
||||||
//
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
|
||||||
#define GENERATED_PLUGIN_REGISTRANT_
|
|
||||||
|
|
||||||
#include <flutter_linux/flutter_linux.h>
|
|
||||||
|
|
||||||
// Registers Flutter plugins.
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry);
|
|
||||||
|
|
||||||
#endif // GENERATED_PLUGIN_REGISTRANT_
|
|
@ -1,26 +0,0 @@
|
|||||||
#
|
|
||||||
# Generated file, do not edit.
|
|
||||||
#
|
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
|
||||||
dynamic_color
|
|
||||||
flutter_acrylic
|
|
||||||
url_launcher_linux
|
|
||||||
)
|
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
|
||||||
)
|
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
|
||||||
|
|
||||||
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
|
||||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
|
|
||||||
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
|
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
|
||||||
endforeach(plugin)
|
|
||||||
|
|
||||||
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
|
|
||||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
|
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
|
|
||||||
endforeach(ffi_plugin)
|
|
@ -1,28 +0,0 @@
|
|||||||
//
|
|
||||||
// Generated file. Do not edit.
|
|
||||||
//
|
|
||||||
|
|
||||||
import FlutterMacOS
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
import connectivity_plus
|
|
||||||
import dynamic_color
|
|
||||||
import flutter_local_notifications
|
|
||||||
import macos_window_utils
|
|
||||||
import package_info_plus
|
|
||||||
import path_provider_foundation
|
|
||||||
import share_plus
|
|
||||||
import sqflite
|
|
||||||
import url_launcher_macos
|
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|
||||||
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
|
|
||||||
DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin"))
|
|
||||||
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
|
|
||||||
MacOSWindowUtilsPlugin.register(with: registry.registrar(forPlugin: "MacOSWindowUtilsPlugin"))
|
|
||||||
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
|
|
||||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
|
||||||
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
|
|
||||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
|
||||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
PODS:
|
|
||||||
- connectivity_plus (0.0.1):
|
|
||||||
- FlutterMacOS
|
|
||||||
- ReachabilitySwift
|
|
||||||
- dynamic_color (0.0.2):
|
|
||||||
- FlutterMacOS
|
|
||||||
- flutter_acrylic (0.1.0):
|
|
||||||
- FlutterMacOS
|
|
||||||
- flutter_local_notifications (0.0.1):
|
|
||||||
- FlutterMacOS
|
|
||||||
- FlutterMacOS (1.0.0)
|
|
||||||
- FMDB (2.7.5):
|
|
||||||
- FMDB/standard (= 2.7.5)
|
|
||||||
- FMDB/standard (2.7.5)
|
|
||||||
- path_provider_foundation (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- FlutterMacOS
|
|
||||||
- ReachabilitySwift (5.0.0)
|
|
||||||
- share_plus_macos (0.0.1):
|
|
||||||
- FlutterMacOS
|
|
||||||
- sqflite (0.0.2):
|
|
||||||
- FlutterMacOS
|
|
||||||
- FMDB (>= 2.7.5)
|
|
||||||
- url_launcher_macos (0.0.1):
|
|
||||||
- FlutterMacOS
|
|
||||||
|
|
||||||
DEPENDENCIES:
|
|
||||||
- connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`)
|
|
||||||
- dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`)
|
|
||||||
- flutter_acrylic (from `Flutter/ephemeral/.symlinks/plugins/flutter_acrylic/macos`)
|
|
||||||
- flutter_local_notifications (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos`)
|
|
||||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
|
||||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
|
||||||
- share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`)
|
|
||||||
- sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`)
|
|
||||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
|
||||||
|
|
||||||
SPEC REPOS:
|
|
||||||
trunk:
|
|
||||||
- FMDB
|
|
||||||
- ReachabilitySwift
|
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
|
||||||
connectivity_plus:
|
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos
|
|
||||||
dynamic_color:
|
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos
|
|
||||||
flutter_acrylic:
|
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/flutter_acrylic/macos
|
|
||||||
flutter_local_notifications:
|
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos
|
|
||||||
FlutterMacOS:
|
|
||||||
:path: Flutter/ephemeral
|
|
||||||
path_provider_foundation:
|
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
|
|
||||||
share_plus_macos:
|
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos
|
|
||||||
sqflite:
|
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos
|
|
||||||
url_launcher_macos:
|
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
|
||||||
connectivity_plus: 18d3c32514c886e046de60e9c13895109866c747
|
|
||||||
dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f
|
|
||||||
flutter_acrylic: c3df24ae52ab6597197837ce59ef2a8542640c17
|
|
||||||
flutter_local_notifications: 3805ca215b2fb7f397d78b66db91f6a747af52e4
|
|
||||||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
|
||||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
|
||||||
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
|
|
||||||
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
|
||||||
share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4
|
|
||||||
sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea
|
|
||||||
url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451
|
|
||||||
|
|
||||||
PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7
|
|
||||||
|
|
||||||
COCOAPODS: 1.12.1
|
|
@ -3,7 +3,7 @@ description: "Nem hivatalos e-napló alkalmazás az e-Kréta rendszerhez"
|
|||||||
homepage: https://refilc.hu
|
homepage: https://refilc.hu
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
|
|
||||||
version: 4.1.1+216
|
version: 4.2.0+220
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.17.0 <3.0.0"
|
sdk: ">=2.17.0 <3.0.0"
|
||||||
@ -68,6 +68,9 @@ dependencies:
|
|||||||
screenshot: ^2.1.0
|
screenshot: ^2.1.0
|
||||||
flutter_staggered_grid_view: ^0.7.0
|
flutter_staggered_grid_view: ^0.7.0
|
||||||
sqflite_common_ffi_web: ^0.4.0
|
sqflite_common_ffi_web: ^0.4.0
|
||||||
|
image_crop:
|
||||||
|
git:
|
||||||
|
url: https://github.com/kimaah/image_crop.git
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_lints: ^2.0.1
|
flutter_lints: ^2.0.1
|
||||||
@ -83,6 +86,7 @@ flutter:
|
|||||||
- assets/icons/ic_splash.png
|
- assets/icons/ic_splash.png
|
||||||
- assets/animations/
|
- assets/animations/
|
||||||
- assets/images/
|
- assets/images/
|
||||||
|
- assets/images/subject_covers/
|
||||||
|
|
||||||
fonts:
|
fonts:
|
||||||
- family: FilcIcons
|
- family: FilcIcons
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
// This is a basic Flutter widget test.
|
// // This is a basic Flutter widget test.
|
||||||
//
|
// //
|
||||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
// // To perform an interaction with a widget in your test, use the WidgetTester
|
||||||
// utility in the flutter_test package. For example, you can send tap and scroll
|
// // utility in the flutter_test package. For example, you can send tap and scroll
|
||||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
// // gestures. You can also use WidgetTester to find child widgets in the widget
|
||||||
// tree, read text, and verify that the values of widget properties are correct.
|
// // tree, read text, and verify that the values of widget properties are correct.
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
// import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
// import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
import 'package:filcnaplo/main.dart';
|
// import 'package:filcnaplo/main.dart';
|
||||||
|
|
||||||
void main() {
|
// void main() {
|
||||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
// testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||||
// Build our app and trigger a frame.
|
// // Build our app and trigger a frame.
|
||||||
await tester.pumpWidget(const MyApp());
|
// await tester.pumpWidget(const MyApp());
|
||||||
|
|
||||||
// Verify that our counter starts at 0.
|
// // Verify that our counter starts at 0.
|
||||||
expect(find.text('0'), findsOneWidget);
|
// expect(find.text('0'), findsOneWidget);
|
||||||
expect(find.text('1'), findsNothing);
|
// expect(find.text('1'), findsNothing);
|
||||||
|
|
||||||
// Tap the '+' icon and trigger a frame.
|
// // Tap the '+' icon and trigger a frame.
|
||||||
await tester.tap(find.byIcon(Icons.add));
|
// await tester.tap(find.byIcon(Icons.add));
|
||||||
await tester.pump();
|
// await tester.pump();
|
||||||
|
|
||||||
// Verify that our counter has incremented.
|
// // Verify that our counter has incremented.
|
||||||
expect(find.text('0'), findsNothing);
|
// expect(find.text('0'), findsNothing);
|
||||||
expect(find.text('1'), findsOneWidget);
|
// expect(find.text('1'), findsOneWidget);
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
@ -35,7 +35,8 @@ class SubjectAbsence {
|
|||||||
List<Absence> absences;
|
List<Absence> absences;
|
||||||
double percentage;
|
double percentage;
|
||||||
|
|
||||||
SubjectAbsence({required this.subject, this.absences = const [], this.percentage = 0.0});
|
SubjectAbsence(
|
||||||
|
{required this.subject, this.absences = const [], this.percentage = 0.0});
|
||||||
}
|
}
|
||||||
|
|
||||||
class AbsencesPage extends StatefulWidget {
|
class AbsencesPage extends StatefulWidget {
|
||||||
@ -45,7 +46,8 @@ class AbsencesPage extends StatefulWidget {
|
|||||||
_AbsencesPageState createState() => _AbsencesPageState();
|
_AbsencesPageState createState() => _AbsencesPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMixin {
|
class _AbsencesPageState extends State<AbsencesPage>
|
||||||
|
with TickerProviderStateMixin {
|
||||||
late UserProvider user;
|
late UserProvider user;
|
||||||
late AbsenceProvider absenceProvider;
|
late AbsenceProvider absenceProvider;
|
||||||
late TimetableProvider timetableProvider;
|
late TimetableProvider timetableProvider;
|
||||||
@ -65,7 +67,9 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
|
|||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
for (final lesson in timetableProvider.getWeek(Week.current()) ?? []) {
|
for (final lesson in timetableProvider.getWeek(Week.current()) ?? []) {
|
||||||
if (!lesson.isEmpty && lesson.subject.id != '' && lesson.lessonYearIndex != null) {
|
if (!lesson.isEmpty &&
|
||||||
|
lesson.subject.id != '' &&
|
||||||
|
lesson.lessonYearIndex != null) {
|
||||||
_lessonCount.update(
|
_lessonCount.update(
|
||||||
lesson.subject,
|
lesson.subject,
|
||||||
(value) {
|
(value) {
|
||||||
@ -89,25 +93,30 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
|
|||||||
if (absence.delay != 0) continue;
|
if (absence.delay != 0) continue;
|
||||||
|
|
||||||
if (!_absences.containsKey(absence.subject)) {
|
if (!_absences.containsKey(absence.subject)) {
|
||||||
_absences[absence.subject] = SubjectAbsence(subject: absence.subject, absences: [absence]);
|
_absences[absence.subject] =
|
||||||
|
SubjectAbsence(subject: absence.subject, absences: [absence]);
|
||||||
} else {
|
} else {
|
||||||
_absences[absence.subject]?.absences.add(absence);
|
_absences[absence.subject]?.absences.add(absence);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_absences.forEach((subject, absence) {
|
_absences.forEach((subject, absence) {
|
||||||
final absentLessonsOfSubject = absenceProvider.absences.where((e) => e.subject == subject && e.delay == 0).length;
|
final absentLessonsOfSubject = absenceProvider.absences
|
||||||
|
.where((e) => e.subject == subject && e.delay == 0)
|
||||||
|
.length;
|
||||||
final totalLessonsOfSubject = _lessonCount[subject]?.lessonYearIndex ?? 0;
|
final totalLessonsOfSubject = _lessonCount[subject]?.lessonYearIndex ?? 0;
|
||||||
|
|
||||||
double absentLessonsOfSubjectPercentage;
|
double absentLessonsOfSubjectPercentage;
|
||||||
|
|
||||||
if (absentLessonsOfSubject <= totalLessonsOfSubject) {
|
if (absentLessonsOfSubject <= totalLessonsOfSubject) {
|
||||||
absentLessonsOfSubjectPercentage = absentLessonsOfSubject / totalLessonsOfSubject * 100;
|
absentLessonsOfSubjectPercentage =
|
||||||
|
absentLessonsOfSubject / totalLessonsOfSubject * 100;
|
||||||
} else {
|
} else {
|
||||||
absentLessonsOfSubjectPercentage = -1;
|
absentLessonsOfSubjectPercentage = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_absences[subject]?.percentage = absentLessonsOfSubjectPercentage.clamp(-1, 100.0);
|
_absences[subject]?.percentage =
|
||||||
|
absentLessonsOfSubjectPercentage.clamp(-1, 100.0);
|
||||||
});
|
});
|
||||||
|
|
||||||
absences = _absences.values.toList();
|
absences = _absences.values.toList();
|
||||||
@ -131,7 +140,8 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
|
|||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.only(top: 12.0),
|
padding: const EdgeInsets.only(top: 12.0),
|
||||||
child: NestedScrollView(
|
child: NestedScrollView(
|
||||||
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
|
physics: const BouncingScrollPhysics(
|
||||||
|
parent: AlwaysScrollableScrollPhysics()),
|
||||||
headerSliverBuilder: (context, _) => [
|
headerSliverBuilder: (context, _) => [
|
||||||
SliverAppBar(
|
SliverAppBar(
|
||||||
pinned: true,
|
pinned: true,
|
||||||
@ -145,7 +155,10 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
|
|||||||
padding: const EdgeInsets.only(left: 8.0),
|
padding: const EdgeInsets.only(left: 8.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
"Absences".i18n,
|
"Absences".i18n,
|
||||||
style: TextStyle(color: AppColors.of(context).text, fontSize: 32.0, fontWeight: FontWeight.bold),
|
style: TextStyle(
|
||||||
|
color: AppColors.of(context).text,
|
||||||
|
fontSize: 32.0,
|
||||||
|
fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
bottom: FilterBar(items: [
|
bottom: FilterBar(items: [
|
||||||
@ -158,7 +171,8 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
|
|||||||
body: TabBarView(
|
body: TabBarView(
|
||||||
physics: const BouncingScrollPhysics(),
|
physics: const BouncingScrollPhysics(),
|
||||||
controller: _tabController,
|
controller: _tabController,
|
||||||
children: List.generate(3, (index) => filterViewBuilder(context, index))),
|
children: List.generate(
|
||||||
|
3, (index) => filterViewBuilder(context, index))),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -174,10 +188,17 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
|
|||||||
widget: AbsenceSubjectTile(
|
widget: AbsenceSubjectTile(
|
||||||
a.subject,
|
a.subject,
|
||||||
percentage: a.percentage,
|
percentage: a.percentage,
|
||||||
excused: a.absences.where((a) => a.state == Justification.excused).length,
|
excused: a.absences
|
||||||
unexcused: a.absences.where((a) => a.state == Justification.unexcused).length,
|
.where((a) => a.state == Justification.excused)
|
||||||
pending: a.absences.where((a) => a.state == Justification.pending).length,
|
.length,
|
||||||
onTap: () => AbsenceSubjectView.show(a.subject, a.absences, context: context),
|
unexcused: a.absences
|
||||||
|
.where((a) => a.state == Justification.unexcused)
|
||||||
|
.length,
|
||||||
|
pending: a.absences
|
||||||
|
.where((a) => a.state == Justification.pending)
|
||||||
|
.length,
|
||||||
|
onTap: () => AbsenceSubjectView.show(a.subject, a.absences,
|
||||||
|
context: context),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -186,15 +207,18 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
|
|||||||
for (var absence in absenceProvider.absences) {
|
for (var absence in absenceProvider.absences) {
|
||||||
if (absence.delay != 0) {
|
if (absence.delay != 0) {
|
||||||
items.add(DateWidget(
|
items.add(DateWidget(
|
||||||
date: absence.date,
|
date: absence.date,
|
||||||
widget: AbsenceViewable(absence, padding: EdgeInsets.zero),
|
widget: AbsenceViewable(
|
||||||
));
|
absence,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AbsenceFilter.misses:
|
case AbsenceFilter.misses:
|
||||||
for (var note in noteProvider.notes) {
|
for (var note in noteProvider.notes) {
|
||||||
if (note.type?.name == "HaziFeladatHiany" || note.type?.name == "Felszereleshiany") {
|
if (note.type?.name == "HaziFeladatHiany" ||
|
||||||
|
note.type?.name == "Felszereleshiany") {
|
||||||
items.add(DateWidget(
|
items.add(DateWidget(
|
||||||
date: note.date,
|
date: note.date,
|
||||||
widget: MissTile(note),
|
widget: MissTile(note),
|
||||||
@ -232,10 +256,15 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
|
|||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(12.0)),
|
||||||
title: Text("attention".i18n),
|
title: Text("attention".i18n),
|
||||||
content: Text("attention_body".i18n),
|
content: Text("attention_body".i18n),
|
||||||
actions: [ActionButton(label: "Ok", onTap: () => Navigator.of(context).pop())],
|
actions: [
|
||||||
|
ActionButton(
|
||||||
|
label: "Ok",
|
||||||
|
onTap: () => Navigator.of(context).pop())
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -262,7 +291,10 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Column(
|
child: Column(
|
||||||
children: getFilterWidgets(AbsenceFilter.values[activeData]).map((e) => e.widget).cast<Widget>().toList(),
|
children: getFilterWidgets(AbsenceFilter.values[activeData])
|
||||||
|
.map((e) => e.widget)
|
||||||
|
.cast<Widget>()
|
||||||
|
.toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -284,7 +316,8 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
|
|||||||
itemCount: max(filterWidgets.length + (activeData <= 1 ? 1 : 0), 1),
|
itemCount: max(filterWidgets.length + (activeData <= 1 ? 1 : 0), 1),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
if (filterWidgets.isNotEmpty) {
|
if (filterWidgets.isNotEmpty) {
|
||||||
if ((index == 0 && activeData == 1) || (index == 0 && activeData == 0)) {
|
if ((index == 0 && activeData == 1) ||
|
||||||
|
(index == 0 && activeData == 0)) {
|
||||||
int value1 = 0;
|
int value1 = 0;
|
||||||
int value2 = 0;
|
int value2 = 0;
|
||||||
String title1 = "";
|
String title1 = "";
|
||||||
@ -292,18 +325,26 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
|
|||||||
String suffix = "";
|
String suffix = "";
|
||||||
|
|
||||||
if (activeData == AbsenceFilter.absences.index) {
|
if (activeData == AbsenceFilter.absences.index) {
|
||||||
value1 = absenceProvider.absences.where((e) => e.delay == 0 && e.state == Justification.excused).length;
|
value1 = absenceProvider.absences
|
||||||
value2 = absenceProvider.absences.where((e) => e.delay == 0 && e.state == Justification.unexcused).length;
|
.where((e) =>
|
||||||
|
e.delay == 0 && e.state == Justification.excused)
|
||||||
|
.length;
|
||||||
|
value2 = absenceProvider.absences
|
||||||
|
.where((e) =>
|
||||||
|
e.delay == 0 && e.state == Justification.unexcused)
|
||||||
|
.length;
|
||||||
title1 = "stat_1".i18n;
|
title1 = "stat_1".i18n;
|
||||||
title2 = "stat_2".i18n;
|
title2 = "stat_2".i18n;
|
||||||
suffix = " " + "hr".i18n;
|
suffix = " " + "hr".i18n;
|
||||||
} else if (activeData == AbsenceFilter.delays.index) {
|
} else if (activeData == AbsenceFilter.delays.index) {
|
||||||
value1 = absenceProvider.absences
|
value1 = absenceProvider.absences
|
||||||
.where((e) => e.delay != 0 && e.state == Justification.excused)
|
.where((e) =>
|
||||||
|
e.delay != 0 && e.state == Justification.excused)
|
||||||
.map((e) => e.delay)
|
.map((e) => e.delay)
|
||||||
.fold(0, (a, b) => a + b);
|
.fold(0, (a, b) => a + b);
|
||||||
value2 = absenceProvider.absences
|
value2 = absenceProvider.absences
|
||||||
.where((e) => e.delay != 0 && e.state == Justification.unexcused)
|
.where((e) =>
|
||||||
|
e.delay != 0 && e.state == Justification.unexcused)
|
||||||
.map((e) => e.delay)
|
.map((e) => e.delay)
|
||||||
.fold(0, (a, b) => a + b);
|
.fold(0, (a, b) => a + b);
|
||||||
title1 = "stat_3".i18n;
|
title1 = "stat_3".i18n;
|
||||||
@ -312,7 +353,8 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 24.0, left: 24.0, right: 24.0),
|
padding: const EdgeInsets.only(
|
||||||
|
bottom: 24.0, left: 24.0, right: 24.0),
|
||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: StatisticsTile(
|
child: StatisticsTile(
|
||||||
@ -348,7 +390,8 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 6.0),
|
padding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: 24.0, vertical: 6.0),
|
||||||
child: filterWidgets[index - (activeData <= 1 ? 1 : 0)],
|
child: filterWidgets[index - (activeData <= 1 ? 1 : 0)],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -12,6 +12,7 @@ import 'package:flutter_acrylic/flutter_acrylic.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:filcnaplo/models/settings.dart';
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||||
|
import 'package:filcnaplo_premium/providers/goal_provider.dart';
|
||||||
|
|
||||||
class NavigationScreen extends StatefulWidget {
|
class NavigationScreen extends StatefulWidget {
|
||||||
const NavigationScreen({Key? key}) : super(key: key);
|
const NavigationScreen({Key? key}) : super(key: key);
|
||||||
@ -29,6 +30,7 @@ class NavigationScreenState extends State<NavigationScreen>
|
|||||||
late NavigationRoute selected;
|
late NavigationRoute selected;
|
||||||
late SettingsProvider settings;
|
late SettingsProvider settings;
|
||||||
late NewsProvider newsProvider;
|
late NewsProvider newsProvider;
|
||||||
|
late GoalProvider goalProvider;
|
||||||
double topInset = 0.0;
|
double topInset = 0.0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -45,10 +47,14 @@ class NavigationScreenState extends State<NavigationScreen>
|
|||||||
Provider.of<KretaClient>(context, listen: false).userAgent =
|
Provider.of<KretaClient>(context, listen: false).userAgent =
|
||||||
settings.config.userAgent;
|
settings.config.userAgent;
|
||||||
|
|
||||||
// Get news
|
// get news
|
||||||
newsProvider = Provider.of<NewsProvider>(context, listen: false);
|
newsProvider = Provider.of<NewsProvider>(context, listen: false);
|
||||||
newsProvider.restore().then((value) => newsProvider.fetch());
|
newsProvider.restore().then((value) => newsProvider.fetch());
|
||||||
|
|
||||||
|
// get goals
|
||||||
|
// goalProvider = Provider.of<GoalProvider>(context, listen: false);
|
||||||
|
// goalProvider.fetchDone();
|
||||||
|
|
||||||
// Initial sync
|
// Initial sync
|
||||||
syncAll(context);
|
syncAll(context);
|
||||||
|
|
||||||
@ -98,13 +104,17 @@ class NavigationScreenState extends State<NavigationScreen>
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
settings = Provider.of<SettingsProvider>(context);
|
settings = Provider.of<SettingsProvider>(context);
|
||||||
newsProvider = Provider.of<NewsProvider>(context);
|
newsProvider = Provider.of<NewsProvider>(context);
|
||||||
|
goalProvider = Provider.of<GoalProvider>(context);
|
||||||
|
|
||||||
// Show news
|
// show news / complete goals
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
if (newsProvider.show) {
|
if (newsProvider.show) {
|
||||||
newsProvider.lock();
|
newsProvider.lock();
|
||||||
// NewsView.show(newsProvider.news[newsProvider.state], context: context).then((value) => newsProvider.release());
|
// NewsView.show(newsProvider.news[newsProvider.state], context: context).then((value) => newsProvider.release());
|
||||||
}
|
}
|
||||||
|
if (goalProvider.hasDoneGoals) {
|
||||||
|
// to-do
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
import 'package:filcnaplo/api/providers/update_provider.dart';
|
import 'package:filcnaplo/api/providers/update_provider.dart';
|
||||||
import 'package:filcnaplo/theme/colors/accent.dart';
|
|
||||||
import 'package:filcnaplo/theme/observer.dart';
|
|
||||||
import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/event_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/event_provider.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/exam_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/exam_provider.dart';
|
||||||
|
@ -66,8 +66,12 @@ class KretaClient {
|
|||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
if (autoHeader) {
|
if (autoHeader) {
|
||||||
if (!headerMap.containsKey("authorization") && accessToken != null) headerMap["authorization"] = "Bearer $accessToken";
|
if (!headerMap.containsKey("authorization") && accessToken != null) {
|
||||||
if (!headerMap.containsKey("user-agent") && userAgent != null) headerMap["user-agent"] = "$userAgent";
|
headerMap["authorization"] = "Bearer $accessToken";
|
||||||
|
}
|
||||||
|
if (!headerMap.containsKey("user-agent") && userAgent != null) {
|
||||||
|
headerMap["user-agent"] = "$userAgent";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res = await client.get(Uri.parse(url), headers: headerMap);
|
res = await client.get(Uri.parse(url), headers: headerMap);
|
||||||
@ -94,7 +98,8 @@ class KretaClient {
|
|||||||
return res.body;
|
return res.body;
|
||||||
}
|
}
|
||||||
} on http.ClientException catch (error) {
|
} on http.ClientException catch (error) {
|
||||||
print("ERROR: KretaClient.getAPI ($url) ClientException: ${error.message}");
|
print(
|
||||||
|
"ERROR: KretaClient.getAPI ($url) ClientException: ${error.message}");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
print("ERROR: KretaClient.getAPI ($url) ${error.runtimeType}: $error");
|
print("ERROR: KretaClient.getAPI ($url) ${error.runtimeType}: $error");
|
||||||
}
|
}
|
||||||
@ -120,9 +125,15 @@ class KretaClient {
|
|||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
if (autoHeader) {
|
if (autoHeader) {
|
||||||
if (!headerMap.containsKey("authorization") && accessToken != null) headerMap["authorization"] = "Bearer $accessToken";
|
if (!headerMap.containsKey("authorization") && accessToken != null) {
|
||||||
if (!headerMap.containsKey("user-agent") && userAgent != null) headerMap["user-agent"] = "$userAgent";
|
headerMap["authorization"] = "Bearer $accessToken";
|
||||||
if (!headerMap.containsKey("content-type")) headerMap["content-type"] = "application/json";
|
}
|
||||||
|
if (!headerMap.containsKey("user-agent") && userAgent != null) {
|
||||||
|
headerMap["user-agent"] = "$userAgent";
|
||||||
|
}
|
||||||
|
if (!headerMap.containsKey("content-type")) {
|
||||||
|
headerMap["content-type"] = "application/json";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res = await client.post(Uri.parse(url), headers: headerMap, body: body);
|
res = await client.post(Uri.parse(url), headers: headerMap, body: body);
|
||||||
@ -142,9 +153,10 @@ class KretaClient {
|
|||||||
return res.body;
|
return res.body;
|
||||||
}
|
}
|
||||||
} on http.ClientException catch (error) {
|
} on http.ClientException catch (error) {
|
||||||
print("ERROR: KretaClient.getAPI ($url) ClientException: ${error.message}");
|
print(
|
||||||
|
"ERROR: KretaClient.postAPI ($url) ClientException: ${error.message}");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
print("ERROR: KretaClient.getAPI ($url) ${error.runtimeType}: $error");
|
print("ERROR: KretaClient.postAPI ($url) ${error.runtimeType}: $error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +169,8 @@ class KretaClient {
|
|||||||
};
|
};
|
||||||
|
|
||||||
String nonceStr = await getAPI(KretaAPI.nonce, json: false);
|
String nonceStr = await getAPI(KretaAPI.nonce, json: false);
|
||||||
Nonce nonce = getNonce(nonceStr, loginUser.username, loginUser.instituteCode);
|
Nonce nonce =
|
||||||
|
getNonce(nonceStr, loginUser.username, loginUser.instituteCode);
|
||||||
headers.addAll(nonce.header());
|
headers.addAll(nonce.header());
|
||||||
|
|
||||||
if (_settings.presentationMode) {
|
if (_settings.presentationMode) {
|
||||||
@ -175,18 +188,28 @@ class KretaClient {
|
|||||||
));
|
));
|
||||||
|
|
||||||
if (loginRes != null) {
|
if (loginRes != null) {
|
||||||
if (loginRes.containsKey("access_token")) accessToken = loginRes["access_token"];
|
if (loginRes.containsKey("access_token")) {
|
||||||
if (loginRes.containsKey("refresh_token")) refreshToken = loginRes["refresh_token"];
|
accessToken = loginRes["access_token"];
|
||||||
|
}
|
||||||
|
if (loginRes.containsKey("refresh_token")) {
|
||||||
|
refreshToken = loginRes["refresh_token"];
|
||||||
|
}
|
||||||
|
|
||||||
// Update role
|
// Update role
|
||||||
loginUser.role = JwtUtils.getRoleFromJWT(accessToken ?? "") ?? Role.student;
|
loginUser.role =
|
||||||
|
JwtUtils.getRoleFromJWT(accessToken ?? "") ?? Role.student;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (refreshToken != null) {
|
if (refreshToken != null) {
|
||||||
Map? refreshRes = await postAPI(KretaAPI.login,
|
Map? refreshRes = await postAPI(KretaAPI.login,
|
||||||
headers: headers, body: User.refreshBody(refreshToken: refreshToken!, instituteCode: loginUser.instituteCode));
|
headers: headers,
|
||||||
|
body: User.refreshBody(
|
||||||
|
refreshToken: refreshToken!,
|
||||||
|
instituteCode: loginUser.instituteCode));
|
||||||
if (refreshRes != null) {
|
if (refreshRes != null) {
|
||||||
if (refreshRes.containsKey("id_token")) idToken = refreshRes["id_token"];
|
if (refreshRes.containsKey("id_token")) {
|
||||||
|
idToken = refreshRes["id_token"];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,10 @@ class TimetableController extends ChangeNotifier {
|
|||||||
current();
|
current();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getWeekId(Week week) => (week.start.difference(getSchoolYearStart()).inDays / DateTime.daysPerWeek).ceil();
|
static int getWeekId(Week week) =>
|
||||||
|
(week.start.difference(getSchoolYearStart()).inDays /
|
||||||
|
DateTime.daysPerWeek)
|
||||||
|
.ceil();
|
||||||
|
|
||||||
static DateTime getSchoolYearStart() {
|
static DateTime getSchoolYearStart() {
|
||||||
DateTime now = DateTime.now();
|
DateTime now = DateTime.now();
|
||||||
@ -48,8 +51,10 @@ class TimetableController extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Jump shortcuts
|
// Jump shortcuts
|
||||||
Future<void> next(BuildContext context) => jump(Week.fromId(currentWeekId + 1), context: context);
|
Future<void> next(BuildContext context) =>
|
||||||
Future<void> previous(BuildContext context) => jump(Week.fromId(currentWeekId - 1), context: context);
|
jump(Week.fromId(currentWeekId + 1), context: context);
|
||||||
|
Future<void> previous(BuildContext context) =>
|
||||||
|
jump(Week.fromId(currentWeekId - 1), context: context);
|
||||||
void current() {
|
void current() {
|
||||||
Week week = Week.current();
|
Week week = Week.current();
|
||||||
int id = getWeekId(week);
|
int id = getWeekId(week);
|
||||||
@ -60,7 +65,11 @@ class TimetableController extends ChangeNotifier {
|
|||||||
_setWeek(Week.fromId(id));
|
_setWeek(Week.fromId(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> jump(Week week, {required BuildContext context, bool initial = false, bool skip = false, bool loader = true}) async {
|
Future<void> jump(Week week,
|
||||||
|
{required BuildContext context,
|
||||||
|
bool initial = false,
|
||||||
|
bool skip = false,
|
||||||
|
bool loader = true}) async {
|
||||||
if (_setWeek(week)) return;
|
if (_setWeek(week)) return;
|
||||||
|
|
||||||
loadType = LoadType.initial;
|
loadType = LoadType.initial;
|
||||||
@ -81,7 +90,9 @@ class TimetableController extends ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await _fetchWeek(week, context: context).timeout(const Duration(seconds: 5), onTimeout: (() => throw "timeout"));
|
await _fetchWeek(week, context: context).timeout(
|
||||||
|
const Duration(seconds: 5),
|
||||||
|
onTimeout: (() => throw "timeout"));
|
||||||
loadType = LoadType.online;
|
loadType = LoadType.online;
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
print("ERROR: TimetableController.jump: $error\n$stack");
|
print("ERROR: TimetableController.jump: $error\n$stack");
|
||||||
@ -95,7 +106,9 @@ class TimetableController extends ChangeNotifier {
|
|||||||
if (week != currentWeek) return;
|
if (week != currentWeek) return;
|
||||||
|
|
||||||
// Jump to next week on weekends
|
// Jump to next week on weekends
|
||||||
if (skip && (days?.length ?? 0) > 0 && days!.last.last.end.isBefore(DateTime.now())) return next(context);
|
if (skip &&
|
||||||
|
(days?.length ?? 0) > 0 &&
|
||||||
|
days!.last.last.end.isBefore(DateTime.now())) return next(context);
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
@ -106,7 +119,9 @@ class TimetableController extends ChangeNotifier {
|
|||||||
if (id < 0) return true; // Min 1.
|
if (id < 0) return true; // Min 1.
|
||||||
|
|
||||||
// Set week start to Sept. 1 of first week
|
// Set week start to Sept. 1 of first week
|
||||||
if (!_differentDate(week.start, Week.fromId(0).start)) week.start = TimetableController.getSchoolYearStart();
|
if (!_differentDate(week.start, Week.fromId(0).start)) {
|
||||||
|
week.start = TimetableController.getSchoolYearStart();
|
||||||
|
}
|
||||||
|
|
||||||
currentWeek = week;
|
currentWeek = week;
|
||||||
previousWeekId = currentWeekId;
|
previousWeekId = currentWeekId;
|
||||||
@ -124,16 +139,17 @@ class TimetableController extends ChangeNotifier {
|
|||||||
List<List<Lesson>> _sortDays(Week week, {required BuildContext context}) {
|
List<List<Lesson>> _sortDays(Week week, {required BuildContext context}) {
|
||||||
List<List<Lesson>> days = [];
|
List<List<Lesson>> days = [];
|
||||||
|
|
||||||
final timetableProvider = context.read<TimetableProvider>();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
final timetableProvider = context.read<TimetableProvider>();
|
||||||
|
|
||||||
List<Lesson> lessons = timetableProvider.getWeek(week) ?? [];
|
List<Lesson> lessons = timetableProvider.getWeek(week) ?? [];
|
||||||
|
|
||||||
if (lessons.isNotEmpty) {
|
if (lessons.isNotEmpty) {
|
||||||
days.add([]);
|
days.add([]);
|
||||||
lessons.sort((a, b) => a.date.compareTo(b.date));
|
lessons.sort((a, b) => a.date.compareTo(b.date));
|
||||||
for (var lesson in lessons) {
|
for (var lesson in lessons) {
|
||||||
if (days.last.isNotEmpty && _differentDate(lesson.date, days.last.last.date)) days.add([]);
|
if (days.last.isNotEmpty &&
|
||||||
|
_differentDate(lesson.date, days.last.last.date)) days.add([]);
|
||||||
days.last.add(lesson);
|
days.last.add(lesson);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +168,8 @@ class TimetableController extends ChangeNotifier {
|
|||||||
|
|
||||||
if (lessonIndexes.isNotEmpty) {
|
if (lessonIndexes.isNotEmpty) {
|
||||||
// Fill missing indexes with empty spaces
|
// Fill missing indexes with empty spaces
|
||||||
for (var i in List<int>.generate(maxIndex - minIndex + 1, (int i) => minIndex + i)) {
|
for (var i in List<int>.generate(
|
||||||
|
maxIndex - minIndex + 1, (int i) => minIndex + i)) {
|
||||||
List<Lesson> indexLessons = _getLessonsByIndex(_day, i);
|
List<Lesson> indexLessons = _getLessonsByIndex(_day, i);
|
||||||
|
|
||||||
// Empty lesson
|
// Empty lesson
|
||||||
@ -160,8 +177,13 @@ class TimetableController extends ChangeNotifier {
|
|||||||
// Get start date by previous lesson
|
// Get start date by previous lesson
|
||||||
List<Lesson> prevLesson = _getLessonsByIndex(day, i - 1);
|
List<Lesson> prevLesson = _getLessonsByIndex(day, i - 1);
|
||||||
try {
|
try {
|
||||||
DateTime? startDate = prevLesson.last.start.add(const Duration(seconds: 1));
|
DateTime startDate =
|
||||||
indexLessons.add(Lesson.fromJson({'isEmpty': true, 'Oraszam': i, 'KezdetIdopont': startDate.toIso8601String()}));
|
prevLesson.last.start.add(const Duration(seconds: 1));
|
||||||
|
indexLessons.add(Lesson.fromJson({
|
||||||
|
'isEmpty': true,
|
||||||
|
'Oraszam': i,
|
||||||
|
'KezdetIdopont': startDate.toIso8601String()
|
||||||
|
}));
|
||||||
// ignore: empty_catches
|
// ignore: empty_catches
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
@ -171,7 +193,8 @@ class TimetableController extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Additional lessons
|
// Additional lessons
|
||||||
day.addAll(_day.where((l) => int.tryParse(l.lessonIndex) == null && l.subject.id != ''));
|
day.addAll(_day.where((l) =>
|
||||||
|
int.tryParse(l.lessonIndex) == null && l.subject.id != ''));
|
||||||
|
|
||||||
day.sort((a, b) => a.start.compareTo(b.start));
|
day.sort((a, b) => a.start.compareTo(b.start));
|
||||||
|
|
||||||
@ -213,5 +236,6 @@ class TimetableController extends ChangeNotifier {
|
|||||||
return indexes;
|
return indexes;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _differentDate(DateTime a, DateTime b) => !(a.year == b.year && a.month == b.month && a.day == b.day);
|
bool _differentDate(DateTime a, DateTime b) =>
|
||||||
|
!(a.year == b.year && a.month == b.month && a.day == b.day);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import "category.dart";
|
import "category.dart";
|
||||||
import "subject.dart";
|
import "subject.dart";
|
||||||
|
import "teacher.dart";
|
||||||
|
|
||||||
class Absence {
|
class Absence {
|
||||||
Map? json;
|
Map? json;
|
||||||
@ -7,7 +8,7 @@ class Absence {
|
|||||||
DateTime date;
|
DateTime date;
|
||||||
int delay;
|
int delay;
|
||||||
DateTime submitDate;
|
DateTime submitDate;
|
||||||
String teacher;
|
Teacher teacher;
|
||||||
Justification state;
|
Justification state;
|
||||||
Category? justification;
|
Category? justification;
|
||||||
Category? type;
|
Category? type;
|
||||||
@ -17,6 +18,14 @@ class Absence {
|
|||||||
DateTime lessonEnd;
|
DateTime lessonEnd;
|
||||||
int? lessonIndex;
|
int? lessonIndex;
|
||||||
String group;
|
String group;
|
||||||
|
bool isSeen;
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is Absence && runtimeType == other.runtimeType && id == other.id;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => id.hashCode;
|
||||||
|
|
||||||
Absence({
|
Absence({
|
||||||
required this.id,
|
required this.id,
|
||||||
@ -34,6 +43,7 @@ class Absence {
|
|||||||
this.lessonIndex,
|
this.lessonIndex,
|
||||||
required this.group,
|
required this.group,
|
||||||
this.json,
|
this.json,
|
||||||
|
this.isSeen = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory Absence.fromJson(Map json) {
|
factory Absence.fromJson(Map json) {
|
||||||
@ -41,8 +51,12 @@ class Absence {
|
|||||||
DateTime lessonEnd;
|
DateTime lessonEnd;
|
||||||
int? lessonIndex;
|
int? lessonIndex;
|
||||||
if (json["Ora"] != null) {
|
if (json["Ora"] != null) {
|
||||||
lessonStart = json["Ora"]["KezdoDatum"] != null ? DateTime.parse(json["Ora"]["KezdoDatum"]).toLocal() : DateTime(0);
|
lessonStart = json["Ora"]["KezdoDatum"] != null
|
||||||
lessonEnd = json["Ora"]["VegDatum"] != null ? DateTime.parse(json["Ora"]["VegDatum"]).toLocal() : DateTime(0);
|
? DateTime.parse(json["Ora"]["KezdoDatum"]).toLocal()
|
||||||
|
: DateTime(0);
|
||||||
|
lessonEnd = json["Ora"]["VegDatum"] != null
|
||||||
|
? DateTime.parse(json["Ora"]["VegDatum"]).toLocal()
|
||||||
|
: DateTime(0);
|
||||||
lessonIndex = json["Ora"]["Oraszam"];
|
lessonIndex = json["Ora"]["Oraszam"];
|
||||||
} else {
|
} else {
|
||||||
lessonStart = DateTime(0);
|
lessonStart = DateTime(0);
|
||||||
@ -51,26 +65,34 @@ class Absence {
|
|||||||
|
|
||||||
return Absence(
|
return Absence(
|
||||||
id: json["Uid"],
|
id: json["Uid"],
|
||||||
date: json["Datum"] != null ? DateTime.parse(json["Datum"]).toLocal() : DateTime(0),
|
date: json["Datum"] != null
|
||||||
|
? DateTime.parse(json["Datum"]).toLocal()
|
||||||
|
: DateTime(0),
|
||||||
delay: json["KesesPercben"] ?? 0,
|
delay: json["KesesPercben"] ?? 0,
|
||||||
submitDate: json["KeszitesDatuma"] != null ? DateTime.parse(json["KeszitesDatuma"]).toLocal() : DateTime(0),
|
submitDate: json["KeszitesDatuma"] != null
|
||||||
teacher: (json["RogzitoTanarNeve"] ?? "").trim(),
|
? DateTime.parse(json["KeszitesDatuma"]).toLocal()
|
||||||
|
: DateTime(0),
|
||||||
|
teacher: Teacher.fromString((json["RogzitoTanarNeve"] ?? "").trim()),
|
||||||
state: json["IgazolasAllapota"] == "Igazolt"
|
state: json["IgazolasAllapota"] == "Igazolt"
|
||||||
? Justification.excused
|
? Justification.excused
|
||||||
: json["IgazolasAllapota"] == "Igazolando"
|
: json["IgazolasAllapota"] == "Igazolando"
|
||||||
? Justification.pending
|
? Justification.pending
|
||||||
: Justification.unexcused,
|
: Justification.unexcused,
|
||||||
justification: json["IgazolasTipusa"] != null ? Category.fromJson(json["IgazolasTipusa"]) : null,
|
justification: json["IgazolasTipusa"] != null
|
||||||
|
? Category.fromJson(json["IgazolasTipusa"])
|
||||||
|
: null,
|
||||||
type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
|
type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
|
||||||
mode: json["Mod"] != null ? Category.fromJson(json["Mod"]) : null,
|
mode: json["Mod"] != null ? Category.fromJson(json["Mod"]) : null,
|
||||||
subject: Subject.fromJson(json["Tantargy"] ?? {}),
|
subject: Subject.fromJson(json["Tantargy"] ?? {}),
|
||||||
lessonStart: lessonStart,
|
lessonStart: lessonStart,
|
||||||
lessonEnd: lessonEnd,
|
lessonEnd: lessonEnd,
|
||||||
lessonIndex: lessonIndex,
|
lessonIndex: lessonIndex,
|
||||||
group: json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Uid"] : "",
|
group:
|
||||||
|
json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Uid"] : "",
|
||||||
|
isSeen: false,
|
||||||
json: json,
|
json: json,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Justification { excused, unexcused, pending }
|
enum Justification { excused, unexcused, pending }
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'category.dart';
|
import 'category.dart';
|
||||||
|
import 'teacher.dart';
|
||||||
|
|
||||||
class Exam {
|
class Exam {
|
||||||
Map? json;
|
Map? json;
|
||||||
@ -7,7 +8,7 @@ class Exam {
|
|||||||
Category? mode;
|
Category? mode;
|
||||||
int? subjectIndex;
|
int? subjectIndex;
|
||||||
String subjectName;
|
String subjectName;
|
||||||
String teacher;
|
Teacher teacher;
|
||||||
String description;
|
String description;
|
||||||
String group;
|
String group;
|
||||||
String id;
|
String id;
|
||||||
@ -28,14 +29,20 @@ class Exam {
|
|||||||
factory Exam.fromJson(Map json) {
|
factory Exam.fromJson(Map json) {
|
||||||
return Exam(
|
return Exam(
|
||||||
id: json["Uid"] ?? "",
|
id: json["Uid"] ?? "",
|
||||||
date: json["BejelentesDatuma"] != null ? DateTime.parse(json["BejelentesDatuma"]).toLocal() : DateTime(0),
|
date: json["BejelentesDatuma"] != null
|
||||||
writeDate: json["Datum"] != null ? DateTime.parse(json["Datum"]).toLocal() : DateTime(0),
|
? DateTime.parse(json["BejelentesDatuma"]).toLocal()
|
||||||
|
: DateTime(0),
|
||||||
|
writeDate: json["Datum"] != null
|
||||||
|
? DateTime.parse(json["Datum"]).toLocal()
|
||||||
|
: DateTime(0),
|
||||||
mode: json["Modja"] != null ? Category.fromJson(json["Modja"]) : null,
|
mode: json["Modja"] != null ? Category.fromJson(json["Modja"]) : null,
|
||||||
subjectIndex: json["OrarendiOraOraszama"],
|
subjectIndex: json["OrarendiOraOraszama"],
|
||||||
subjectName: json["TantargyNeve"] ?? "",
|
subjectName: json["TantargyNeve"] ?? "",
|
||||||
teacher: (json["RogzitoTanarNeve"] ?? "").trim(),
|
teacher: Teacher.fromString((json["RogzitoTanarNeve"] ?? "").trim()),
|
||||||
description: (json["Temaja"] ?? "").trim(),
|
description: (json["Temaja"] ?? "").trim(),
|
||||||
group: json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Uid"] ?? "" : "",
|
group: json["OsztalyCsoport"] != null
|
||||||
|
? json["OsztalyCsoport"]["Uid"] ?? ""
|
||||||
|
: "",
|
||||||
json: json,
|
json: json,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import 'package:filcnaplo/utils/format.dart';
|
import 'package:filcnaplo/utils/format.dart';
|
||||||
import 'category.dart';
|
import 'category.dart';
|
||||||
import 'subject.dart';
|
import 'subject.dart';
|
||||||
|
import 'teacher.dart';
|
||||||
|
|
||||||
class Grade {
|
class Grade {
|
||||||
Map? json;
|
Map? json;
|
||||||
String id;
|
String id;
|
||||||
DateTime date;
|
DateTime date;
|
||||||
GradeValue value;
|
GradeValue value;
|
||||||
String teacher;
|
Teacher teacher;
|
||||||
String description;
|
String description;
|
||||||
GradeType type;
|
GradeType type;
|
||||||
String groupId;
|
String groupId;
|
||||||
@ -38,23 +39,35 @@ class Grade {
|
|||||||
factory Grade.fromJson(Map json) {
|
factory Grade.fromJson(Map json) {
|
||||||
return Grade(
|
return Grade(
|
||||||
id: json["Uid"] ?? "",
|
id: json["Uid"] ?? "",
|
||||||
date: json["KeszitesDatuma"] != null ? DateTime.parse(json["KeszitesDatuma"]).toLocal() : DateTime(0),
|
date: json["KeszitesDatuma"] != null
|
||||||
|
? DateTime.parse(json["KeszitesDatuma"]).toLocal()
|
||||||
|
: DateTime(0),
|
||||||
value: GradeValue(
|
value: GradeValue(
|
||||||
json["SzamErtek"] ?? 0,
|
json["SzamErtek"] ?? 0,
|
||||||
json["SzovegesErtek"] ?? "",
|
json["SzovegesErtek"] ?? "",
|
||||||
json["SzovegesErtekelesRovidNev"] ?? "",
|
json["SzovegesErtekelesRovidNev"] ?? "",
|
||||||
json["SulySzazalekErteke"] ?? 0,
|
json["SulySzazalekErteke"] ?? 0,
|
||||||
percentage: json["ErtekFajta"] != null ? json["ErtekFajta"]["Uid"] == "3,Szazalekos" : false,
|
percentage: json["ErtekFajta"] != null
|
||||||
|
? json["ErtekFajta"]["Uid"] == "3,Szazalekos"
|
||||||
|
: false,
|
||||||
),
|
),
|
||||||
teacher: (json["ErtekeloTanarNeve"] ?? "").trim(),
|
teacher: Teacher.fromString((json["ErtekeloTanarNeve"] ?? "").trim()),
|
||||||
description: json["Tema"] ?? "",
|
description: json["Tema"] ?? "",
|
||||||
type: json["Tipus"] != null ? Category.getGradeType(json["Tipus"]["Nev"]) : GradeType.unknown,
|
type: json["Tipus"] != null
|
||||||
|
? Category.getGradeType(json["Tipus"]["Nev"])
|
||||||
|
: GradeType.unknown,
|
||||||
groupId: (json["OsztalyCsoport"] ?? {})["Uid"] ?? "",
|
groupId: (json["OsztalyCsoport"] ?? {})["Uid"] ?? "",
|
||||||
subject: Subject.fromJson(json["Tantargy"] ?? {}),
|
subject: Subject.fromJson(json["Tantargy"] ?? {}),
|
||||||
gradeType: json["ErtekFajta"] != null ? Category.fromJson(json["ErtekFajta"]) : null,
|
gradeType: json["ErtekFajta"] != null
|
||||||
|
? Category.fromJson(json["ErtekFajta"])
|
||||||
|
: null,
|
||||||
mode: Category.fromJson(json["Mod"] ?? {}),
|
mode: Category.fromJson(json["Mod"] ?? {}),
|
||||||
writeDate: json["RogzitesDatuma"] != null ? DateTime.parse(json["RogzitesDatuma"]).toLocal() : DateTime(0),
|
writeDate: json["RogzitesDatuma"] != null
|
||||||
seenDate: json["LattamozasDatuma"] != null ? DateTime.parse(json["LattamozasDatuma"]).toLocal() : DateTime(0),
|
? DateTime.parse(json["RogzitesDatuma"]).toLocal()
|
||||||
|
: DateTime(0),
|
||||||
|
seenDate: json["LattamozasDatuma"] != null
|
||||||
|
? DateTime.parse(json["LattamozasDatuma"]).toLocal()
|
||||||
|
: DateTime(0),
|
||||||
form: (json["Jelleg"] ?? "Na") != "Na" ? json["Jelleg"] : "",
|
form: (json["Jelleg"] ?? "Na") != "Na" ? json["Jelleg"] : "",
|
||||||
json: json,
|
json: json,
|
||||||
);
|
);
|
||||||
@ -76,7 +89,8 @@ class GradeValue {
|
|||||||
set value(int v) => _value = v;
|
set value(int v) => _value = v;
|
||||||
int get value {
|
int get value {
|
||||||
String _valueName = valueName.toLowerCase().specialChars();
|
String _valueName = valueName.toLowerCase().specialChars();
|
||||||
if (_value == 0 && ["peldas", "jo", "valtozo", "rossz", "hanyag"].contains(_valueName)) {
|
if (_value == 0 &&
|
||||||
|
["peldas", "jo", "valtozo", "rossz", "hanyag"].contains(_valueName)) {
|
||||||
switch (_valueName) {
|
switch (_valueName) {
|
||||||
case "peldas":
|
case "peldas":
|
||||||
return 5;
|
return 5;
|
||||||
@ -87,7 +101,16 @@ class GradeValue {
|
|||||||
case "rossz":
|
case "rossz":
|
||||||
return 2;
|
return 2;
|
||||||
case "hanyag":
|
case "hanyag":
|
||||||
|
return 1;
|
||||||
|
// other
|
||||||
|
case "jeles":
|
||||||
|
return 5;
|
||||||
|
case "kozepes":
|
||||||
|
return 3;
|
||||||
|
case "elegseges":
|
||||||
return 2;
|
return 2;
|
||||||
|
case "elegtelen":
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _value;
|
return _value;
|
||||||
@ -101,7 +124,8 @@ class GradeValue {
|
|||||||
set weight(int v) => _weight = v;
|
set weight(int v) => _weight = v;
|
||||||
int get weight {
|
int get weight {
|
||||||
String _valueName = valueName.toLowerCase().specialChars();
|
String _valueName = valueName.toLowerCase().specialChars();
|
||||||
if (_value == 0 && ["peldas", "jo", "valtozo", "rossz", "hanyag"].contains(_valueName)) {
|
if (_value == 0 &&
|
||||||
|
["peldas", "jo", "valtozo", "rossz", "hanyag"].contains(_valueName)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return _weight;
|
return _weight;
|
||||||
@ -110,11 +134,23 @@ class GradeValue {
|
|||||||
final bool _percentage;
|
final bool _percentage;
|
||||||
bool get percentage => _percentage;
|
bool get percentage => _percentage;
|
||||||
|
|
||||||
GradeValue(int value, String valueName, this.shortName, int weight, {bool percentage = false})
|
GradeValue(int value, String valueName, this.shortName, int weight,
|
||||||
|
{bool percentage = false})
|
||||||
: _value = value,
|
: _value = value,
|
||||||
_valueName = valueName,
|
_valueName = valueName,
|
||||||
_weight = weight,
|
_weight = weight,
|
||||||
_percentage = percentage;
|
_percentage = percentage;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum GradeType { midYear, firstQ, secondQ, halfYear, thirdQ, fourthQ, endYear, levelExam, ghost, unknown }
|
enum GradeType {
|
||||||
|
midYear,
|
||||||
|
firstQ,
|
||||||
|
secondQ,
|
||||||
|
halfYear,
|
||||||
|
thirdQ,
|
||||||
|
fourthQ,
|
||||||
|
endYear,
|
||||||
|
levelExam,
|
||||||
|
ghost,
|
||||||
|
unknown
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||||
|
|
||||||
import 'subject.dart';
|
import 'subject.dart';
|
||||||
|
import 'teacher.dart';
|
||||||
|
|
||||||
class Homework {
|
class Homework {
|
||||||
Map? json;
|
Map? json;
|
||||||
@ -9,7 +10,7 @@ class Homework {
|
|||||||
DateTime deadline;
|
DateTime deadline;
|
||||||
bool byTeacher;
|
bool byTeacher;
|
||||||
bool homeworkEnabled;
|
bool homeworkEnabled;
|
||||||
String teacher;
|
Teacher teacher;
|
||||||
String content;
|
String content;
|
||||||
Subject subject;
|
Subject subject;
|
||||||
String group;
|
String group;
|
||||||
@ -45,7 +46,7 @@ class Homework {
|
|||||||
: DateTime(0),
|
: DateTime(0),
|
||||||
byTeacher: json["IsTanarRogzitette"] ?? true,
|
byTeacher: json["IsTanarRogzitette"] ?? true,
|
||||||
homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false,
|
homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false,
|
||||||
teacher: (json["RogzitoTanarNeve"] ?? "").trim(),
|
teacher: Teacher.fromString((json["RogzitoTanarNeve"] ?? "").trim()),
|
||||||
content: (json["Szoveg"] ?? "").trim(),
|
content: (json["Szoveg"] ?? "").trim(),
|
||||||
subject: Subject.fromJson(json["Tantargy"] ?? {}),
|
subject: Subject.fromJson(json["Tantargy"] ?? {}),
|
||||||
group: json["OsztalyCsoport"] != null
|
group: json["OsztalyCsoport"] != null
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'subject.dart';
|
import 'subject.dart';
|
||||||
import 'category.dart';
|
import 'category.dart';
|
||||||
|
import 'teacher.dart';
|
||||||
|
|
||||||
class Lesson {
|
class Lesson {
|
||||||
Map? json;
|
Map? json;
|
||||||
@ -8,8 +9,8 @@ class Lesson {
|
|||||||
Subject subject;
|
Subject subject;
|
||||||
String lessonIndex;
|
String lessonIndex;
|
||||||
int? lessonYearIndex;
|
int? lessonYearIndex;
|
||||||
String substituteTeacher;
|
Teacher? substituteTeacher;
|
||||||
String teacher;
|
Teacher teacher;
|
||||||
bool homeworkEnabled;
|
bool homeworkEnabled;
|
||||||
DateTime start;
|
DateTime start;
|
||||||
DateTime end;
|
DateTime end;
|
||||||
@ -24,6 +25,7 @@ class Lesson {
|
|||||||
String name;
|
String name;
|
||||||
bool online;
|
bool online;
|
||||||
bool isEmpty;
|
bool isEmpty;
|
||||||
|
bool isSeen;
|
||||||
|
|
||||||
Lesson({
|
Lesson({
|
||||||
this.status,
|
this.status,
|
||||||
@ -31,7 +33,7 @@ class Lesson {
|
|||||||
required this.subject,
|
required this.subject,
|
||||||
required this.lessonIndex,
|
required this.lessonIndex,
|
||||||
this.lessonYearIndex,
|
this.lessonYearIndex,
|
||||||
this.substituteTeacher = "",
|
this.substituteTeacher,
|
||||||
required this.teacher,
|
required this.teacher,
|
||||||
this.homeworkEnabled = false,
|
this.homeworkEnabled = false,
|
||||||
required this.start,
|
required this.start,
|
||||||
@ -48,36 +50,56 @@ class Lesson {
|
|||||||
this.online = false,
|
this.online = false,
|
||||||
this.isEmpty = false,
|
this.isEmpty = false,
|
||||||
this.json,
|
this.json,
|
||||||
|
this.isSeen = false,
|
||||||
});
|
});
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is Lesson && runtimeType == other.runtimeType && id == other.id;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => id.hashCode;
|
||||||
|
|
||||||
factory Lesson.fromJson(Map json) {
|
factory Lesson.fromJson(Map json) {
|
||||||
return Lesson(
|
return Lesson(
|
||||||
id: json["Uid"] ?? "",
|
id: json["Uid"] ?? "",
|
||||||
status: json["Allapot"] != null ? Category.fromJson(json["Allapot"]) : null,
|
status:
|
||||||
date: json["Datum"] != null ? DateTime.parse(json["Datum"]).toLocal() : DateTime(0),
|
json["Allapot"] != null ? Category.fromJson(json["Allapot"]) : null,
|
||||||
|
date: json["Datum"] != null
|
||||||
|
? DateTime.parse(json["Datum"]).toLocal()
|
||||||
|
: DateTime(0),
|
||||||
subject: Subject.fromJson(json["Tantargy"] ?? {}),
|
subject: Subject.fromJson(json["Tantargy"] ?? {}),
|
||||||
lessonIndex: json["Oraszam"] != null ? json["Oraszam"].toString() : "+",
|
lessonIndex: json["Oraszam"] != null ? json["Oraszam"].toString() : "+",
|
||||||
lessonYearIndex: json["OraEvesSorszama"],
|
lessonYearIndex: json["OraEvesSorszama"],
|
||||||
substituteTeacher: (json["HelyettesTanarNeve"] ?? "").trim(),
|
substituteTeacher:
|
||||||
teacher: (json["TanarNeve"] ?? "").trim(),
|
Teacher.fromString((json["HelyettesTanarNeve"] ?? "").trim()),
|
||||||
|
teacher: Teacher.fromString((json["TanarNeve"] ?? "").trim()),
|
||||||
homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false,
|
homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false,
|
||||||
start: json["KezdetIdopont"] != null ? DateTime.parse(json["KezdetIdopont"]).toLocal() : DateTime(0),
|
start: json["KezdetIdopont"] != null
|
||||||
|
? DateTime.parse(json["KezdetIdopont"]).toLocal()
|
||||||
|
: DateTime(0),
|
||||||
studentPresence: json["TanuloJelenlet"] != null
|
studentPresence: json["TanuloJelenlet"] != null
|
||||||
? (json["TanuloJelenlet"]["Nev"] ?? "") == "Hianyzas"
|
? (json["TanuloJelenlet"]["Nev"] ?? "") == "Hianyzas"
|
||||||
? false
|
? false
|
||||||
: true
|
: true
|
||||||
: true,
|
: true,
|
||||||
end: json["VegIdopont"] != null ? DateTime.parse(json["VegIdopont"]).toLocal() : DateTime(0),
|
end: json["VegIdopont"] != null
|
||||||
|
? DateTime.parse(json["VegIdopont"]).toLocal()
|
||||||
|
: DateTime(0),
|
||||||
homeworkId: json["HaziFeladatUid"] ?? "",
|
homeworkId: json["HaziFeladatUid"] ?? "",
|
||||||
exam: json["BejelentettSzamonkeresUid"] ?? "",
|
exam: json["BejelentettSzamonkeresUid"] ?? "",
|
||||||
type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
|
type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
|
||||||
description: json["Tema"] ?? "",
|
description: json["Tema"] ?? "",
|
||||||
room: ((json["TeremNeve"] ?? "").split("_").join(" ") as String).replaceAll(RegExp(r" ?terem ?", caseSensitive: false), ""),
|
room: ((json["TeremNeve"] ?? "").split("_").join(" ") as String)
|
||||||
groupName: json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Nev"] ?? "" : "",
|
.replaceAll(RegExp(r" ?terem ?", caseSensitive: false), ""),
|
||||||
|
groupName: json["OsztalyCsoport"] != null
|
||||||
|
? json["OsztalyCsoport"]["Nev"] ?? ""
|
||||||
|
: "",
|
||||||
name: json["Nev"] ?? "",
|
name: json["Nev"] ?? "",
|
||||||
online: json["IsDigitalisOra"] ?? false,
|
online: json["IsDigitalisOra"] ?? false,
|
||||||
isEmpty: json['isEmpty'] ?? false,
|
isEmpty: json['isEmpty'] ?? false,
|
||||||
json: json,
|
json: json,
|
||||||
|
isSeen: false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,6 +114,6 @@ class Lesson {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get isChanged => status?.name == "Elmaradt" || substituteTeacher != "";
|
bool get isChanged => status?.name == "Elmaradt" || substituteTeacher != null;
|
||||||
bool get swapDesc => room.length > 8;
|
bool get swapDesc => room.length > 8;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ class Message {
|
|||||||
MessageType? type;
|
MessageType? type;
|
||||||
List<Recipient> recipients;
|
List<Recipient> recipients;
|
||||||
List<Attachment> attachments;
|
List<Attachment> attachments;
|
||||||
|
bool isSeen;
|
||||||
|
|
||||||
Message({
|
Message({
|
||||||
required this.id,
|
required this.id,
|
||||||
@ -32,7 +33,15 @@ class Message {
|
|||||||
this.replyId,
|
this.replyId,
|
||||||
this.conversationId,
|
this.conversationId,
|
||||||
this.json,
|
this.json,
|
||||||
|
this.isSeen = false,
|
||||||
});
|
});
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is Message && runtimeType == other.runtimeType && id == other.id;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => id.hashCode;
|
||||||
|
|
||||||
factory Message.fromJson(Map json, {MessageType? forceType}) {
|
factory Message.fromJson(Map json, {MessageType? forceType}) {
|
||||||
Map message = json["uzenet"];
|
Map message = json["uzenet"];
|
||||||
@ -69,6 +78,7 @@ class Message {
|
|||||||
replyId: message["elozoUzenetAzonosito"],
|
replyId: message["elozoUzenetAzonosito"],
|
||||||
conversationId: message["beszelgetesAzonosito"],
|
conversationId: message["beszelgetesAzonosito"],
|
||||||
json: json,
|
json: json,
|
||||||
|
isSeen: false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'category.dart';
|
import 'category.dart';
|
||||||
|
import 'teacher.dart';
|
||||||
|
|
||||||
class Note {
|
class Note {
|
||||||
Map? json;
|
Map? json;
|
||||||
@ -6,7 +7,7 @@ class Note {
|
|||||||
String title;
|
String title;
|
||||||
DateTime date;
|
DateTime date;
|
||||||
DateTime submitDate;
|
DateTime submitDate;
|
||||||
String teacher;
|
Teacher teacher;
|
||||||
DateTime seenDate;
|
DateTime seenDate;
|
||||||
String groupId;
|
String groupId;
|
||||||
String content;
|
String content;
|
||||||
@ -29,11 +30,19 @@ class Note {
|
|||||||
return Note(
|
return Note(
|
||||||
id: json["Uid"] ?? "",
|
id: json["Uid"] ?? "",
|
||||||
title: json["Cim"] ?? "",
|
title: json["Cim"] ?? "",
|
||||||
date: json["Datum"] != null ? DateTime.parse(json["Datum"]).toLocal() : DateTime(0),
|
date: json["Datum"] != null
|
||||||
submitDate: json["KeszitesDatuma"] != null ? DateTime.parse(json["KeszitesDatuma"]).toLocal() : DateTime(0),
|
? DateTime.parse(json["Datum"]).toLocal()
|
||||||
teacher: (json["KeszitoTanarNeve"] ?? "").trim(),
|
: DateTime(0),
|
||||||
seenDate: json["LattamozasDatuma"] != null ? DateTime.parse(json["LattamozasDatuma"]).toLocal() : DateTime(0),
|
submitDate: json["KeszitesDatuma"] != null
|
||||||
groupId: json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Uid"] ?? "" : "",
|
? DateTime.parse(json["KeszitesDatuma"]).toLocal()
|
||||||
|
: DateTime(0),
|
||||||
|
teacher: Teacher.fromString((json["KeszitoTanarNeve"] ?? "").trim()),
|
||||||
|
seenDate: json["LattamozasDatuma"] != null
|
||||||
|
? DateTime.parse(json["LattamozasDatuma"]).toLocal()
|
||||||
|
: DateTime(0),
|
||||||
|
groupId: json["OsztalyCsoport"] != null
|
||||||
|
? json["OsztalyCsoport"]["Uid"] ?? ""
|
||||||
|
: "",
|
||||||
content: json["Tartalom"].replaceAll("\r", "") ?? "",
|
content: json["Tartalom"].replaceAll("\r", "") ?? "",
|
||||||
type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
|
type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
|
||||||
json: json,
|
json: json,
|
||||||
|
34
filcnaplo_kreta_api/lib/models/teacher.dart
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import 'package:filcnaplo/utils/format.dart';
|
||||||
|
|
||||||
|
class Teacher {
|
||||||
|
String id;
|
||||||
|
String name;
|
||||||
|
String? renamedTo;
|
||||||
|
|
||||||
|
bool get isRenamed => renamedTo != null;
|
||||||
|
|
||||||
|
Teacher({required this.id, required this.name, this.renamedTo});
|
||||||
|
|
||||||
|
factory Teacher.fromJson(Map json) {
|
||||||
|
return Teacher(
|
||||||
|
id: json["Uid"] ?? "",
|
||||||
|
name: (json["Nev"] ?? "").trim(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory Teacher.fromString(String string) {
|
||||||
|
return Teacher(
|
||||||
|
id: string.trim().replaceAll(' ', '').toLowerCase().specialChars(),
|
||||||
|
name: string.trim(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(other) {
|
||||||
|
if (other is! Teacher) return false;
|
||||||
|
return id == other.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => id.hashCode;
|
||||||
|
}
|
@ -27,7 +27,10 @@ class AbsenceProvider with ChangeNotifier {
|
|||||||
|
|
||||||
// Load absences from the database
|
// Load absences from the database
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
var dbAbsences = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getAbsences(userId: userId);
|
var dbAbsences =
|
||||||
|
await Provider.of<DatabaseProvider>(_context, listen: false)
|
||||||
|
.userQuery
|
||||||
|
.getAbsences(userId: userId);
|
||||||
_absences = dbAbsences;
|
_absences = dbAbsences;
|
||||||
await convertBySettings();
|
await convertBySettings();
|
||||||
}
|
}
|
||||||
@ -36,12 +39,26 @@ class AbsenceProvider with ChangeNotifier {
|
|||||||
// for renamed subjects
|
// for renamed subjects
|
||||||
Future<void> convertBySettings() async {
|
Future<void> convertBySettings() async {
|
||||||
final _database = Provider.of<DatabaseProvider>(_context, listen: false);
|
final _database = Provider.of<DatabaseProvider>(_context, listen: false);
|
||||||
Map<String, String> renamedSubjects = (await _database.query.getSettings(_database)).renamedSubjectsEnabled
|
Map<String, String> renamedSubjects =
|
||||||
? await _database.userQuery.renamedSubjects(userId: Provider.of<UserProvider>(_context, listen: false).user!.id)
|
(await _database.query.getSettings(_database)).renamedSubjectsEnabled
|
||||||
: {};
|
? await _database.userQuery.renamedSubjects(
|
||||||
|
userId:
|
||||||
|
Provider.of<UserProvider>(_context, listen: false).user!.id)
|
||||||
|
: {};
|
||||||
|
Map<String, String> renamedTeachers =
|
||||||
|
(await _database.query.getSettings(_database)).renamedTeachersEnabled
|
||||||
|
? await _database.userQuery.renamedTeachers(
|
||||||
|
userId:
|
||||||
|
Provider.of<UserProvider>(_context, listen: false).user!.id)
|
||||||
|
: {};
|
||||||
|
|
||||||
for (Absence absence in _absences) {
|
for (Absence absence in _absences) {
|
||||||
absence.subject.renamedTo = renamedSubjects.isNotEmpty ? renamedSubjects[absence.subject.id] : null;
|
absence.subject.renamedTo = renamedSubjects.isNotEmpty
|
||||||
|
? renamedSubjects[absence.subject.id]
|
||||||
|
: null;
|
||||||
|
absence.teacher.renamedTo = renamedTeachers.isNotEmpty
|
||||||
|
? renamedTeachers[absence.teacher.id]
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@ -53,9 +70,11 @@ class AbsenceProvider with ChangeNotifier {
|
|||||||
if (user == null) throw "Cannot fetch Absences for User null";
|
if (user == null) throw "Cannot fetch Absences for User null";
|
||||||
String iss = user.instituteCode;
|
String iss = user.instituteCode;
|
||||||
|
|
||||||
List? absencesJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.absences(iss));
|
List? absencesJson = await Provider.of<KretaClient>(_context, listen: false)
|
||||||
|
.getAPI(KretaAPI.absences(iss));
|
||||||
if (absencesJson == null) throw "Cannot fetch Absences for User ${user.id}";
|
if (absencesJson == null) throw "Cannot fetch Absences for User ${user.id}";
|
||||||
List<Absence> absences = absencesJson.map((e) => Absence.fromJson(e)).toList();
|
List<Absence> absences =
|
||||||
|
absencesJson.map((e) => Absence.fromJson(e)).toList();
|
||||||
|
|
||||||
if (absences.isNotEmpty || _absences.isNotEmpty) await store(absences);
|
if (absences.isNotEmpty || _absences.isNotEmpty) await store(absences);
|
||||||
}
|
}
|
||||||
@ -66,7 +85,9 @@ class AbsenceProvider with ChangeNotifier {
|
|||||||
if (user == null) throw "Cannot store Absences for User null";
|
if (user == null) throw "Cannot store Absences for User null";
|
||||||
String userId = user.id;
|
String userId = user.id;
|
||||||
|
|
||||||
await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeAbsences(absences, userId: userId);
|
await Provider.of<DatabaseProvider>(_context, listen: false)
|
||||||
|
.userStore
|
||||||
|
.storeAbsences(absences, userId: userId);
|
||||||
_absences = absences;
|
_absences = absences;
|
||||||
await convertBySettings();
|
await convertBySettings();
|
||||||
}
|
}
|
||||||
|
@ -83,10 +83,15 @@ class GradeProvider with ChangeNotifier {
|
|||||||
Map<String, String> renamedSubjects = _settings.renamedSubjectsEnabled
|
Map<String, String> renamedSubjects = _settings.renamedSubjectsEnabled
|
||||||
? await _database.userQuery.renamedSubjects(userId: _user.user!.id)
|
? await _database.userQuery.renamedSubjects(userId: _user.user!.id)
|
||||||
: {};
|
: {};
|
||||||
|
Map<String, String> renamedTeachers = _settings.renamedTeachersEnabled
|
||||||
|
? await _database.userQuery.renamedTeachers(userId: _user.user!.id)
|
||||||
|
: {};
|
||||||
|
|
||||||
for (Grade grade in _grades) {
|
for (Grade grade in _grades) {
|
||||||
grade.subject.renamedTo =
|
grade.subject.renamedTo =
|
||||||
renamedSubjects.isNotEmpty ? renamedSubjects[grade.subject.id] : null;
|
renamedSubjects.isNotEmpty ? renamedSubjects[grade.subject.id] : null;
|
||||||
|
grade.teacher.renamedTo =
|
||||||
|
renamedTeachers.isNotEmpty ? renamedTeachers[grade.teacher.id] : null;
|
||||||
|
|
||||||
grade.value.value =
|
grade.value.value =
|
||||||
_settings.goodStudent ? 5 : grade.json!["SzamErtek"] ?? 0;
|
_settings.goodStudent ? 5 : grade.json!["SzamErtek"] ?? 0;
|
||||||
|
@ -22,9 +22,11 @@ class HomeworkProvider with ChangeNotifier {
|
|||||||
HomeworkProvider({
|
HomeworkProvider({
|
||||||
List<Homework> initialHomework = const [],
|
List<Homework> initialHomework = const [],
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
|
required DatabaseProvider database,
|
||||||
}) {
|
}) {
|
||||||
_homework = List.castFrom(initialHomework);
|
_homework = List.castFrom(initialHomework);
|
||||||
_context = context;
|
_context = context;
|
||||||
|
_database = database;
|
||||||
|
|
||||||
if (_homework.isEmpty) restore();
|
if (_homework.isEmpty) restore();
|
||||||
}
|
}
|
||||||
@ -48,11 +50,18 @@ class HomeworkProvider with ChangeNotifier {
|
|||||||
(await _database.query.getSettings(_database)).renamedSubjectsEnabled
|
(await _database.query.getSettings(_database)).renamedSubjectsEnabled
|
||||||
? await _database.userQuery.renamedSubjects(userId: _user.id!)
|
? await _database.userQuery.renamedSubjects(userId: _user.id!)
|
||||||
: {};
|
: {};
|
||||||
|
Map<String, String> renamedTeachers =
|
||||||
|
(await _database.query.getSettings(_database)).renamedTeachersEnabled
|
||||||
|
? await _database.userQuery.renamedTeachers(userId: _user.id!)
|
||||||
|
: {};
|
||||||
|
|
||||||
for (Homework homework in _homework) {
|
for (Homework homework in _homework) {
|
||||||
homework.subject.renamedTo = renamedSubjects.isNotEmpty
|
homework.subject.renamedTo = renamedSubjects.isNotEmpty
|
||||||
? renamedSubjects[homework.subject.id]
|
? renamedSubjects[homework.subject.id]
|
||||||
: null;
|
: null;
|
||||||
|
homework.teacher.renamedTo = renamedTeachers.isNotEmpty
|
||||||
|
? renamedTeachers[homework.teacher.id]
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
@ -8,7 +8,7 @@ import 'package:filcnaplo_kreta_api/models/week.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class TimetableProvider with ChangeNotifier {
|
class TimetableProvider with ChangeNotifier {
|
||||||
Map<Week, List<Lesson>> _lessons = {};
|
Map<Week, List<Lesson>> lessons = {};
|
||||||
late final UserProvider _user;
|
late final UserProvider _user;
|
||||||
late final DatabaseProvider _database;
|
late final DatabaseProvider _database;
|
||||||
late final KretaClient _kreta;
|
late final KretaClient _kreta;
|
||||||
@ -29,7 +29,7 @@ class TimetableProvider with ChangeNotifier {
|
|||||||
// Load lessons from the database
|
// Load lessons from the database
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
var dbLessons = await _database.userQuery.getLessons(userId: userId);
|
var dbLessons = await _database.userQuery.getLessons(userId: userId);
|
||||||
_lessons = dbLessons;
|
lessons = dbLessons;
|
||||||
await convertBySettings();
|
await convertBySettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,17 +40,24 @@ class TimetableProvider with ChangeNotifier {
|
|||||||
(await _database.query.getSettings(_database)).renamedSubjectsEnabled
|
(await _database.query.getSettings(_database)).renamedSubjectsEnabled
|
||||||
? await _database.userQuery.renamedSubjects(userId: _user.id!)
|
? await _database.userQuery.renamedSubjects(userId: _user.id!)
|
||||||
: {};
|
: {};
|
||||||
|
Map<String, String> renamedTeachers =
|
||||||
|
(await _database.query.getSettings(_database)).renamedTeachersEnabled
|
||||||
|
? await _database.userQuery.renamedTeachers(userId: _user.id!)
|
||||||
|
: {};
|
||||||
|
|
||||||
for (Lesson lesson in _lessons.values.expand((e) => e)) {
|
for (Lesson lesson in lessons.values.expand((e) => e)) {
|
||||||
lesson.subject.renamedTo = renamedSubjects.isNotEmpty
|
lesson.subject.renamedTo = renamedSubjects.isNotEmpty
|
||||||
? renamedSubjects[lesson.subject.id]
|
? renamedSubjects[lesson.subject.id]
|
||||||
: null;
|
: null;
|
||||||
|
lesson.teacher.renamedTo = renamedTeachers.isNotEmpty
|
||||||
|
? renamedTeachers[lesson.teacher.id]
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Lesson>? getWeek(Week week) => _lessons[week];
|
List<Lesson>? getWeek(Week week) => lessons[week];
|
||||||
|
|
||||||
// Fetches Lessons from the Kreta API then stores them in the database
|
// Fetches Lessons from the Kreta API then stores them in the database
|
||||||
Future<void> fetch({Week? week}) async {
|
Future<void> fetch({Week? week}) async {
|
||||||
@ -61,11 +68,11 @@ class TimetableProvider with ChangeNotifier {
|
|||||||
List? lessonsJson = await _kreta
|
List? lessonsJson = await _kreta
|
||||||
.getAPI(KretaAPI.timetable(iss, start: week.start, end: week.end));
|
.getAPI(KretaAPI.timetable(iss, start: week.start, end: week.end));
|
||||||
if (lessonsJson == null) throw "Cannot fetch Lessons for User ${user.id}";
|
if (lessonsJson == null) throw "Cannot fetch Lessons for User ${user.id}";
|
||||||
List<Lesson> lessons = lessonsJson.map((e) => Lesson.fromJson(e)).toList();
|
List<Lesson> lessonsList = lessonsJson.map((e) => Lesson.fromJson(e)).toList();
|
||||||
|
|
||||||
if (lessons.isEmpty && _lessons.isEmpty) return;
|
if (lessons.isEmpty && lessons.isEmpty) return;
|
||||||
|
|
||||||
_lessons[week] = lessons;
|
lessons[week] = lessonsList;
|
||||||
|
|
||||||
await store();
|
await store();
|
||||||
await convertBySettings();
|
await convertBySettings();
|
||||||
@ -78,7 +85,7 @@ class TimetableProvider with ChangeNotifier {
|
|||||||
String userId = user.id;
|
String userId = user.id;
|
||||||
|
|
||||||
// -TODO: clear indexes with weeks outside of the current school year
|
// -TODO: clear indexes with weeks outside of the current school year
|
||||||
await _database.userStore.storeLessons(_lessons, userId: userId);
|
await _database.userStore.storeLessons(lessons, userId: userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Future<void> setLessonCount(SubjectLessonCount lessonCount, {bool store = true}) async {
|
// Future<void> setLessonCount(SubjectLessonCount lessonCount, {bool store = true}) async {
|
||||||
|
41
filcnaplo_mobile_ui/lib/common/beta_chip.dart
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import 'package:filcnaplo/theme/colors/colors.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class BetaChip extends StatelessWidget {
|
||||||
|
const BetaChip({Key? key, this.disabled = false}) : super(key: key);
|
||||||
|
|
||||||
|
final bool disabled;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SizedBox(
|
||||||
|
height: 25,
|
||||||
|
child: AnimatedContainer(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 8, right: 8),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
"BETA",
|
||||||
|
softWrap: true,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 10,
|
||||||
|
color: disabled
|
||||||
|
? AppColors.of(context).text.withOpacity(.5)
|
||||||
|
: Colors.white,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: !disabled
|
||||||
|
? Theme.of(context).colorScheme.secondary
|
||||||
|
: AppColors.of(context).text.withOpacity(.25),
|
||||||
|
borderRadius: BorderRadius.circular(40),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -75,6 +75,7 @@ class ProfileButton extends StatelessWidget {
|
|||||||
snapSpec: const SnapSpec(
|
snapSpec: const SnapSpec(
|
||||||
snap: true,
|
snap: true,
|
||||||
snappings: [1.0],
|
snappings: [1.0],
|
||||||
|
initialSnap: 1.0,
|
||||||
positioning: SnapPositioning.relativeToSheetHeight,
|
positioning: SnapPositioning.relativeToSheetHeight,
|
||||||
),
|
),
|
||||||
cornerRadius: 16,
|
cornerRadius: 16,
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class ProgressBar extends StatelessWidget {
|
class ProgressBar extends StatelessWidget {
|
||||||
const ProgressBar({Key? key, required this.value, this.backgroundColor}) : super(key: key);
|
const ProgressBar(
|
||||||
|
{Key? key, required this.value, this.backgroundColor, this.height = 8.0})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
final double value;
|
final double value;
|
||||||
final Color? backgroundColor;
|
final Color? backgroundColor;
|
||||||
|
final double height;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -13,11 +16,13 @@ class ProgressBar extends StatelessWidget {
|
|||||||
// Background
|
// Background
|
||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).brightness == Brightness.light ? Colors.black.withOpacity(0.1) : Colors.white.withOpacity(0.1),
|
color: Theme.of(context).brightness == Brightness.light
|
||||||
|
? Colors.black.withOpacity(0.1)
|
||||||
|
: Colors.white.withOpacity(0.1),
|
||||||
borderRadius: BorderRadius.circular(45.0),
|
borderRadius: BorderRadius.circular(45.0),
|
||||||
),
|
),
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: 8.0,
|
height: height,
|
||||||
),
|
),
|
||||||
|
|
||||||
// Slider
|
// Slider
|
||||||
@ -26,8 +31,9 @@ class ProgressBar extends StatelessWidget {
|
|||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: CustomPaint(
|
child: CustomPaint(
|
||||||
painter: ProgressPainter(
|
painter: ProgressPainter(
|
||||||
backgroundColor: backgroundColor ?? Theme.of(context).colorScheme.secondary,
|
backgroundColor:
|
||||||
height: 8.0,
|
backgroundColor ?? Theme.of(context).colorScheme.secondary,
|
||||||
|
height: height,
|
||||||
value: value.clamp(0, 1),
|
value: value.clamp(0, 1),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -38,7 +44,10 @@ class ProgressBar extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ProgressPainter extends CustomPainter {
|
class ProgressPainter extends CustomPainter {
|
||||||
ProgressPainter({required this.height, required this.value, required this.backgroundColor});
|
ProgressPainter(
|
||||||
|
{required this.height,
|
||||||
|
required this.value,
|
||||||
|
required this.backgroundColor});
|
||||||
|
|
||||||
final double height;
|
final double height;
|
||||||
final double value;
|
final double value;
|
||||||
@ -64,6 +73,8 @@ class ProgressPainter extends CustomPainter {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool shouldRepaint(ProgressPainter oldDelegate) {
|
bool shouldRepaint(ProgressPainter oldDelegate) {
|
||||||
return value != oldDelegate.value || height != oldDelegate.height || backgroundColor != oldDelegate.backgroundColor;
|
return value != oldDelegate.value ||
|
||||||
|
height != oldDelegate.height ||
|
||||||
|
backgroundColor != oldDelegate.backgroundColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
30
filcnaplo_mobile_ui/lib/common/round_border_icon.dart
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class RoundBorderIcon extends StatelessWidget {
|
||||||
|
final Color color;
|
||||||
|
final double width;
|
||||||
|
final double padding;
|
||||||
|
final Widget icon;
|
||||||
|
|
||||||
|
const RoundBorderIcon(
|
||||||
|
{Key? key,
|
||||||
|
this.color = Colors.black,
|
||||||
|
this.width = 1.5,
|
||||||
|
this.padding = 5.0,
|
||||||
|
required this.icon})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(color: color, width: width),
|
||||||
|
borderRadius: BorderRadius.circular(50.0),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.all(padding),
|
||||||
|
child: icon,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,9 @@ import 'package:provider/provider.dart';
|
|||||||
import 'absence_tile.i18n.dart';
|
import 'absence_tile.i18n.dart';
|
||||||
|
|
||||||
class AbsenceTile extends StatelessWidget {
|
class AbsenceTile extends StatelessWidget {
|
||||||
const AbsenceTile(this.absence, {Key? key, this.onTap, this.elevation = 0.0, this.padding}) : super(key: key);
|
const AbsenceTile(this.absence,
|
||||||
|
{Key? key, this.onTap, this.elevation = 0.0, this.padding})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
final Absence absence;
|
final Absence absence;
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
@ -37,39 +39,61 @@ class AbsenceTile extends StatelessWidget {
|
|||||||
child: Material(
|
child: Material(
|
||||||
type: MaterialType.transparency,
|
type: MaterialType.transparency,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: padding ?? (group ? EdgeInsets.zero : const EdgeInsets.symmetric(horizontal: 8.0)),
|
padding: padding ??
|
||||||
|
(group
|
||||||
|
? EdgeInsets.zero
|
||||||
|
: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8.0,
|
||||||
|
)),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
dense: group,
|
dense: group,
|
||||||
contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
|
contentPadding: const EdgeInsets.only(
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(!group ? 14.0 : 12.0)),
|
left: 14.0, right: 12.0, top: 2.0, bottom: 2.0),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(!group ? 14.0 : 12.0)),
|
||||||
leading: Container(
|
leading: Container(
|
||||||
width: 44.0,
|
width: 44.0,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: !group ? color.withOpacity(.25) : null,
|
color: !group ? color.withOpacity(.25) : null,
|
||||||
),
|
),
|
||||||
child: Center(child: Icon(justificationIcon(absence.state), color: color)),
|
child: Center(
|
||||||
|
child: Icon(justificationIcon(absence.state), color: color)),
|
||||||
),
|
),
|
||||||
title: !group
|
title: !group
|
||||||
? Text.rich(TextSpan(
|
? Text.rich(TextSpan(
|
||||||
text: "${absence.delay == 0 ? "" : absence.delay}",
|
text: "${absence.delay == 0 ? "" : absence.delay}",
|
||||||
style: const TextStyle(fontWeight: FontWeight.w700, fontSize: 15.5),
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w700, fontSize: 15.5),
|
||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: absence.delay == 0
|
text: absence.delay == 0
|
||||||
? justificationName(absence.state).fill(["absence".i18n]).capital()
|
? justificationName(absence.state)
|
||||||
: 'minute'.plural(absence.delay) + justificationName(absence.state).fill(["delay".i18n]),
|
.fill(["absence".i18n]).capital()
|
||||||
|
: 'minute'.plural(absence.delay) +
|
||||||
|
justificationName(absence.state)
|
||||||
|
.fill(["delay".i18n]),
|
||||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
))
|
))
|
||||||
: Text(
|
: Text(
|
||||||
(absence.lessonIndex != null ? "${absence.lessonIndex}. " : "") + (absence.subject.renamedTo ?? absence.subject.name.capital()),
|
(absence.lessonIndex != null
|
||||||
|
? "${absence.lessonIndex}. "
|
||||||
|
: "") +
|
||||||
|
(absence.subject.renamedTo ??
|
||||||
|
absence.subject.name.capital()),
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 14.0, fontStyle: absence.subject.isRenamed && settingsProvider.renamedSubjectsItalics ? FontStyle.italic : null),
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
fontSize: 14.0,
|
||||||
|
fontStyle: absence.subject.isRenamed &&
|
||||||
|
settingsProvider.renamedSubjectsItalics
|
||||||
|
? FontStyle.italic
|
||||||
|
: null),
|
||||||
),
|
),
|
||||||
subtitle: !group
|
subtitle: !group
|
||||||
? Text(
|
? Text(
|
||||||
@ -77,7 +101,12 @@ class AbsenceTile extends StatelessWidget {
|
|||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
// DateFormat("MM. dd. (EEEEE)", I18n.of(context).locale.toString()).format(absence.date),
|
// DateFormat("MM. dd. (EEEEE)", I18n.of(context).locale.toString()).format(absence.date),
|
||||||
style: TextStyle(fontWeight: FontWeight.w500, fontStyle: absence.subject.isRenamed && settingsProvider.renamedSubjectsItalics ? FontStyle.italic : null),
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
fontStyle: absence.subject.isRenamed &&
|
||||||
|
settingsProvider.renamedSubjectsItalics
|
||||||
|
? FontStyle.italic
|
||||||
|
: null),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
@ -97,7 +126,8 @@ class AbsenceTile extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Color justificationColor(Justification state, {required BuildContext context}) {
|
static Color justificationColor(Justification state,
|
||||||
|
{required BuildContext context}) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case Justification.excused:
|
case Justification.excused:
|
||||||
return AppColors.of(context).green;
|
return AppColors.of(context).green;
|
||||||
|
@ -17,19 +17,23 @@ import 'package:provider/provider.dart';
|
|||||||
import 'absence_view.i18n.dart';
|
import 'absence_view.i18n.dart';
|
||||||
|
|
||||||
class AbsenceView extends StatelessWidget {
|
class AbsenceView extends StatelessWidget {
|
||||||
const AbsenceView(this.absence, {Key? key, this.outsideContext, this.viewable = false}) : super(key: key);
|
const AbsenceView(this.absence,
|
||||||
|
{Key? key, this.outsideContext, this.viewable = false})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
final Absence absence;
|
final Absence absence;
|
||||||
final BuildContext? outsideContext;
|
final BuildContext? outsideContext;
|
||||||
final bool viewable;
|
final bool viewable;
|
||||||
|
|
||||||
static show(Absence absence, {required BuildContext context}) {
|
static show(Absence absence, {required BuildContext context}) {
|
||||||
showBottomCard(context: context, child: AbsenceView(absence, outsideContext: context));
|
showBottomCard(
|
||||||
|
context: context, child: AbsenceView(absence, outsideContext: context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Color color = AbsenceTile.justificationColor(absence.state, context: context);
|
Color color =
|
||||||
|
AbsenceTile.justificationColor(absence.state, context: context);
|
||||||
SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
|
SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
@ -41,7 +45,8 @@ class AbsenceView extends StatelessWidget {
|
|||||||
ListTile(
|
ListTile(
|
||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
contentPadding: const EdgeInsets.only(left: 16.0, right: 12.0),
|
contentPadding: const EdgeInsets.only(left: 16.0, right: 12.0),
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0)),
|
||||||
leading: Container(
|
leading: Container(
|
||||||
width: 44.0,
|
width: 44.0,
|
||||||
height: 44.0,
|
height: 44.0,
|
||||||
@ -60,10 +65,18 @@ class AbsenceView extends StatelessWidget {
|
|||||||
absence.subject.renamedTo ?? absence.subject.name.capital(),
|
absence.subject.renamedTo ?? absence.subject.name.capital(),
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(fontWeight: FontWeight.w700, fontStyle: absence.subject.isRenamed && settingsProvider.renamedSubjectsItalics ? FontStyle.italic : null),
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
fontStyle: absence.subject.isRenamed &&
|
||||||
|
settingsProvider.renamedSubjectsItalics
|
||||||
|
? FontStyle.italic
|
||||||
|
: null),
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
absence.teacher,
|
(absence.teacher.isRenamed
|
||||||
|
? absence.teacher.renamedTo
|
||||||
|
: absence.teacher.name) ??
|
||||||
|
'',
|
||||||
// DateFormat("MM. dd. (EEEEE)", I18n.of(context).locale.toString()).format(absence.date),
|
// DateFormat("MM. dd. (EEEEE)", I18n.of(context).locale.toString()).format(absence.date),
|
||||||
style: const TextStyle(fontWeight: FontWeight.w500),
|
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||||
),
|
),
|
||||||
@ -77,12 +90,15 @@ class AbsenceView extends StatelessWidget {
|
|||||||
if (absence.delay > 0)
|
if (absence.delay > 0)
|
||||||
Detail(
|
Detail(
|
||||||
title: "delay".i18n,
|
title: "delay".i18n,
|
||||||
description: absence.delay.toString() + " " + "minutes".i18n.plural(absence.delay),
|
description: absence.delay.toString() +
|
||||||
|
" " +
|
||||||
|
"minutes".i18n.plural(absence.delay),
|
||||||
),
|
),
|
||||||
if (absence.lessonIndex != null)
|
if (absence.lessonIndex != null)
|
||||||
Detail(
|
Detail(
|
||||||
title: "Lesson".i18n,
|
title: "Lesson".i18n,
|
||||||
description: "${absence.lessonIndex}. (${absence.lessonStart.format(context, timeOnly: true)}"
|
description:
|
||||||
|
"${absence.lessonIndex}. (${absence.lessonStart.format(context, timeOnly: true)}"
|
||||||
" - "
|
" - "
|
||||||
"${absence.lessonEnd.format(context, timeOnly: true)})",
|
"${absence.lessonEnd.format(context, timeOnly: true)})",
|
||||||
),
|
),
|
||||||
@ -91,13 +107,19 @@ class AbsenceView extends StatelessWidget {
|
|||||||
title: "Excuse".i18n,
|
title: "Excuse".i18n,
|
||||||
description: absence.justification?.description ?? "",
|
description: absence.justification?.description ?? "",
|
||||||
),
|
),
|
||||||
if (absence.mode != null) Detail(title: "Mode".i18n, description: absence.mode?.description ?? ""),
|
if (absence.mode != null)
|
||||||
Detail(title: "Submit date".i18n, description: absence.submitDate.format(context)),
|
Detail(
|
||||||
|
title: "Mode".i18n,
|
||||||
|
description: absence.mode?.description ?? ""),
|
||||||
|
Detail(
|
||||||
|
title: "Submit date".i18n,
|
||||||
|
description: absence.submitDate.format(context)),
|
||||||
|
|
||||||
// Show in timetable
|
// Show in timetable
|
||||||
if (!viewable)
|
if (!viewable)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 16.0, right: 16.0, bottom: 6.0, top: 12.0),
|
padding: const EdgeInsets.only(
|
||||||
|
left: 16.0, right: 16.0, bottom: 6.0, top: 12.0),
|
||||||
child: PanelActionButton(
|
child: PanelActionButton(
|
||||||
leading: const Icon(FeatherIcons.calendar),
|
leading: const Icon(FeatherIcons.calendar),
|
||||||
title: Text(
|
title: Text(
|
||||||
@ -109,12 +131,15 @@ class AbsenceView extends StatelessWidget {
|
|||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
|
||||||
if (outsideContext != null) {
|
if (outsideContext != null) {
|
||||||
ReverseSearch.getLessonByAbsence(absence, context).then((lesson) {
|
ReverseSearch.getLessonByAbsence(absence, context)
|
||||||
|
.then((lesson) {
|
||||||
if (lesson != null) {
|
if (lesson != null) {
|
||||||
TimetablePage.jump(outsideContext!, lesson: lesson);
|
TimetablePage.jump(outsideContext!, lesson: lesson);
|
||||||
} else {
|
} else {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
|
ScaffoldMessenger.of(context)
|
||||||
content: Text("Cannot find lesson".i18n, style: const TextStyle(color: Colors.white)),
|
.showSnackBar(CustomSnackBar(
|
||||||
|
content: Text("Cannot find lesson".i18n,
|
||||||
|
style: const TextStyle(color: Colors.white)),
|
||||||
backgroundColor: AppColors.of(context).red,
|
backgroundColor: AppColors.of(context).red,
|
||||||
context: context,
|
context: context,
|
||||||
));
|
));
|
||||||
|
@ -5,6 +5,8 @@ import 'package:filcnaplo_mobile_ui/common/widgets/absence_group/absence_group_c
|
|||||||
import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_tile.dart';
|
import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_tile.dart';
|
||||||
import 'package:filcnaplo/utils/format.dart';
|
import 'package:filcnaplo/utils/format.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||||
|
import 'package:rounded_expansion_tile/rounded_expansion_tile.dart';
|
||||||
import 'absence_group_tile.i18n.dart';
|
import 'absence_group_tile.i18n.dart';
|
||||||
|
|
||||||
class AbsenceGroupTile extends StatelessWidget {
|
class AbsenceGroupTile extends StatelessWidget {
|
||||||
@ -30,13 +32,17 @@ class AbsenceGroupTile extends StatelessWidget {
|
|||||||
child: Material(
|
child: Material(
|
||||||
type: MaterialType.transparency,
|
type: MaterialType.transparency,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
|
padding: padding ??
|
||||||
|
const EdgeInsets.symmetric(horizontal: 0.0, vertical: 0.0),
|
||||||
child: AbsenceGroupContainer(
|
child: AbsenceGroupContainer(
|
||||||
child: ExpansionTile(
|
child: RoundedExpansionTile(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(10)),
|
borderRadius: BorderRadius.circular(10)),
|
||||||
tilePadding: const EdgeInsets.symmetric(horizontal: 8.0),
|
childrenPadding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
backgroundColor: Colors.transparent,
|
tileColor: Colors.transparent,
|
||||||
|
duration: const Duration(milliseconds: 250),
|
||||||
|
trailingDuration: 0.5,
|
||||||
|
trailing: const Icon(FeatherIcons.chevronDown),
|
||||||
leading: Container(
|
leading: Container(
|
||||||
width: 44.0,
|
width: 44.0,
|
||||||
height: 44.0,
|
height: 44.0,
|
||||||
|
@ -12,7 +12,8 @@ class ExamView extends StatelessWidget {
|
|||||||
|
|
||||||
final Exam exam;
|
final Exam exam;
|
||||||
|
|
||||||
static show(Exam exam, {required BuildContext context}) => showBottomCard(context: context, child: ExamView(exam));
|
static show(Exam exam, {required BuildContext context}) =>
|
||||||
|
showBottomCard(context: context, child: ExamView(exam));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -27,7 +28,8 @@ class ExamView extends StatelessWidget {
|
|||||||
leading: Padding(
|
leading: Padding(
|
||||||
padding: const EdgeInsets.only(left: 6.0),
|
padding: const EdgeInsets.only(left: 6.0),
|
||||||
child: Icon(
|
child: Icon(
|
||||||
SubjectIcon.resolveVariant(subjectName: exam.subjectName, context: context),
|
SubjectIcon.resolveVariant(
|
||||||
|
subjectName: exam.subjectName, context: context),
|
||||||
size: 36.0,
|
size: 36.0,
|
||||||
color: AppColors.of(context).text.withOpacity(.75),
|
color: AppColors.of(context).text.withOpacity(.75),
|
||||||
),
|
),
|
||||||
@ -39,7 +41,10 @@ class ExamView extends StatelessWidget {
|
|||||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
exam.teacher,
|
(exam.teacher.isRenamed
|
||||||
|
? exam.teacher.renamedTo
|
||||||
|
: exam.teacher.name) ??
|
||||||
|
'',
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: const TextStyle(fontWeight: FontWeight.w500),
|
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||||
@ -51,9 +56,14 @@ class ExamView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
|
|
||||||
// Details
|
// Details
|
||||||
if (exam.writeDate.year != 0) Detail(title: "date".i18n, description: exam.writeDate.format(context)),
|
if (exam.writeDate.year != 0)
|
||||||
if (exam.description != "") Detail(title: "description".i18n, description: exam.description),
|
Detail(
|
||||||
if (exam.mode != null) Detail(title: "mode".i18n, description: exam.mode!.description),
|
title: "date".i18n,
|
||||||
|
description: exam.writeDate.format(context)),
|
||||||
|
if (exam.description != "")
|
||||||
|
Detail(title: "description".i18n, description: exam.description),
|
||||||
|
if (exam.mode != null)
|
||||||
|
Detail(title: "mode".i18n, description: exam.mode!.description),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -11,7 +11,8 @@ import 'grade_view.i18n.dart';
|
|||||||
class GradeView extends StatelessWidget {
|
class GradeView extends StatelessWidget {
|
||||||
const GradeView(this.grade, {Key? key}) : super(key: key);
|
const GradeView(this.grade, {Key? key}) : super(key: key);
|
||||||
|
|
||||||
static show(Grade grade, {required BuildContext context}) => showBottomCard(context: context, child: GradeView(grade));
|
static show(Grade grade, {required BuildContext context}) =>
|
||||||
|
showBottomCard(context: context, child: GradeView(grade));
|
||||||
|
|
||||||
final Grade grade;
|
final Grade grade;
|
||||||
|
|
||||||
@ -30,10 +31,21 @@ class GradeView extends StatelessWidget {
|
|||||||
grade.subject.renamedTo ?? grade.subject.name.capital(),
|
grade.subject.renamedTo ?? grade.subject.name.capital(),
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(fontWeight: FontWeight.w600, fontStyle: grade.subject.isRenamed && settingsProvider.renamedSubjectsItalics ? FontStyle.italic : null),
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontStyle: grade.subject.isRenamed &&
|
||||||
|
settingsProvider.renamedSubjectsItalics
|
||||||
|
? FontStyle.italic
|
||||||
|
: null),
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
!Provider.of<SettingsProvider>(context, listen: false).presentationMode ? grade.teacher : "Tanár",
|
!Provider.of<SettingsProvider>(context, listen: false)
|
||||||
|
.presentationMode
|
||||||
|
? (grade.teacher.isRenamed
|
||||||
|
? grade.teacher.renamedTo
|
||||||
|
: grade.teacher.name) ??
|
||||||
|
''
|
||||||
|
: "Tanár",
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: const TextStyle(fontWeight: FontWeight.w500),
|
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||||
@ -49,13 +61,20 @@ class GradeView extends StatelessWidget {
|
|||||||
title: "value".i18n,
|
title: "value".i18n,
|
||||||
description: "${grade.value.valueName} " + percentText(),
|
description: "${grade.value.valueName} " + percentText(),
|
||||||
),
|
),
|
||||||
if (grade.description != "") Detail(title: "description".i18n, description: grade.description),
|
if (grade.description != "")
|
||||||
if (grade.mode.description != "") Detail(title: "mode".i18n, description: grade.mode.description),
|
Detail(title: "description".i18n, description: grade.description),
|
||||||
if (grade.writeDate.year != 0) Detail(title: "date".i18n, description: grade.writeDate.format(context)),
|
if (grade.mode.description != "")
|
||||||
|
Detail(title: "mode".i18n, description: grade.mode.description),
|
||||||
|
if (grade.writeDate.year != 0)
|
||||||
|
Detail(
|
||||||
|
title: "date".i18n,
|
||||||
|
description: grade.writeDate.format(context)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String percentText() => grade.value.weight != 100 && grade.value.weight > 0 ? "${grade.value.weight}%" : "";
|
String percentText() => grade.value.weight != 100 && grade.value.weight > 0
|
||||||
|
? "${grade.value.weight}%"
|
||||||
|
: "";
|
||||||
}
|
}
|
||||||
|
@ -51,10 +51,18 @@ class HomeworkView extends StatelessWidget {
|
|||||||
homework.subject.renamedTo ?? homework.subject.name.capital(),
|
homework.subject.renamedTo ?? homework.subject.name.capital(),
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(fontWeight: FontWeight.w600, fontStyle: homework.subject.isRenamed && settingsProvider.renamedSubjectsItalics ? FontStyle.italic : null),
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontStyle: homework.subject.isRenamed &&
|
||||||
|
settingsProvider.renamedSubjectsItalics
|
||||||
|
? FontStyle.italic
|
||||||
|
: null),
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
homework.teacher,
|
(homework.teacher.isRenamed
|
||||||
|
? homework.teacher.renamedTo
|
||||||
|
: homework.teacher.name) ??
|
||||||
|
'',
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: const TextStyle(fontWeight: FontWeight.w500),
|
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||||
|
@ -6,7 +6,8 @@ import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
|||||||
import 'changed_lesson_tile.i18n.dart';
|
import 'changed_lesson_tile.i18n.dart';
|
||||||
|
|
||||||
class ChangedLessonTile extends StatelessWidget {
|
class ChangedLessonTile extends StatelessWidget {
|
||||||
const ChangedLessonTile(this.lesson, {Key? key, this.onTap, this.padding}) : super(key: key);
|
const ChangedLessonTile(this.lesson, {Key? key, this.onTap, this.padding})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
final Lesson lesson;
|
final Lesson lesson;
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
@ -21,7 +22,7 @@ class ChangedLessonTile extends StatelessWidget {
|
|||||||
|
|
||||||
Color accent = Theme.of(context).colorScheme.secondary;
|
Color accent = Theme.of(context).colorScheme.secondary;
|
||||||
|
|
||||||
if (lesson.substituteTeacher != "") {
|
if (lesson.substituteTeacher?.name != '') {
|
||||||
accent = AppColors.of(context).yellow;
|
accent = AppColors.of(context).yellow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +39,8 @@ class ChangedLessonTile extends StatelessWidget {
|
|||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
|
contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
|
shape:
|
||||||
|
RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
|
||||||
leading: SizedBox(
|
leading: SizedBox(
|
||||||
width: 44.0,
|
width: 44.0,
|
||||||
height: 44.0,
|
height: 44.0,
|
||||||
@ -55,7 +57,9 @@ class ChangedLessonTile extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
lesson.substituteTeacher != "" ? "substituted".i18n : "cancelled".i18n,
|
lesson.substituteTeacher?.name != ""
|
||||||
|
? "substituted".i18n
|
||||||
|
: "cancelled".i18n,
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||||
@ -64,7 +68,9 @@ class ChangedLessonTile extends StatelessWidget {
|
|||||||
lesson.subject.renamedTo ?? lesson.subject.name.capital(),
|
lesson.subject.renamedTo ?? lesson.subject.name.capital(),
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(fontWeight: FontWeight.w500, fontStyle: lesson.subject.isRenamed ? FontStyle.italic : null),
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
fontStyle: lesson.subject.isRenamed ? FontStyle.italic : null),
|
||||||
),
|
),
|
||||||
trailing: const Icon(FeatherIcons.arrowRight),
|
trailing: const Icon(FeatherIcons.arrowRight),
|
||||||
minLeadingWidth: 0,
|
minLeadingWidth: 0,
|
||||||
|
@ -22,7 +22,7 @@ class LessonView extends StatelessWidget {
|
|||||||
|
|
||||||
if (RegExp(r'\d').hasMatch(lesson.lessonIndex)) lessonIndexTrailing = ".";
|
if (RegExp(r'\d').hasMatch(lesson.lessonIndex)) lessonIndexTrailing = ".";
|
||||||
|
|
||||||
if (lesson.substituteTeacher != "") {
|
if (lesson.substituteTeacher?.name != "") {
|
||||||
accent = AppColors.of(context).yellow;
|
accent = AppColors.of(context).yellow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,10 +54,23 @@ class LessonView extends StatelessWidget {
|
|||||||
lesson.subject.renamedTo ?? lesson.subject.name.capital(),
|
lesson.subject.renamedTo ?? lesson.subject.name.capital(),
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(fontWeight: FontWeight.w600, fontStyle: lesson.subject.isRenamed && settingsProvider.renamedSubjectsItalics ? FontStyle.italic : null),
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontStyle: lesson.subject.isRenamed &&
|
||||||
|
settingsProvider.renamedSubjectsItalics
|
||||||
|
? FontStyle.italic
|
||||||
|
: null),
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
lesson.substituteTeacher == "" ? lesson.teacher : lesson.substituteTeacher,
|
((lesson.substituteTeacher == null ||
|
||||||
|
lesson.substituteTeacher!.name == "")
|
||||||
|
? (lesson.teacher.isRenamed
|
||||||
|
? lesson.teacher.renamedTo
|
||||||
|
: lesson.teacher.name)
|
||||||
|
: (lesson.substituteTeacher!.isRenamed
|
||||||
|
? lesson.substituteTeacher!.renamedTo
|
||||||
|
: lesson.substituteTeacher!.name)) ??
|
||||||
|
'',
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: const TextStyle(fontWeight: FontWeight.w500),
|
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||||
@ -69,10 +82,18 @@ class LessonView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
|
|
||||||
// Details
|
// Details
|
||||||
if (lesson.room != "") Detail(title: "Room".i18n, description: lesson.room.replaceAll("_", " ")),
|
if (lesson.room != "")
|
||||||
if (lesson.description != "") Detail(title: "Description".i18n, description: lesson.description),
|
Detail(
|
||||||
if (lesson.lessonYearIndex != null) Detail(title: "Lesson Number".i18n, description: "${lesson.lessonYearIndex}."),
|
title: "Room".i18n,
|
||||||
if (lesson.groupName != "") Detail(title: "Group".i18n, description: lesson.groupName),
|
description: lesson.room.replaceAll("_", " ")),
|
||||||
|
if (lesson.description != "")
|
||||||
|
Detail(title: "Description".i18n, description: lesson.description),
|
||||||
|
if (lesson.lessonYearIndex != null)
|
||||||
|
Detail(
|
||||||
|
title: "Lesson Number".i18n,
|
||||||
|
description: "${lesson.lessonYearIndex}."),
|
||||||
|
if (lesson.groupName != "")
|
||||||
|
Detail(title: "Group".i18n, description: lesson.groupName),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -4,7 +4,8 @@ import 'package:filcnaplo_mobile_ui/common/profile_image/profile_image.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class NoteTile extends StatelessWidget {
|
class NoteTile extends StatelessWidget {
|
||||||
const NoteTile(this.note, {Key? key, this.onTap, this.padding}) : super(key: key);
|
const NoteTile(this.note, {Key? key, this.onTap, this.padding})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
final Note note;
|
final Note note;
|
||||||
final void Function()? onTap;
|
final void Function()? onTap;
|
||||||
@ -20,11 +21,20 @@ class NoteTile extends StatelessWidget {
|
|||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
|
contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0),
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
|
shape:
|
||||||
|
RoundedRectangleBorder(borderRadius: BorderRadius.circular(14.0)),
|
||||||
leading: ProfileImage(
|
leading: ProfileImage(
|
||||||
name: note.teacher,
|
name: (note.teacher.isRenamed
|
||||||
|
? note.teacher.renamedTo
|
||||||
|
: note.teacher.name) ??
|
||||||
|
'',
|
||||||
radius: 22.0,
|
radius: 22.0,
|
||||||
backgroundColor: ColorUtils.stringToColor(note.teacher),
|
backgroundColor: ColorUtils.stringToColor(
|
||||||
|
(note.teacher.isRenamed
|
||||||
|
? note.teacher.renamedTo
|
||||||
|
: note.teacher.name) ??
|
||||||
|
'',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
note.title,
|
note.title,
|
||||||
|
@ -12,7 +12,8 @@ class NoteView extends StatelessWidget {
|
|||||||
|
|
||||||
final Note note;
|
final Note note;
|
||||||
|
|
||||||
static void show(Note note, {required BuildContext context}) => showSlidingBottomSheet(context: context, child: NoteView(note));
|
static void show(Note note, {required BuildContext context}) =>
|
||||||
|
showSlidingBottomSheet(context: context, child: NoteView(note));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -25,9 +26,17 @@ class NoteView extends StatelessWidget {
|
|||||||
// Header
|
// Header
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: ProfileImage(
|
leading: ProfileImage(
|
||||||
name: note.teacher,
|
name: (note.teacher.isRenamed
|
||||||
|
? note.teacher.renamedTo
|
||||||
|
: note.teacher.name) ??
|
||||||
|
'',
|
||||||
radius: 22.0,
|
radius: 22.0,
|
||||||
backgroundColor: ColorUtils.stringToColor(note.teacher),
|
backgroundColor: ColorUtils.stringToColor(
|
||||||
|
(note.teacher.isRenamed
|
||||||
|
? note.teacher.renamedTo
|
||||||
|
: note.teacher.name) ??
|
||||||
|
'',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
note.title,
|
note.title,
|
||||||
@ -36,7 +45,10 @@ class NoteView extends StatelessWidget {
|
|||||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
note.teacher,
|
(note.teacher.isRenamed
|
||||||
|
? note.teacher.renamedTo
|
||||||
|
: note.teacher.name) ??
|
||||||
|
'',
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: const TextStyle(fontWeight: FontWeight.w500),
|
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||||
|
@ -19,14 +19,18 @@ import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_view.i18n.dar
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class AbsenceSubjectView extends StatelessWidget {
|
class AbsenceSubjectView extends StatelessWidget {
|
||||||
const AbsenceSubjectView(this.subject, {Key? key, this.absences = const []}) : super(key: key);
|
const AbsenceSubjectView(this.subject, {Key? key, this.absences = const []})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
final Subject subject;
|
final Subject subject;
|
||||||
final List<Absence> absences;
|
final List<Absence> absences;
|
||||||
|
|
||||||
static void show(Subject subject, List<Absence> absences, {required BuildContext context}) {
|
static void show(Subject subject, List<Absence> absences,
|
||||||
|
{required BuildContext context}) {
|
||||||
Navigator.of(context, rootNavigator: true)
|
Navigator.of(context, rootNavigator: true)
|
||||||
.push<Absence>(CupertinoPageRoute(builder: (context) => AbsenceSubjectView(subject, absences: absences)))
|
.push<Absence>(CupertinoPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
|
AbsenceSubjectView(subject, absences: absences)))
|
||||||
.then((value) {
|
.then((value) {
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
|
|
||||||
@ -36,7 +40,8 @@ class AbsenceSubjectView extends StatelessWidget {
|
|||||||
TimetablePage.jump(context, lesson: lesson);
|
TimetablePage.jump(context, lesson: lesson);
|
||||||
} else {
|
} else {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
|
||||||
content: Text("Cannot find lesson".i18n, style: const TextStyle(color: Colors.white)),
|
content: Text("Cannot find lesson".i18n,
|
||||||
|
style: const TextStyle(color: Colors.white)),
|
||||||
backgroundColor: AppColors.of(context).red,
|
backgroundColor: AppColors.of(context).red,
|
||||||
context: context,
|
context: context,
|
||||||
));
|
));
|
||||||
@ -54,7 +59,10 @@ class AbsenceSubjectView extends StatelessWidget {
|
|||||||
date: a.date,
|
date: a.date,
|
||||||
))
|
))
|
||||||
.toList();
|
.toList();
|
||||||
List<Widget> absenceTiles = sortDateWidgets(context, dateWidgets: dateWidgets, padding: EdgeInsets.zero, hasShadow: true);
|
List<Widget> absenceTiles = sortDateWidgets(context,
|
||||||
|
dateWidgets: dateWidgets,
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 6.0),
|
||||||
|
hasShadow: true);
|
||||||
|
|
||||||
SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
|
SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import 'dart:math';
|
|||||||
import 'package:filcnaplo_kreta_api/models/category.dart';
|
import 'package:filcnaplo_kreta_api/models/category.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/subject.dart';
|
import 'package:filcnaplo_kreta_api/models/subject.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/teacher.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/common/custom_snack_bar.dart';
|
import 'package:filcnaplo_mobile_ui/common/custom_snack_bar.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/common/material_action_button.dart';
|
import 'package:filcnaplo_mobile_ui/common/material_action_button.dart';
|
||||||
import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
|
import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
|
||||||
@ -42,7 +43,8 @@ class _GradeCalculatorState extends State<GradeCalculator> {
|
|||||||
padding: const EdgeInsets.only(bottom: 8.0),
|
padding: const EdgeInsets.only(bottom: 8.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
"Grade Calculator".i18n,
|
"Grade Calculator".i18n,
|
||||||
style: const TextStyle(fontSize: 20.0, fontWeight: FontWeight.w600),
|
style:
|
||||||
|
const TextStyle(fontSize: 20.0, fontWeight: FontWeight.w600),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -63,7 +65,9 @@ class _GradeCalculatorState extends State<GradeCalculator> {
|
|||||||
Container(
|
Container(
|
||||||
width: 80.0,
|
width: 80.0,
|
||||||
padding: const EdgeInsets.only(right: 12.0),
|
padding: const EdgeInsets.only(right: 12.0),
|
||||||
child: Center(child: GradeValueWidget(GradeValue(newValue.toInt(), "", "", 0))),
|
child: Center(
|
||||||
|
child: GradeValueWidget(
|
||||||
|
GradeValue(newValue.toInt(), "", "", 0))),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
@ -90,7 +94,8 @@ class _GradeCalculatorState extends State<GradeCalculator> {
|
|||||||
child: Center(
|
child: Center(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: _weightController,
|
controller: _weightController,
|
||||||
style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 22.0),
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w600, fontSize: 22.0),
|
||||||
autocorrect: false,
|
autocorrect: false,
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
@ -121,8 +126,9 @@ class _GradeCalculatorState extends State<GradeCalculator> {
|
|||||||
child: MaterialActionButton(
|
child: MaterialActionButton(
|
||||||
child: Text("Add Grade".i18n),
|
child: Text("Add Grade".i18n),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (calculatorProvider.ghosts.length >= 30) {
|
if (calculatorProvider.ghosts.length >= 50) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(content: Text("limit_reached".i18n), context: context));
|
ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
|
||||||
|
content: Text("limit_reached".i18n), context: context));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +139,11 @@ class _GradeCalculatorState extends State<GradeCalculator> {
|
|||||||
grades.sort((a, b) => -a.writeDate.compareTo(b.writeDate));
|
grades.sort((a, b) => -a.writeDate.compareTo(b.writeDate));
|
||||||
date = grades.first.date.add(const Duration(days: 7));
|
date = grades.first.date.add(const Duration(days: 7));
|
||||||
} else {
|
} else {
|
||||||
List<Grade> grades = calculatorProvider.grades.where((e) => e.type == GradeType.midYear && e.subject == widget.subject).toList();
|
List<Grade> grades = calculatorProvider.grades
|
||||||
|
.where((e) =>
|
||||||
|
e.type == GradeType.midYear &&
|
||||||
|
e.subject == widget.subject)
|
||||||
|
.toList();
|
||||||
grades.sort((a, b) => -a.writeDate.compareTo(b.writeDate));
|
grades.sort((a, b) => -a.writeDate.compareTo(b.writeDate));
|
||||||
date = grades.first.date;
|
date = grades.first.date;
|
||||||
}
|
}
|
||||||
@ -143,8 +153,9 @@ class _GradeCalculatorState extends State<GradeCalculator> {
|
|||||||
date: date,
|
date: date,
|
||||||
writeDate: date,
|
writeDate: date,
|
||||||
description: "Ghost Grade".i18n,
|
description: "Ghost Grade".i18n,
|
||||||
value: GradeValue(newValue.toInt(), "", "", newWeight.toInt()),
|
value:
|
||||||
teacher: "Ghost",
|
GradeValue(newValue.toInt(), "", "", newWeight.toInt()),
|
||||||
|
teacher: Teacher.fromString("Ghost"),
|
||||||
type: GradeType.ghost,
|
type: GradeType.ghost,
|
||||||
form: "",
|
form: "",
|
||||||
subject: widget.subject,
|
subject: widget.subject,
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:animations/animations.dart';
|
import 'package:animations/animations.dart';
|
||||||
|
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||||
|
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||||
import 'package:filcnaplo/models/settings.dart';
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
import 'package:filcnaplo/utils/format.dart';
|
import 'package:filcnaplo/utils/format.dart';
|
||||||
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
||||||
@ -21,6 +23,11 @@ import 'package:filcnaplo_mobile_ui/pages/grades/calculator/grade_calculator_pro
|
|||||||
import 'package:filcnaplo_mobile_ui/pages/grades/grades_count.dart';
|
import 'package:filcnaplo_mobile_ui/pages/grades/grades_count.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/pages/grades/graph.dart';
|
import 'package:filcnaplo_mobile_ui/pages/grades/graph.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/pages/grades/subject_grades_container.dart';
|
import 'package:filcnaplo_mobile_ui/pages/grades/subject_grades_container.dart';
|
||||||
|
import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_planner_screen.dart';
|
||||||
|
import 'package:filcnaplo_premium/models/premium_scopes.dart';
|
||||||
|
import 'package:filcnaplo_premium/providers/premium_provider.dart';
|
||||||
|
import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_state_screen.dart';
|
||||||
|
import 'package:filcnaplo_premium/ui/mobile/premium/upsell.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
|
import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
|
||||||
@ -58,12 +65,16 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
|
|||||||
late GradeProvider gradeProvider;
|
late GradeProvider gradeProvider;
|
||||||
late GradeCalculatorProvider calculatorProvider;
|
late GradeCalculatorProvider calculatorProvider;
|
||||||
late SettingsProvider settingsProvider;
|
late SettingsProvider settingsProvider;
|
||||||
|
late DatabaseProvider dbProvider;
|
||||||
|
late UserProvider user;
|
||||||
|
|
||||||
late double average;
|
late double average;
|
||||||
late Widget gradeGraph;
|
late Widget gradeGraph;
|
||||||
|
|
||||||
bool gradeCalcMode = false;
|
bool gradeCalcMode = false;
|
||||||
|
|
||||||
|
String plan = '';
|
||||||
|
|
||||||
List<Grade> getSubjectGrades(Subject subject) => !gradeCalcMode
|
List<Grade> getSubjectGrades(Subject subject) => !gradeCalcMode
|
||||||
? gradeProvider.grades.where((e) => e.subject == subject).toList()
|
? gradeProvider.grades.where((e) => e.subject == subject).toList()
|
||||||
: calculatorProvider.grades.where((e) => e.subject == subject).toList();
|
: calculatorProvider.grades.where((e) => e.subject == subject).toList();
|
||||||
@ -147,6 +158,20 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
|
|||||||
gradeTiles = List.castFrom(tiles);
|
gradeTiles = List.castFrom(tiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
user = Provider.of<UserProvider>(context, listen: false);
|
||||||
|
dbProvider = Provider.of<DatabaseProvider>(context, listen: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fetchGoalPlans() async {
|
||||||
|
plan = (await dbProvider.userQuery
|
||||||
|
.subjectGoalPlans(userId: user.id!))[widget.subject.id] ??
|
||||||
|
'';
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
gradeProvider = Provider.of<GradeProvider>(context);
|
gradeProvider = Provider.of<GradeProvider>(context);
|
||||||
@ -192,6 +217,8 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
|
|||||||
buildTiles(ghostGrades);
|
buildTiles(ghostGrades);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fetchGoalPlans();
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
key: _scaffoldKey,
|
key: _scaffoldKey,
|
||||||
floatingActionButtonLocation: ExpandableFab.location,
|
floatingActionButtonLocation: ExpandableFab.location,
|
||||||
@ -209,31 +236,33 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
|
|||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
FloatingActionButton.small(
|
FloatingActionButton.small(
|
||||||
|
heroTag: "btn_ghost_grades",
|
||||||
child: const Icon(FeatherIcons.plus),
|
child: const Icon(FeatherIcons.plus),
|
||||||
backgroundColor: Theme.of(context).colorScheme.secondary,
|
backgroundColor: Theme.of(context).colorScheme.secondary,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
gradeCalc(context);
|
gradeCalc(context);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
// FloatingActionButton.small(
|
FloatingActionButton.small(
|
||||||
// child: const Icon(FeatherIcons.flag, size: 20.0),
|
heroTag: "btn_goal_planner",
|
||||||
// backgroundColor: Theme.of(context).colorScheme.secondary,
|
child: const Icon(FeatherIcons.flag, size: 20.0),
|
||||||
// onPressed: () {
|
backgroundColor: Theme.of(context).colorScheme.secondary,
|
||||||
// if (!Provider.of<PremiumProvider>(context, listen: false)
|
onPressed: () {
|
||||||
// .hasScope(PremiumScopes.goalPlanner)) {
|
if (!Provider.of<PremiumProvider>(context, listen: false)
|
||||||
// PremiumLockedFeatureUpsell.show(
|
.hasScope(PremiumScopes.goalPlanner)) {
|
||||||
// context: context, feature: PremiumFeature.goalplanner);
|
PremiumLockedFeatureUpsell.show(
|
||||||
// return;
|
context: context, feature: PremiumFeature.goalplanner);
|
||||||
// }
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// ScaffoldMessenger.of(context).showSnackBar(
|
// ScaffoldMessenger.of(context).showSnackBar(
|
||||||
// const SnackBar(content: Text("Hamarosan...")));
|
// const SnackBar(content: Text("Hamarosan...")));
|
||||||
|
|
||||||
// Navigator.of(context).push(CupertinoPageRoute(
|
Navigator.of(context).push(CupertinoPageRoute(
|
||||||
// builder: (context) => PremiumGoalplannerNewGoalScreen(
|
builder: (context) =>
|
||||||
// subject: widget.subject)));
|
GoalPlannerScreen(subject: widget.subject)));
|
||||||
// },
|
},
|
||||||
// ),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -257,13 +286,42 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
|
|||||||
const SizedBox(width: 6.0),
|
const SizedBox(width: 6.0),
|
||||||
if (average != 0)
|
if (average != 0)
|
||||||
Center(child: AverageDisplay(average: average)),
|
Center(child: AverageDisplay(average: average)),
|
||||||
|
const SizedBox(width: 6.0),
|
||||||
|
if (plan != '')
|
||||||
|
Center(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.of(context).push(CupertinoPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
|
GoalStateScreen(subject: widget.subject)));
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
width: 54.0,
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(45.0),
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.primary
|
||||||
|
.withOpacity(.15),
|
||||||
|
),
|
||||||
|
child: Icon(
|
||||||
|
FeatherIcons.flag,
|
||||||
|
size: 17.0,
|
||||||
|
weight: 2.5,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
const SizedBox(width: 12.0),
|
const SizedBox(width: 12.0),
|
||||||
],
|
],
|
||||||
icon: SubjectIcon.resolveVariant(
|
icon: SubjectIcon.resolveVariant(
|
||||||
subject: widget.subject, context: context),
|
subject: widget.subject, context: context),
|
||||||
scrollController: _scrollController,
|
scrollController: _scrollController,
|
||||||
title: widget.subject.renamedTo ?? widget.subject.name.capital(),
|
title: widget.subject.renamedTo ?? widget.subject.name.capital(),
|
||||||
italic: settingsProvider.renamedSubjectsItalics && widget.subject.isRenamed,
|
italic: settingsProvider.renamedSubjectsItalics &&
|
||||||
|
widget.subject.isRenamed,
|
||||||
child: SubjectGradesContainer(
|
child: SubjectGradesContainer(
|
||||||
child: CupertinoScrollbar(
|
child: CupertinoScrollbar(
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
|
@ -356,14 +356,14 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
|||||||
// confetti 🎊
|
// confetti 🎊
|
||||||
if (_confettiController != null)
|
if (_confettiController != null)
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.bottomCenter,
|
alignment: Alignment.topCenter,
|
||||||
child: ConfettiWidget(
|
child: ConfettiWidget(
|
||||||
confettiController: _confettiController!,
|
confettiController: _confettiController!,
|
||||||
blastDirection: -pi / 2,
|
blastDirectionality: BlastDirectionality.explosive,
|
||||||
emissionFrequency: 0.01,
|
emissionFrequency: 0.02,
|
||||||
numberOfParticles: 80,
|
numberOfParticles: 120,
|
||||||
maxBlastForce: 100,
|
maxBlastForce: 20,
|
||||||
minBlastForce: 90,
|
minBlastForce: 10,
|
||||||
gravity: 0.3,
|
gravity: 0.3,
|
||||||
minimumSize: const Size(5, 5),
|
minimumSize: const Size(5, 5),
|
||||||
maximumSize: const Size(20, 20),
|
maximumSize: const Size(20, 20),
|
||||||
|
@ -3,6 +3,7 @@ import 'package:filcnaplo/helpers/quick_actions.dart';
|
|||||||
import 'package:filcnaplo/models/settings.dart';
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
import 'package:filcnaplo/theme/observer.dart';
|
import 'package:filcnaplo/theme/observer.dart';
|
||||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/common/system_chrome.dart';
|
import 'package:filcnaplo_mobile_ui/common/system_chrome.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/screens/navigation/nabar.dart';
|
import 'package:filcnaplo_mobile_ui/screens/navigation/nabar.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/screens/navigation/navbar_item.dart';
|
import 'package:filcnaplo_mobile_ui/screens/navigation/navbar_item.dart';
|
||||||
@ -12,6 +13,7 @@ import 'package:filcnaplo/icons/filc_icons.dart';
|
|||||||
import 'package:filcnaplo_mobile_ui/screens/navigation/status_bar.dart';
|
import 'package:filcnaplo_mobile_ui/screens/navigation/status_bar.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/screens/news/news_view.dart';
|
import 'package:filcnaplo_mobile_ui/screens/news/news_view.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.dart';
|
import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.dart';
|
||||||
|
import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_complete_modal.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@ -23,6 +25,7 @@ import 'package:filcnaplo/api/providers/sync.dart';
|
|||||||
import 'package:home_widget/home_widget.dart';
|
import 'package:home_widget/home_widget.dart';
|
||||||
import 'package:wtf_sliding_sheet/wtf_sliding_sheet.dart';
|
import 'package:wtf_sliding_sheet/wtf_sliding_sheet.dart';
|
||||||
import 'package:background_fetch/background_fetch.dart';
|
import 'package:background_fetch/background_fetch.dart';
|
||||||
|
import 'package:filcnaplo_premium/providers/goal_provider.dart';
|
||||||
|
|
||||||
class NavigationScreen extends StatefulWidget {
|
class NavigationScreen extends StatefulWidget {
|
||||||
const NavigationScreen({Key? key}) : super(key: key);
|
const NavigationScreen({Key? key}) : super(key: key);
|
||||||
@ -42,7 +45,9 @@ class NavigationScreenState extends State<NavigationScreen>
|
|||||||
|
|
||||||
late SettingsProvider settings;
|
late SettingsProvider settings;
|
||||||
late NewsProvider newsProvider;
|
late NewsProvider newsProvider;
|
||||||
|
late GoalProvider goalProvider;
|
||||||
late UpdateProvider updateProvider;
|
late UpdateProvider updateProvider;
|
||||||
|
late GradeProvider gradeProvicer;
|
||||||
|
|
||||||
NavigatorState? get navigator => _navigatorState.currentState;
|
NavigatorState? get navigator => _navigatorState.currentState;
|
||||||
|
|
||||||
@ -82,6 +87,7 @@ class NavigationScreenState extends State<NavigationScreen>
|
|||||||
snapSpec: const SnapSpec(
|
snapSpec: const SnapSpec(
|
||||||
snap: true,
|
snap: true,
|
||||||
snappings: [1.0],
|
snappings: [1.0],
|
||||||
|
initialSnap: 1.0,
|
||||||
positioning: SnapPositioning.relativeToSheetHeight,
|
positioning: SnapPositioning.relativeToSheetHeight,
|
||||||
),
|
),
|
||||||
cornerRadius: 16,
|
cornerRadius: 16,
|
||||||
@ -139,7 +145,6 @@ class NavigationScreenState extends State<NavigationScreen>
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
|
||||||
HomeWidget.setAppGroupId('hu.refilc.naplo.group');
|
HomeWidget.setAppGroupId('hu.refilc.naplo.group');
|
||||||
|
|
||||||
_checkForWidgetLaunch();
|
_checkForWidgetLaunch();
|
||||||
@ -156,15 +161,22 @@ class NavigationScreenState extends State<NavigationScreen>
|
|||||||
Provider.of<KretaClient>(context, listen: false).userAgent =
|
Provider.of<KretaClient>(context, listen: false).userAgent =
|
||||||
settings.config.userAgent;
|
settings.config.userAgent;
|
||||||
|
|
||||||
// Get news
|
// get news
|
||||||
newsProvider = Provider.of<NewsProvider>(context, listen: false);
|
newsProvider = Provider.of<NewsProvider>(context, listen: false);
|
||||||
newsProvider.restore().then((value) => newsProvider.fetch());
|
newsProvider.restore().then((value) => newsProvider.fetch());
|
||||||
|
|
||||||
// Get releases
|
// init grade provider (for goals)
|
||||||
|
gradeProvicer = Provider.of<GradeProvider>(context, listen: false);
|
||||||
|
|
||||||
|
// get goals
|
||||||
|
goalProvider = Provider.of<GoalProvider>(context, listen: false);
|
||||||
|
goalProvider.fetchDone(gradeProvider: gradeProvicer);
|
||||||
|
|
||||||
|
// get releases
|
||||||
updateProvider = Provider.of<UpdateProvider>(context, listen: false);
|
updateProvider = Provider.of<UpdateProvider>(context, listen: false);
|
||||||
updateProvider.fetch();
|
updateProvider.fetch();
|
||||||
|
|
||||||
// Initial sync
|
// initial sync
|
||||||
syncAll(context);
|
syncAll(context);
|
||||||
setupQuickActions();
|
setupQuickActions();
|
||||||
}
|
}
|
||||||
@ -195,13 +207,19 @@ class NavigationScreenState extends State<NavigationScreen>
|
|||||||
setSystemChrome(context);
|
setSystemChrome(context);
|
||||||
settings = Provider.of<SettingsProvider>(context);
|
settings = Provider.of<SettingsProvider>(context);
|
||||||
newsProvider = Provider.of<NewsProvider>(context);
|
newsProvider = Provider.of<NewsProvider>(context);
|
||||||
|
goalProvider = Provider.of<GoalProvider>(context);
|
||||||
|
|
||||||
// Show news
|
// show news and complete goals
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
if (newsProvider.show) {
|
if (newsProvider.show) {
|
||||||
newsProvider.lock();
|
NewsView.show(newsProvider.news[0], context: context)
|
||||||
NewsView.show(newsProvider.news[newsProvider.state], context: context)
|
|
||||||
.then((value) => newsProvider.release());
|
.then((value) => newsProvider.release());
|
||||||
|
newsProvider.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (goalProvider.hasDoneGoals) {
|
||||||
|
GoalCompleteModal.show(goalProvider.doneSubject!, context: context);
|
||||||
|
goalProvider.lock();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -31,23 +31,30 @@ class NewsView extends StatelessWidget {
|
|||||||
physics: const BouncingScrollPhysics(),
|
physics: const BouncingScrollPhysics(),
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 8.0, right: 6.0, top: 14.0, bottom: 8.0),
|
padding: const EdgeInsets.only(
|
||||||
|
left: 8.0, right: 6.0, top: 14.0, bottom: 8.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
news.title,
|
news.title,
|
||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 18.0),
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w600, fontSize: 18.0),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SelectableLinkify(
|
SelectableLinkify(
|
||||||
text: news.content.escapeHtml(),
|
text: news.content.escapeHtml(),
|
||||||
options: const LinkifyOptions(looseUrl: true, removeWww: true),
|
options:
|
||||||
|
const LinkifyOptions(looseUrl: true, removeWww: true),
|
||||||
onOpen: (link) {
|
onOpen: (link) {
|
||||||
launch(
|
launch(
|
||||||
link.url,
|
link.url,
|
||||||
customTabsOption: CustomTabsOption(showPageTitle: true, toolbarColor: Theme.of(context).scaffoldBackgroundColor),
|
customTabsOption: CustomTabsOption(
|
||||||
|
showPageTitle: true,
|
||||||
|
toolbarColor:
|
||||||
|
Theme.of(context).scaffoldBackgroundColor),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 14.0),
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w500, fontSize: 14.0),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -59,10 +66,15 @@ class NewsView extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
if (news.link != "")
|
if (news.link != "")
|
||||||
DialogButton(
|
DialogButton(
|
||||||
label: news.openLabel != "" ? news.openLabel : "open".i18n.toUpperCase(),
|
label: news.openLabel != ""
|
||||||
|
? news.openLabel
|
||||||
|
: "open".i18n.toUpperCase(),
|
||||||
onTap: () => launch(
|
onTap: () => launch(
|
||||||
news.link,
|
news.link,
|
||||||
customTabsOption: CustomTabsOption(showPageTitle: true, toolbarColor: Theme.of(context).scaffoldBackgroundColor),
|
customTabsOption: CustomTabsOption(
|
||||||
|
showPageTitle: true,
|
||||||
|
toolbarColor:
|
||||||
|
Theme.of(context).scaffoldBackgroundColor),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
DialogButton(
|
DialogButton(
|
||||||
@ -78,12 +90,15 @@ class NewsView extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<T?> show<T>(News news, {required BuildContext context, bool force = false}) {
|
static Future<T?> show<T>(News news,
|
||||||
|
{required BuildContext context, bool force = false}) {
|
||||||
if (news.title == "") return Future<T?>.value(null);
|
if (news.title == "") return Future<T?>.value(null);
|
||||||
|
|
||||||
bool popup = news.platform == '' || force;
|
bool popup = news.platform == 'all' || force;
|
||||||
|
|
||||||
if (Provider.of<SettingsProvider>(context, listen: false).newsEnabled || news.emergency || force) {
|
if (Provider.of<SettingsProvider>(context, listen: false).newsEnabled ||
|
||||||
|
news.emergency ||
|
||||||
|
force) {
|
||||||
switch (news.platform.trim().toLowerCase()) {
|
switch (news.platform.trim().toLowerCase()) {
|
||||||
case "android":
|
case "android":
|
||||||
if (Platform.isAndroid) popup = true;
|
if (Platform.isAndroid) popup = true;
|
||||||
@ -100,6 +115,9 @@ class NewsView extends StatelessWidget {
|
|||||||
case "macos":
|
case "macos":
|
||||||
if (Platform.isMacOS) popup = true;
|
if (Platform.isMacOS) popup = true;
|
||||||
break;
|
break;
|
||||||
|
case "all":
|
||||||
|
popup = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
popup = true;
|
popup = true;
|
||||||
}
|
}
|
||||||
@ -108,7 +126,10 @@ class NewsView extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (popup) {
|
if (popup) {
|
||||||
return showDialog<T?>(context: context, builder: (context) => NewsView(news), barrierDismissible: true);
|
return showDialog<T?>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => NewsView(news),
|
||||||
|
barrierDismissible: true);
|
||||||
} else {
|
} else {
|
||||||
return Future<T?>.value(null);
|
return Future<T?>.value(null);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,226 @@
|
|||||||
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
|
import 'package:filcnaplo/theme/colors/colors.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/beta_chip.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'notifications_screen.i18n.dart';
|
||||||
|
|
||||||
|
class MenuNotifications extends StatelessWidget {
|
||||||
|
const MenuNotifications({Key? key, required this.settings}) : super(key: key);
|
||||||
|
|
||||||
|
final SettingsProvider settings;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return PanelButton(
|
||||||
|
padding: const EdgeInsets.only(left: 14.0),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context, rootNavigator: true).push(
|
||||||
|
CupertinoPageRoute(builder: (context) => const NotificationsScreen()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"notifications_screen".i18n,
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.of(context)
|
||||||
|
.text
|
||||||
|
.withOpacity(settings.notificationsEnabled ? 1.0 : .5)),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 5.0),
|
||||||
|
BetaChip(
|
||||||
|
disabled: !settings.notificationsEnabled,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
leading: settings.notificationsEnabled
|
||||||
|
? const Icon(FeatherIcons.messageSquare)
|
||||||
|
: Icon(FeatherIcons.messageSquare,
|
||||||
|
color: AppColors.of(context).text.withOpacity(.25)),
|
||||||
|
trailingDivider: true,
|
||||||
|
trailing: Switch(
|
||||||
|
onChanged: (v) async {
|
||||||
|
settings.update(notificationsEnabled: v);
|
||||||
|
},
|
||||||
|
value: settings.notificationsEnabled,
|
||||||
|
activeColor: Theme.of(context).colorScheme.secondary,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotificationsScreen extends StatelessWidget {
|
||||||
|
const NotificationsScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
SettingsProvider settings = Provider.of<SettingsProvider>(context);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
leading: BackButton(color: AppColors.of(context).text),
|
||||||
|
title: Text(
|
||||||
|
"notifications_screen".i18n,
|
||||||
|
style: TextStyle(color: AppColors.of(context).text),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0),
|
||||||
|
child: Panel(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Material(
|
||||||
|
type: MaterialType.transparency,
|
||||||
|
child: SwitchListTile(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(12.0)),
|
||||||
|
value: settings.notificationsGradesEnabled,
|
||||||
|
onChanged: (v) =>
|
||||||
|
settings.update(notificationsGradesEnabled: v),
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
FeatherIcons.bookmark,
|
||||||
|
color: settings.notificationsGradesEnabled
|
||||||
|
? Theme.of(context).colorScheme.secondary
|
||||||
|
: AppColors.of(context).text.withOpacity(.25),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 14.0),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"grades".i18n,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 16.0,
|
||||||
|
color: AppColors.of(context).text.withOpacity(
|
||||||
|
settings.notificationsGradesEnabled
|
||||||
|
? 1.0
|
||||||
|
: .5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Material(
|
||||||
|
type: MaterialType.transparency,
|
||||||
|
child: SwitchListTile(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(12.0)),
|
||||||
|
value: settings.notificationsAbsencesEnabled,
|
||||||
|
onChanged: (v) =>
|
||||||
|
settings.update(notificationsAbsencesEnabled: v),
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
FeatherIcons.clock,
|
||||||
|
color: settings.notificationsAbsencesEnabled
|
||||||
|
? Theme.of(context).colorScheme.secondary
|
||||||
|
: AppColors.of(context).text.withOpacity(.25),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 14.0),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"absences".i18n,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 16.0,
|
||||||
|
color: AppColors.of(context).text.withOpacity(
|
||||||
|
settings.notificationsAbsencesEnabled
|
||||||
|
? 1.0
|
||||||
|
: .5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Material(
|
||||||
|
type: MaterialType.transparency,
|
||||||
|
child: SwitchListTile(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(12.0)),
|
||||||
|
value: settings.notificationsMessagesEnabled,
|
||||||
|
onChanged: (v) =>
|
||||||
|
settings.update(notificationsMessagesEnabled: v),
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
FeatherIcons.messageSquare,
|
||||||
|
color: settings.notificationsMessagesEnabled
|
||||||
|
? Theme.of(context).colorScheme.secondary
|
||||||
|
: AppColors.of(context).text.withOpacity(.25),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 14.0),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"messages".i18n,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 16.0,
|
||||||
|
color: AppColors.of(context).text.withOpacity(
|
||||||
|
settings.notificationsMessagesEnabled
|
||||||
|
? 1.0
|
||||||
|
: .5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Material(
|
||||||
|
type: MaterialType.transparency,
|
||||||
|
child: SwitchListTile(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(12.0)),
|
||||||
|
value: settings.notificationsLessonsEnabled,
|
||||||
|
onChanged: (v) =>
|
||||||
|
settings.update(notificationsLessonsEnabled: v),
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
FeatherIcons.calendar,
|
||||||
|
color: settings.notificationsLessonsEnabled
|
||||||
|
? Theme.of(context).colorScheme.secondary
|
||||||
|
: AppColors.of(context).text.withOpacity(.25),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 14.0),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"lessons".i18n,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 16.0,
|
||||||
|
color: AppColors.of(context).text.withOpacity(
|
||||||
|
settings.notificationsLessonsEnabled
|
||||||
|
? 1.0
|
||||||
|
: .5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
import 'package:i18n_extension/i18n_extension.dart';
|
||||||
|
|
||||||
|
extension SettingsLocalization on String {
|
||||||
|
static final _t = Translations.byLocale("hu_hu") +
|
||||||
|
{
|
||||||
|
"en_en": {
|
||||||
|
"notifications_screen": "Notifications",
|
||||||
|
"grades": "Grades",
|
||||||
|
"absences": "Absences",
|
||||||
|
"messages": "Messages",
|
||||||
|
"lessons": "Lessons"
|
||||||
|
|
||||||
|
},
|
||||||
|
"hu_hu": {
|
||||||
|
"notifications_screen": "Értesítések",
|
||||||
|
"grades": "Jegyek",
|
||||||
|
"absences": "Hiányzások",
|
||||||
|
"messages": "Üzenetek",
|
||||||
|
"lessons": "Órák"
|
||||||
|
},
|
||||||
|
"de_de": {
|
||||||
|
"notifications_screen": "Mitteilung",
|
||||||
|
"grades": "Noten",
|
||||||
|
"absences": "Fehlen",
|
||||||
|
"messages": "Nachrichten",
|
||||||
|
"lessons": "Unterricht"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
String get i18n => localize(this, _t);
|
||||||
|
String fill(List<Object> params) => localizeFill(this, params);
|
||||||
|
String plural(int value) => localizePlural(value, this, _t);
|
||||||
|
String version(Object modifier) => localizeVersion(modifier, this, _t);
|
||||||
|
}
|
@ -28,27 +28,22 @@ class PrivacyView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
SelectableLinkify(
|
SelectableLinkify(
|
||||||
text: """
|
text: """
|
||||||
A reFilc egy kliensalkalmazás, segítségével az e-Kréta rendszeréből letöltheted és felhasználóbarát módon megjelenítheted az adataidat.
|
• A reFilc (továbbiakban alkalmazás) egy mobilos, asztali és webes kliensalkalmazás, segítségével az e-Kréta rendszeréből letöltheted és felhasználóbarát módon megjelenítheted az adataidat. Tanulmányi adataid csak közvetlenül az alkalmazás és a Kréta-szerverek között közlekednek, titkosított kapcsolaton keresztül.
|
||||||
Tanulmányi adataid csak közvetlenül az alkalmazás és a Kréta-szerverek között közlekednek, titkosított kapcsolaton keresztül.
|
|
||||||
|
|
||||||
A reFilc fejlesztői és üzemeltetői a tanulmányi adataidat semmilyen célból nem másolják, nem tárolják és harmadik félnek nem továbbítják. Ezeket így az e-Kréta Informatikai Zrt. kezeli, az ő tájékoztatójukat itt találod: https://tudasbazis.ekreta.hu/pages/viewpage.action?pageId=4065038.
|
• A reFilc fejlesztői és/vagy üzemeltetői, valamint az alkalmazás a tanulmányi és személyes adataidat semmilyen célból és semmilyen körülmények között nem másolják, nem tárolják és harmadik félnek nem továbbítják. Ezeket így az Educational Development Informatikai Zrt. kezeli, az Ő adatkezeléssel kapcsolatos tájékoztatójukat itt találod: https://tudasbazis.ekreta.hu/pages/viewpage.action?pageId=4065038
|
||||||
Azok törlésével vagy módosítával kapcsolatban keresd az osztályfőnöködet vagy az iskolád rendszergazdáját.
|
|
||||||
|
|
||||||
Az alkalmazás névtelen használati statisztikákat gyűjt, ezek alapján tudjuk meghatározni a felhasználók és a telepítések számát. Ezt a beállításokban kikapcsolhatod.
|
• Azok törlésével vagy módosítával kapcsolatban keresd az osztályfőnöködet vagy az iskolád rendszergazdáját.
|
||||||
Kérünk, hogy ha csak teheted, hagyd ezt a funkciót bekapcsolva.
|
|
||||||
|
|
||||||
Amikor az alkalmazás hibába ütközik, lehetőség van hibajelentés küldésére.
|
• Az alkalmazás névtelen használati statisztikákat gyűjt, ezek alapján tudjuk meghatározni a felhasználók és a telepítések számát, valamint az eszközük platformját. Ezt a beállításokban kikapcsolhatod. Kérünk, hogy ha csak teheted, hagyd ezt a funkciót bekapcsolva, hogy pontosabb információnk legyen a felhasználóink platform-megoszlásáról.
|
||||||
Ez személyes- vagy tanulmányi adatokat nem tartalmaz, viszont részletes információval szolgál a hibáról és eszközödről.
|
|
||||||
A küldés előtt megjelenő képernyőn a te felelősséged átnézni a továbbításra kerülő adatsort.
|
|
||||||
A hibajelentéseket a reFilc fejlesztői felületén és egy privát Discord szobában tároljuk, ezekhez csak az app fejlesztői férnek hozzá.
|
|
||||||
Az alkalmazás belépéskor a GitHub API segítségével ellenőrzi, hogy elérhető-e új verzió, és kérésre innen is tölti le a telepítőt.
|
|
||||||
|
|
||||||
Ha az adataiddal kapcsolatban bármilyen kérdésed van (törlés, módosítás, adathordozás), keress minket a filcnaplo@filcnaplo.hu címen.
|
• Amikor az alkalmazás hibába ütközik, lehetőség van hibajelentés küldésére. Ez személyes- és/vagy tanulmányi adatokat nem tartalmaz, viszont részletes információval szolgál a hibáról, annak okáról és eszközödről. A küldés előtt megjelenő képernyőn a te felelősséged átnézni a továbbításra kerülő adatsort. A hibajelentéseket a reFilc fejlesztői felületén és egy privát Discord szobában tároljuk, ezekhez csak az app fejlesztői férnek hozzá.
|
||||||
|
|
||||||
Az alkalmazás használatával jelzed, hogy ezt a tájékoztatót tudomásul vetted.
|
• Az alkalmazás (az alábbi platformokon: Android, Linux, Windows) minden egyes indításakor a reFilc API, valamint a Github API segítségével ellenőrzi, hogy elérhető-e új verzió, és kérésre innen letölti és telepíti a frissítést.
|
||||||
|
|
||||||
Utolsó módosítás: 2023. 05. 28.
|
• Amennyiben az adataiddal kapcsolatban bármilyen kérdésed van (megtekintés, törlés, módosítás, adathordozás), keress minket a social@refilc.hu e-mail címen, vagy Discord szerverünkön!
|
||||||
""",
|
|
||||||
|
• A kliensalkalmazás bármely eszközön és platformon történő használatával tudomásul vetted és elfogadod a jelen adatkezelési tájékoztatót. A reFilc csapata fenntartja a jogot a tájékoztató módosítására és a módosításokról nem köteles értesíteni a felhasználóit!
|
||||||
|
""",
|
||||||
onOpen: (link) => launch(link.url,
|
onOpen: (link) => launch(link.url,
|
||||||
customTabsOption: CustomTabsOption(
|
customTabsOption: CustomTabsOption(
|
||||||
toolbarColor: Theme.of(context).scaffoldBackgroundColor,
|
toolbarColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
|