Compare commits

...

27 Commits
4.2.0 ... 4.2.2

Author SHA1 Message Date
Márton Kiss
023329f021 Merge pull request #43 from refilc/dev
Dev
2023-09-05 22:06:51 +02:00
Kima
e66fdbaeac added expire date to ads 2023-09-05 21:59:53 +02:00
Kima
bbbaea9224 fixed ad isBefore 2023-09-05 21:55:51 +02:00
Márton Kiss
c7c18cf684 Merge pull request #42 from refilc/dev
changed version number
2023-09-05 21:23:48 +02:00
Kima
4d501fed3e changed version number 2023-09-05 21:23:30 +02:00
Márton Kiss
8168ef5329 Merge pull request #41 from refilc/dev
Dev
2023-09-05 21:18:27 +02:00
Kima
608bc58771 fixed padding on ad tile 2023-09-05 21:17:54 +02:00
Kima
2cba1ec286 ads api working 2023-09-05 21:08:06 +02:00
Kima
b6eb65814f Merge branch 'dev' of github.com:refilc/naplo into dev 2023-09-05 18:49:16 +02:00
Kima
a5a43ea0b9 added ad provider 2023-09-05 18:49:14 +02:00
Márton Kiss
da356bb212 Merge pull request #40 from refilc/dev
Dev
2023-09-04 23:15:01 +02:00
Márton Kiss
c29ab3de29 Merge pull request #39 from Monke14/dev
Android widget fix
2023-09-04 23:14:38 +02:00
Kima
fceb4e050f FINALLY FIXED AUTO UPDATE 2023-09-04 23:13:54 +02:00
Kima
8feea02f68 added api endpoint and auto update fix 2023-09-04 21:45:11 +02:00
hihihaha
939e4f4d48 widget fix 2023-09-04 21:31:50 +02:00
Kima
a401ff32d9 something 2023-09-04 20:17:38 +02:00
Márton Kiss
84e7fc60c2 Merge pull request #38 from refilc/dev
dev to master
2023-09-04 18:40:16 +02:00
Kima
6821887263 Merge branch 'dev' of github.com:refilc/naplo into dev 2023-09-04 18:39:53 +02:00
Kima
8f8ceb0597 removed prints 2023-09-04 18:39:49 +02:00
Márton Kiss
deb2403c23 Merge pull request #37 from refilc/master
master readme to dev branch
2023-09-04 18:38:06 +02:00
Márton Kiss
d65c722ef0 Merge pull request #36 from refilc/dev
dev minden is master-be
2023-09-04 18:37:18 +02:00
Kima
1bdc1409e4 updated version number 2023-09-04 18:33:24 +02:00
Kima
467eca6c14 fixed that shit timetable bug 2023-09-04 18:31:47 +02:00
Kima
da3abb7fb7 fixed school select (omfg nagyon szarul csinaltak) 2023-09-04 17:10:09 +02:00
Márton Kiss
a8a818225e modified readme 2023-09-03 23:53:28 +02:00
Kima
5e650869f2 added some hint for spaces after username 2023-09-03 22:13:39 +02:00
Kima
6e06d82b1a made goal planner modal dark mode compatible 2023-09-03 21:17:22 +02:00
35 changed files with 529 additions and 225 deletions

1
.gitignore vendored
View File

@@ -48,3 +48,4 @@ filcnaplo/ios/Podfile.lock
key.properties key.properties
.flutter-plugins* .flutter-plugins*
filcnaplo/ios/Flutter/flutter_export_environment 4.sh

29
.vscode/launch.json vendored
View File

@@ -10,17 +10,16 @@
"--dart-define=APPVER=$(cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1)" "--dart-define=APPVER=$(cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1)"
] ]
}, },
{ // {
"name": "filcnaplo release", // "name": "filcnaplo release",
"cwd": "filcnaplo release", // "cwd": "filcnaplo release",
"request": "launch", // "request": "launch",
"type": "dart", // "type": "dart",
"flutterMode": "release", // "program": "lib/main.dart",
"program": "lib/main.dart", // "toolArgs": [
"toolArgs": [ // "--dart-define=APPVER=$(cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1)"
"--dart-define=APPVER=$(cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1)" // ]
] // },
},
{ {
"name": "Flutter", "name": "Flutter",
"program": "lib/main.dart", "program": "lib/main.dart",
@@ -28,6 +27,14 @@
"request": "launch", "request": "launch",
"type": "dart", "type": "dart",
"flutterMode": "debug" "flutterMode": "debug"
},
{
"name": "Flutter (release)",
"program": "lib/main.dart",
"cwd": "filcnaplo",
"request": "launch",
"type": "dart",
"flutterMode": "release"
} }
] ]
} }

View File

