Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b92ac9ffbc | ||
|
|
f435f31523 | ||
|
|
6abc61db7b | ||
|
|
cd8ab8bfdb | ||
|
|
24a6393aca | ||
|
|
64fb22de74 | ||
|
|
14ce4c82fb | ||
|
|
7d1f4e992c | ||
|
|
17b8b96767 | ||
|
|
7ac5d64d19 | ||
|
|
d9bd555e6a | ||
|
|
b5bf994b8d | ||
|
|
8b216bd27b | ||
|
|
a9bd11a4d7 | ||
|
|
129a95f359 | ||
|
|
8b65d4d519 | ||
|
|
353297bc90 | ||
|
|
63d24f7e89 | ||
|
|
4b93c891c8 | ||
|
|
6f85a4ebc1 | ||
|
|
b37af9f5a5 | ||
|
|
3a26fd9ec9 | ||
|
|
9cda8c5d29 | ||
|
|
6212489001 | ||
|
|
b4ff2fa815 | ||
|
|
a11ebce6fb | ||
|
|
fa75c1ec06 | ||
|
|
79677d657e | ||
|
|
50d1803a18 | ||
|
|
34f9929b16 | ||
|
|
7b517b333a | ||
|
|
d1a9625d93 | ||
|
|
056bf7ab58 | ||
|
|
c4dc03f41d | ||
|
|
6d7a21dc02 | ||
|
|
9406efee8d | ||
|
|
151e97b243 | ||
|
|
1ba0f4d8d3 | ||
|
|
4b8dbf0691 | ||
|
|
98d7468f24 | ||
|
|
fa46d6cbd3 | ||
|
|
a0c68a4e5a | ||
|
|
f2f35b2fbd | ||
|
|
a782dbd22f | ||
|
|
6293bb4017 | ||
|
|
03a5057269 | ||
|
|
4a15514ba0 |
@@ -221,9 +221,9 @@
|
|||||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||||
97C146EC1CF9000F007C117D /* Resources */,
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
|
3127F74F28EAEC8A00C2EFB3 /* Embed Foundation Extensions */,
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
71459C0EB905E05018E3D78F /* [CP] Embed Pods Frameworks */,
|
71459C0EB905E05018E3D78F /* [CP] Embed Pods Frameworks */,
|
||||||
3127F74F28EAEC8A00C2EFB3 /* Embed Foundation Extensions */,
|
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@@ -478,7 +478,7 @@
|
|||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 195;
|
CURRENT_PROJECT_VERSION = 195;
|
||||||
DEVELOPMENT_TEAM = 48XS7JAZB7;
|
DEVELOPMENT_TEAM = 4DKAF249F3;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = reFilc;
|
INFOPLIST_KEY_CFBundleDisplayName = reFilc;
|
||||||
@@ -488,7 +488,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 3.6.0;
|
MARKETING_VERSION = 3.6.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.refilctest.naplo;
|
PRODUCT_BUNDLE_IDENTIFIER = com.refilc2.naplo;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
@@ -510,7 +510,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = 48XS7JAZB7;
|
DEVELOPMENT_TEAM = 4DKAF249F3;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = livecard/Info.plist;
|
INFOPLIST_FILE = livecard/Info.plist;
|
||||||
@@ -526,7 +526,7 @@
|
|||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.refilctest.naplo.livecardpro;
|
PRODUCT_BUNDLE_IDENTIFIER = com.refilc2.naplo.livecardpro;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
@@ -552,7 +552,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = 48XS7JAZB7;
|
DEVELOPMENT_TEAM = 4DKAF249F3;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = livecard/Info.plist;
|
INFOPLIST_FILE = livecard/Info.plist;
|
||||||
@@ -567,7 +567,7 @@
|
|||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.refilctest.naplo.livecardpro;
|
PRODUCT_BUNDLE_IDENTIFIER = com.refilc2.naplo.livecardpro;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
@@ -592,7 +592,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = 48XS7JAZB7;
|
DEVELOPMENT_TEAM = 4DKAF249F3;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = livecard/Info.plist;
|
INFOPLIST_FILE = livecard/Info.plist;
|
||||||
@@ -607,7 +607,7 @@
|
|||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.refilctest.naplo.livecardpro;
|
PRODUCT_BUNDLE_IDENTIFIER = com.refilc2.naplo.livecardpro;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
@@ -736,7 +736,7 @@
|
|||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 195;
|
CURRENT_PROJECT_VERSION = 195;
|
||||||
DEVELOPMENT_TEAM = 48XS7JAZB7;
|
DEVELOPMENT_TEAM = 4DKAF249F3;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = reFilc;
|
INFOPLIST_KEY_CFBundleDisplayName = reFilc;
|
||||||
@@ -746,7 +746,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 3.6.0;
|
MARKETING_VERSION = 3.6.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.refilctest.naplo;
|
PRODUCT_BUNDLE_IDENTIFIER = com.refilc2.naplo;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
@@ -764,7 +764,7 @@
|
|||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 195;
|
CURRENT_PROJECT_VERSION = 195;
|
||||||
DEVELOPMENT_TEAM = 48XS7JAZB7;
|
DEVELOPMENT_TEAM = 4DKAF249F3;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = reFilc;
|
INFOPLIST_KEY_CFBundleDisplayName = reFilc;
|
||||||
@@ -774,7 +774,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 3.6.0;
|
MARKETING_VERSION = 3.6.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.refilctest.naplo;
|
PRODUCT_BUNDLE_IDENTIFIER = com.refilc2.naplo;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<string>development</string>
|
<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.refilc2.livecard</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class LessonData {
|
|||||||
var nextRoom: String
|
var nextRoom: String
|
||||||
|
|
||||||
init?() {
|
init?() {
|
||||||
let sharedDefault = UserDefaults(suiteName: "group.refilc.livecard")!
|
let sharedDefault = UserDefaults(suiteName: "group.refilc2.livecard")!
|
||||||
|
|
||||||
self.color = sharedDefault.string(forKey: "color")!
|
self.color = sharedDefault.string(forKey: "color")!
|
||||||
self.icon = sharedDefault.string(forKey: "icon")!
|
self.icon = sharedDefault.string(forKey: "icon")!
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<string>development</string>
|
<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.refilc2.livecard</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -91,14 +91,15 @@ struct LockScreenLiveActivityView: View {
|
|||||||
Text(timerInterval: lesson!.date, countsDown: true)
|
Text(timerInterval: lesson!.date, countsDown: true)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
.frame(width: 85)
|
.frame(width: 85)
|
||||||
.font(.title)
|
.font(.title2)
|
||||||
.monospacedDigit()
|
.monospacedDigit()
|
||||||
.padding(.trailing, CGFloat(24))
|
.padding(.trailing, CGFloat(24))
|
||||||
}
|
}
|
||||||
.activityBackgroundTint(
|
.activityBackgroundTint(
|
||||||
lesson!.color == "#676767"
|
lesson!.color != "#676767"
|
||||||
? nil
|
? Color(hex: lesson!.color)
|
||||||
: Color(hex: lesson!.color)
|
// Ha nem megy hat nem megy
|
||||||
|
: Color.clear
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,12 +119,22 @@ struct LiveCardWidget: Widget {
|
|||||||
DynamicIslandExpandedRegion(.leading) {
|
DynamicIslandExpandedRegion(.leading) {
|
||||||
VStack {
|
VStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
|
ProgressView(
|
||||||
|
timerInterval: lesson!.date,
|
||||||
|
countsDown: true,
|
||||||
|
label: {
|
||||||
Image(systemName: lesson!.icon)
|
Image(systemName: lesson!.icon)
|
||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(contentMode: .fit)
|
.aspectRatio(contentMode: .fit)
|
||||||
.frame(width: CGFloat(30), height: CGFloat(30))
|
.frame(width: CGFloat(32), height: CGFloat(32))
|
||||||
.padding(.leading, CGFloat(6))
|
},
|
||||||
.padding(.bottom, CGFloat(6))
|
currentValueLabel: {
|
||||||
|
Image(systemName: lesson!.icon)
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: CGFloat(32), height: CGFloat(32))
|
||||||
|
}
|
||||||
|
).progressViewStyle(.circular)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DynamicIslandExpandedRegion(.center) {
|
DynamicIslandExpandedRegion(.center) {
|
||||||
@@ -136,7 +147,7 @@ struct LiveCardWidget: Widget {
|
|||||||
Text(lesson!.description)
|
Text(lesson!.description)
|
||||||
.lineLimit(2)
|
.lineLimit(2)
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
}
|
}.padding(EdgeInsets(top: 0.0, leading: 5.0, bottom: 0.0, trailing: 0.0))
|
||||||
}
|
}
|
||||||
DynamicIslandExpandedRegion(.trailing) {
|
DynamicIslandExpandedRegion(.trailing) {
|
||||||
VStack {
|
VStack {
|
||||||
@@ -156,7 +167,8 @@ struct LiveCardWidget: Widget {
|
|||||||
Image(systemName: lesson!.icon)
|
Image(systemName: lesson!.icon)
|
||||||
}
|
}
|
||||||
.font(.caption2)
|
.font(.caption2)
|
||||||
} compactTrailing: {
|
}
|
||||||
|
compactTrailing: {
|
||||||
Text(timerInterval: lesson!.date, countsDown: true)
|
Text(timerInterval: lesson!.date, countsDown: true)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
.frame(width: 40)
|
.frame(width: 40)
|
||||||
@@ -164,22 +176,29 @@ struct LiveCardWidget: Widget {
|
|||||||
|
|
||||||
/// Collapsed
|
/// Collapsed
|
||||||
} minimal: {
|
} minimal: {
|
||||||
VStack(alignment: .center) {
|
VStack(alignment: .center, content: {
|
||||||
|
ProgressView(
|
||||||
|
timerInterval: lesson!.date,
|
||||||
|
countsDown: true,
|
||||||
|
label: {
|
||||||
|
Image(systemName: lesson!.icon)
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: CGFloat(12), height: CGFloat(12))
|
||||||
|
},
|
||||||
|
currentValueLabel: {
|
||||||
Image(systemName: lesson!.icon)
|
Image(systemName: lesson!.icon)
|
||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(contentMode: .fit)
|
.aspectRatio(contentMode: .fit)
|
||||||
.frame(width: CGFloat(12), height: CGFloat(12))
|
.frame(width: CGFloat(12), height: CGFloat(12))
|
||||||
|
|
||||||
Text(timerInterval: lesson!.date, countsDown: true)
|
|
||||||
.multilineTextAlignment(.center)
|
|
||||||
.monospacedDigit()
|
|
||||||
.font(.system(size: CGFloat(10)))
|
|
||||||
}
|
}
|
||||||
|
).progressViewStyle(.circular)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
.keylineTint(
|
.keylineTint(
|
||||||
lesson!.color == "#676767"
|
lesson!.color != "#676767"
|
||||||
? nil
|
? Color(hex: lesson!.color)
|
||||||
: Color(hex: lesson!.color)
|
: Color.clear
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,11 @@ class FilcAPI {
|
|||||||
static const allThemes = "$themeGet/all";
|
static const allThemes = "$themeGet/all";
|
||||||
static const themeByID = "$themeGet/";
|
static const themeByID = "$themeGet/";
|
||||||
|
|
||||||
|
static const gradeColorsShare = "$baseUrl/v2/shared/grade-colors/add";
|
||||||
|
static const gradeColorsGet = "$baseUrl/v2/shared/grade-colors/get";
|
||||||
|
static const allGradeColors = "$gradeColorsGet/all";
|
||||||
|
static const gradeColorsByID = "$gradeColorsGet/";
|
||||||
|
|
||||||
static Future<bool> checkConnectivity() async =>
|
static Future<bool> checkConnectivity() async =>
|
||||||
(await Connectivity().checkConnectivity()) != ConnectivityResult.none;
|
(await Connectivity().checkConnectivity()) != ConnectivityResult.none;
|
||||||
|
|
||||||
@@ -53,9 +58,14 @@ class FilcAPI {
|
|||||||
.map((json) => School.fromJson(json))
|
.map((json) => School.fromJson(json))
|
||||||
.toList();
|
.toList();
|
||||||
schools.add(School(
|
schools.add(School(
|
||||||
city: "Tiszabura",
|
city: "Stockholm",
|
||||||
instituteCode: "supporttest-reni-tiszabura-teszt01",
|
instituteCode: "refilc-test-sweden",
|
||||||
name: "FILC Éles Reni tiszabura-teszt",
|
name: "reFilc Test SE - Leo Ekström High School",
|
||||||
|
));
|
||||||
|
schools.add(School(
|
||||||
|
city: "Madrid",
|
||||||
|
instituteCode: "refilc-test-spain",
|
||||||
|
name: "reFilc Test ES - Emilio Obrero University",
|
||||||
));
|
));
|
||||||
return schools;
|
return schools;
|
||||||
} else {
|
} else {
|
||||||
@@ -204,6 +214,9 @@ class FilcAPI {
|
|||||||
theme.json['panels_color'] = theme.panelsColor.value.toString();
|
theme.json['panels_color'] = theme.panelsColor.value.toString();
|
||||||
theme.json['accent_color'] = theme.accentColor.value.toString();
|
theme.json['accent_color'] = theme.accentColor.value.toString();
|
||||||
|
|
||||||
|
// set linked grade colors
|
||||||
|
theme.json['grade_colors_id'] = theme.gradeColors.id;
|
||||||
|
|
||||||
http.Response res = await http.post(
|
http.Response res = await http.post(
|
||||||
Uri.parse(themeShare),
|
Uri.parse(themeShare),
|
||||||
body: theme.json,
|
body: theme.json,
|
||||||
@@ -230,7 +243,49 @@ class FilcAPI {
|
|||||||
throw "HTTP ${res.statusCode}: ${res.body}";
|
throw "HTTP ${res.statusCode}: ${res.body}";
|
||||||
}
|
}
|
||||||
} on Exception catch (error, stacktrace) {
|
} on Exception catch (error, stacktrace) {
|
||||||
log("ERROR: FilcAPI.addSharedTheme: $error $stacktrace");
|
log("ERROR: FilcAPI.getSharedTheme: $error $stacktrace");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> addSharedGradeColors(
|
||||||
|
SharedGradeColors gradeColors) async {
|
||||||
|
try {
|
||||||
|
gradeColors.json.remove('json');
|
||||||
|
gradeColors.json['is_public'] = gradeColors.isPublic.toString();
|
||||||
|
gradeColors.json['five_color'] = gradeColors.fiveColor.value.toString();
|
||||||
|
gradeColors.json['four_color'] = gradeColors.fourColor.value.toString();
|
||||||
|
gradeColors.json['three_color'] = gradeColors.threeColor.value.toString();
|
||||||
|
gradeColors.json['two_color'] = gradeColors.twoColor.value.toString();
|
||||||
|
gradeColors.json['one_color'] = gradeColors.oneColor.value.toString();
|
||||||
|
|
||||||
|
http.Response res = await http.post(
|
||||||
|
Uri.parse(gradeColorsShare),
|
||||||
|
body: gradeColors.json,
|
||||||
|
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (res.statusCode != 201) {
|
||||||
|
throw "HTTP ${res.statusCode}: ${res.body}";
|
||||||
|
}
|
||||||
|
|
||||||
|
log('Shared grade colors successfully with ID: ${gradeColors.id}');
|
||||||
|
} on Exception catch (error, stacktrace) {
|
||||||
|
log("ERROR: FilcAPI.addSharedGradeColors: $error $stacktrace");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<Map?> getSharedGradeColors(String id) async {
|
||||||
|
try {
|
||||||
|
http.Response res = await http.get(Uri.parse(gradeColorsByID + id));
|
||||||
|
|
||||||
|
if (res.statusCode == 200) {
|
||||||
|
return (jsonDecode(res.body) as Map);
|
||||||
|
} else {
|
||||||
|
throw "HTTP ${res.statusCode}: ${res.body}";
|
||||||
|
}
|
||||||
|
} on Exception catch (error, stacktrace) {
|
||||||
|
log("ERROR: FilcAPI.getSharedGradeColors: $error $stacktrace");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// ignore_for_file: avoid_print, use_build_context_synchronously
|
// ignore_for_file: avoid_print, use_build_context_synchronously
|
||||||
|
|
||||||
import 'package:filcnaplo/utils/jwt.dart';
|
import 'package:filcnaplo/utils/jwt.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/school.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';
|
||||||
@@ -20,6 +21,7 @@ import 'package:filcnaplo_kreta_api/models/week.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:filcnaplo/api/nonce.dart';
|
import 'package:filcnaplo/api/nonce.dart';
|
||||||
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
enum LoginState {
|
enum LoginState {
|
||||||
missingFields,
|
missingFields,
|
||||||
@@ -47,6 +49,58 @@ Future loginAPI({
|
|||||||
void Function(User)? onLogin,
|
void Function(User)? onLogin,
|
||||||
void Function()? onSuccess,
|
void Function()? onSuccess,
|
||||||
}) async {
|
}) async {
|
||||||
|
Future testLogin(School school) async {
|
||||||
|
var user = User(
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
instituteCode: instituteCode,
|
||||||
|
name: 'Teszt Lajos',
|
||||||
|
student: Student(
|
||||||
|
birth: DateTime.now(),
|
||||||
|
id: const Uuid().v4(),
|
||||||
|
name: 'Teszt Lajos',
|
||||||
|
school: school,
|
||||||
|
yearId: '1',
|
||||||
|
parents: ['Teszt András', 'Teszt Linda'],
|
||||||
|
json: {"a": "b"},
|
||||||
|
address: '1117 Budapest, Gábor Dénes utca 4.',
|
||||||
|
),
|
||||||
|
role: Role.parent,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (onLogin != null) onLogin(user);
|
||||||
|
|
||||||
|
// store test user in db
|
||||||
|
await Provider.of<DatabaseProvider>(context, listen: false)
|
||||||
|
.store
|
||||||
|
.storeUser(user);
|
||||||
|
Provider.of<UserProvider>(context, listen: false).addUser(user);
|
||||||
|
Provider.of<UserProvider>(context, listen: false).setUser(user.id);
|
||||||
|
|
||||||
|
if (onSuccess != null) onSuccess();
|
||||||
|
|
||||||
|
return LoginState.success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if institute matches one of test things do test login
|
||||||
|
if (instituteCode == 'refilc-test-sweden') {
|
||||||
|
School school = School(
|
||||||
|
city: "Stockholm",
|
||||||
|
instituteCode: "refilc-test-sweden",
|
||||||
|
name: "reFilc Test SE - Leo Ekström High School",
|
||||||
|
);
|
||||||
|
|
||||||
|
await testLogin(school);
|
||||||
|
} else if (instituteCode == 'refilc-test-spain') {
|
||||||
|
School school = School(
|
||||||
|
city: "Madrid",
|
||||||
|
instituteCode: "refilc-test-spain",
|
||||||
|
name: "reFilc Test ES - Emilio Obrero University",
|
||||||
|
);
|
||||||
|
|
||||||
|
await testLogin(school);
|
||||||
|
} else {
|
||||||
|
// normal login from here
|
||||||
Provider.of<KretaClient>(context, listen: false).userAgent =
|
Provider.of<KretaClient>(context, listen: false).userAgent =
|
||||||
Provider.of<SettingsProvider>(context, listen: false).config.userAgent;
|
Provider.of<SettingsProvider>(context, listen: false).config.userAgent;
|
||||||
|
|
||||||
@@ -129,5 +183,7 @@ Future loginAPI({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return LoginState.failed;
|
return LoginState.failed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
_liveActivitiesPlugin.init(appGroupId: "group.refilc.livecard");
|
_liveActivitiesPlugin.init(appGroupId: "group.refilc2.livecard");
|
||||||
|
|
||||||
_liveActivitiesPlugin.getAllActivitiesIds().then((value) {
|
_liveActivitiesPlugin.getAllActivitiesIds().then((value) {
|
||||||
_latestActivityId = value.isNotEmpty ? value.first : null;
|
_latestActivityId = value.isNotEmpty ? value.first : null;
|
||||||
@@ -88,7 +88,7 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
// Debugging
|
// Debugging
|
||||||
static DateTime _now() {
|
static DateTime _now() {
|
||||||
// return DateTime(2023, 8, 31, 8, 0);
|
// return DateTime(2023, 9, 27, 9, 30);
|
||||||
return DateTime.now();
|
return DateTime.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
"index":
|
"index":
|
||||||
currentLesson != null ? '${currentLesson!.lessonIndex}. ' : "",
|
currentLesson != null ? '${currentLesson!.lessonIndex}. ' : "",
|
||||||
"title": currentLesson != null
|
"title": currentLesson != null
|
||||||
? ShortSubject.resolve(subject: currentLesson?.subject).capital()
|
? currentLesson?.subject.renamedTo ?? ShortSubject.resolve(subject: currentLesson?.subject).capital()
|
||||||
: "",
|
: "",
|
||||||
"subtitle": currentLesson?.room.replaceAll("_", " ") ?? "",
|
"subtitle": currentLesson?.room.replaceAll("_", " ") ?? "",
|
||||||
"description": currentLesson?.description ?? "",
|
"description": currentLesson?.description ?? "",
|
||||||
@@ -131,7 +131,7 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
_delay.inMilliseconds)
|
_delay.inMilliseconds)
|
||||||
.toString(),
|
.toString(),
|
||||||
"nextSubject": nextLesson != null
|
"nextSubject": nextLesson != null
|
||||||
? ShortSubject.resolve(subject: nextLesson?.subject).capital()
|
? nextLesson?.subject.renamedTo ?? ShortSubject.resolve(subject: nextLesson?.subject).capital()
|
||||||
: "",
|
: "",
|
||||||
"nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
|
"nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
|
||||||
};
|
};
|
||||||
@@ -160,7 +160,7 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
_delay.inMilliseconds)
|
_delay.inMilliseconds)
|
||||||
.toString(),
|
.toString(),
|
||||||
"nextSubject": (nextLesson != null
|
"nextSubject": (nextLesson != null
|
||||||
? ShortSubject.resolve(subject: nextLesson?.subject)
|
? nextLesson?.subject.renamedTo ?? ShortSubject.resolve(subject: nextLesson?.subject).capital()
|
||||||
: "")
|
: "")
|
||||||
.capital(),
|
.capital(),
|
||||||
"nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
|
"nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
enum Status { network, maintenance, syncing }
|
enum Status { network, maintenance, syncing, apiError }
|
||||||
|
|
||||||
class StatusProvider extends ChangeNotifier {
|
class StatusProvider extends ChangeNotifier {
|
||||||
final List<Status> _stack = [];
|
final List<Status> _stack = [];
|
||||||
@@ -12,6 +14,7 @@ class StatusProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
StatusProvider() {
|
StatusProvider() {
|
||||||
_handleNetworkChanges();
|
_handleNetworkChanges();
|
||||||
|
_handleDNSFailure();
|
||||||
Connectivity().checkConnectivity().then((value) => _networkType = value);
|
Connectivity().checkConnectivity().then((value) => _networkType = value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,6 +27,7 @@ class StatusProvider extends ChangeNotifier {
|
|||||||
_networkType = event;
|
_networkType = event;
|
||||||
if (event == ConnectivityResult.none) {
|
if (event == ConnectivityResult.none) {
|
||||||
if (!_stack.contains(Status.network)) {
|
if (!_stack.contains(Status.network)) {
|
||||||
|
_stack.remove(Status.apiError);
|
||||||
_stack.insert(0, Status.network);
|
_stack.insert(0, Status.network);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
@@ -36,8 +40,34 @@ class StatusProvider extends ChangeNotifier {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _handleDNSFailure() {
|
||||||
|
try {
|
||||||
|
InternetAddress.lookup('api.refilc.hu').then((status) {
|
||||||
|
if (status.isEmpty) {
|
||||||
|
if (!_stack.contains(Status.network)) {
|
||||||
|
_stack.remove(Status.apiError);
|
||||||
|
_stack.insert(0, Status.network);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_stack.contains(Status.network)) {
|
||||||
|
_stack.remove(Status.network);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} on SocketException catch (_) {
|
||||||
|
if (!_stack.contains(Status.network)) {
|
||||||
|
_stack.remove(Status.apiError);
|
||||||
|
_stack.insert(0, Status.network);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void triggerRequest(http.Response res) {
|
void triggerRequest(http.Response res) {
|
||||||
if (res.headers.containsKey("x-maintenance-mode") || res.statusCode == 503) {
|
if (res.headers.containsKey("x-maintenance-mode") ||
|
||||||
|
res.statusCode == 503) {
|
||||||
if (!_stack.contains(Status.maintenance)) {
|
if (!_stack.contains(Status.maintenance)) {
|
||||||
_stack.insert(0, Status.maintenance);
|
_stack.insert(0, Status.maintenance);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@@ -48,6 +78,22 @@ class StatusProvider extends ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_stack.contains(Status.network)) return;
|
||||||
|
if (res.body == "invalid_grant" ||
|
||||||
|
res.body.replaceAll(' ', '') == '' ||
|
||||||
|
res.statusCode == 400) {
|
||||||
|
if (!_stack.contains(Status.apiError)) {
|
||||||
|
_stack.insert(0, Status.apiError);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_stack.contains(Status.apiError) &&
|
||||||
|
res.request?.url.path != '/nonce') {
|
||||||
|
_stack.remove(Status.apiError);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void triggerSync({required int current, required int max}) {
|
void triggerSync({required int current, required int max}) {
|
||||||
|
|||||||
@@ -33,9 +33,12 @@ class UpdateProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
// Check for new releases
|
// Check for new releases
|
||||||
if (_releases.isNotEmpty) {
|
if (_releases.isNotEmpty) {
|
||||||
|
if (!_releases.first.prerelease) {
|
||||||
_available = _releases.first.version
|
_available = _releases.first.version
|
||||||
.compareTo(Version.fromString(currentVersion)) ==
|
.compareTo(Version.fromString(currentVersion)) ==
|
||||||
1;
|
1;
|
||||||
|
}
|
||||||
|
|
||||||
// ignore: avoid_print
|
// ignore: avoid_print
|
||||||
if (_available) print("INFO: New update: ${releases.first.version}");
|
if (_available) print("INFO: New update: ${releases.first.version}");
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ const settingsDB = DatabaseStruct("settings", {
|
|||||||
"renamed_subjects_italics": int, "renamed_teachers_enabled": int,
|
"renamed_subjects_italics": int, "renamed_teachers_enabled": int,
|
||||||
"renamed_teachers_italics": int,
|
"renamed_teachers_italics": int,
|
||||||
"live_activity_color": String,
|
"live_activity_color": String,
|
||||||
|
"welcome_message": 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!!!
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ class Ad {
|
|||||||
});
|
});
|
||||||
|
|
||||||
factory Ad.fromJson(Map json) {
|
factory Ad.fromJson(Map json) {
|
||||||
print(json);
|
|
||||||
return Ad(
|
return Ad(
|
||||||
title: json['title'] ?? 'Ad',
|
title: json['title'] ?? 'Ad',
|
||||||
description: json['description'] ?? '',
|
description: json['description'] ?? '',
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
bool _renamedTeachersEnabled;
|
bool _renamedTeachersEnabled;
|
||||||
bool _renamedTeachersItalics;
|
bool _renamedTeachersItalics;
|
||||||
Color _liveActivityColor;
|
Color _liveActivityColor;
|
||||||
|
String _welcomeMessage;
|
||||||
|
|
||||||
SettingsProvider({
|
SettingsProvider({
|
||||||
DatabaseProvider? database,
|
DatabaseProvider? database,
|
||||||
@@ -120,6 +121,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
required bool renameTeachersEnabled,
|
required bool renameTeachersEnabled,
|
||||||
required bool renameTeachersItalics,
|
required bool renameTeachersItalics,
|
||||||
required Color liveActivityColor,
|
required Color liveActivityColor,
|
||||||
|
required String welcomeMessage,
|
||||||
}) : _database = database,
|
}) : _database = database,
|
||||||
_language = language,
|
_language = language,
|
||||||
_startPage = startPage,
|
_startPage = startPage,
|
||||||
@@ -161,7 +163,8 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
_renamedSubjectsItalics = renameSubjectsItalics,
|
_renamedSubjectsItalics = renameSubjectsItalics,
|
||||||
_renamedTeachersEnabled = renameTeachersEnabled,
|
_renamedTeachersEnabled = renameTeachersEnabled,
|
||||||
_renamedTeachersItalics = renameTeachersItalics,
|
_renamedTeachersItalics = renameTeachersItalics,
|
||||||
_liveActivityColor = liveActivityColor;
|
_liveActivityColor = liveActivityColor,
|
||||||
|
_welcomeMessage = welcomeMessage;
|
||||||
|
|
||||||
factory SettingsProvider.fromMap(Map map,
|
factory SettingsProvider.fromMap(Map map,
|
||||||
{required DatabaseProvider database}) {
|
{required DatabaseProvider database}) {
|
||||||
@@ -223,6 +226,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
renameTeachersEnabled: map["renamed_teachers_enabled"] == 1,
|
renameTeachersEnabled: map["renamed_teachers_enabled"] == 1,
|
||||||
renameTeachersItalics: map["renamed_teachers_italics"] == 1,
|
renameTeachersItalics: map["renamed_teachers_italics"] == 1,
|
||||||
liveActivityColor: Color(map["live_activity_color"]),
|
liveActivityColor: Color(map["live_activity_color"]),
|
||||||
|
welcomeMessage: map["welcome_message"],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,6 +276,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
"renamed_teachers_enabled": _renamedTeachersEnabled ? 1 : 0,
|
"renamed_teachers_enabled": _renamedTeachersEnabled ? 1 : 0,
|
||||||
"renamed_teachers_italics": _renamedTeachersItalics ? 1 : 0,
|
"renamed_teachers_italics": _renamedTeachersItalics ? 1 : 0,
|
||||||
"live_activity_color": _liveActivityColor.value,
|
"live_activity_color": _liveActivityColor.value,
|
||||||
|
"welcome_message": _welcomeMessage,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,6 +330,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
renameTeachersEnabled: false,
|
renameTeachersEnabled: false,
|
||||||
renameTeachersItalics: false,
|
renameTeachersItalics: false,
|
||||||
liveActivityColor: const Color(0xFF676767),
|
liveActivityColor: const Color(0xFF676767),
|
||||||
|
welcomeMessage: '',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,6 +379,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
bool get renamedTeachersEnabled => _renamedTeachersEnabled;
|
bool get renamedTeachersEnabled => _renamedTeachersEnabled;
|
||||||
bool get renamedTeachersItalics => _renamedTeachersItalics;
|
bool get renamedTeachersItalics => _renamedTeachersItalics;
|
||||||
Color get liveActivityColor => _liveActivityColor;
|
Color get liveActivityColor => _liveActivityColor;
|
||||||
|
String get welcomeMessage => _welcomeMessage;
|
||||||
|
|
||||||
Future<void> update({
|
Future<void> update({
|
||||||
bool store = true,
|
bool store = true,
|
||||||
@@ -417,6 +424,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
bool? renamedTeachersEnabled,
|
bool? renamedTeachersEnabled,
|
||||||
bool? renamedTeachersItalics,
|
bool? renamedTeachersItalics,
|
||||||
Color? liveActivityColor,
|
Color? liveActivityColor,
|
||||||
|
String? welcomeMessage,
|
||||||
}) 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;
|
||||||
@@ -535,6 +543,9 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
if (liveActivityColor != null && liveActivityColor != _liveActivityColor) {
|
if (liveActivityColor != null && liveActivityColor != _liveActivityColor) {
|
||||||
_liveActivityColor = liveActivityColor;
|
_liveActivityColor = liveActivityColor;
|
||||||
}
|
}
|
||||||
|
if (welcomeMessage != null && welcomeMessage != _welcomeMessage) {
|
||||||
|
_welcomeMessage = welcomeMessage;
|
||||||
|
}
|
||||||
if (store) await _database?.store.storeSettings(this);
|
if (store) await _database?.store.storeSettings(this);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ class SharedTheme {
|
|||||||
Color backgroundColor;
|
Color backgroundColor;
|
||||||
Color panelsColor;
|
Color panelsColor;
|
||||||
Color accentColor;
|
Color accentColor;
|
||||||
|
SharedGradeColors gradeColors;
|
||||||
|
|
||||||
SharedTheme({
|
SharedTheme({
|
||||||
required this.json,
|
required this.json,
|
||||||
@@ -17,9 +18,10 @@ class SharedTheme {
|
|||||||
required this.backgroundColor,
|
required this.backgroundColor,
|
||||||
required this.panelsColor,
|
required this.panelsColor,
|
||||||
required this.accentColor,
|
required this.accentColor,
|
||||||
|
required this.gradeColors,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory SharedTheme.fromJson(Map json) {
|
factory SharedTheme.fromJson(Map json, SharedGradeColors gradeColors) {
|
||||||
return SharedTheme(
|
return SharedTheme(
|
||||||
json: json,
|
json: json,
|
||||||
id: json['public_id'],
|
id: json['public_id'],
|
||||||
@@ -28,6 +30,45 @@ class SharedTheme {
|
|||||||
backgroundColor: Color(json['background_color']),
|
backgroundColor: Color(json['background_color']),
|
||||||
panelsColor: Color(json['panels_color']),
|
panelsColor: Color(json['panels_color']),
|
||||||
accentColor: Color(json['accent_color']),
|
accentColor: Color(json['accent_color']),
|
||||||
|
gradeColors: gradeColors,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SharedGradeColors {
|
||||||
|
Map json;
|
||||||
|
String id;
|
||||||
|
bool isPublic;
|
||||||
|
String nickname;
|
||||||
|
Color fiveColor;
|
||||||
|
Color fourColor;
|
||||||
|
Color threeColor;
|
||||||
|
Color twoColor;
|
||||||
|
Color oneColor;
|
||||||
|
|
||||||
|
SharedGradeColors({
|
||||||
|
required this.json,
|
||||||
|
required this.id,
|
||||||
|
this.isPublic = false,
|
||||||
|
this.nickname = 'Anonymous',
|
||||||
|
required this.fiveColor,
|
||||||
|
required this.fourColor,
|
||||||
|
required this.threeColor,
|
||||||
|
required this.twoColor,
|
||||||
|
required this.oneColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory SharedGradeColors.fromJson(Map json) {
|
||||||
|
return SharedGradeColors(
|
||||||
|
json: json,
|
||||||
|
id: json['public_id'],
|
||||||
|
isPublic: json['is_public'] ?? false,
|
||||||
|
nickname: json['nickname'] ?? 'Anonymous',
|
||||||
|
fiveColor: Color(json['five_color']),
|
||||||
|
fourColor: Color(json['four_color']),
|
||||||
|
threeColor: Color(json['three_color']),
|
||||||
|
twoColor: Color(json['two_color']),
|
||||||
|
oneColor: Color(json['one_color']),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/school.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/student.dart';
|
import 'package:filcnaplo_kreta_api/models/student.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
@@ -43,7 +44,16 @@ class User {
|
|||||||
username: map["username"],
|
username: map["username"],
|
||||||
password: map["password"],
|
password: map["password"],
|
||||||
name: map["name"].trim(),
|
name: map["name"].trim(),
|
||||||
student: Student.fromJson(jsonDecode(map["student"])),
|
student: map["student"] != 'null'
|
||||||
|
? Student.fromJson(jsonDecode(map["student"]))
|
||||||
|
: Student(
|
||||||
|
id: const Uuid().v4(),
|
||||||
|
name: 'Ismeretlen Diák',
|
||||||
|
school: School(instituteCode: '', name: '', city: ''),
|
||||||
|
birth: DateTime.now(),
|
||||||
|
yearId: '1',
|
||||||
|
parents: [],
|
||||||
|
),
|
||||||
role: Role.values[map["role"] ?? 0],
|
role: Role.values[map["role"] ?? 0],
|
||||||
nickname: map["nickname"] ?? "",
|
nickname: map["nickname"] ?? "",
|
||||||
picture: map["picture"] ?? "",
|
picture: map["picture"] ?? "",
|
||||||
@@ -93,4 +103,13 @@ class User {
|
|||||||
"refresh_user_data": "false",
|
"refresh_user_data": "false",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Map<String, Object?> logoutBody({
|
||||||
|
required String refreshToken,
|
||||||
|
}) {
|
||||||
|
return {
|
||||||
|
"refresh_token": refreshToken,
|
||||||
|
"client_id": KretaAPI.clientId,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ Future<List<DateWidget>> getFilterWidgets(FilterType activeData,
|
|||||||
gradeProvider.grades, gradeProvider.lastSeenDate);
|
gradeProvider.grades, gradeProvider.lastSeenDate);
|
||||||
if (settingsProvider.gradeOpeningFun) {
|
if (settingsProvider.gradeOpeningFun) {
|
||||||
items.addAll(
|
items.addAll(
|
||||||
|
// ignore: use_build_context_synchronously
|
||||||
await getFilterWidgets(FilterType.newGrades, context: context));
|
await getFilterWidgets(FilterType.newGrades, context: context));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -40,11 +40,11 @@ static void my_application_activate(GApplication* application) {
|
|||||||
if (use_header_bar) {
|
if (use_header_bar) {
|
||||||
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
|
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
|
||||||
gtk_widget_show(GTK_WIDGET(header_bar));
|
gtk_widget_show(GTK_WIDGET(header_bar));
|
||||||
gtk_header_bar_set_title(header_bar, "Filc Napló");
|
gtk_header_bar_set_title(header_bar, "reFilc");
|
||||||
gtk_header_bar_set_show_close_button(header_bar, TRUE);
|
gtk_header_bar_set_show_close_button(header_bar, TRUE);
|
||||||
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
|
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
|
||||||
} else {
|
} else {
|
||||||
gtk_window_set_title(window, "Filc Napló");
|
gtk_window_set_title(window, "reFilc");
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_window_set_default_size(window, 1280, 720);
|
gtk_window_set_default_size(window, 1280, 720);
|
||||||
|
|||||||
@@ -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.3+223
|
version: 4.3.0+226
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.17.0 <3.0.0"
|
sdk: ">=2.17.0 <3.0.0"
|
||||||
@@ -44,7 +44,7 @@ dependencies:
|
|||||||
quick_actions: ^1.0.1
|
quick_actions: ^1.0.1
|
||||||
animated_list_plus: ^0.5.0
|
animated_list_plus: ^0.5.0
|
||||||
dynamic_color: ^1.2.2
|
dynamic_color: ^1.2.2
|
||||||
material_color_utilities: ^0.2.0
|
material_color_utilities: ^0.5.0
|
||||||
crypto: ^3.0.2
|
crypto: ^3.0.2
|
||||||
elegant_notification: ^1.6.1
|
elegant_notification: ^1.6.1
|
||||||
flutter_feather_icons: ^2.0.0+1
|
flutter_feather_icons: ^2.0.0+1
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import 'package:filcnaplo/api/client.dart';
|
|||||||
import 'package:filcnaplo/api/login.dart';
|
import 'package:filcnaplo/api/login.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/screens/login/login_button.dart';
|
import 'package:filcnaplo_mobile_ui/screens/login/login_button.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/screens/login/login_input.dart';
|
import 'package:filcnaplo_mobile_ui/screens/login/login_input.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/screens/login/school_input/school_input.dart';
|
// import 'package:filcnaplo_desktop_ui/screens/login/school_input/school_input.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_acrylic/flutter_acrylic.dart';
|
import 'package:flutter_acrylic/flutter_acrylic.dart';
|
||||||
@@ -15,11 +15,11 @@ import 'login_screen.i18n.dart';
|
|||||||
|
|
||||||
const LinearGradient _backgroundGradient = LinearGradient(
|
const LinearGradient _backgroundGradient = LinearGradient(
|
||||||
colors: [
|
colors: [
|
||||||
Color.fromARGB(255, 0, 0, 0),
|
Color.fromARGB(255, 61, 122, 244),
|
||||||
Color.fromARGB(255, 23, 77, 185),
|
Color.fromARGB(255, 23, 77, 185),
|
||||||
Color.fromARGB(255, 7, 42, 112),
|
Color.fromARGB(255, 7, 42, 112),
|
||||||
],
|
],
|
||||||
begin: Alignment(-0.8, -2),
|
begin: Alignment(-0.8, -2.0),
|
||||||
end: Alignment(0.8, 1.0),
|
end: Alignment(0.8, 1.0),
|
||||||
stops: [-1.0, 0.0, 1.0],
|
stops: [-1.0, 0.0, 1.0],
|
||||||
);
|
);
|
||||||
@@ -36,8 +36,8 @@ class LoginScreen extends StatefulWidget {
|
|||||||
class _LoginScreenState extends State<LoginScreen> {
|
class _LoginScreenState extends State<LoginScreen> {
|
||||||
final usernameController = TextEditingController();
|
final usernameController = TextEditingController();
|
||||||
final passwordController = TextEditingController();
|
final passwordController = TextEditingController();
|
||||||
final schoolController = SchoolInputController();
|
// final schoolController = SchoolInputController();
|
||||||
final _scrollController = ScrollController();
|
// final _scrollController = ScrollController();
|
||||||
|
|
||||||
LoginState _loginState = LoginState.normal;
|
LoginState _loginState = LoginState.normal;
|
||||||
bool showBack = false;
|
bool showBack = false;
|
||||||
@@ -57,9 +57,9 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
|
|
||||||
FilcAPI.getSchools().then((schools) {
|
FilcAPI.getSchools().then((schools) {
|
||||||
if (schools != null) {
|
if (schools != null) {
|
||||||
schoolController.update(() {
|
// schoolController.update(() {
|
||||||
schoolController.schools = schools;
|
// schoolController.schools = schools;
|
||||||
});
|
// });
|
||||||
} else {
|
} else {
|
||||||
ElegantNotification.error(
|
ElegantNotification.error(
|
||||||
background: Colors.white,
|
background: Colors.white,
|
||||||
@@ -90,7 +90,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Container(
|
body: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
gradient: _backgroundGradient,
|
gradient: _backgroundGradient,
|
||||||
),
|
),
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
@@ -238,10 +238,10 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SchoolInput(
|
// SchoolInput(
|
||||||
scroll: _scrollController,
|
// scroll: _scrollController,
|
||||||
controller: schoolController,
|
// controller: schoolController,
|
||||||
),
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -320,8 +320,10 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
String password = passwordController.text;
|
String password = passwordController.text;
|
||||||
|
|
||||||
if (username == "" ||
|
if (username == "" ||
|
||||||
password == "" ||
|
password ==
|
||||||
schoolController.selectedSchool == null) {
|
"" /*||
|
||||||
|
schoolController.selectedSchool == null*/
|
||||||
|
) {
|
||||||
return setState(() => _loginState = LoginState.missingFields);
|
return setState(() => _loginState = LoginState.missingFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,7 +332,8 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
loginAPI(
|
loginAPI(
|
||||||
username: username,
|
username: username,
|
||||||
password: password,
|
password: password,
|
||||||
instituteCode: schoolController.selectedSchool!.instituteCode,
|
instituteCode: 'shit',
|
||||||
|
// instituteCode: schoolController.selectedSchool!.instituteCode,
|
||||||
context: context,
|
context: context,
|
||||||
onLogin: (user) {
|
onLogin: (user) {
|
||||||
ElegantNotification.success(
|
ElegantNotification.success(
|
||||||
|
|||||||
@@ -63,8 +63,12 @@ class NavigationScreenState extends State<NavigationScreen>
|
|||||||
await Window.initialize();
|
await Window.initialize();
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
// Transparent sidebar
|
// Transparent sidebar
|
||||||
|
if (Platform.isLinux) return;
|
||||||
|
|
||||||
await Window.setEffect(
|
await Window.setEffect(
|
||||||
effect: WindowEffect.acrylic,
|
effect: Platform.isLinux
|
||||||
|
? WindowEffect.transparent
|
||||||
|
: WindowEffect.acrylic,
|
||||||
color: Platform.isMacOS
|
color: Platform.isMacOS
|
||||||
? Colors.transparent
|
? Colors.transparent
|
||||||
: const Color.fromARGB(27, 27, 27, 27));
|
: const Color.fromARGB(27, 27, 27, 27));
|
||||||
|
|||||||
@@ -176,13 +176,16 @@ class _SidebarState extends State<Sidebar> {
|
|||||||
String? userId = user.id;
|
String? userId = user.id;
|
||||||
if (userId == null) return;
|
if (userId == null) return;
|
||||||
|
|
||||||
// Delete User
|
// revoke refresh token
|
||||||
|
await Provider.of<KretaClient>(context, listen: false).logout();
|
||||||
|
|
||||||
|
// delete user from app
|
||||||
user.removeUser(userId);
|
user.removeUser(userId);
|
||||||
await Provider.of<DatabaseProvider>(context, listen: false)
|
await Provider.of<DatabaseProvider>(context, listen: false)
|
||||||
.store
|
.store
|
||||||
.removeUser(userId);
|
.removeUser(userId);
|
||||||
|
|
||||||
// If no other Users left, go back to LoginScreen
|
// if no other users left, go back to login screen
|
||||||
if (user.getUsers().isNotEmpty) {
|
if (user.getUsers().isNotEmpty) {
|
||||||
user.setUser(user.getUsers().first.id);
|
user.setUser(user.getUsers().first.id);
|
||||||
restore().then((_) => user.setUser(user.getUsers().first.id));
|
restore().then((_) => user.setUser(user.getUsers().first.id));
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ extension SettingsLocalization on String {
|
|||||||
{
|
{
|
||||||
"en_en": {
|
"en_en": {
|
||||||
"personal_details": "Personal Details",
|
"personal_details": "Personal Details",
|
||||||
"open_dkt": "Open DKT",
|
"open_dkt": "Open DCS",
|
||||||
"edit_nickname": "Edit Nickname",
|
"edit_nickname": "Edit Nickname",
|
||||||
"edit_profile_picture": "Edit Profile Picture",
|
"edit_profile_picture": "Edit Profile Picture",
|
||||||
"remove_profile_picture": "Remove Profile Picture",
|
"remove_profile_picture": "Remove Profile Picture",
|
||||||
@@ -39,7 +39,8 @@ extension SettingsLocalization on String {
|
|||||||
"done": "Done",
|
"done": "Done",
|
||||||
"reset": "Reset",
|
"reset": "Reset",
|
||||||
"open": "Open",
|
"open": "Open",
|
||||||
"data_collected": "Data collected: Platform (eg. Android), App version (eg. 3.0.0), Unique Install Identifier",
|
"data_collected":
|
||||||
|
"Data collected: Platform (eg. Android), App version (eg. 3.0.0), Unique Install Identifier",
|
||||||
"Analytics": "Analytics",
|
"Analytics": "Analytics",
|
||||||
"Anonymous Usage Analytics": "Anonymous Usage Analytics",
|
"Anonymous Usage Analytics": "Anonymous Usage Analytics",
|
||||||
"graph_class_avg": "Class average on graph",
|
"graph_class_avg": "Class average on graph",
|
||||||
@@ -98,7 +99,8 @@ extension SettingsLocalization on String {
|
|||||||
"done": "Kész",
|
"done": "Kész",
|
||||||
"reset": "Visszaállítás",
|
"reset": "Visszaállítás",
|
||||||
"open": "Megnyitás",
|
"open": "Megnyitás",
|
||||||
"data_collected": "Gyűjtött adat: Platform (pl. Android), App verzió (pl. 3.0.0), Egyedi telepítési azonosító",
|
"data_collected":
|
||||||
|
"Gyűjtött adat: Platform (pl. Android), App verzió (pl. 3.0.0), Egyedi telepítési azonosító",
|
||||||
"Analytics": "Analitika",
|
"Analytics": "Analitika",
|
||||||
"Anonymous Usage Analytics": "Névtelen használati analitika",
|
"Anonymous Usage Analytics": "Névtelen használati analitika",
|
||||||
"graph_class_avg": "Osztályátlag a grafikonon",
|
"graph_class_avg": "Osztályátlag a grafikonon",
|
||||||
@@ -123,7 +125,7 @@ extension SettingsLocalization on String {
|
|||||||
},
|
},
|
||||||
"de_de": {
|
"de_de": {
|
||||||
"personal_details": "Persönliche Angaben",
|
"personal_details": "Persönliche Angaben",
|
||||||
"open_dkt": "Öffnen DKT",
|
"open_dkt": "Öffnen RDZ",
|
||||||
"edit_nickname": "Spitznamen bearbeiten",
|
"edit_nickname": "Spitznamen bearbeiten",
|
||||||
"edit_profile_picture": "Profilbild bearbeiten",
|
"edit_profile_picture": "Profilbild bearbeiten",
|
||||||
"remove_profile_picture": "Profilbild entfernen",
|
"remove_profile_picture": "Profilbild entfernen",
|
||||||
@@ -157,7 +159,8 @@ extension SettingsLocalization on String {
|
|||||||
"done": "Fertig",
|
"done": "Fertig",
|
||||||
"reset": "Zurücksetzen",
|
"reset": "Zurücksetzen",
|
||||||
"open": "Öffnen",
|
"open": "Öffnen",
|
||||||
"data_collected": "Erhobene Daten: Plattform (z.B. Android), App version (z.B. 3.0.0), Eindeutige Installationskennung",
|
"data_collected":
|
||||||
|
"Erhobene Daten: Plattform (z.B. Android), App version (z.B. 3.0.0), Eindeutige Installationskennung",
|
||||||
"Analytics": "Analytik",
|
"Analytics": "Analytik",
|
||||||
"Anonymous Usage Analytics": "Anonyme Nutzungsanalyse",
|
"Anonymous Usage Analytics": "Anonyme Nutzungsanalyse",
|
||||||
"graph_class_avg": "Klassendurchschnitt in der Grafik",
|
"graph_class_avg": "Klassendurchschnitt in der Grafik",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'package:intl/intl.dart';
|
|||||||
class KretaAPI {
|
class KretaAPI {
|
||||||
// IDP API
|
// IDP API
|
||||||
static const login = BaseKreta.kretaIdp + KretaApiEndpoints.token;
|
static const login = BaseKreta.kretaIdp + KretaApiEndpoints.token;
|
||||||
|
static const logout = BaseKreta.kretaIdp + KretaApiEndpoints.revoke;
|
||||||
static const nonce = BaseKreta.kretaIdp + KretaApiEndpoints.nonce;
|
static const nonce = BaseKreta.kretaIdp + KretaApiEndpoints.nonce;
|
||||||
static const clientId = "kreta-ellenorzo-mobile-android";
|
static const clientId = "kreta-ellenorzo-mobile-android";
|
||||||
|
|
||||||
@@ -86,6 +87,7 @@ class BaseKreta {
|
|||||||
|
|
||||||
class KretaApiEndpoints {
|
class KretaApiEndpoints {
|
||||||
static const token = "/connect/token";
|
static const token = "/connect/token";
|
||||||
|
static const revoke = "/connect/revocation";
|
||||||
static const nonce = "/nonce";
|
static const nonce = "/nonce";
|
||||||
static const notes = "/ellenorzo/V3/Sajat/Feljegyzesek";
|
static const notes = "/ellenorzo/V3/Sajat/Feljegyzesek";
|
||||||
static const events = "/ellenorzo/V3/Sajat/FaliujsagElemek";
|
static const events = "/ellenorzo/V3/Sajat/FaliujsagElemek";
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ class KretaClient {
|
|||||||
late final UserProvider _user;
|
late final UserProvider _user;
|
||||||
late final StatusProvider _status;
|
late final StatusProvider _status;
|
||||||
|
|
||||||
|
bool _loginRefreshing = false;
|
||||||
|
|
||||||
KretaClient({
|
KretaClient({
|
||||||
this.accessToken,
|
this.accessToken,
|
||||||
required SettingsProvider settings,
|
required SettingsProvider settings,
|
||||||
@@ -89,6 +91,9 @@ class KretaClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (res == null) throw "Login error";
|
if (res == null) throw "Login error";
|
||||||
|
if (res.body == 'invalid_grant' || res.body.replaceAll(' ', '') == '') {
|
||||||
|
throw "Auth error";
|
||||||
|
}
|
||||||
|
|
||||||
if (json) {
|
if (json) {
|
||||||
return jsonDecode(res.body);
|
return jsonDecode(res.body);
|
||||||
@@ -161,6 +166,9 @@ class KretaClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> refreshLogin() async {
|
Future<void> refreshLogin() async {
|
||||||
|
if (_loginRefreshing) return;
|
||||||
|
_loginRefreshing = true;
|
||||||
|
|
||||||
User? loginUser = _user.user;
|
User? loginUser = _user.user;
|
||||||
if (loginUser == null) return;
|
if (loginUser == null) return;
|
||||||
|
|
||||||
@@ -179,13 +187,15 @@ class KretaClient {
|
|||||||
print("DEBUG: refreshLogin: ${loginUser.id} ${loginUser.name}");
|
print("DEBUG: refreshLogin: ${loginUser.id} ${loginUser.name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
Map? loginRes = await postAPI(KretaAPI.login,
|
Map? loginRes = await postAPI(
|
||||||
|
KretaAPI.login,
|
||||||
headers: headers,
|
headers: headers,
|
||||||
body: User.loginBody(
|
body: User.loginBody(
|
||||||
username: loginUser.username,
|
username: loginUser.username,
|
||||||
password: loginUser.password,
|
password: loginUser.password,
|
||||||
instituteCode: loginUser.instituteCode,
|
instituteCode: loginUser.instituteCode,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
|
|
||||||
if (loginRes != null) {
|
if (loginRes != null) {
|
||||||
if (loginRes.containsKey("access_token")) {
|
if (loginRes.containsKey("access_token")) {
|
||||||
@@ -212,5 +222,25 @@ class KretaClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_loginRefreshing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> logout() async {
|
||||||
|
User? loginUser = _user.user;
|
||||||
|
if (loginUser == null) return;
|
||||||
|
|
||||||
|
Map<String, String> headers = {
|
||||||
|
"content-type": "application/x-www-form-urlencoded",
|
||||||
|
};
|
||||||
|
|
||||||
|
await postAPI(
|
||||||
|
KretaAPI.logout,
|
||||||
|
headers: headers,
|
||||||
|
body: User.logoutBody(
|
||||||
|
refreshToken: refreshToken!,
|
||||||
|
),
|
||||||
|
json: false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:filcnaplo/models/user.dart';
|
|||||||
import 'package:filcnaplo_kreta_api/client/api.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/homework.dart';
|
import 'package:filcnaplo_kreta_api/models/homework.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
@@ -83,7 +84,10 @@ class HomeworkProvider with ChangeNotifier {
|
|||||||
// error fetcing homework (unknown error)
|
// error fetcing homework (unknown error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (homeworkJson == null) throw "Cannot fetch Homework for User ${user.id}";
|
if (homeworkJson == null) {
|
||||||
|
if (kDebugMode) print("Cannot fetch Homework for User ${user.id}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
List<Homework> homework = [];
|
List<Homework> homework = [];
|
||||||
await Future.forEach(homeworkJson.cast<Map>(), (Map hw) async {
|
await Future.forEach(homeworkJson.cast<Map>(), (Map hw) async {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ 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/lesson.dart';
|
import 'package:filcnaplo_kreta_api/models/lesson.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/week.dart';
|
import 'package:filcnaplo_kreta_api/models/week.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
class TimetableProvider with ChangeNotifier {
|
class TimetableProvider with ChangeNotifier {
|
||||||
Map<Week, List<Lesson>> lessons = {};
|
Map<Week, List<Lesson>> lessons = {};
|
||||||
@@ -67,16 +67,22 @@ class TimetableProvider with ChangeNotifier {
|
|||||||
String iss = user.instituteCode;
|
String iss = user.instituteCode;
|
||||||
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}";
|
|
||||||
List<Lesson> lessonsList = lessonsJson.map((e) => Lesson.fromJson(e)).toList();
|
|
||||||
|
|
||||||
if (lessons.isEmpty && lessons.isEmpty) return;
|
if (lessonsJson == null) {
|
||||||
|
if (kDebugMode) print('Cannot fetch Lessons for User ${user.id}');
|
||||||
|
|
||||||
|
return;
|
||||||
|
// throw "Cannot fetch Lessons for User ${user.id}";
|
||||||
|
} else {
|
||||||
|
List<Lesson> lessonsList =
|
||||||
|
lessonsJson.map((e) => Lesson.fromJson(e)).toList();
|
||||||
|
|
||||||
lessons[week] = lessonsList;
|
lessons[week] = lessonsList;
|
||||||
|
|
||||||
await store();
|
await store();
|
||||||
await convertBySettings();
|
await convertBySettings();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Stores Lessons in the database
|
// Stores Lessons in the database
|
||||||
Future<void> store() async {
|
Future<void> store() async {
|
||||||
|
|||||||
@@ -13,9 +13,6 @@ class AdTile extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
print('geic');
|
|
||||||
print(ad);
|
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
|
padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
child: PanelButton(
|
child: PanelButton(
|
||||||
@@ -38,12 +35,15 @@ class AdTile extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
leading: ad.logoUrl != null
|
leading: ad.logoUrl != null
|
||||||
? Image.network(
|
? ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(50.0),
|
||||||
|
child: Image.network(
|
||||||
ad.logoUrl.toString(),
|
ad.logoUrl.toString(),
|
||||||
errorBuilder: (context, error, stackTrace) {
|
errorBuilder: (context, error, stackTrace) {
|
||||||
ad.logoUrl = null;
|
ad.logoUrl = null;
|
||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
},
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
trailing: const Icon(FeatherIcons.externalLink),
|
trailing: const Icon(FeatherIcons.externalLink),
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ class MissedExamView extends StatelessWidget {
|
|||||||
|
|
||||||
final List<Lesson> missedExams;
|
final List<Lesson> missedExams;
|
||||||
|
|
||||||
static show(List<Lesson> missedExams, {required BuildContext context}) => showRoundedModalBottomSheet(context, child: MissedExamView(missedExams));
|
static show(List<Lesson> missedExams, {required BuildContext context}) =>
|
||||||
|
showRoundedModalBottomSheet(context, child: MissedExamView(missedExams));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -25,7 +26,8 @@ class MissedExamView extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class MissedExamViewTile extends StatelessWidget {
|
class MissedExamViewTile extends StatelessWidget {
|
||||||
const MissedExamViewTile(this.lesson, {Key? key, this.padding}) : super(key: key);
|
const MissedExamViewTile(this.lesson, {Key? key, this.padding})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
final EdgeInsetsGeometry? padding;
|
final EdgeInsetsGeometry? padding;
|
||||||
final Lesson lesson;
|
final Lesson lesson;
|
||||||
@@ -33,23 +35,36 @@ class MissedExamViewTile extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
|
SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
|
||||||
|
|
||||||
|
String? teacherName = lesson.teacher.isRenamed
|
||||||
|
? lesson.teacher.renamedTo
|
||||||
|
: lesson.teacher.name;
|
||||||
|
|
||||||
return Material(
|
return Material(
|
||||||
type: MaterialType.transparency,
|
type: MaterialType.transparency,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
|
padding: padding ??
|
||||||
|
const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
|
shape:
|
||||||
|
RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
|
||||||
leading: Icon(
|
leading: Icon(
|
||||||
SubjectIcon.resolveVariant(subject: lesson.subject, context: context),
|
SubjectIcon.resolveVariant(
|
||||||
|
subject: lesson.subject, context: context),
|
||||||
color: AppColors.of(context).text.withOpacity(.8),
|
color: AppColors.of(context).text.withOpacity(.8),
|
||||||
size: 32.0,
|
size: 32.0,
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
"${lesson.subject.renamedTo ?? lesson.subject.name.capital()} • ${lesson.date.format(context)}",
|
"${lesson.subject.renamedTo ?? lesson.subject.name.capital()} • ${lesson.date.format(context)}",
|
||||||
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(
|
||||||
"missed_exam_contact".i18n.fill([lesson.teacher]),
|
"missed_exam_contact".i18n.fill([teacherName ?? '']),
|
||||||
style: const TextStyle(fontWeight: FontWeight.w500),
|
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||||
),
|
),
|
||||||
trailing: const Icon(FeatherIcons.arrowRight),
|
trailing: const Icon(FeatherIcons.arrowRight),
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import 'package:provider/provider.dart';
|
|||||||
import 'home_page.i18n.dart';
|
import 'home_page.i18n.dart';
|
||||||
import 'package:filcnaplo/ui/filter/widgets.dart';
|
import 'package:filcnaplo/ui/filter/widgets.dart';
|
||||||
import 'package:filcnaplo/ui/filter/sort.dart';
|
import 'package:filcnaplo/ui/filter/sort.dart';
|
||||||
|
import 'package:i18n_extension/i18n_extension.dart';
|
||||||
|
|
||||||
class HomePage extends StatefulWidget {
|
class HomePage extends StatefulWidget {
|
||||||
const HomePage({Key? key}) : super(key: key);
|
const HomePage({Key? key}) : super(key: key);
|
||||||
@@ -94,6 +95,13 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
|||||||
|
|
||||||
void setGreeting() {
|
void setGreeting() {
|
||||||
DateTime now = DateTime.now();
|
DateTime now = DateTime.now();
|
||||||
|
List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
|
||||||
|
if (!settings.presentationMode) {
|
||||||
|
firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
|
||||||
|
} else {
|
||||||
|
firstName = "János";
|
||||||
|
}
|
||||||
|
|
||||||
if (now.isBefore(DateTime(now.year, DateTime.august, 31)) &&
|
if (now.isBefore(DateTime(now.year, DateTime.august, 31)) &&
|
||||||
now.isAfter(DateTime(now.year, DateTime.june, 14))) {
|
now.isAfter(DateTime(now.year, DateTime.june, 14))) {
|
||||||
greeting = "goodrest";
|
greeting = "goodrest";
|
||||||
@@ -104,16 +112,16 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
|||||||
Future.delayed(const Duration(seconds: 1))
|
Future.delayed(const Duration(seconds: 1))
|
||||||
.then((value) => mounted ? _confettiController?.play() : null);
|
.then((value) => mounted ? _confettiController?.play() : null);
|
||||||
}
|
}
|
||||||
} else if (now.month == user.student?.birth.month &&
|
// } else if (now.month == user.student?.birth.month &&
|
||||||
now.day == user.student?.birth.day) {
|
// now.day == user.student?.birth.day) {
|
||||||
greeting = "happybirthday";
|
// greeting = "happybirthday";
|
||||||
|
|
||||||
if (NavigationScreen.of(context)?.init("confetti") ?? false) {
|
// if (NavigationScreen.of(context)?.init("confetti") ?? false) {
|
||||||
_confettiController =
|
// _confettiController =
|
||||||
ConfettiController(duration: const Duration(seconds: 3));
|
// ConfettiController(duration: const Duration(seconds: 3));
|
||||||
Future.delayed(const Duration(seconds: 1))
|
// Future.delayed(const Duration(seconds: 1))
|
||||||
.then((value) => mounted ? _confettiController?.play() : null);
|
// .then((value) => mounted ? _confettiController?.play() : null);
|
||||||
}
|
// }
|
||||||
} else if (now.isAfter(DateTime(now.year, DateTime.may, 28)) &&
|
} else if (now.isAfter(DateTime(now.year, DateTime.may, 28)) &&
|
||||||
now.isBefore(DateTime(now.year, DateTime.may, 30))) {
|
now.isBefore(DateTime(now.year, DateTime.may, 30))) {
|
||||||
greeting = "refilcopen";
|
greeting = "refilcopen";
|
||||||
@@ -130,6 +138,12 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
|||||||
greeting = "merryxmas";
|
greeting = "merryxmas";
|
||||||
} else if (now.month == DateTime.january && now.day == 1) {
|
} else if (now.month == DateTime.january && now.day == 1) {
|
||||||
greeting = "happynewyear";
|
greeting = "happynewyear";
|
||||||
|
} else if (settings.welcomeMessage.replaceAll(' ', '') != '') {
|
||||||
|
greeting = settings.welcomeMessage;
|
||||||
|
greeting = localizeFill(
|
||||||
|
settings.welcomeMessage,
|
||||||
|
[firstName],
|
||||||
|
);
|
||||||
} else if (now.hour >= 18) {
|
} else if (now.hour >= 18) {
|
||||||
greeting = "goodevening";
|
greeting = "goodevening";
|
||||||
} else if (now.hour >= 10) {
|
} else if (now.hour >= 10) {
|
||||||
@@ -155,13 +169,6 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
|||||||
|
|
||||||
setGreeting();
|
setGreeting();
|
||||||
|
|
||||||
List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
|
|
||||||
if (!settings.presentationMode) {
|
|
||||||
firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
|
|
||||||
} else {
|
|
||||||
firstName = "János";
|
|
||||||
}
|
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Stack(
|
body: Stack(
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ extension Localization on String {
|
|||||||
"welcome": "Welcome, %s!",
|
"welcome": "Welcome, %s!",
|
||||||
"missing_fields": "Missing Fields!",
|
"missing_fields": "Missing Fields!",
|
||||||
"invalid_grant":
|
"invalid_grant":
|
||||||
"Invalid Username/Password! (Try adding spaces after Username)",
|
// "Invalid Username/Password! (Try adding spaces after Username)",
|
||||||
|
"Invalid Username/Password!",
|
||||||
"error": "Failed to log in.",
|
"error": "Failed to log in.",
|
||||||
"schools_error": "Failed to get schools."
|
"schools_error": "Failed to get schools."
|
||||||
},
|
},
|
||||||
@@ -27,7 +28,8 @@ extension Localization on String {
|
|||||||
"welcome": "Üdv, %s!",
|
"welcome": "Üdv, %s!",
|
||||||
"missing_fields": "Hiányzó adatok!",
|
"missing_fields": "Hiányzó adatok!",
|
||||||
"invalid_grant":
|
"invalid_grant":
|
||||||
"Helytelen Felhasználónév/Jelszó! (Próbálj szóközöket írni a Felhasználónév után)",
|
// "Helytelen Felhasználónév/Jelszó! (Próbálj szóközöket írni a Felhasználónév után)",
|
||||||
|
"Helytelen Felhasználónév/Jelszó!",
|
||||||
"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."
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ class _StatusBarState extends State<StatusBar> {
|
|||||||
height: currentStatus != null ? 28.0 : 0,
|
height: currentStatus != null ? 28.0 : 0,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: backgroundColor,
|
color: backgroundColor,
|
||||||
boxShadow: [BoxShadow(color: Theme.of(context).shadowColor, blurRadius: 8.0)],
|
boxShadow: [
|
||||||
|
BoxShadow(color: Theme.of(context).shadowColor, blurRadius: 8.0)
|
||||||
|
],
|
||||||
borderRadius: BorderRadius.circular(45.0),
|
borderRadius: BorderRadius.circular(45.0),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -53,9 +55,12 @@ class _StatusBarState extends State<StatusBar> {
|
|||||||
height: currentStatus != null ? 28.0 : 0,
|
height: currentStatus != null ? 28.0 : 0,
|
||||||
duration: const Duration(milliseconds: 250),
|
duration: const Duration(milliseconds: 250),
|
||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOut,
|
||||||
width: MediaQuery.of(context).size.width * statusProvider.progress - 16.0,
|
width: MediaQuery.of(context).size.width *
|
||||||
|
statusProvider.progress -
|
||||||
|
16.0,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).colorScheme.secondary.withOpacity(0.8),
|
color:
|
||||||
|
Theme.of(context).colorScheme.secondary.withOpacity(0.8),
|
||||||
borderRadius: BorderRadius.circular(45.0),
|
borderRadius: BorderRadius.circular(45.0),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -82,6 +87,8 @@ class _StatusBarState extends State<StatusBar> {
|
|||||||
return "Syncing data".i18n;
|
return "Syncing data".i18n;
|
||||||
case Status.maintenance:
|
case Status.maintenance:
|
||||||
return "KRETA Maintenance".i18n;
|
return "KRETA Maintenance".i18n;
|
||||||
|
case Status.apiError:
|
||||||
|
return "KRETA API error".i18n;
|
||||||
case Status.network:
|
case Status.network:
|
||||||
return "No connection".i18n;
|
return "No connection".i18n;
|
||||||
default:
|
default:
|
||||||
@@ -93,10 +100,13 @@ class _StatusBarState extends State<StatusBar> {
|
|||||||
switch (status) {
|
switch (status) {
|
||||||
case Status.maintenance:
|
case Status.maintenance:
|
||||||
return AppColors.of(context).red;
|
return AppColors.of(context).red;
|
||||||
|
case Status.apiError:
|
||||||
|
return AppColors.of(context).red;
|
||||||
case Status.network:
|
case Status.network:
|
||||||
case Status.syncing:
|
case Status.syncing:
|
||||||
default:
|
default:
|
||||||
HSLColor color = HSLColor.fromColor(Theme.of(context).scaffoldBackgroundColor);
|
HSLColor color =
|
||||||
|
HSLColor.fromColor(Theme.of(context).scaffoldBackgroundColor);
|
||||||
if (color.lightness >= 0.5) {
|
if (color.lightness >= 0.5) {
|
||||||
color = color.withSaturation(0.3);
|
color = color.withSaturation(0.3);
|
||||||
color = color.withLightness(color.lightness - 0.1);
|
color = color.withLightness(color.lightness - 0.1);
|
||||||
|
|||||||
@@ -6,16 +6,19 @@ extension Localization on String {
|
|||||||
"en_en": {
|
"en_en": {
|
||||||
"Syncing data": "Syncing data",
|
"Syncing data": "Syncing data",
|
||||||
"KRETA Maintenance": "KRETA Maintenance",
|
"KRETA Maintenance": "KRETA Maintenance",
|
||||||
|
"KRETA API error": "KRETA API Error",
|
||||||
"No connection": "No connection",
|
"No connection": "No connection",
|
||||||
},
|
},
|
||||||
"hu_hu": {
|
"hu_hu": {
|
||||||
"Syncing data": "Adatok frissítése",
|
"Syncing data": "Adatok frissítése",
|
||||||
"KRETA Maintenance": "KRÉTA Karbantartás",
|
"KRETA Maintenance": "KRÉTA Karbantartás",
|
||||||
|
"KRETA API error": "KRÉTA API Hiba",
|
||||||
"No connection": "Nincs kapcsolat",
|
"No connection": "Nincs kapcsolat",
|
||||||
},
|
},
|
||||||
"de_de": {
|
"de_de": {
|
||||||
"Syncing data": "Daten aktualisieren",
|
"Syncing data": "Daten aktualisieren",
|
||||||
"KRETA Maintenance": "KRETA Wartung",
|
"KRETA Maintenance": "KRETA Wartung",
|
||||||
|
"KRETA API error": "KRETA API Fehler",
|
||||||
"No connection": "Keine Verbindung",
|
"No connection": "Keine Verbindung",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import 'package:filcnaplo_premium/ui/mobile/settings/profile_pic.dart';
|
|||||||
import 'package:filcnaplo_premium/ui/mobile/settings/icon_pack.dart';
|
import 'package:filcnaplo_premium/ui/mobile/settings/icon_pack.dart';
|
||||||
import 'package:filcnaplo_premium/ui/mobile/settings/modify_subject_names.dart';
|
import 'package:filcnaplo_premium/ui/mobile/settings/modify_subject_names.dart';
|
||||||
import 'package:filcnaplo_premium/ui/mobile/settings/modify_teacher_names.dart';
|
import 'package:filcnaplo_premium/ui/mobile/settings/modify_teacher_names.dart';
|
||||||
|
import 'package:filcnaplo_premium/ui/mobile/settings/welcome_message.dart';
|
||||||
|
|
||||||
class SettingsScreen extends StatefulWidget {
|
class SettingsScreen extends StatefulWidget {
|
||||||
const SettingsScreen({Key? key}) : super(key: key);
|
const SettingsScreen({Key? key}) : super(key: key);
|
||||||
@@ -206,7 +207,7 @@ class _SettingsScreenState extends State<SettingsScreen>
|
|||||||
opacity: 1 - _hideContainersController.value,
|
opacity: 1 - _hideContainersController.value,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 32.0),
|
const SizedBox(height: 45.0),
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
@@ -454,6 +455,7 @@ class _SettingsScreenState extends State<SettingsScreen>
|
|||||||
Material(
|
Material(
|
||||||
type: MaterialType.transparency,
|
type: MaterialType.transparency,
|
||||||
child: MenuNotifications(settings: settings)),
|
child: MenuNotifications(settings: settings)),
|
||||||
|
WelcomeMessagePanelButton(settings, user),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -73,6 +73,9 @@ extension SettingsLocalization on String {
|
|||||||
"devsettings": "Developer Settings",
|
"devsettings": "Developer Settings",
|
||||||
"devmode": "Developer Mode",
|
"devmode": "Developer Mode",
|
||||||
"copy_jwt": "Copy JWT",
|
"copy_jwt": "Copy JWT",
|
||||||
|
"welcome_msg": "Welcome Message",
|
||||||
|
"default": "Default",
|
||||||
|
"edit_welcome_msg": "Edit welcome message",
|
||||||
},
|
},
|
||||||
"hu_hu": {
|
"hu_hu": {
|
||||||
"personal_details": "Személyes információk",
|
"personal_details": "Személyes információk",
|
||||||
@@ -144,6 +147,9 @@ extension SettingsLocalization on String {
|
|||||||
"devsettings": "Fejlesztői Beállítások",
|
"devsettings": "Fejlesztői Beállítások",
|
||||||
"devmode": "Fejlesztői mód",
|
"devmode": "Fejlesztői mód",
|
||||||
"copy_jwt": "JWT másolása",
|
"copy_jwt": "JWT másolása",
|
||||||
|
"welcome_msg": "Üdvözlő üzenet",
|
||||||
|
"default": "Alapértelmezett",
|
||||||
|
"edit_welcome_msg": "Üdvözlő üzenet szerkesztése",
|
||||||
},
|
},
|
||||||
"de_de": {
|
"de_de": {
|
||||||
"personal_details": "Persönliche Angaben",
|
"personal_details": "Persönliche Angaben",
|
||||||
@@ -214,6 +220,9 @@ extension SettingsLocalization on String {
|
|||||||
"devsettings": "Entwickleroptionen",
|
"devsettings": "Entwickleroptionen",
|
||||||
"devmode": "Entwicklermodus",
|
"devmode": "Entwicklermodus",
|
||||||
"copy_jwt": "JWT kopieren",
|
"copy_jwt": "JWT kopieren",
|
||||||
|
"welcome_msg": "Willkommensnachricht",
|
||||||
|
"default": "Standard",
|
||||||
|
"edit_welcome_msg": "Begrüßungsnachricht bearbeiten",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,12 @@ class ShareProvider extends ChangeNotifier {
|
|||||||
// Future<void> shareTheme({required SharedTheme theme}) async {
|
// Future<void> shareTheme({required SharedTheme theme}) async {
|
||||||
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// themes
|
||||||
Future<SharedTheme> shareCurrentTheme(BuildContext context,
|
Future<SharedTheme> shareCurrentTheme(BuildContext context,
|
||||||
{bool isPublic = false, bool shareNick = true}) async {
|
{bool isPublic = false,
|
||||||
|
bool shareNick = true,
|
||||||
|
required SharedGradeColors gradeColors}) async {
|
||||||
final SettingsProvider settings =
|
final SettingsProvider settings =
|
||||||
Provider.of<SettingsProvider>(context, listen: false);
|
Provider.of<SettingsProvider>(context, listen: false);
|
||||||
|
|
||||||
@@ -38,7 +42,7 @@ class ShareProvider extends ChangeNotifier {
|
|||||||
const Color(0xFF3D7BF4).value,
|
const Color(0xFF3D7BF4).value,
|
||||||
};
|
};
|
||||||
|
|
||||||
SharedTheme theme = SharedTheme.fromJson(themeJson);
|
SharedTheme theme = SharedTheme.fromJson(themeJson, gradeColors);
|
||||||
FilcAPI.addSharedTheme(theme);
|
FilcAPI.addSharedTheme(theme);
|
||||||
|
|
||||||
return theme;
|
return theme;
|
||||||
@@ -49,9 +53,54 @@ class ShareProvider extends ChangeNotifier {
|
|||||||
Map? themeJson = await FilcAPI.getSharedTheme(id);
|
Map? themeJson = await FilcAPI.getSharedTheme(id);
|
||||||
|
|
||||||
if (themeJson != null) {
|
if (themeJson != null) {
|
||||||
SharedTheme theme = SharedTheme.fromJson(themeJson);
|
Map? gradeColorsJson =
|
||||||
|
await FilcAPI.getSharedGradeColors(themeJson['grade_colors_id']);
|
||||||
|
|
||||||
|
if (gradeColorsJson != null) {
|
||||||
|
SharedTheme theme = SharedTheme.fromJson(
|
||||||
|
themeJson, SharedGradeColors.fromJson(gradeColorsJson));
|
||||||
return theme;
|
return theme;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// grade colors
|
||||||
|
Future<SharedGradeColors> shareCurrentGradeColors(
|
||||||
|
BuildContext context, {
|
||||||
|
bool isPublic = false,
|
||||||
|
bool shareNick = true,
|
||||||
|
}) async {
|
||||||
|
final SettingsProvider settings =
|
||||||
|
Provider.of<SettingsProvider>(context, listen: false);
|
||||||
|
|
||||||
|
Map gradeColorsJson = {
|
||||||
|
'public_id': const Uuid().v4(),
|
||||||
|
'is_public': isPublic,
|
||||||
|
'nickname': shareNick ? _user.nickname : 'Anonymous',
|
||||||
|
'five_color': settings.gradeColors[4].value,
|
||||||
|
'four_color': settings.gradeColors[3].value,
|
||||||
|
'three_color': settings.gradeColors[2].value,
|
||||||
|
'two_color': settings.gradeColors[1].value,
|
||||||
|
'one_color': settings.gradeColors[0].value,
|
||||||
|
};
|
||||||
|
|
||||||
|
SharedGradeColors gradeColors = SharedGradeColors.fromJson(gradeColorsJson);
|
||||||
|
FilcAPI.addSharedGradeColors(gradeColors);
|
||||||
|
|
||||||
|
return gradeColors;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<SharedGradeColors?> getGradeColorsById(BuildContext context,
|
||||||
|
{required String id}) async {
|
||||||
|
Map? gradeColorsJson = await FilcAPI.getSharedGradeColors(id);
|
||||||
|
|
||||||
|
if (gradeColorsJson != null) {
|
||||||
|
SharedGradeColors gradeColors =
|
||||||
|
SharedGradeColors.fromJson(gradeColorsJson);
|
||||||
|
return gradeColors;
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import 'package:filcnaplo/ui/widgets/message/message_tile.dart';
|
|||||||
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/homework.dart';
|
import 'package:filcnaplo_kreta_api/models/homework.dart';
|
||||||
import 'package:filcnaplo_kreta_api/models/message.dart';
|
import 'package:filcnaplo_kreta_api/models/message.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/action_button.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/common/filter_bar.dart';
|
import 'package:filcnaplo_mobile_ui/common/filter_bar.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
|
import 'package:filcnaplo_mobile_ui/common/panel/panel.dart';
|
||||||
import 'package:filcnaplo_mobile_ui/common/widgets/grade/new_grades.dart';
|
import 'package:filcnaplo_mobile_ui/common/widgets/grade/new_grades.dart';
|
||||||
@@ -268,10 +269,40 @@ class _PremiumCustomAccentColorSettingState
|
|||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
// );
|
// );
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => WillPopScope(
|
||||||
|
onWillPop: () async => false,
|
||||||
|
child: AlertDialog(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(12.0)),
|
||||||
|
title: Text("attention".i18n),
|
||||||
|
content: Text("share_disclaimer".i18n),
|
||||||
|
actions: [
|
||||||
|
ActionButton(
|
||||||
|
label: "understand".i18n,
|
||||||
|
onTap: () async {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
|
||||||
|
SharedGradeColors gradeColors =
|
||||||
|
await shareProvider
|
||||||
|
.shareCurrentGradeColors(context);
|
||||||
SharedTheme theme =
|
SharedTheme theme =
|
||||||
await shareProvider.shareCurrentTheme(context);
|
await shareProvider.shareCurrentTheme(
|
||||||
Share.share(theme.id,
|
context,
|
||||||
subject: 'reFilc Téma / reFilc Theme');
|
gradeColors: gradeColors,
|
||||||
|
);
|
||||||
|
|
||||||
|
Share.share(
|
||||||
|
theme.id,
|
||||||
|
subject: 'share_subj_theme'.i18n,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
FeatherIcons.share2,
|
FeatherIcons.share2,
|
||||||
@@ -781,6 +812,18 @@ class _PremiumCustomAccentColorSettingState
|
|||||||
setTheme(settings.theme, true);
|
setTheme(settings.theme, true);
|
||||||
},
|
},
|
||||||
onThemeIdProvided: (theme) {
|
onThemeIdProvided: (theme) {
|
||||||
|
// changing grade colors
|
||||||
|
List<Color> colors = [
|
||||||
|
theme.gradeColors.oneColor,
|
||||||
|
theme.gradeColors.twoColor,
|
||||||
|
theme.gradeColors.threeColor,
|
||||||
|
theme.gradeColors.fourColor,
|
||||||
|
theme.gradeColors.fiveColor,
|
||||||
|
];
|
||||||
|
settings.update(
|
||||||
|
gradeColors: colors);
|
||||||
|
|
||||||
|
// changing theme
|
||||||
setState(() {
|
setState(() {
|
||||||
updateCustomColor(
|
updateCustomColor(
|
||||||
null,
|
null,
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ extension SettingsLocalization on String {
|
|||||||
"enter_id": "Enter ID",
|
"enter_id": "Enter ID",
|
||||||
"theme_id": "Theme ID...",
|
"theme_id": "Theme ID...",
|
||||||
"theme_not_found": "Theme not found!",
|
"theme_not_found": "Theme not found!",
|
||||||
|
"attention": "Attention!",
|
||||||
|
"share_disclaimer":
|
||||||
|
"By sharing the theme, you agree that the nickname you set and all settings of the theme will be shared publicly.",
|
||||||
|
"understand": "I understand",
|
||||||
},
|
},
|
||||||
"hu_hu": {
|
"hu_hu": {
|
||||||
"theme_prev": "Előnézet",
|
"theme_prev": "Előnézet",
|
||||||
@@ -26,6 +30,10 @@ extension SettingsLocalization on String {
|
|||||||
"enter_id": "ID megadása",
|
"enter_id": "ID megadása",
|
||||||
"theme_id": "Téma azonosító...",
|
"theme_id": "Téma azonosító...",
|
||||||
"theme_not_found": "A téma nem található!",
|
"theme_not_found": "A téma nem található!",
|
||||||
|
"attention": "Figyelem!",
|
||||||
|
"share_disclaimer":
|
||||||
|
"A téma megosztásával elfogadod, hogy az általad beállított becenév és a téma minden beállítása nyilvánosan megosztásra kerüljön.",
|
||||||
|
"understand": "Értem",
|
||||||
},
|
},
|
||||||
"de_de": {
|
"de_de": {
|
||||||
"theme_prev": "Vorschau",
|
"theme_prev": "Vorschau",
|
||||||
@@ -39,6 +47,10 @@ extension SettingsLocalization on String {
|
|||||||
"enter_id": "Geben Sie die ID ein",
|
"enter_id": "Geben Sie die ID ein",
|
||||||
"theme_id": "Themen-ID...",
|
"theme_id": "Themen-ID...",
|
||||||
"theme_not_found": "Thema nicht gefunden!",
|
"theme_not_found": "Thema nicht gefunden!",
|
||||||
|
"attention": "Achtung!",
|
||||||
|
"share_disclaimer":
|
||||||
|
"Durch das Teilen des Themes erklären Sie sich damit einverstanden, dass der von Ihnen festgelegte Spitzname und alle Einstellungen des Themes öffentlich geteilt werden.",
|
||||||
|
"understand": "Ich verstehe",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
140
filcnaplo_premium/lib/ui/mobile/settings/welcome_message.dart
Normal file
140
filcnaplo_premium/lib/ui/mobile/settings/welcome_message.dart
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||||
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/panel/panel_button.dart';
|
||||||
|
import 'package:filcnaplo_premium/models/premium_scopes.dart';
|
||||||
|
import 'package:filcnaplo_premium/providers/premium_provider.dart';
|
||||||
|
import 'package:filcnaplo_premium/ui/mobile/premium/upsell.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/screens/settings/settings_screen.i18n.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:i18n_extension/i18n_extension.dart';
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
|
class WelcomeMessagePanelButton extends StatelessWidget {
|
||||||
|
late SettingsProvider settingsProvider;
|
||||||
|
late UserProvider user;
|
||||||
|
|
||||||
|
WelcomeMessagePanelButton(this.settingsProvider, this.user, {Key? key})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
String finalName = ((user.nickname ?? '') != ''
|
||||||
|
? user.nickname
|
||||||
|
: (user.displayName ?? '') != ''
|
||||||
|
? user.displayName
|
||||||
|
: 'János') ??
|
||||||
|
'János';
|
||||||
|
|
||||||
|
return PanelButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (!Provider.of<PremiumProvider>(context, listen: false)
|
||||||
|
.hasScope(PremiumScopes.all)) {
|
||||||
|
PremiumLockedFeatureUpsell.show(
|
||||||
|
context: context, feature: PremiumFeature.profile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => WelcomeMessageEditor(settingsProvider));
|
||||||
|
},
|
||||||
|
title: Text("welcome_msg".i18n),
|
||||||
|
leading: const Icon(FeatherIcons.smile),
|
||||||
|
trailing: Container(
|
||||||
|
constraints: const BoxConstraints(maxWidth: 100),
|
||||||
|
child: Text(
|
||||||
|
settingsProvider.welcomeMessage.replaceAll(' ', '') != ''
|
||||||
|
? localizeFill(
|
||||||
|
settingsProvider.welcomeMessage,
|
||||||
|
[finalName],
|
||||||
|
)
|
||||||
|
: 'default'.i18n,
|
||||||
|
style: const TextStyle(fontSize: 14.0),
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
softWrap: true,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
|
class WelcomeMessageEditor extends StatefulWidget {
|
||||||
|
late SettingsProvider settingsProvider;
|
||||||
|
|
||||||
|
WelcomeMessageEditor(this.settingsProvider, {Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<WelcomeMessageEditor> createState() => _WelcomeMessageEditorState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _WelcomeMessageEditorState extends State<WelcomeMessageEditor> {
|
||||||
|
final _welcomeMsg = TextEditingController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_welcomeMsg.text =
|
||||||
|
widget.settingsProvider.welcomeMessage.replaceAll('%s', '%name%');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text("edit_welcome_msg".i18n),
|
||||||
|
content: TextField(
|
||||||
|
controller: _welcomeMsg,
|
||||||
|
autofocus: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: const OutlineInputBorder(),
|
||||||
|
label: Text('welcome_msg'.i18n),
|
||||||
|
suffixIcon: IconButton(
|
||||||
|
icon: const Icon(FeatherIcons.x),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_welcomeMsg.text = "";
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
child: Text(
|
||||||
|
"cancel".i18n,
|
||||||
|
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).maybePop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
child: Text(
|
||||||
|
"done".i18n,
|
||||||
|
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
// var trimmed = _welcomeMsg.text.trim();
|
||||||
|
|
||||||
|
// var defLen = trimmed.length;
|
||||||
|
// var replacedLen = trimmed.replaceAll('%s', '').length;
|
||||||
|
|
||||||
|
// if (defLen - 2 > replacedLen) {
|
||||||
|
// print('fuck yourself rn');
|
||||||
|
// }
|
||||||
|
var finalText = _welcomeMsg.text
|
||||||
|
.trim()
|
||||||
|
.replaceAll('%s', '')
|
||||||
|
.replaceFirst('%name%', '%s');
|
||||||
|
|
||||||
|
widget.settingsProvider
|
||||||
|
.update(welcomeMessage: finalText, store: true);
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user