@@ -3,7 +3,7 @@
<h1 align=center><b>reFilc</b></h1> <h1 align=center><b>reFilc</b></h1>
</p> </p>
#### Nem hivatalos e-napló alkalmazás az eKRÉTA rendszerhez - tanulóktól, tanulóknak. #### Nem hivatalos e-napló alkalmazás az e-KRÉTA rendszerhez - tanulóktól, tanulóknak.
[![Downloads](https://img.shields.io/github/downloads-pre/refilc/naplo/total?&logo=github&label=Downloads)](https://github.com/refilc/naplo/releases) &nbsp; [![Discord](https://img.shields.io/discord/1111649116020285532?logo=discord&label=Discord)](https://dc.refilc.hu) [![Downloads](https://img.shields.io/github/downloads-pre/refilc/naplo/total?&logo=github&label=Downloads)](https://github.com/refilc/naplo/releases) &nbsp; [![Discord](https://img.shields.io/discord/1111649116020285532?logo=discord&label=Discord)](https://dc.refilc.hu)
@@ -35,10 +35,16 @@ Az összes (ugyan azon verzióhoz tartozó) contribution meg fog jelenni a relea
------- -------
# Developers # Team
**annon:** a Filc napló készítője (ez az app a Filcen alapul) **kima:** head developer / project manager
**kima, mog, WolfY:** fő fejlesztők **Reiner, pdf, Pearoo:** community- and project manager / developer
**Regő, Pearoo:** weboldal design és community management **vrolandd, TMarccci:** head developer
**dwe., xou:** designer
**Péter:** social media manager / video editor
**annon:** a régi Filc Napló fejlesztője (ez az app, ha bár sokban változott, alapjaiban a Filc-re épül)

View File

@@ -26,6 +26,11 @@ 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 java.util.Map;
import java.util.HashMap;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import hu.refilc.naplo.database.DBManager; import hu.refilc.naplo.database.DBManager;
import hu.refilc.naplo.MainActivity; import hu.refilc.naplo.MainActivity;
@@ -247,71 +252,61 @@ public class WidgetTimetable extends HomeWidgetProvider {
} }
public static List<JSONArray> genJsonDays(Context context) { public static List<JSONArray> genJsonDays(Context context) {
List<JSONArray> gen_days = new ArrayList<>(); List<JSONArray> genDays = new ArrayList<>();
Map<String, JSONArray> dayMap = new HashMap<>();
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();
if(ct.getCount() == 0) { if (ct.getCount() == 0) {
return gen_days; return genDays;
} }
JSONObject fecthtt = new JSONObject(ct.getString(0)); JSONObject fetchedTimetable = new JSONObject(ct.getString(0));
String currentWeek = String.valueOf(Week.current().id());
JSONArray week = fetchedTimetable.getJSONArray(currentWeek);
JSONArray dayArray = new JSONArray(); // Organize lessons into dates
String currday = ""; for (int i = 0; i < week.length(); i++) {
String currweek = String.valueOf(Week.current().id());
JSONArray week = fecthtt.getJSONArray(currweek);
for (int i=0; i < week.length(); i++)
{
try { try {
if(i == 0) currday = week.getJSONObject(0).getString("Datum"); JSONObject entry = week.getJSONObject(i);
JSONObject oraObj = week.getJSONObject(i); String date = entry.getString("Datum");
dayMap.computeIfAbsent(date, k -> new JSONArray()).put(entry);
if(!currday.equals(oraObj.getString("Datum"))) { } catch (JSONException e) {
gen_days.add(dayArray);
currday = week.getJSONObject(i).getString("Datum");
dayArray = new JSONArray();
}
dayArray.put(oraObj);
if(i == week.length() - 1) {
gen_days.add(dayArray);
}
} catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
genDays.addAll(dayMap.values());
// Sort the 'genDays' list of JSON based on the start time of the first entry
genDays.sort((day1, day2) -> {
try {
// Extract the start time of the first entry in each day's JSON
String startTime1 = day1.getJSONObject(0).getString("KezdetIdopont");
String startTime2 = day2.getJSONObject(0).getString("KezdetIdopont");
// Compare the start times and return the result for sorting
return startTime1.compareTo(startTime2);
} catch (JSONException e) {
e.printStackTrace();
return 0;
}
});
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} finally {
dbManager.close();
} }
Collections.sort(gen_days, new Comparator<JSONArray>() { return genDays;
public int compare(JSONArray a, JSONArray b) {
long valA = 0;
long valB = 0;
try {
valA = (long) new DateTime( a.getJSONObject(0).getString("Datum")).getMillis();
valB = (long) new DateTime( b.getJSONObject(0).getString("Datum")).getMillis();
}
catch (JSONException ignored) {
}
return (int) (valA - valB);
}
});
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);

View File

@@ -335,10 +335,12 @@ public class WidgetTimetableDataProvider implements RemoteViewsService.RemoteVie
public Lesson jsonToLesson(JSONObject json) { public Lesson jsonToLesson(JSONObject json) {
try { try {
String name = json.getString("Nev");
name = name.substring(0, 1).toUpperCase() + name.substring(1); // Capitalize name
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"), name,
json.getString("Tema"), json.getString("Tema"),
json.getString("TeremNeve"), json.getString("TeremNeve"),
new DateTime(json.getString("KezdetIdopont")).getMillis(), new DateTime(json.getString("KezdetIdopont")).getMillis(),

View File

@@ -1,15 +1,14 @@
// This is a generated file; do not edit or check into version control. // This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=/Users/kima/development/flutter FLUTTER_ROOT=/Users/kima/src/flutter
FLUTTER_APPLICATION_PATH=/Users/kima/Documents/refilc/app/naplo/filcnaplo FLUTTER_APPLICATION_PATH=/Users/kima/Documents/refilc/app/naplo/filcnaplo
COCOAPODS_PARALLEL_CODE_SIGN=true COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_TARGET=/Users/kima/Documents/refilc/app/naplo/filcnaplo/lib/main.dart FLUTTER_TARGET=lib/main.dart
FLUTTER_BUILD_DIR=build FLUTTER_BUILD_DIR=build
FLUTTER_BUILD_NAME=3.5.1 FLUTTER_BUILD_NAME=4.2.0
FLUTTER_BUILD_NUMBER=197 FLUTTER_BUILD_NUMBER=220
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386 EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
EXCLUDED_ARCHS[sdk=iphoneos*]=armv7 EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==,RkxVVFRFUl9XRUJfQ0FOVkFTS0lUX1VSTD1odHRwczovL3d3dy5nc3RhdGljLmNvbS9mbHV0dGVyLWNhbnZhc2tpdC9iNGZiMTEyMTRkZDJkZGE2Y2UwMTJkZDk4ZWE0OThlOWU4YjkxMjYyLw==
DART_OBFUSCATION=false DART_OBFUSCATION=false
TRACK_WIDGET_CREATION=true TRACK_WIDGET_CREATION=true
TREE_SHAKE_ICONS=false TREE_SHAKE_ICONS=false
PACKAGE_CONFIG=/Users/kima/Documents/refilc/app/naplo/filcnaplo/.dart_tool/package_config.json PACKAGE_CONFIG=.dart_tool/package_config.json

View File

@@ -1,15 +1,14 @@
// This is a generated file; do not edit or check into version control. // This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=/Users/kima/development/flutter FLUTTER_ROOT=/Users/kima/src/flutter
FLUTTER_APPLICATION_PATH=/Users/kima/Documents/refilc/app/naplo/filcnaplo FLUTTER_APPLICATION_PATH=/Users/kima/Documents/refilc/app/naplo/filcnaplo
COCOAPODS_PARALLEL_CODE_SIGN=true COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_TARGET=/Users/kima/Documents/refilc/app/naplo/filcnaplo/lib/main.dart FLUTTER_TARGET=lib/main.dart
FLUTTER_BUILD_DIR=build FLUTTER_BUILD_DIR=build
FLUTTER_BUILD_NAME=4.1.0 FLUTTER_BUILD_NAME=4.2.0
FLUTTER_BUILD_NUMBER=213 FLUTTER_BUILD_NUMBER=220
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386 EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
EXCLUDED_ARCHS[sdk=iphoneos*]=armv7 EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==,RkxVVFRFUl9XRUJfQ0FOVkFTS0lUX1VSTD1odHRwczovL3d3dy5nc3RhdGljLmNvbS9mbHV0dGVyLWNhbnZhc2tpdC8yYTM0MDFjOWJiYjVhOWE5YWVjNzRkNGY3MzVkMThhOWRkM2ViZjJkLw==
DART_OBFUSCATION=false DART_OBFUSCATION=false
TRACK_WIDGET_CREATION=true TRACK_WIDGET_CREATION=true
TREE_SHAKE_ICONS=false TREE_SHAKE_ICONS=false
PACKAGE_CONFIG=/Users/kima/Documents/refilc/app/naplo/filcnaplo/.dart_tool/package_config.json PACKAGE_CONFIG=.dart_tool/package_config.json

View File

@@ -1,14 +1,13 @@
#!/bin/sh #!/bin/sh
# This is a generated file; do not edit or check into version control. # This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/kima/development/flutter" export "FLUTTER_ROOT=/Users/kima/src/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/kima/Documents/refilc/app/naplo/filcnaplo" export "FLUTTER_APPLICATION_PATH=/Users/kima/Documents/refilc/app/naplo/filcnaplo"
export "COCOAPODS_PARALLEL_CODE_SIGN=true" export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_TARGET=/Users/kima/Documents/refilc/app/naplo/filcnaplo/lib/main.dart" export "FLUTTER_TARGET=lib/main.dart"
export "FLUTTER_BUILD_DIR=build" export "FLUTTER_BUILD_DIR=build"
export "FLUTTER_BUILD_NAME=4.1.0" export "FLUTTER_BUILD_NAME=4.2.0"
export "FLUTTER_BUILD_NUMBER=213" export "FLUTTER_BUILD_NUMBER=220"
export "DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==,RkxVVFRFUl9XRUJfQ0FOVkFTS0lUX1VSTD1odHRwczovL3d3dy5nc3RhdGljLmNvbS9mbHV0dGVyLWNhbnZhc2tpdC8yYTM0MDFjOWJiYjVhOWE5YWVjNzRkNGY3MzVkMThhOWRkM2ViZjJkLw=="
export "DART_OBFUSCATION=false" export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=true" export "TRACK_WIDGET_CREATION=true"
export "TREE_SHAKE_ICONS=false" export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=/Users/kima/Documents/refilc/app/naplo/filcnaplo/.dart_tool/package_config.json" export "PACKAGE_CONFIG=.dart_tool/package_config.json"

View File

@@ -0,0 +1,13 @@
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/kima/src/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/kima/Documents/refilc/app/naplo/filcnaplo"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_TARGET=lib/main.dart"
export "FLUTTER_BUILD_DIR=build"
export "FLUTTER_BUILD_NAME=4.2.0"
export "FLUTTER_BUILD_NUMBER=220"
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=true"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.dart_tool/package_config.json"

View File

@@ -1,6 +1,7 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:developer'; import 'dart:developer';
import 'package:filcnaplo/models/ad.dart';
import 'package:filcnaplo/models/config.dart'; import 'package:filcnaplo/models/config.dart';
import 'package:filcnaplo/models/news.dart'; import 'package:filcnaplo/models/news.dart';
import 'package:filcnaplo/models/release.dart'; import 'package:filcnaplo/models/release.dart';
@@ -18,6 +19,7 @@ class FilcAPI {
static const supporters = "https://api.refilc.hu/v1/public/supporters"; static const supporters = "https://api.refilc.hu/v1/public/supporters";
// Private API // Private API
static const ads = "https://api.refilc.hu/v1/private/ads";
static const config = "https://api.refilc.hu/v1/private/config"; static const config = "https://api.refilc.hu/v1/private/config";
static const reportApi = "https://api.refilc.hu/v1/private/crash-report"; static const reportApi = "https://api.refilc.hu/v1/private/crash-report";
static const premiumApi = "https://api.filcnaplo.hu/premium/activate"; static const premiumApi = "https://api.filcnaplo.hu/premium/activate";
@@ -117,6 +119,24 @@ class FilcAPI {
return null; return null;
} }
static Future<List<Ad>?> getAds() async {
try {
http.Response res = await http.get(Uri.parse(ads));
if (res.statusCode == 200) {
return (jsonDecode(res.body) as List)
.cast<Map>()
.map((e) => Ad.fromJson(e))
.toList();
} else {
throw "HTTP ${res.statusCode}: ${res.body}";
}
} on Exception catch (error, stacktrace) {
log("ERROR: FilcAPI.getAds: $error $stacktrace");
}
return null;
}
static Future<List<Release>?> getReleases() async { static Future<List<Release>?> getReleases() async {
try { try {
http.Response res = await http.get(Uri.parse(releases)); http.Response res = await http.get(Uri.parse(releases));

View File

@@ -27,7 +27,7 @@ enum LoginState {
failed, failed,
normal, normal,
inProgress, inProgress,
success success,
} }
Nonce getNonce(String nonce, String username, String instituteCode) { Nonce getNonce(String nonce, String username, String instituteCode) {
@@ -39,7 +39,7 @@ Nonce getNonce(String nonce, String username, String instituteCode) {
return nonceEncoder; return nonceEncoder;
} }
Future loginApi({ Future loginAPI({
required String username, required String username,
required String password, required String password,
required String instituteCode, required String instituteCode,
@@ -121,7 +121,7 @@ Future loginApi({
return LoginState.success; return LoginState.success;
} catch (error) { } catch (error) {
print("ERROR: loginApi: $error"); print("ERROR: loginAPI: $error");
// maybe check debug mode // maybe check debug mode
// ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("ERROR: $error"))); // ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("ERROR: $error")));
return LoginState.failed; return LoginState.failed;

View File

@@ -0,0 +1,29 @@
import 'package:filcnaplo/api/client.dart';
import 'package:filcnaplo/models/ad.dart';
import 'package:flutter/material.dart';
class AdProvider extends ChangeNotifier {
// private
late List<Ad> _ads;
bool get available => _ads.isNotEmpty;
// public
List<Ad> get ads => _ads;
AdProvider({
List<Ad> initialAds = const [],
required BuildContext context,
}) {
_ads = List.castFrom(initialAds);
}
Future<void> fetch() async {
_ads = await FilcAPI.getAds() ?? [];
_ads.sort((a, b) => -a.date.compareTo(b.date));
// check for new ads
if (_ads.isNotEmpty) {
notifyListeners();
}
}
}

View File

@@ -3,6 +3,7 @@ import 'dart:math';
import 'package:dynamic_color/dynamic_color.dart'; import 'package:dynamic_color/dynamic_color.dart';
import 'package:filcnaplo/api/client.dart'; import 'package:filcnaplo/api/client.dart';
import 'package:filcnaplo/api/providers/ad_provider.dart';
import 'package:filcnaplo/api/providers/live_card_provider.dart'; import 'package:filcnaplo/api/providers/live_card_provider.dart';
import 'package:filcnaplo/api/providers/news_provider.dart'; import 'package:filcnaplo/api/providers/news_provider.dart';
import 'package:filcnaplo/api/providers/database_provider.dart'; import 'package:filcnaplo/api/providers/database_provider.dart';
@@ -104,6 +105,8 @@ class App extends StatelessWidget {
create: (context) => NewsProvider(context: context)), create: (context) => NewsProvider(context: context)),
ChangeNotifierProvider<UpdateProvider>( ChangeNotifierProvider<UpdateProvider>(
create: (context) => UpdateProvider(context: context)), create: (context) => UpdateProvider(context: context)),
ChangeNotifierProvider<AdProvider>(
create: (context) => AdProvider(context: context)),
// user data (kreten) providers // user data (kreten) providers
ChangeNotifierProvider<GradeProvider>( ChangeNotifierProvider<GradeProvider>(

View File

@@ -9,7 +9,7 @@ import 'package:permission_handler/permission_handler.dart';
class StorageHelper { class StorageHelper {
static Future<bool> write(String path, Uint8List data) async { static Future<bool> write(String path, Uint8List data) async {
try { try {
if (await Permission.storage.request().isGranted) { if (await Permission.manageExternalStorage.request().isGranted) {
await File(path).writeAsBytes(data); await File(path).writeAsBytes(data);
return true; return true;
} else { } else {
@@ -34,5 +34,6 @@ class StorageHelper {
} }
return downloads; return downloads;
// return (await getTemporaryDirectory()).path;
} }
} }

View File

@@ -33,10 +33,10 @@ extension UpdateHelper on Release {
updateCallback(-1, UpdateState.installing); updateCallback(-1, UpdateState.installing);
var permStatus = var installPerms =
(await Permission.manageExternalStorage.request().isGranted && (await Permission.manageExternalStorage.request().isGranted &&
await Permission.requestInstallPackages.request().isGranted); await Permission.requestInstallPackages.request().isGranted);
if (permStatus) { if (installPerms) {
var result = await OpenFile.open(apk.path); var result = await OpenFile.open(apk.path);
if (result.type != ResultType.done) { if (result.type != ResultType.done) {

View File

@@ -0,0 +1,38 @@
class Ad {
String title;
String description;
String author;
Uri? logoUrl;
bool overridePremium;
DateTime date;
DateTime expireDate;
Uri launchUrl;
Ad({
required this.title,
required this.description,
required this.author,
this.logoUrl,
this.overridePremium = false,
required this.date,
required this.expireDate,
required this.launchUrl,
});
factory Ad.fromJson(Map json) {
print(json);
return Ad(
title: json['title'] ?? 'Ad',
description: json['description'] ?? '',
author: json['author'] ?? 'reFilc',
logoUrl: json['logo_url'] != null ? Uri.parse(json['logo_url']) : null,
overridePremium: json['override_premium'] ?? false,
date:
json['date'] != null ? DateTime.parse(json['date']) : DateTime.now(),
expireDate: json['expire_date'] != null
? DateTime.parse(json['expire_date'])
: DateTime.now(),
launchUrl: Uri.parse(json['launch_url'] ?? 'https://refilc.hu'),
);
}
}

View File

@@ -1,3 +1,4 @@
import 'package:filcnaplo/api/providers/ad_provider.dart';
import 'package:filcnaplo/api/providers/update_provider.dart'; import 'package:filcnaplo/api/providers/update_provider.dart';
import 'package:filcnaplo/models/settings.dart'; import 'package:filcnaplo/models/settings.dart';
import 'package:filcnaplo/ui/date_widget.dart'; import 'package:filcnaplo/ui/date_widget.dart';
@@ -14,6 +15,7 @@ import 'package:filcnaplo/ui/filter/widgets/lessons.dart' as lesson_filter;
import 'package:filcnaplo/ui/filter/widgets/update.dart' as update_filter; import 'package:filcnaplo/ui/filter/widgets/update.dart' as update_filter;
import 'package:filcnaplo/ui/filter/widgets/missed_exams.dart' import 'package:filcnaplo/ui/filter/widgets/missed_exams.dart'
as missed_exam_filter; as missed_exam_filter;
import 'package:filcnaplo/ui/filter/widgets/ads.dart' as ad_filter;
import 'package:filcnaplo_kreta_api/models/week.dart'; import 'package:filcnaplo_kreta_api/models/week.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';
@@ -50,7 +52,8 @@ enum FilterType {
lessons, lessons,
updates, updates,
certifications, certifications,
missedExams missedExams,
ads,
} }
Future<List<DateWidget>> getFilterWidgets(FilterType activeData, Future<List<DateWidget>> getFilterWidgets(FilterType activeData,
@@ -65,6 +68,7 @@ Future<List<DateWidget>> getFilterWidgets(FilterType activeData,
final eventProvider = Provider.of<EventProvider>(context); final eventProvider = Provider.of<EventProvider>(context);
final updateProvider = Provider.of<UpdateProvider>(context); final updateProvider = Provider.of<UpdateProvider>(context);
final settingsProvider = Provider.of<SettingsProvider>(context); final settingsProvider = Provider.of<SettingsProvider>(context);
final adProvider = Provider.of<AdProvider>(context);
List<DateWidget> items = []; List<DateWidget> items = [];
@@ -82,6 +86,7 @@ Future<List<DateWidget>> getFilterWidgets(FilterType activeData,
getFilterWidgets(FilterType.updates, context: context), getFilterWidgets(FilterType.updates, context: context),
getFilterWidgets(FilterType.certifications, context: context), getFilterWidgets(FilterType.certifications, context: context),
getFilterWidgets(FilterType.missedExams, context: context), getFilterWidgets(FilterType.missedExams, context: context),
getFilterWidgets(FilterType.ads, context: context),
]); ]);
items = all.expand((x) => x).toList(); items = all.expand((x) => x).toList();
@@ -89,9 +94,9 @@ Future<List<DateWidget>> getFilterWidgets(FilterType activeData,
// Grades // Grades
case FilterType.grades: case FilterType.grades:
if(!settingsProvider.gradeOpeningFun) { if (!settingsProvider.gradeOpeningFun) {
gradeProvider.seenAll(); gradeProvider.seenAll();
} }
items = grade_filter.getWidgets( items = grade_filter.getWidgets(
gradeProvider.grades, gradeProvider.lastSeenDate); gradeProvider.grades, gradeProvider.lastSeenDate);
if (settingsProvider.gradeOpeningFun) { if (settingsProvider.gradeOpeningFun) {
@@ -164,6 +169,13 @@ Future<List<DateWidget>> getFilterWidgets(FilterType activeData,
items = missed_exam_filter items = missed_exam_filter
.getWidgets(timetableProvider.getWeek(Week.current()) ?? []); .getWidgets(timetableProvider.getWeek(Week.current()) ?? []);
break; break;
// Ads
case FilterType.ads:
if (adProvider.available) {
items = ad_filter.getWidgets(adProvider.ads);
}
break;
} }
return items; return items;
} }

View File

@@ -0,0 +1,25 @@
import 'package:filcnaplo/models/ad.dart';
import 'package:filcnaplo/ui/date_widget.dart';
import 'package:filcnaplo_mobile_ui/common/widgets/ad/ad_viewable.dart'
as mobile;
List<DateWidget> getWidgets(List<Ad> providerAds) {
List<DateWidget> items = [];
if (providerAds.isNotEmpty) {
for (var ad in providerAds) {
if (ad.date.isBefore(DateTime.now()) &&
ad.expireDate.isAfter(DateTime.now())) {
providerAds.sort((a, b) => -a.date.compareTo(b.date));
items.add(DateWidget(
key: ad.description,
date: ad.date,
widget: mobile.AdViewable(ad),
));
}
}
}
return items;
}

View File

@@ -44,7 +44,8 @@ class LessonTile extends StatelessWidget {
fillLeading = true; fillLeading = true;
} }
if (lesson.substituteTeacher?.name != "") { if (lesson.substituteTeacher != null &&
lesson.substituteTeacher?.name != "") {
fill = true; fill = true;
accent = AppColors.of(context).yellow; accent = AppColors.of(context).yellow;
} }

View File

@@ -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.2.0+220 version: 4.2.2+222
environment: environment:
sdk: ">=2.17.0 <3.0.0" sdk: ">=2.17.0 <3.0.0"

View File

@@ -235,7 +235,7 @@ class _LoginScreenState extends State<LoginScreen> {
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 15.0, fontSize: 15.0,
)), )),
onPressed: () => _loginApi(context: context), onPressed: () => _loginAPI(context: context),
), ),
visible: _loginState != LoginState.inProgress, visible: _loginState != LoginState.inProgress,
replacement: const Padding( replacement: const Padding(
@@ -279,7 +279,7 @@ class _LoginScreenState extends State<LoginScreen> {
); );
} }
void _loginApi({required BuildContext context}) { void _loginAPI({required BuildContext context}) {
String username = usernameController.text; String username = usernameController.text;
String password = passwordController.text; String password = passwordController.text;
@@ -289,7 +289,7 @@ class _LoginScreenState extends State<LoginScreen> {
setState(() => _loginState = LoginState.inProgress); setState(() => _loginState = LoginState.inProgress);
loginApi( loginAPI(
username: username, username: username,
password: password, password: password,
instituteCode: schoolController.selectedSchool!.instituteCode, instituteCode: schoolController.selectedSchool!.instituteCode,

View File

@@ -24,6 +24,11 @@ class KretaAPI {
KretaApiEndpoints.groupAverages + KretaApiEndpoints.groupAverages +
"?oktatasiNevelesiFeladatUid=" + "?oktatasiNevelesiFeladatUid=" +
uid; uid;
static String averages(String iss, String uid) =>
BaseKreta.kreta(iss) +
KretaApiEndpoints.averages +
"?oktatasiNevelesiFeladatUid=" +
uid;
static String timetable(String iss, {DateTime? start, DateTime? end}) => static String timetable(String iss, {DateTime? start, DateTime? end}) =>
BaseKreta.kreta(iss) + BaseKreta.kreta(iss) +
KretaApiEndpoints.timetable + KretaApiEndpoints.timetable +
@@ -90,6 +95,7 @@ class KretaApiEndpoints {
static const groups = "/ellenorzo/V3/Sajat/OsztalyCsoportok"; static const groups = "/ellenorzo/V3/Sajat/OsztalyCsoportok";
static const groupAverages = static const groupAverages =
"/ellenorzo/V3/Sajat/Ertekelesek/Atlagok/OsztalyAtlagok"; "/ellenorzo/V3/Sajat/Ertekelesek/Atlagok/OsztalyAtlagok";
static const averages = "/ellenorzo/V3/idk";
static const timetable = "/ellenorzo/V3/Sajat/OrarendElemek"; static const timetable = "/ellenorzo/V3/Sajat/OrarendElemek";
static const exams = "/ellenorzo/V3/Sajat/BejelentettSzamonkeresek"; static const exams = "/ellenorzo/V3/Sajat/BejelentettSzamonkeresek";
static const homework = "/ellenorzo/V3/Sajat/HaziFeladatok"; static const homework = "/ellenorzo/V3/Sajat/HaziFeladatok";

View File

@@ -62,45 +62,45 @@ class Lesson {
factory Lesson.fromJson(Map json) { factory Lesson.fromJson(Map json) {
return Lesson( return Lesson(
id: json["Uid"] ?? "", id: json["Uid"] ?? "",
status: status:
json["Allapot"] != null ? Category.fromJson(json["Allapot"]) : null, json["Allapot"] != null ? Category.fromJson(json["Allapot"]) : null,
date: json["Datum"] != null date: json["Datum"] != null
? DateTime.parse(json["Datum"]).toLocal() ? DateTime.parse(json["Datum"]).toLocal()
: DateTime(0), : 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: substituteTeacher: json["HelyettesTanarNeve"] != null
Teacher.fromString((json["HelyettesTanarNeve"] ?? "").trim()), ? Teacher.fromString((json["HelyettesTanarNeve"]).trim())
teacher: Teacher.fromString((json["TanarNeve"] ?? "").trim()), : null,
homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false, teacher: Teacher.fromString((json["TanarNeve"] ?? "").trim()),
start: json["KezdetIdopont"] != null homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false,
? DateTime.parse(json["KezdetIdopont"]).toLocal() start: json["KezdetIdopont"] != null
: DateTime(0), ? DateTime.parse(json["KezdetIdopont"]).toLocal()
studentPresence: json["TanuloJelenlet"] != null : DateTime(0),
? (json["TanuloJelenlet"]["Nev"] ?? "") == "Hianyzas" studentPresence: json["TanuloJelenlet"] != null
? false ? (json["TanuloJelenlet"]["Nev"] ?? "") == "Hianyzas"
: true ? false
: true, : true
end: json["VegIdopont"] != null : true,
? DateTime.parse(json["VegIdopont"]).toLocal() end: json["VegIdopont"] != null
: DateTime(0), ? DateTime.parse(json["VegIdopont"]).toLocal()
homeworkId: json["HaziFeladatUid"] ?? "", : DateTime(0),
exam: json["BejelentettSzamonkeresUid"] ?? "", homeworkId: json["HaziFeladatUid"] ?? "",
type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null, exam: json["BejelentettSzamonkeresUid"] ?? "",
description: json["Tema"] ?? "", type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
room: ((json["TeremNeve"] ?? "").split("_").join(" ") as String) description: json["Tema"] ?? "",
.replaceAll(RegExp(r" ?terem ?", caseSensitive: false), ""), room: ((json["TeremNeve"] ?? "").split("_").join(" ") as String)
groupName: json["OsztalyCsoport"] != null .replaceAll(RegExp(r" ?terem ?", caseSensitive: false), ""),
? json["OsztalyCsoport"]["Nev"] ?? "" groupName: json["OsztalyCsoport"] != null
: "", ? json["OsztalyCsoport"]["Nev"] ?? ""
name: json["Nev"] ?? "", : "",
online: json["IsDigitalisOra"] ?? false, name: json["Nev"] ?? "",
isEmpty: json['isEmpty'] ?? false, online: json["IsDigitalisOra"] ?? false,
json: json, isEmpty: json['isEmpty'] ?? false,
isSeen: false json: json,
); isSeen: false);
} }
int? getFloor() { int? getFloor() {

View File

@@ -73,8 +73,16 @@ class HomeworkProvider with ChangeNotifier {
if (user == null) throw "Cannot fetch Homework for User null"; if (user == null) throw "Cannot fetch Homework for User null";
String iss = user.instituteCode; String iss = user.instituteCode;
List? homeworkJson = await Provider.of<KretaClient>(_context, listen: false)
.getAPI(KretaAPI.homework(iss, start: from)); List? homeworkJson = [];
try {
homeworkJson = await Provider.of<KretaClient>(_context, listen: false)
.getAPI(KretaAPI.homework(iss, start: from));
} catch (e) {
// error fetcing homework (unknown error)
}
if (homeworkJson == null) throw "Cannot fetch Homework for User ${user.id}"; if (homeworkJson == null) throw "Cannot fetch Homework for User ${user.id}";
List<Homework> homework = []; List<Homework> homework = [];

View File

@@ -0,0 +1,53 @@
import 'package:filcnaplo/models/ad.dart';
import 'package:filcnaplo/theme/colors/colors.dart';
import 'package:flutter/material.dart';
import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart';
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
class AdTile extends StatelessWidget {
const AdTile(this.ad, {Key? key, this.onTap, this.padding}) : super(key: key);
final Ad ad;
final Function()? onTap;
final EdgeInsetsGeometry? padding;
@override
Widget build(BuildContext context) {
print('geic');
print(ad);
return Padding(
padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
child: PanelButton(
padding: const EdgeInsets.only(left: 8.0, right: 16.0),
onPressed: onTap,
title: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
ad.title,
),
Text(
ad.description,
style: TextStyle(
fontWeight: FontWeight.w500,
color: AppColors.of(context).text.withOpacity(0.7),
),
),
],
),
leading: ad.logoUrl != null
? Image.network(
ad.logoUrl.toString(),
errorBuilder: (context, error, stackTrace) {
ad.logoUrl = null;
return const SizedBox();
},
)
: null,
trailing: const Icon(FeatherIcons.externalLink),
),
);
}
}

View File

@@ -0,0 +1,22 @@
import 'package:filcnaplo/models/ad.dart';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'ad_tile.dart';
class AdViewable extends StatelessWidget {
const AdViewable(this.ad, {Key? key}) : super(key: key);
final Ad ad;
@override
Widget build(BuildContext context) {
return AdTile(
ad,
onTap: () => launchUrl(
ad.launchUrl,
mode: LaunchMode.externalApplication,
),
);
}
}

View File

@@ -22,7 +22,8 @@ class LessonView extends StatelessWidget {
if (RegExp(r'\d').hasMatch(lesson.lessonIndex)) lessonIndexTrailing = "."; if (RegExp(r'\d').hasMatch(lesson.lessonIndex)) lessonIndexTrailing = ".";
if (lesson.substituteTeacher?.name != "") { if (lesson.substituteTeacher != null &&
lesson.substituteTeacher?.name != "") {
accent = AppColors.of(context).yellow; accent = AppColors.of(context).yellow;
} }

View File

@@ -18,7 +18,8 @@ class UpdateView extends StatefulWidget {
final Release release; final Release release;
static void show(Release release, {required BuildContext context}) => showBottomCard(context: context, child: UpdateView(release)); static void show(Release release, {required BuildContext context}) =>
showBottomCard(context: context, child: UpdateView(release));
@override @override
_UpdateViewState createState() => _UpdateViewState(); _UpdateViewState createState() => _UpdateViewState();
@@ -45,7 +46,8 @@ class _UpdateViewState extends State<UpdateView> {
children: [ children: [
Text( Text(
"new_update".i18n, "new_update".i18n,
style: const TextStyle(fontWeight: FontWeight.w700, fontSize: 18.0), style: const TextStyle(
fontWeight: FontWeight.w700, fontSize: 18.0),
), ),
Text( Text(
"${widget.release.version}", "${widget.release.version}",
@@ -75,7 +77,7 @@ class _UpdateViewState extends State<UpdateView> {
borderRadius: BorderRadius.circular(12.0), borderRadius: BorderRadius.circular(12.0),
), ),
child: SizedBox( child: SizedBox(
height: 125.0, height: 200.0,
child: Markdown( child: Markdown(
padding: const EdgeInsets.symmetric(horizontal: 12.0), padding: const EdgeInsets.symmetric(horizontal: 12.0),
physics: const BouncingScrollPhysics(), physics: const BouncingScrollPhysics(),
@@ -91,21 +93,30 @@ class _UpdateViewState extends State<UpdateView> {
child: Row( child: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
if (state == UpdateState.downloading || state == UpdateState.preparing) if (state == UpdateState.downloading ||
state == UpdateState.preparing)
Container( Container(
height: 18.0, height: 18.0,
width: 18.0, width: 18.0,
margin: const EdgeInsets.only(right: 8.0), margin: const EdgeInsets.only(right: 8.0),
child: CircularProgressIndicator( child: CircularProgressIndicator(
value: progress > 0.05 ? progress : null, value: progress > 0.05 ? progress : null,
color: ColorUtils.foregroundColor(AppColors.of(context).filc), color: ColorUtils.foregroundColor(
AppColors.of(context).filc),
), ),
), ),
Text(["download".i18n, "downloading".i18n, "downloading".i18n, "installing".i18n][state.index].toUpperCase()), Text([
"download".i18n,
"downloading".i18n,
"downloading".i18n,
"installing".i18n
][state.index]
.toUpperCase()),
], ],
), ),
backgroundColor: AppColors.of(context).filc, backgroundColor: AppColors.of(context).filc,
onPressed: state == UpdateState.none ? () => downloadPrecheck() : null, onPressed:
state == UpdateState.none ? () => downloadPrecheck() : null,
), ),
), ),
], ],
@@ -113,7 +124,8 @@ class _UpdateViewState extends State<UpdateView> {
); );
} }
String fmtSize() => "${(widget.release.downloads.first.size / 1024 / 1024).toStringAsFixed(1)} MB"; String fmtSize() =>
"${(widget.release.downloads.first.size / 1024 / 1024).toStringAsFixed(1)} MB";
void downloadPrecheck() { void downloadPrecheck() {
final status = Provider.of<StatusProvider>(context, listen: false); final status = Provider.of<StatusProvider>(context, listen: false);
@@ -157,6 +169,7 @@ class _UpdateViewState extends State<UpdateView> {
.then((_) => Navigator.of(context).maybePop()) .then((_) => Navigator.of(context).maybePop())
.catchError((error, stackTrace) { .catchError((error, stackTrace) {
if (mounted) { if (mounted) {
Navigator.of(context).maybePop();
ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar( ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
context: context, context: context,
content: Text("error".i18n), content: Text("error".i18n),

View File

@@ -5,6 +5,8 @@ import 'package:filcnaplo/api/providers/database_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/utils/format.dart'; import 'package:filcnaplo/utils/format.dart';
// import 'package:filcnaplo_kreta_api/client/api.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/helpers/average_helper.dart'; import 'package:filcnaplo/helpers/average_helper.dart';
import 'package:filcnaplo/helpers/subject.dart'; import 'package:filcnaplo/helpers/subject.dart';

View File

@@ -2,6 +2,8 @@ import 'dart:math';
import 'package:auto_size_text/auto_size_text.dart'; import 'package:auto_size_text/auto_size_text.dart';
import 'package:filcnaplo/api/providers/update_provider.dart'; import 'package:filcnaplo/api/providers/update_provider.dart';
// import 'package:filcnaplo_kreta_api/client/api.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/api/providers/user_provider.dart'; import 'package:filcnaplo/api/providers/user_provider.dart';
import 'package:filcnaplo/theme/colors/colors.dart'; import 'package:filcnaplo/theme/colors/colors.dart';
@@ -112,6 +114,18 @@ class _GradesPageState extends State<GradesPage> {
} else { } else {
tiles.insert( tiles.insert(
0, 0,
// TextButton(
// onPressed: () async {
// var url = KretaAPI.averages(
// user.instituteCode!,
// user.id!,
// );
// print(url);
// var res = await Provider.of<KretaClient>(context, listen: false)
// .getAPI(url);
// print(res);
// },
// child: Text('test')),
Padding( Padding(
padding: const EdgeInsets.only(top: 24.0), padding: const EdgeInsets.only(top: 24.0),
child: Empty(subtitle: "empty".i18n), child: Empty(subtitle: "empty".i18n),

View File

@@ -1,3 +1,4 @@
// import 'dart:async';
import 'dart:ui'; import 'dart:ui';
import 'package:filcnaplo/api/client.dart'; import 'package:filcnaplo/api/client.dart';
@@ -42,6 +43,8 @@ class _LoginScreenState extends State<LoginScreen> {
stops: [-1.0, 0.0, 1.0], stops: [-1.0, 0.0, 1.0],
); );
late String tempUsername = '';
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@@ -250,7 +253,7 @@ class _LoginScreenState extends State<LoginScreen> {
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 15.0, fontSize: 15.0,
)), )),
onPressed: () => _loginApi(context: context), onPressed: () => _loginAPI(context: context),
), ),
visible: _loginState != LoginState.inProgress, visible: _loginState != LoginState.inProgress,
replacement: const Padding( replacement: const Padding(
@@ -275,7 +278,10 @@ class _LoginScreenState extends State<LoginScreen> {
][_loginState.index] ][_loginState.index]
.i18n, .i18n,
style: const TextStyle( style: const TextStyle(
color: Colors.red, fontWeight: FontWeight.w500), color: Colors.red,
fontWeight: FontWeight.w500,
),
textAlign: TextAlign.center,
), ),
), ),
const Spacer() const Spacer()
@@ -288,35 +294,54 @@ class _LoginScreenState extends State<LoginScreen> {
); );
} }
void _loginApi({required BuildContext context}) { void _loginAPI({required BuildContext context}) {
String username = usernameController.text; String username = usernameController.text;
String password = passwordController.text; String password = passwordController.text;
tempUsername = username;
if (username == "" || if (username == "" ||
password == "" || password == "" ||
schoolController.selectedSchool == null) { schoolController.selectedSchool == null) {
return setState(() => _loginState = LoginState.missingFields); return setState(() => _loginState = LoginState.missingFields);
} }
setState(() => _loginState = LoginState.inProgress); void _callAPI() {
loginAPI(
username: username,
password: password,
instituteCode: schoolController.selectedSchool!.instituteCode,
context: context,
onLogin: (user) {
ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
context: context,
brightness: Brightness.light,
content: Text("welcome".i18n.fill([user.name]),
overflow: TextOverflow.ellipsis),
));
},
onSuccess: () {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
setSystemChrome(context);
Navigator.of(context).pushReplacementNamed("login_to_navigation");
}).then(
(res) => setState(() {
// if (res == LoginState.invalidGrant &&
// tempUsername.replaceAll(username, '').length <= 3) {
// tempUsername = username + ' ';
// Timer(
// const Duration(milliseconds: 500),
// () => _loginAPI(context: context),
// );
// // _loginAPI(context: context);
// } else {
_loginState = res;
// }
}),
);
}
loginApi( setState(() => _loginState = LoginState.inProgress);
username: username, _callAPI();
password: password,
instituteCode: schoolController.selectedSchool!.instituteCode,
context: context,
onLogin: (user) {
ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
context: context,
brightness: Brightness.light,
content: Text("welcome".i18n.fill([user.name]),
overflow: TextOverflow.ellipsis),
));
},
onSuccess: () {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
setSystemChrome(context);
Navigator.of(context).pushReplacementNamed("login_to_navigation");
}).then((res) => setState(() => _loginState = res));
} }
} }

View File

@@ -12,7 +12,8 @@ extension Localization on String {
"login": "Log in", "login": "Log in",
"welcome": "Welcome, %s!", "welcome": "Welcome, %s!",
"missing_fields": "Missing Fields!", "missing_fields": "Missing Fields!",
"invalid_grant": "Invalid Username/Password!", "invalid_grant":
"Invalid Username/Password! (Try adding spaces after Username)",
"error": "Failed to log in.", "error": "Failed to log in.",
"schools_error": "Failed to get schools." "schools_error": "Failed to get schools."
}, },
@@ -25,7 +26,8 @@ extension Localization on String {
"login": "Belépés", "login": "Belépés",
"welcome": "Üdv, %s!", "welcome": "Üdv, %s!",
"missing_fields": "Hiányzó adatok!", "missing_fields": "Hiányzó adatok!",
"invalid_grant": "Helytelen Felhasználónév/Jelszó!", "invalid_grant":
"Helytelen Felhasználónév/Jelszó! (Próbálj szóközöket írni a Felhasználónév után)",
"error": "Sikertelen bejelentkezés.", "error": "Sikertelen bejelentkezés.",
"schools_error": "Nem sikerült lekérni az iskolákat." "schools_error": "Nem sikerült lekérni az iskolákat."
}, },

View File

@@ -12,51 +12,48 @@ class SchoolInputTile extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( return Padding(
padding: const EdgeInsets.all(4.0), padding: const EdgeInsets.all(4.0),
child: GestureDetector( child: InkWell(
onPanDown: (e) { onTap: () {
onTap!(); onTap!();
}, },
child: InkWell( borderRadius: BorderRadius.circular(6.0),
onTapDown: (e) {}, child: Padding(
borderRadius: BorderRadius.circular(6.0), padding: const EdgeInsets.all(6.0),
child: Padding( child: Column(
padding: const EdgeInsets.all(6.0), crossAxisAlignment: CrossAxisAlignment.start,
child: Column( children: [
crossAxisAlignment: CrossAxisAlignment.start, // School name
children: [ Padding(
// School name padding: const EdgeInsets.only(bottom: 4.0),
Padding( child: Text(
padding: const EdgeInsets.only(bottom: 4.0), school.name,
child: Text( maxLines: 2,
school.name, overflow: TextOverflow.ellipsis,
maxLines: 2, style: const TextStyle(fontWeight: FontWeight.w600),
overflow: TextOverflow.ellipsis, ),
style: const TextStyle(fontWeight: FontWeight.w600), ),
Row(
children: [
// School id
Expanded(
child: Text(
school.instituteCode,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
), ),
), // School city
Row( Expanded(
children: [ child: Text(
// School id school.city,
Expanded( textAlign: TextAlign.right,
child: Text( maxLines: 1,
school.instituteCode, overflow: TextOverflow.ellipsis,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
), ),
// School city ),
Expanded( ],
child: Text( ),
school.city, ],
textAlign: TextAlign.right,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
],
),
],
),
), ),
), ),
), ),

View File

@@ -26,6 +26,7 @@ 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'; import 'package:filcnaplo_premium/providers/goal_provider.dart';
import 'package:filcnaplo/api/providers/ad_provider.dart';
class NavigationScreen extends StatefulWidget { class NavigationScreen extends StatefulWidget {
const NavigationScreen({Key? key}) : super(key: key); const NavigationScreen({Key? key}) : super(key: key);
@@ -48,6 +49,7 @@ class NavigationScreenState extends State<NavigationScreen>
late GoalProvider goalProvider; late GoalProvider goalProvider;
late UpdateProvider updateProvider; late UpdateProvider updateProvider;
late GradeProvider gradeProvicer; late GradeProvider gradeProvicer;
late AdProvider adProvider;
NavigatorState? get navigator => _navigatorState.currentState; NavigatorState? get navigator => _navigatorState.currentState;
@@ -176,6 +178,10 @@ class NavigationScreenState extends State<NavigationScreen>
updateProvider = Provider.of<UpdateProvider>(context, listen: false); updateProvider = Provider.of<UpdateProvider>(context, listen: false);
updateProvider.fetch(); updateProvider.fetch();
// get advertisements
adProvider = Provider.of<AdProvider>(context, listen: false);
adProvider.fetch();
// initial sync // initial sync
syncAll(context); syncAll(context);
setupQuickActions(); setupQuickActions();

View File

@@ -1,5 +1,6 @@
import 'package:filcnaplo/api/providers/database_provider.dart'; import 'package:filcnaplo/api/providers/database_provider.dart';
import 'package:filcnaplo/api/providers/user_provider.dart'; import 'package:filcnaplo/api/providers/user_provider.dart';
import 'package:filcnaplo/theme/colors/colors.dart';
import 'package:filcnaplo_kreta_api/models/subject.dart'; import 'package:filcnaplo_kreta_api/models/subject.dart';
import 'package:filcnaplo_mobile_ui/common/average_display.dart'; import 'package:filcnaplo_mobile_ui/common/average_display.dart';
import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_state_screen.i18n.dart'; import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_state_screen.i18n.dart';
@@ -33,7 +34,7 @@ class GoalCompleteModal extends StatelessWidget {
child: Container( child: Container(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Theme.of(context).colorScheme.background,
borderRadius: BorderRadius.circular(20.0), borderRadius: BorderRadius.circular(20.0),
), ),
child: Column( child: Column(
@@ -79,19 +80,21 @@ class GoalCompleteModal extends StatelessWidget {
Text( Text(
'congrats_title'.i18n, 'congrats_title'.i18n,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: const TextStyle( style: TextStyle(
fontSize: 27.0, fontSize: 27.0,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
height: 1.1, height: 1.2,
color: AppColors.of(context).text,
), ),
), ),
Text( Text(
'goal_reached'.i18n.fill(['20']), 'goal_reached'.i18n.fill(['20']),
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: const TextStyle( style: TextStyle(
fontSize: 15.0, fontSize: 15.0,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
height: 1.1, height: 1.1,
color: AppColors.of(context).text,
), ),
), ),
const SizedBox(height: 18.0), const SizedBox(height: 18.0),
@@ -103,9 +106,10 @@ class GoalCompleteModal extends StatelessWidget {
Text( Text(
'started_at'.i18n, 'started_at'.i18n,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: const TextStyle( style: TextStyle(
fontSize: 17.0, fontSize: 17.0,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: AppColors.of(context).text,
), ),
), ),
const SizedBox(width: 5.0), const SizedBox(width: 5.0),
@@ -119,9 +123,10 @@ class GoalCompleteModal extends StatelessWidget {
averageDifference.toStringAsFixed(2) + '%', averageDifference.toStringAsFixed(2) + '%',
]), ]),
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: const TextStyle( style: TextStyle(
fontSize: 17.0, fontSize: 17.0,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: AppColors.of(context).text,
), ),
), ),
], ],
@@ -173,17 +178,17 @@ class GoalCompleteModal extends StatelessWidget {
width: double.infinity, width: double.infinity,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0), borderRadius: BorderRadius.circular(10.0),
color: const Color(0xFFF5FAF9), color: const Color.fromARGB(38, 131, 131, 131),
), ),
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0), padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Text( child: Text(
'later'.i18n, 'later'.i18n,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: const TextStyle( style: TextStyle(
fontSize: 18.0, fontSize: 18.0,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
color: Color(0xFF01342D), color: AppColors.of(context).text,
), ),
), ),
), ),