Compare commits
103 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93eaa5a74b | ||
|
|
5503b41be3 | ||
|
|
bd716e1717 | ||
|
|
7f8b716712 | ||
|
|
1a7b59f2fc | ||
|
|
9f62e44b52 | ||
|
|
7c34552aa5 | ||
|
|
57d784443a | ||
|
|
e73ee5a1f2 | ||
|
|
4277f0662a | ||
|
|
604e9dcaad | ||
|
|
c0dd84c665 | ||
|
|
7dc33d3b87 | ||
|
|
9bee0daeb5 | ||
|
|
dd8a4430a9 | ||
|
|
47934620ea | ||
|
|
9e815aff2f | ||
|
|
d8393b24e1 | ||
|
|
1abe990847 | ||
|
|
3a92716019 | ||
|
|
9b947256c8 | ||
|
|
0586da3742 | ||
|
|
9d863e1ec0 | ||
|
|
e080800aa8 | ||
|
|
e6f7728e42 | ||
|
|
ac11da1744 | ||
|
|
cad7bd19dc | ||
|
|
e1870b08e5 | ||
|
|
7842aa447f | ||
|
|
a23b2d63e5 | ||
|
|
58faeb4fa2 | ||
|
|
48e64d7761 | ||
|
|
aef8f78d16 | ||
|
|
2b36528327 | ||
|
|
918252ae4b | ||
|
|
63c650b68d | ||
|
|
090b0ccc85 | ||
|
|
0768dc9404 | ||
|
|
d36351d76b | ||
|
|
45a8e0dd71 | ||
|
|
94da2a9756 | ||
|
|
37aa1858a8 | ||
|
|
82f8a489dd | ||
|
|
96b69b89ae | ||
|
|
d9da7625ed | ||
|
|
c016258fb9 | ||
|
|
855e48aea8 | ||
|
|
b7e83d10dc | ||
|
|
45ffdff324 | ||
|
|
cd0729fa5e | ||
|
|
30cfdfe784 | ||
|
|
16f2593d22 | ||
|
|
14ab0c4ce3 | ||
|
|
9eb1317143 | ||
|
|
910a38650d | ||
|
|
a1f166980d | ||
|
|
0598b94ab9 | ||
|
|
1310ad4f2e | ||
|
|
4d32500d90 | ||
|
|
67558b76a3 | ||
|
|
7ab8914076 | ||
|
|
b0eb819afa | ||
|
|
416f42f42d | ||
|
|
a319b26d82 | ||
|
|
84537fdcef | ||
|
|
30f24d5d33 | ||
|
|
8c118eedc1 | ||
|
|
4dbe3d07a3 | ||
|
|
f1b1b23234 | ||
|
|
540e4d2812 | ||
|
|
93dd275969 | ||
|
|
c79c45705d | ||
|
|
ce31182a5c | ||
|
|
174046f954 | ||
|
|
3fc14ffbb8 | ||
|
|
f579270886 | ||
|
|
365bd7957e | ||
|
|
d24c4ec187 | ||
|
|
75ba5405bb | ||
|
|
e0bf8ac5e5 | ||
|
|
1a3d78a5bc | ||
|
|
c205bc592c | ||
|
|
308c8f966f | ||
|
|
139ac28be6 | ||
|
|
bbe53b8c01 | ||
|
|
56a0c2c02e | ||
|
|
122a5ea210 | ||
|
|
aaa3d79b30 | ||
|
|
cacf566794 | ||
|
|
9b29ede6eb | ||
|
|
9e9e46d0f8 | ||
|
|
9901251cfc | ||
|
|
e7ec93132d | ||
|
|
7cec2ff525 | ||
|
|
2ca8f4b8fe | ||
|
|
ae66a462e7 | ||
|
|
c85f15eb49 | ||
|
|
e04cc5ea2b | ||
|
|
3ed456c01f | ||
|
|
f64b1360d9 | ||
|
|
c9db496e59 | ||
|
|
d915200faa | ||
|
|
32abfe7037 |
56
Jenkinsfile
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
environment {
|
||||
ANDROID_SDK = '/home/jenkins/flutter_things/android-sdk'
|
||||
ANDROID_PATH="$ANDROID_SDK/tools:$ANDROID_SDK/platform-tools"
|
||||
FLUTTER = '/home/jenkins/flutter_things/flutter/bin'
|
||||
PATH = "$PATH:$ANDROID_PATH:$FLUTTER"
|
||||
//TODO: need to fix flutter
|
||||
}
|
||||
|
||||
|
||||
stages {
|
||||
stage('Copy Key Properties') {
|
||||
steps {
|
||||
// Copy the key.properties file
|
||||
sh 'cp /home/jenkins/key.properties refilc/android/key.properties'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Flutter Doctor') {
|
||||
steps {
|
||||
// Ensure Flutter is set up correctly
|
||||
sh 'flutter doctor'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Dependencies') {
|
||||
steps {
|
||||
// Get Flutter dependencies
|
||||
sh 'cd refilc && flutter pub get'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Build') {
|
||||
steps {
|
||||
// Build the Flutter project
|
||||
sh 'cd refilc && flutter build apk --release'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Archive') {
|
||||
steps {
|
||||
// Archive the APK
|
||||
archiveArtifacts artifacts: 'build/app/outputs/flutter-apk/app-release.apk', fingerprint: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
always {
|
||||
// Clean up workspace after build
|
||||
cleanWs()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@
|
||||
android:gravity="center"
|
||||
android:text="1."
|
||||
android:textColor="@color/filc"
|
||||
android:textColorLink="#ff3D7BF4"
|
||||
android:textColorLink="#ff052460"
|
||||
android:textSize="30sp"
|
||||
android:textStyle="bold"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<color name="yellow_light">#ffFFCC00</color>
|
||||
<color name="light_yellow_light">#40FFD60A</color>
|
||||
<color name="green_light">#ff34C759</color>
|
||||
<color name="filc_light">#ff3D7BF4</color>
|
||||
<color name="filc_light">#ff052460</color>
|
||||
<color name="teal_light">#ff5AC8FA</color>
|
||||
<color name="blue_light">#ff007AFF</color>
|
||||
<color name="indigo_light">#ff5856D6</color>
|
||||
@@ -49,8 +49,8 @@
|
||||
<color name="yellow">#ffFFD60A</color>
|
||||
<color name="light_yellow">#40FFD60A</color>
|
||||
<color name="green">#ff32D74B</color>
|
||||
<color name="filc">#ff3D7BF4</color>
|
||||
<color name="filc_gradient">#ff3D93F5</color>
|
||||
<color name="filc">#ff052460</color>
|
||||
<color name="filc_gradient">#ff06348f</color>
|
||||
<color name="teal">#ff64D2FF</color>
|
||||
<color name="blue">#ff0A84FF</color>
|
||||
<color name="indigo">#ff5E5CE6</color>
|
||||
|
||||
43
refilc/assets/svg/cover_arts/grid.svg
Normal file
@@ -0,0 +1,43 @@
|
||||
<svg width="375" height="174" viewBox="0 0 375 174" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1575_5258)">
|
||||
<g style="mix-blend-mode:color-burn">
|
||||
<rect x="187.881" y="36.8047" width="50.4482" height="50.4482" stroke="#858585"/>
|
||||
<rect x="238.186" y="36.8047" width="50.4482" height="50.4482" stroke="#858585"/>
|
||||
<rect x="187.881" y="-13.5" width="50.4482" height="50.4482" stroke="#858585"/>
|
||||
<rect x="238.186" y="-13.5" width="50.4482" height="50.4482" stroke="#858585"/>
|
||||
<rect x="288.49" y="36.8047" width="49.3049" height="50.4482" stroke="#858585"/>
|
||||
<rect x="337.652" y="36.8047" width="50.4482" height="50.4482" stroke="#858585"/>
|
||||
<rect x="288.49" y="-13.5" width="49.3049" height="50.4482" stroke="#858585"/>
|
||||
<rect x="337.652" y="-13.5" width="50.4482" height="50.4482" stroke="#858585"/>
|
||||
<rect x="187.881" y="136.271" width="50.4482" height="50.4482" stroke="#858585"/>
|
||||
<rect x="238.186" y="136.271" width="50.4482" height="50.4482" stroke="#858585"/>
|
||||
<rect x="187.881" y="87.1099" width="50.4482" height="49.3049" stroke="#858585"/>
|
||||
<rect x="238.186" y="87.1099" width="50.4482" height="49.3049" stroke="#858585"/>
|
||||
<rect x="288.49" y="136.271" width="49.3049" height="50.4482" stroke="#858585"/>
|
||||
<rect x="337.652" y="136.271" width="50.4482" height="50.4482" stroke="#858585"/>
|
||||
<rect x="288.49" y="87.1099" width="49.3049" height="49.3049" stroke="#858585"/>
|
||||
<rect x="337.652" y="87.1099" width="50.4482" height="49.3049" stroke="#858585"/>
|
||||
<rect x="-12.1953" y="36.8047" width="50.4482" height="50.4482" stroke="#858585"/>
|
||||
<rect x="-12.1953" y="-13.5" width="50.4482" height="50.4482" stroke="#858585"/>
|
||||
<rect x="38.1094" y="36.8047" width="49.3049" height="50.4482" stroke="#858585"/>
|
||||
<rect x="87.2705" y="36.8047" width="50.4482" height="50.4482" stroke="#858585"/>
|
||||
<rect x="38.1094" y="-13.5" width="49.3049" height="50.4482" stroke="#858585"/>
|
||||
<rect x="87.2705" y="-13.5" width="50.4482" height="50.4482" stroke="#858585"/>
|
||||
<rect x="-12.1953" y="136.271" width="50.4482" height="50.4482" stroke="#858585"/>
|
||||
<rect x="-12.1953" y="87.1099" width="50.4482" height="49.3049" stroke="#858585"/>
|
||||
<rect x="38.1094" y="136.271" width="49.3049" height="50.4482" stroke="#858585"/>
|
||||
<rect x="87.2705" y="136.271" width="50.4482" height="50.4482" stroke="#858585"/>
|
||||
<rect x="38.1094" y="87.1099" width="49.3049" height="49.3049" stroke="#858585"/>
|
||||
<rect x="87.2705" y="87.1099" width="50.4482" height="49.3049" stroke="#858585"/>
|
||||
<rect x="137.576" y="36.8047" width="50.4482" height="50.4482" stroke="#858585"/>
|
||||
<rect x="137.576" y="-13.5" width="50.4482" height="50.4482" stroke="#858585"/>
|
||||
<rect x="137.576" y="136.271" width="50.4482" height="50.4482" stroke="#858585"/>
|
||||
<rect x="137.576" y="87.1099" width="50.4482" height="49.3049" stroke="#858585"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1575_5258">
|
||||
<rect width="375" height="173.78" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
27
refilc/assets/svg/cover_arts/line.svg
Normal file
@@ -0,0 +1,27 @@
|
||||
<svg width="375" height="175" viewBox="0 0 375 175" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1575_5259)">
|
||||
<g style="mix-blend-mode:color-burn">
|
||||
<mask id="path-1-inside-1_1575_5259" fill="white">
|
||||
<path d="M0 37H375V89H0V37Z"/>
|
||||
</mask>
|
||||
<path d="M0 38H375V36H0V38Z" fill="#858585" mask="url(#path-1-inside-1_1575_5259)"/>
|
||||
<mask id="path-3-inside-2_1575_5259" fill="white">
|
||||
<path d="M0 -13H375V38H0V-13Z"/>
|
||||
</mask>
|
||||
<path d="M0 -12H375V-14H0V-12Z" fill="#858585" mask="url(#path-3-inside-2_1575_5259)"/>
|
||||
<mask id="path-5-inside-3_1575_5259" fill="white">
|
||||
<path d="M0 137H375V188H0V137Z"/>
|
||||
</mask>
|
||||
<path d="M0 138H375V136H0V138Z" fill="#858585" mask="url(#path-5-inside-3_1575_5259)"/>
|
||||
<mask id="path-7-inside-4_1575_5259" fill="white">
|
||||
<path d="M0 87H375V138H0V87Z"/>
|
||||
</mask>
|
||||
<path d="M0 88H375V86H0V88Z" fill="#858585" mask="url(#path-7-inside-4_1575_5259)"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1575_5259">
|
||||
<rect width="375" height="173.78" fill="white" transform="translate(0 0.780518)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
47
refilc/assets/svg/cover_arts/plain.svg
Normal file
@@ -0,0 +1,47 @@
|
||||
<svg width="375" height="175" viewBox="0 0 375 175" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1575_5260)">
|
||||
<g style="mix-blend-mode:color-burn">
|
||||
<circle cx="17" cy="19.561" r="1" fill="#858585"/>
|
||||
<circle cx="59" cy="19.561" r="1" fill="#858585"/>
|
||||
<circle cx="101" cy="19.561" r="1" fill="#858585"/>
|
||||
<circle cx="143" cy="19.561" r="1" fill="#858585"/>
|
||||
<circle cx="185" cy="19.561" r="1" fill="#858585"/>
|
||||
<circle cx="227" cy="19.561" r="1" fill="#858585"/>
|
||||
<circle cx="269" cy="19.561" r="1" fill="#858585"/>
|
||||
<circle cx="311" cy="19.561" r="1" fill="#858585"/>
|
||||
<circle cx="353" cy="19.561" r="1" fill="#858585"/>
|
||||
<circle cx="17" cy="61.561" r="1" fill="#858585"/>
|
||||
<circle cx="59" cy="61.561" r="1" fill="#858585"/>
|
||||
<circle cx="101" cy="61.561" r="1" fill="#858585"/>
|
||||
<circle cx="143" cy="61.561" r="1" fill="#858585"/>
|
||||
<circle cx="185" cy="61.561" r="1" fill="#858585"/>
|
||||
<circle cx="227" cy="61.561" r="1" fill="#858585"/>
|
||||
<circle cx="269" cy="61.561" r="1" fill="#858585"/>
|
||||
<circle cx="311" cy="61.561" r="1" fill="#858585"/>
|
||||
<circle cx="353" cy="61.561" r="1" fill="#858585"/>
|
||||
<circle cx="17" cy="103.561" r="1" fill="#858585"/>
|
||||
<circle cx="59" cy="103.561" r="1" fill="#858585"/>
|
||||
<circle cx="101" cy="103.561" r="1" fill="#858585"/>
|
||||
<circle cx="143" cy="103.561" r="1" fill="#858585"/>
|
||||
<circle cx="185" cy="103.561" r="1" fill="#858585"/>
|
||||
<circle cx="227" cy="103.561" r="1" fill="#858585"/>
|
||||
<circle cx="269" cy="103.561" r="1" fill="#858585"/>
|
||||
<circle cx="311" cy="103.561" r="1" fill="#858585"/>
|
||||
<circle cx="353" cy="103.561" r="1" fill="#858585"/>
|
||||
<circle cx="17" cy="145.561" r="1" fill="#858585"/>
|
||||
<circle cx="59" cy="145.561" r="1" fill="#858585"/>
|
||||
<circle cx="101" cy="145.561" r="1" fill="#858585"/>
|
||||
<circle cx="143" cy="145.561" r="1" fill="#858585"/>
|
||||
<circle cx="185" cy="145.561" r="1" fill="#858585"/>
|
||||
<circle cx="227" cy="145.561" r="1" fill="#858585"/>
|
||||
<circle cx="269" cy="145.561" r="1" fill="#858585"/>
|
||||
<circle cx="311" cy="145.561" r="1" fill="#858585"/>
|
||||
<circle cx="353" cy="145.561" r="1" fill="#858585"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1575_5260">
|
||||
<rect width="375" height="173.78" fill="white" transform="translate(0 0.561035)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
28
refilc/assets/svg/cover_arts/vocal.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<svg width="375" height="175" viewBox="0 0 375 175" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1575_5261)">
|
||||
<g style="mix-blend-mode:color-burn">
|
||||
<path d="M0 63.0001H375" stroke="#858585"/>
|
||||
<path d="M0 75.0001H375" stroke="#858585"/>
|
||||
<path d="M0 87.0001H375" stroke="#858585"/>
|
||||
<path d="M0 99.0001H375" stroke="#858585"/>
|
||||
<path d="M0 111H375" stroke="#858585"/>
|
||||
</g>
|
||||
<g style="mix-blend-mode:color-burn">
|
||||
<path d="M0 135H375" stroke="#858585"/>
|
||||
<path d="M0 147H375" stroke="#858585"/>
|
||||
<path d="M0 159H375" stroke="#858585"/>
|
||||
<path d="M0 171H375" stroke="#858585"/>
|
||||
</g>
|
||||
<g style="mix-blend-mode:color-burn">
|
||||
<path d="M0 3.00012H375" stroke="#858585"/>
|
||||
<path d="M0 15.0001H375" stroke="#858585"/>
|
||||
<path d="M0 27.0001H375" stroke="#858585"/>
|
||||
<path d="M0 39.0001H375" stroke="#858585"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1575_5261">
|
||||
<rect width="375" height="173.78" fill="white" transform="translate(0 0.341431)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 973 B |
@@ -1,43 +0,0 @@
|
||||
<svg width="375" height="174" viewBox="0 0 375 174" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_581_2504)">
|
||||
<g style="mix-blend-mode:color-burn">
|
||||
<rect x="138.881" y="36.8047" width="50.4482" height="50.4482" stroke="black"/>
|
||||
<rect x="189.186" y="36.8047" width="50.4482" height="50.4482" stroke="black"/>
|
||||
<rect x="138.881" y="-13.5" width="50.4482" height="50.4482" stroke="black"/>
|
||||
<rect x="189.186" y="-13.5" width="50.4482" height="50.4482" stroke="black"/>
|
||||
<rect x="239.49" y="36.8047" width="49.3049" height="50.4482" stroke="black"/>
|
||||
<rect x="288.652" y="36.8047" width="50.4482" height="50.4482" stroke="black"/>
|
||||
<rect x="239.49" y="-13.5" width="49.3049" height="50.4482" stroke="black"/>
|
||||
<rect x="288.652" y="-13.5" width="50.4482" height="50.4482" stroke="black"/>
|
||||
<rect x="138.881" y="136.271" width="50.4482" height="50.4482" stroke="black"/>
|
||||
<rect x="189.186" y="136.271" width="50.4482" height="50.4482" stroke="black"/>
|
||||
<rect x="138.881" y="87.1099" width="50.4482" height="49.3049" stroke="black"/>
|
||||
<rect x="189.186" y="87.1099" width="50.4482" height="49.3049" stroke="black"/>
|
||||
<rect x="239.49" y="136.271" width="49.3049" height="50.4482" stroke="black"/>
|
||||
<rect x="288.652" y="136.271" width="50.4482" height="50.4482" stroke="black"/>
|
||||
<rect x="239.49" y="87.1099" width="49.3049" height="49.3049" stroke="black"/>
|
||||
<rect x="288.652" y="87.1099" width="50.4482" height="49.3049" stroke="black"/>
|
||||
<rect x="338.957" y="36.8047" width="50.4482" height="50.4482" stroke="black"/>
|
||||
<rect x="338.957" y="-13.5" width="50.4482" height="50.4482" stroke="black"/>
|
||||
<rect x="338.957" y="136.271" width="50.4482" height="50.4482" stroke="black"/>
|
||||
<rect x="338.957" y="87.1099" width="50.4482" height="49.3049" stroke="black"/>
|
||||
<rect x="-10.8906" y="36.8047" width="49.3049" height="50.4482" stroke="black"/>
|
||||
<rect x="38.2705" y="36.8047" width="50.4482" height="50.4482" stroke="black"/>
|
||||
<rect x="-10.8906" y="-13.5" width="49.3049" height="50.4482" stroke="black"/>
|
||||
<rect x="38.2705" y="-13.5" width="50.4482" height="50.4482" stroke="black"/>
|
||||
<rect x="-10.8906" y="136.271" width="49.3049" height="50.4482" stroke="black"/>
|
||||
<rect x="38.2705" y="136.271" width="50.4482" height="50.4482" stroke="black"/>
|
||||
<rect x="-10.8906" y="87.1099" width="49.3049" height="49.3049" stroke="black"/>
|
||||
<rect x="38.2705" y="87.1099" width="50.4482" height="49.3049" stroke="black"/>
|
||||
<rect x="88.5762" y="36.8047" width="50.4482" height="50.4482" stroke="black"/>
|
||||
<rect x="88.5762" y="-13.5" width="50.4482" height="50.4482" stroke="black"/>
|
||||
<rect x="88.5762" y="136.271" width="50.4482" height="50.4482" stroke="black"/>
|
||||
<rect x="88.5762" y="87.1099" width="50.4482" height="49.3049" stroke="black"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_581_2504">
|
||||
<rect width="375" height="173.78" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
@@ -517,7 +517,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 255;
|
||||
CURRENT_PROJECT_VERSION = 257;
|
||||
DEVELOPMENT_TEAM = 4DKAF249F3;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
@@ -549,7 +549,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = livecard/livecard.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 255;
|
||||
CURRENT_PROJECT_VERSION = 257;
|
||||
DEVELOPMENT_TEAM = 4DKAF249F3;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -591,7 +591,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = livecard/livecard.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 255;
|
||||
CURRENT_PROJECT_VERSION = 257;
|
||||
DEVELOPMENT_TEAM = 4DKAF249F3;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -631,7 +631,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = livecard/livecard.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 255;
|
||||
CURRENT_PROJECT_VERSION = 257;
|
||||
DEVELOPMENT_TEAM = 4DKAF249F3;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -775,7 +775,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 255;
|
||||
CURRENT_PROJECT_VERSION = 257;
|
||||
DEVELOPMENT_TEAM = 4DKAF249F3;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
@@ -803,7 +803,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 255;
|
||||
CURRENT_PROJECT_VERSION = 257;
|
||||
DEVELOPMENT_TEAM = 4DKAF249F3;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "reFilc_Logo.png",
|
||||
"filename" : "rf_1024.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
|
||||
|
Before Width: | Height: | Size: 577 KiB |
BIN
refilc/ios/Runner/Assets.xcassets/AppIcon.appiconset/rf_1024.png
Normal file
|
After Width: | Height: | Size: 180 KiB |
@@ -52,14 +52,31 @@ struct LockScreenLiveActivityView: View {
|
||||
VStack(alignment: .center) {
|
||||
// Jelenlegi óra
|
||||
VStack {
|
||||
Text(context.state.index + " " + context.state.title)
|
||||
.font(.body)
|
||||
.bold()
|
||||
.multilineTextAlignment(.center)
|
||||
if(context.state.title.contains("Az első órádig")) {
|
||||
Text(context.state.title)
|
||||
.font(.system(size: 15))
|
||||
.bold()
|
||||
.multilineTextAlignment(.center)
|
||||
} else if(context.state.title == "Szünet") {
|
||||
Text(context.state.title)
|
||||
.font(.body)
|
||||
.bold()
|
||||
.padding(.trailing, 90)
|
||||
|
||||
Text("Terem: \(context.state.subtitle)")
|
||||
.italic()
|
||||
.font(.caption)
|
||||
} else {
|
||||
MultilineTextView(text: "\(context.state.index) \(context.state.title)", limit: 25)
|
||||
.font(.body)
|
||||
.bold()
|
||||
.multilineTextAlignment(.center)
|
||||
}
|
||||
|
||||
//Terem
|
||||
if (!context.state.subtitle.isEmpty) {
|
||||
Text(context.state.subtitle)
|
||||
.italic()
|
||||
.bold()
|
||||
.font(.system(size: 13))
|
||||
}
|
||||
}
|
||||
|
||||
// Leírás
|
||||
@@ -69,6 +86,7 @@ struct LockScreenLiveActivityView: View {
|
||||
}
|
||||
|
||||
// Következő óra
|
||||
if(context.state.nextSubject != "" && context.state.nextRoom != "") {
|
||||
HStack {
|
||||
Image(systemName: "arrow.right")
|
||||
.resizable()
|
||||
@@ -80,6 +98,12 @@ struct LockScreenLiveActivityView: View {
|
||||
.font(.caption2)
|
||||
}
|
||||
.multilineTextAlignment(.center)
|
||||
} else {
|
||||
Spacer(minLength: 5)
|
||||
Text("Ez az utolsó óra! Kitartást!")
|
||||
.font(.system(size: 15))
|
||||
}
|
||||
|
||||
}
|
||||
.padding(15)
|
||||
|
||||
@@ -91,7 +115,7 @@ struct LockScreenLiveActivityView: View {
|
||||
.frame(width: 85)
|
||||
.font(.title2)
|
||||
.monospacedDigit()
|
||||
.padding(.trailing, CGFloat(24))
|
||||
.padding(.trailing)
|
||||
}
|
||||
.activityBackgroundTint(
|
||||
context.state.color != "#676767"
|
||||
@@ -133,32 +157,88 @@ struct LiveCardWidget: Widget {
|
||||
).progressViewStyle(.circular)
|
||||
}
|
||||
}
|
||||
DynamicIslandExpandedRegion(.center) {
|
||||
VStack(alignment: .center) {
|
||||
Text(context.state.index + context.state.title)
|
||||
.lineLimit(1)
|
||||
.font(.body)
|
||||
.bold()
|
||||
DynamicIslandExpandedRegion(.center) {
|
||||
VStack(alignment: .center) {
|
||||
// Első óra előtti expanded DynamicIsland
|
||||
if(context.state.title.contains("Az első órádig")) {
|
||||
Text("Az első órád:")
|
||||
.font(.body)
|
||||
.bold()
|
||||
.padding(.trailing, -15)
|
||||
MultilineTextView(text: "\(context.state.nextSubject)", limit: 25)
|
||||
.font(.body)
|
||||
.padding(.trailing, -25)
|
||||
|
||||
Text(context.state.subtitle)
|
||||
.lineLimit(1)
|
||||
.font(.subheadline)
|
||||
Spacer()
|
||||
Text("Ebben a teremben:")
|
||||
.font(.body)
|
||||
.bold()
|
||||
.padding(.leading, 15)
|
||||
Text(context.state.nextRoom)
|
||||
.font(.body)
|
||||
.padding(.leading, 15)
|
||||
} else if(context.state.title == "Szünet") {
|
||||
// Amikor szünet van, expanded DynamicIsland
|
||||
Text(context.state.title)
|
||||
.lineLimit(1)
|
||||
.font(.body)
|
||||
.bold()
|
||||
.padding(.leading, 15)
|
||||
|
||||
Text(context.state.description)
|
||||
.lineLimit(2)
|
||||
.font(.caption)
|
||||
}.padding(EdgeInsets(top: 0.0, leading: 5.0, bottom: 0.0, trailing: 0.0))
|
||||
}
|
||||
Spacer(minLength: 5)
|
||||
Text("Következő óra és terem:")
|
||||
.font(.system(size: 13))
|
||||
.padding(.leading, 25)
|
||||
Text(context.state.nextSubject)
|
||||
.font(.caption)
|
||||
.padding(.leading, 15)
|
||||
Text(context.state.nextRoom)
|
||||
.font(.caption2)
|
||||
.padding(.leading, 15)
|
||||
|
||||
} else {
|
||||
// Amikor óra van, expanded DynamicIsland
|
||||
MultilineTextView(text: "\(context.state.index) \(context.state.title)", limit: 25)
|
||||
.lineLimit(1)
|
||||
.font(.body)
|
||||
.bold()
|
||||
.padding(.trailing, -35)
|
||||
|
||||
Text(context.state.subtitle)
|
||||
.lineLimit(1)
|
||||
.italic()
|
||||
.bold()
|
||||
.font(.system(size: 13))
|
||||
.padding(.trailing, -50)
|
||||
|
||||
Spacer(minLength: 5)
|
||||
|
||||
if(context.state.nextRoom != "" && context.state.nextSubject != "") {
|
||||
Text("Következő óra és terem:")
|
||||
.font(.system(size: 14))
|
||||
.padding(.trailing, -35)
|
||||
Spacer(minLength: 2)
|
||||
Text(context.state.nextSubject)
|
||||
.modifier(DynamicFontSizeModifier(text: context.state.nextSubject))
|
||||
.padding(.trailing, -35)
|
||||
Text(context.state.nextRoom)
|
||||
// ignore: based on nextSubject characters, I check that the font size of the room is the same as the next subject.
|
||||
.modifier(DynamicFontSizeModifier(text: context.state.nextSubject))
|
||||
.padding(.trailing, -35)
|
||||
} else {
|
||||
Text("Ez az utolsó óra! Kitartást!")
|
||||
.font(.system(size: 14))
|
||||
.padding(.trailing, -30)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}.padding(EdgeInsets(top: 0.0, leading: 5.0, bottom: 0.0, trailing: 0.0))
|
||||
|
||||
}
|
||||
|
||||
/// Compact
|
||||
} compactLeading: {
|
||||
Label {
|
||||
Text(context.state.title)
|
||||
} icon: {
|
||||
Image(systemName: context.state.icon)
|
||||
}
|
||||
.font(.caption2)
|
||||
Image(systemName: context.state.icon)
|
||||
}
|
||||
compactTrailing: {
|
||||
Text(timerInterval: context.state.date, countsDown: true)
|
||||
@@ -191,7 +271,59 @@ struct LiveCardWidget: Widget {
|
||||
context.state.color != "#676767"
|
||||
? Color(hex: context.state.color)
|
||||
: Color.clear
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct MultilineTextView: View {
|
||||
var text: String
|
||||
var limit: Int = 20 // default is 20 character
|
||||
|
||||
var body: some View {
|
||||
let words = text.split(separator: " ")
|
||||
var currentLine = ""
|
||||
var lines: [String] = []
|
||||
|
||||
for word in words {
|
||||
if (currentLine.count + word.count + 1) > limit {
|
||||
lines.append(currentLine)
|
||||
currentLine = ""
|
||||
}
|
||||
if !currentLine.isEmpty {
|
||||
currentLine += " "
|
||||
}
|
||||
currentLine += word
|
||||
}
|
||||
if !currentLine.isEmpty {
|
||||
lines.append(currentLine)
|
||||
}
|
||||
|
||||
return VStack(alignment: .center) {
|
||||
ForEach(lines, id: \.self) { line in
|
||||
Text(line)
|
||||
}
|
||||
Spacer(minLength: 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DynamicFontSizeModifier: ViewModifier {
|
||||
var text: String
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.font(.system(size: fontSize(for: text)))
|
||||
}
|
||||
|
||||
private func fontSize(for text: String) -> CGFloat {
|
||||
let length = text.count
|
||||
if length < 10 {
|
||||
return 12
|
||||
} else if length < 20 {
|
||||
return 12
|
||||
} else {
|
||||
return 11
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,6 +336,8 @@ class FilcAPI {
|
||||
|
||||
if (res.statusCode == 200) {
|
||||
return (jsonDecode(res.body) as Map);
|
||||
} else if (res.statusCode == 404) {
|
||||
return {"public_id": ""};
|
||||
} else {
|
||||
throw "HTTP ${res.statusCode}: ${res.body}";
|
||||
}
|
||||
|
||||
@@ -88,24 +88,24 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
case LiveCardState.morning:
|
||||
return {
|
||||
"color":
|
||||
'#${_settings.liveActivityColor.toString().substring(10, 16)}',
|
||||
'#${_settings.liveActivityColor.toString().substring(10, 16)}',
|
||||
"icon": nextLesson != null
|
||||
? SubjectIcon.resolveName(subject: nextLesson?.subject)
|
||||
: "book",
|
||||
"title": "Első órádig:",
|
||||
"title": "Jó reggelt! Az első órádig:",
|
||||
"subtitle": "",
|
||||
"description": "",
|
||||
"startDate": storeFirstRunDate != null
|
||||
? ((storeFirstRunDate?.millisecondsSinceEpoch ?? 0) -
|
||||
(_delay.inMilliseconds))
|
||||
.toString()
|
||||
(_delay.inMilliseconds))
|
||||
.toString()
|
||||
: "",
|
||||
"endDate": ((nextLesson?.start.millisecondsSinceEpoch ?? 0) -
|
||||
_delay.inMilliseconds)
|
||||
_delay.inMilliseconds)
|
||||
.toString(),
|
||||
"nextSubject": nextLesson != null
|
||||
? nextLesson?.subject.renamedTo ??
|
||||
ShortSubject.resolve(subject: nextLesson?.subject).capital()
|
||||
ShortSubject.resolve(subject: nextLesson?.subject).capital()
|
||||
: "",
|
||||
"nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
|
||||
};
|
||||
@@ -113,24 +113,24 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
case LiveCardState.afternoon:
|
||||
return {
|
||||
"color":
|
||||
'#${_settings.liveActivityColor.toString().substring(10, 16)}',
|
||||
'#${_settings.liveActivityColor.toString().substring(10, 16)}',
|
||||
"icon": nextLesson != null
|
||||
? SubjectIcon.resolveName(subject: nextLesson?.subject)
|
||||
: "book",
|
||||
"title": "Első órádig:",
|
||||
"title": "Jó napot! Az első órádig:",
|
||||
"subtitle": "",
|
||||
"description": "",
|
||||
"startDate": storeFirstRunDate != null
|
||||
? ((storeFirstRunDate?.millisecondsSinceEpoch ?? 0) -
|
||||
(_delay.inMilliseconds))
|
||||
.toString()
|
||||
(_delay.inMilliseconds))
|
||||
.toString()
|
||||
: "",
|
||||
"endDate": ((nextLesson?.start.millisecondsSinceEpoch ?? 0) -
|
||||
_delay.inMilliseconds)
|
||||
_delay.inMilliseconds)
|
||||
.toString(),
|
||||
"nextSubject": nextLesson != null
|
||||
? nextLesson?.subject.renamedTo ??
|
||||
ShortSubject.resolve(subject: nextLesson?.subject).capital()
|
||||
ShortSubject.resolve(subject: nextLesson?.subject).capital()
|
||||
: "",
|
||||
"nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
|
||||
};
|
||||
@@ -138,24 +138,24 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
case LiveCardState.night:
|
||||
return {
|
||||
"color":
|
||||
'#${_settings.liveActivityColor.toString().substring(10, 16)}',
|
||||
'#${_settings.liveActivityColor.toString().substring(10, 16)}',
|
||||
"icon": nextLesson != null
|
||||
? SubjectIcon.resolveName(subject: nextLesson?.subject)
|
||||
: "book",
|
||||
"title": "Első órádig:",
|
||||
"title": "Jó estét! Az első órádig:",
|
||||
"subtitle": "",
|
||||
"description": "",
|
||||
"startDate": storeFirstRunDate != null
|
||||
? ((storeFirstRunDate?.millisecondsSinceEpoch ?? 0) -
|
||||
(_delay.inMilliseconds))
|
||||
.toString()
|
||||
(_delay.inMilliseconds))
|
||||
.toString()
|
||||
: "",
|
||||
"endDate": ((nextLesson?.start.millisecondsSinceEpoch ?? 0) -
|
||||
_delay.inMilliseconds)
|
||||
_delay.inMilliseconds)
|
||||
.toString(),
|
||||
"nextSubject": nextLesson != null
|
||||
? nextLesson?.subject.renamedTo ??
|
||||
ShortSubject.resolve(subject: nextLesson?.subject).capital()
|
||||
ShortSubject.resolve(subject: nextLesson?.subject).capital()
|
||||
: "",
|
||||
"nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
|
||||
};
|
||||
@@ -163,28 +163,28 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
case LiveCardState.duringLesson:
|
||||
return {
|
||||
"color":
|
||||
'#${_settings.liveActivityColor.toString().substring(10, 16)}',
|
||||
'#${_settings.liveActivityColor.toString().substring(10, 16)}',
|
||||
"icon": currentLesson != null
|
||||
? SubjectIcon.resolveName(subject: currentLesson?.subject)
|
||||
: "book",
|
||||
"index":
|
||||
currentLesson != null ? '${currentLesson!.lessonIndex}. ' : "",
|
||||
currentLesson != null ? '${currentLesson!.lessonIndex}. ' : "",
|
||||
"title": currentLesson != null
|
||||
? currentLesson?.subject.renamedTo ??
|
||||
ShortSubject.resolve(subject: currentLesson?.subject)
|
||||
.capital()
|
||||
ShortSubject.resolve(subject: currentLesson?.subject)
|
||||
.capital()
|
||||
: "",
|
||||
"subtitle": currentLesson?.room.replaceAll("_", " ") ?? "",
|
||||
"subtitle": "Terem: ${currentLesson?.room.replaceAll("_", " ") ?? ""}",
|
||||
"description": currentLesson?.description ?? "",
|
||||
"startDate": ((currentLesson?.start.millisecondsSinceEpoch ?? 0) -
|
||||
_delay.inMilliseconds)
|
||||
_delay.inMilliseconds)
|
||||
.toString(),
|
||||
"endDate": ((currentLesson?.end.millisecondsSinceEpoch ?? 0) -
|
||||
_delay.inMilliseconds)
|
||||
_delay.inMilliseconds)
|
||||
.toString(),
|
||||
"nextSubject": nextLesson != null
|
||||
? nextLesson?.subject.renamedTo ??
|
||||
ShortSubject.resolve(subject: nextLesson?.subject).capital()
|
||||
ShortSubject.resolve(subject: nextLesson?.subject).capital()
|
||||
: "",
|
||||
"nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
|
||||
};
|
||||
@@ -200,23 +200,23 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
|
||||
return {
|
||||
"color":
|
||||
'#${_settings.liveActivityColor.toString().substring(10, 16)}',
|
||||
'#${_settings.liveActivityColor.toString().substring(10, 16)}',
|
||||
"icon": iconFloorMap[diff] ?? "cup.and.saucer",
|
||||
"title": "Szünet",
|
||||
"description": "go $diff".i18n.fill([
|
||||
diff != "to room" ? (nextLesson!.getFloor() ?? 0) : nextLesson!.room
|
||||
]),
|
||||
"startDate": ((prevLesson?.end.millisecondsSinceEpoch ?? 0) -
|
||||
_delay.inMilliseconds)
|
||||
_delay.inMilliseconds)
|
||||
.toString(),
|
||||
"endDate": ((nextLesson?.start.millisecondsSinceEpoch ?? 0) -
|
||||
_delay.inMilliseconds)
|
||||
_delay.inMilliseconds)
|
||||
.toString(),
|
||||
"nextSubject": (nextLesson != null
|
||||
? nextLesson?.subject.renamedTo ??
|
||||
ShortSubject.resolve(subject: nextLesson?.subject)
|
||||
.capital()
|
||||
: "")
|
||||
? nextLesson?.subject.renamedTo ??
|
||||
ShortSubject.resolve(subject: nextLesson?.subject)
|
||||
.capital()
|
||||
: "")
|
||||
.capital(),
|
||||
"nextRoom": nextLesson?.room.replaceAll("_", " ") ?? "",
|
||||
"index": "",
|
||||
@@ -243,8 +243,8 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
DateTime now = _now().add(_delay);
|
||||
|
||||
if ((currentState == LiveCardState.morning ||
|
||||
currentState == LiveCardState.afternoon ||
|
||||
currentState == LiveCardState.night) &&
|
||||
currentState == LiveCardState.afternoon ||
|
||||
currentState == LiveCardState.night) &&
|
||||
storeFirstRunDate == null) {
|
||||
storeFirstRunDate = now;
|
||||
}
|
||||
@@ -253,9 +253,9 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
// Filter label lessons #128
|
||||
today = today
|
||||
.where((lesson) =>
|
||||
lesson.status?.name != "Elmaradt" &&
|
||||
lesson.subject.id != '' &&
|
||||
!lesson.isEmpty)
|
||||
lesson.status?.name != "Elmaradt" &&
|
||||
lesson.subject.id != '' &&
|
||||
!lesson.isEmpty)
|
||||
.toList();
|
||||
|
||||
if (today.isNotEmpty) {
|
||||
@@ -263,7 +263,7 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
today.sort((a, b) => a.start.compareTo(b.start));
|
||||
|
||||
final _lesson = today.firstWhere(
|
||||
(l) => l.start.isBefore(now) && l.end.isAfter(now),
|
||||
(l) => l.start.isBefore(now) && l.end.isAfter(now),
|
||||
orElse: () => Lesson.fromJson({}));
|
||||
|
||||
if (_lesson.start.year != 0) {
|
||||
@@ -328,7 +328,7 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
hasActivityStarted = true;
|
||||
} else if (!hasActivityStarted &&
|
||||
((currentState == LiveCardState.duringLesson &&
|
||||
currentLesson != null) ||
|
||||
currentLesson != null) ||
|
||||
currentState == LiveCardState.duringBreak)) {
|
||||
debugPrint("Óra van, vagy szünet, de nincs LiveActivity. létrehozás...");
|
||||
PlatformChannel.createLiveActivity(toMap());
|
||||
@@ -362,7 +362,12 @@ class LiveCardProvider extends ChangeNotifier {
|
||||
}
|
||||
|
||||
//END
|
||||
if (hasActivityStarted &&
|
||||
if ((currentState == LiveCardState.afternoon || currentState == LiveCardState.morning || currentState == LiveCardState.night) && hasActivityStarted && nextLesson != null &&
|
||||
nextLesson!.start.difference(now).inMinutes > 60) {
|
||||
debugPrint("Több, mint 1 óra van az első óráig. Befejezés...");
|
||||
PlatformChannel.endLiveActivity();
|
||||
hasActivityStarted = false;
|
||||
} else if (hasActivityStarted &&
|
||||
!hasDayEnd &&
|
||||
nextLesson == null &&
|
||||
now.isAfter(prevLesson!.end)) {
|
||||
|
||||
@@ -7,17 +7,23 @@ import 'package:provider/provider.dart';
|
||||
|
||||
class SelfNoteProvider with ChangeNotifier {
|
||||
late List<SelfNote> _notes;
|
||||
late List<TodoItem> _todoItems;
|
||||
late BuildContext _context;
|
||||
|
||||
List<SelfNote> get notes => _notes;
|
||||
List<TodoItem> get todos => _todoItems;
|
||||
|
||||
SelfNoteProvider({
|
||||
List<SelfNote> initialNotes = const [],
|
||||
List<TodoItem> initialTodoItems = const [],
|
||||
required BuildContext context,
|
||||
}) {
|
||||
_notes = List.castFrom(initialNotes);
|
||||
_todoItems = List.castFrom(initialTodoItems);
|
||||
_context = context;
|
||||
|
||||
if (_notes.isEmpty) restore();
|
||||
if (_todoItems.isEmpty) restoreTodo();
|
||||
}
|
||||
|
||||
// restore self notes from db
|
||||
@@ -38,6 +44,24 @@ class SelfNoteProvider with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
// restore todo items from db
|
||||
Future<void> restoreTodo() async {
|
||||
String? userId = Provider.of<UserProvider>(_context, listen: false).id;
|
||||
|
||||
// await Provider.of<DatabaseProvider>(_context, listen: false)
|
||||
// .userStore
|
||||
// .storeSelfNotes([], userId: userId!);
|
||||
|
||||
// load self notes from db
|
||||
if (userId != null) {
|
||||
var dbTodo = await Provider.of<DatabaseProvider>(_context, listen: false)
|
||||
.userQuery
|
||||
.getTodoItems(userId: userId);
|
||||
_todoItems = dbTodo;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// fetches fresh data from api (not needed, cuz no api for that)
|
||||
// Future<void> fetch() async {
|
||||
// }
|
||||
@@ -54,4 +78,17 @@ class SelfNoteProvider with ChangeNotifier {
|
||||
_notes = notes;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// store todo items in db
|
||||
Future<void> storeTodo(List<TodoItem> todos) async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot store Self Notes for User null";
|
||||
String userId = user.id;
|
||||
|
||||
await Provider.of<DatabaseProvider>(_context, listen: false)
|
||||
.userStore
|
||||
.storeSelfTodoItems(todos, userId: userId);
|
||||
_todoItems = todos;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ class UserProvider with ChangeNotifier {
|
||||
String? get nickname => user?.nickname;
|
||||
String get picture => user?.picture ?? "";
|
||||
String? get displayName => user?.displayName;
|
||||
int? get gradeStreak => user?.gradeStreak;
|
||||
|
||||
final SettingsProvider _settings;
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ const settingsDB = DatabaseStruct("settings", {
|
||||
// more
|
||||
"show_breaks": int,
|
||||
"font_family": String,
|
||||
"title_only_font": int,
|
||||
"plus_session_id": String,
|
||||
"cal_sync_room_location": String, "cal_sync_show_exams": int,
|
||||
"cal_sync_show_teacher": int, "cal_sync_renamed": int,
|
||||
@@ -52,6 +53,7 @@ const settingsDB = DatabaseStruct("settings", {
|
||||
"nav_shadow": int,
|
||||
"new_colors": int,
|
||||
"uwu_mode": int,
|
||||
"new_popups": int,
|
||||
// quick settings
|
||||
"q_timetable_lesson_num": int, "q_timetable_sub_tiles": int,
|
||||
"q_subjects_sub_tiles": int,
|
||||
@@ -61,7 +63,8 @@ const settingsDB = DatabaseStruct("settings", {
|
||||
const usersDB = DatabaseStruct("users", {
|
||||
"id": String, "name": String, "username": String, "password": String,
|
||||
"institute_code": String, "student": String, "role": int,
|
||||
"nickname": String, "picture": String // premium only
|
||||
"nickname": String, "picture": String, // premium only (it's now plus btw)
|
||||
"grade_streak": int,
|
||||
});
|
||||
const userDataDB = DatabaseStruct("user_data", {
|
||||
"id": String, "grades": String, "timetable": String, "exams": String,
|
||||
@@ -84,12 +87,13 @@ const userDataDB = DatabaseStruct("user_data", {
|
||||
"goal_befores": String,
|
||||
"goal_pin_dates": String,
|
||||
// todo and notes
|
||||
"todo_items": String, "self_notes": String,
|
||||
"todo_items": String, "self_notes": String, "self_todo": String,
|
||||
// v5 shit
|
||||
"roundings": String,
|
||||
"grade_rarities": String,
|
||||
"linked_accounts": String,
|
||||
"custom_lesson_desc": String,
|
||||
"watch_data": String,
|
||||
});
|
||||
|
||||
Future<void> createTable(Database db, DatabaseStruct struct) =>
|
||||
@@ -129,7 +133,12 @@ Future<Database> initDB(DatabaseProvider database) async {
|
||||
await migrateDB(
|
||||
db,
|
||||
struct: usersDB,
|
||||
defaultValues: {"role": 0, "nickname": "", "picture": ""},
|
||||
defaultValues: {
|
||||
"role": 0,
|
||||
"nickname": "",
|
||||
"picture": "",
|
||||
"grade_streak": 0
|
||||
},
|
||||
);
|
||||
await migrateDB(db, struct: userDataDB, defaultValues: {
|
||||
"grades": "[]", "timetable": "[]", "exams": "[]", "homework": "[]",
|
||||
@@ -152,12 +161,13 @@ Future<Database> initDB(DatabaseProvider database) async {
|
||||
"goal_befores": "{}",
|
||||
"goal_pin_dates": "{}",
|
||||
// todo and notes
|
||||
"todo_items": "{}", "self_notes": "[]",
|
||||
"todo_items": "{}", "self_notes": "[]", "self_todo": "[]",
|
||||
// v5 shit
|
||||
"roundings": "{}",
|
||||
"grade_rarities": "{}",
|
||||
"linked_accounts": "[]",
|
||||
"custom_lesson_desc": "{}",
|
||||
"watch_data": "{}",
|
||||
});
|
||||
} catch (error) {
|
||||
print("ERROR: migrateDB: $error");
|
||||
|
||||
@@ -317,6 +317,18 @@ class UserDatabaseQuery {
|
||||
return selfNotes;
|
||||
}
|
||||
|
||||
Future<List<TodoItem>> getTodoItems({required String userId}) async {
|
||||
List<Map> userData =
|
||||
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
|
||||
if (userData.isEmpty) return [];
|
||||
String? todoItemsJson = userData.elementAt(0)["self_todo"] as String?;
|
||||
if (todoItemsJson == null) return [];
|
||||
List<TodoItem> todoItems = (jsonDecode(todoItemsJson) as List)
|
||||
.map((e) => TodoItem.fromJson(e))
|
||||
.toList();
|
||||
return todoItems;
|
||||
}
|
||||
|
||||
// v5
|
||||
Future<Map<String, String>> getRoundings({required String userId}) async {
|
||||
List<Map> userData =
|
||||
|
||||
@@ -196,6 +196,13 @@ class UserDatabaseStore {
|
||||
where: "id = ?", whereArgs: [userId]);
|
||||
}
|
||||
|
||||
Future<void> storeSelfTodoItems(List<TodoItem> todoItems,
|
||||
{required String userId}) async {
|
||||
String todoItemsJson = jsonEncode(todoItems.map((e) => e.json).toList());
|
||||
await db.update("user_data", {"self_todo": todoItemsJson},
|
||||
where: "id = ?", whereArgs: [userId]);
|
||||
}
|
||||
|
||||
// v5
|
||||
Future<void> storeRoundings(Map<String, String> roundings,
|
||||
{required String userId}) async {
|
||||
|
||||
@@ -485,9 +485,10 @@ nem lesz tőle használhatatlan az app, de kikommenteltem, mert még a végén k
|
||||
lesson.lessonIndex,
|
||||
lesson.name,
|
||||
dayTitle(lesson.date),
|
||||
lesson.substituteTeacher!.isRenamed
|
||||
? lesson.substituteTeacher!.renamedTo!
|
||||
: lesson.substituteTeacher!.name
|
||||
((lesson.substituteTeacher?.isRenamed ?? false)
|
||||
? lesson.substituteTeacher?.renamedTo!
|
||||
: lesson.substituteTeacher?.name) ??
|
||||
'',
|
||||
],
|
||||
),
|
||||
notificationDetails,
|
||||
@@ -505,9 +506,10 @@ nem lesz tőle használhatatlan az app, de kikommenteltem, mert még a végén k
|
||||
dayTitle(lesson.date),
|
||||
lesson.lessonIndex,
|
||||
lesson.name,
|
||||
lesson.substituteTeacher!.isRenamed
|
||||
? lesson.substituteTeacher!.renamedTo!
|
||||
: lesson.substituteTeacher!.name
|
||||
((lesson.substituteTeacher?.isRenamed ?? false)
|
||||
? lesson.substituteTeacher?.renamedTo!
|
||||
: lesson.substituteTeacher?.name) ??
|
||||
'',
|
||||
],
|
||||
),
|
||||
notificationDetails,
|
||||
@@ -525,9 +527,10 @@ nem lesz tőle használhatatlan az app, de kikommenteltem, mert még a végén k
|
||||
lesson.lessonIndex,
|
||||
lesson.name,
|
||||
dayTitle(lesson.date),
|
||||
lesson.substituteTeacher!.isRenamed
|
||||
? lesson.substituteTeacher!.renamedTo!
|
||||
: lesson.substituteTeacher!.name
|
||||
((lesson.substituteTeacher?.isRenamed ?? false)
|
||||
? lesson.substituteTeacher?.renamedTo!
|
||||
: lesson.substituteTeacher?.name) ??
|
||||
'',
|
||||
],
|
||||
),
|
||||
notificationDetails,
|
||||
@@ -608,9 +611,10 @@ nem lesz tőle használhatatlan az app, de kikommenteltem, mert még a végén k
|
||||
lesson.lessonIndex,
|
||||
lesson.name,
|
||||
dayTitle(lesson.date),
|
||||
lesson.substituteTeacher!.isRenamed
|
||||
? lesson.substituteTeacher!.renamedTo!
|
||||
: lesson.substituteTeacher!.name
|
||||
((lesson.substituteTeacher?.isRenamed ?? false)
|
||||
? lesson.substituteTeacher?.renamedTo!
|
||||
: lesson.substituteTeacher?.name) ??
|
||||
'',
|
||||
],
|
||||
),
|
||||
notificationDetails,
|
||||
@@ -629,9 +633,10 @@ nem lesz tőle használhatatlan az app, de kikommenteltem, mert még a végén k
|
||||
dayTitle(lesson.date),
|
||||
lesson.lessonIndex,
|
||||
lesson.name,
|
||||
lesson.substituteTeacher!.isRenamed
|
||||
? lesson.substituteTeacher!.renamedTo!
|
||||
: lesson.substituteTeacher!.name
|
||||
((lesson.substituteTeacher?.isRenamed ?? false)
|
||||
? lesson.substituteTeacher?.renamedTo!
|
||||
: lesson.substituteTeacher?.name) ??
|
||||
'',
|
||||
],
|
||||
),
|
||||
notificationDetails,
|
||||
|
||||
@@ -292,3 +292,105 @@ class ShortSubject {
|
||||
return subject?.name.capital() ?? subjectName?.capital() ?? "?";
|
||||
}
|
||||
}
|
||||
|
||||
// new v5 thingie
|
||||
class SubjectBooklet {
|
||||
// static String resolveName({GradeSubject? subject, String? subjectName}) =>
|
||||
// _resolve(subject: subject, subjectName: subjectName).name;
|
||||
static String resolveVariant(
|
||||
{GradeSubject? subject,
|
||||
String? subjectName,
|
||||
required BuildContext context}) =>
|
||||
_resolve(subject: subject, subjectName: subjectName);
|
||||
|
||||
static String _resolve({GradeSubject? subject, String? subjectName}) {
|
||||
assert(!(subject == null && subjectName == null));
|
||||
|
||||
String name = (subject?.name ?? subjectName ?? "")
|
||||
.toLowerCase()
|
||||
.specialChars()
|
||||
.trim();
|
||||
String category =
|
||||
subject?.category.description.toLowerCase().specialChars() ?? "";
|
||||
|
||||
String basePath = "assets/svg/cover_arts";
|
||||
|
||||
// todo: check for categories
|
||||
if (RegExp("mate(k|matika)").hasMatch(name) || category == "matematika") {
|
||||
return "$basePath/grid.svg";
|
||||
} else if (RegExp("magyar nyelv|nyelvtan").hasMatch(name)) {
|
||||
return "$basePath/line.svg";
|
||||
} else if (RegExp("irodalom").hasMatch(name)) {
|
||||
return "$basePath/line.svg";
|
||||
} else if (RegExp("tor(i|tenelem)").hasMatch(name)) {
|
||||
return "$basePath/line.svg";
|
||||
} else if (RegExp("foldrajz").hasMatch(name)) {
|
||||
return "$basePath/plain.svg";
|
||||
} else if (RegExp("rajz|muvtori|muveszet|vizualis").hasMatch(name)) {
|
||||
return "$basePath/plain.svg";
|
||||
} else if (RegExp("fizika").hasMatch(name)) {
|
||||
return "$basePath/plain.svg";
|
||||
} else if (RegExp("^enek|zene|szolfezs|zongora|korus").hasMatch(name)) {
|
||||
return "$basePath/vocal.svg";
|
||||
} else if (RegExp("^tes(i|tneveles)|sport|edzeselmelet").hasMatch(name)) {
|
||||
return "$basePath/plain.svg";
|
||||
} else if (RegExp("kemia").hasMatch(name)) {
|
||||
return "$basePath/plain.svg";
|
||||
} else if (RegExp("biologia").hasMatch(name)) {
|
||||
return "$basePath/plain.svg";
|
||||
} else if (RegExp(
|
||||
"kornyezet|termeszet ?(tudomany|ismeret)|hon( es nep)?ismeret")
|
||||
.hasMatch(name)) {
|
||||
return "$basePath/plain.svg";
|
||||
} else if (RegExp("(hit|erkolcs)tan|vallas|etika|bibliaismeret")
|
||||
.hasMatch(name)) {
|
||||
return "$basePath/line.svg";
|
||||
} else if (RegExp("penzugy").hasMatch(name)) {
|
||||
return "$basePath/plain.svg";
|
||||
} else if (RegExp("informatika|szoftver|iroda|digitalis").hasMatch(name)) {
|
||||
return "$basePath/grid.svg";
|
||||
} else if (RegExp("prog").hasMatch(name)) {
|
||||
return "$basePath/grid.svg";
|
||||
} else if (RegExp("halozat").hasMatch(name)) {
|
||||
return "$basePath/grid.svg";
|
||||
} else if (RegExp("szinhaz").hasMatch(name)) {
|
||||
return "$basePath/vocal.svg";
|
||||
} else if (RegExp("film|media").hasMatch(name)) {
|
||||
return "$basePath/plain.svg";
|
||||
} else if (RegExp("elektro(tech)?nika").hasMatch(name)) {
|
||||
return "$basePath/grid.svg";
|
||||
} else if (RegExp("gepesz|mernok|ipar").hasMatch(name)) {
|
||||
return "$basePath/grid.svg";
|
||||
} else if (RegExp("technika").hasMatch(name)) {
|
||||
return "$basePath/plain.svg";
|
||||
} else if (RegExp("tanc").hasMatch(name)) {
|
||||
return "$basePath/vocal.svg";
|
||||
} else if (RegExp("filozofia").hasMatch(name)) {
|
||||
return "$basePath/line.svg";
|
||||
} else if (RegExp("osztaly(fonoki|kozosseg)|kozossegi|neveles")
|
||||
.hasMatch(name) ||
|
||||
name == "ofo") {
|
||||
return "$basePath/plain.svg";
|
||||
} else if (RegExp("gazdasag").hasMatch(name)) {
|
||||
return "$basePath/line.svg";
|
||||
} else if (RegExp("szorgalom").hasMatch(name)) {
|
||||
return "$basePath/plain.svg";
|
||||
} else if (RegExp("magatartas").hasMatch(name)) {
|
||||
return "$basePath/plain.svg";
|
||||
} else if (RegExp(
|
||||
"angol|nemet|francia|olasz|orosz|spanyol|latin|kinai|nyelv")
|
||||
.hasMatch(name)) {
|
||||
return "$basePath/line.svg";
|
||||
} else if (RegExp("linux").hasMatch(name)) {
|
||||
return "$basePath/plain.svg";
|
||||
} else if (RegExp("adatbazis").hasMatch(name)) {
|
||||
return "$basePath/grid.svg";
|
||||
} else if (RegExp("asztali alkalmazasok").hasMatch(name)) {
|
||||
return "$basePath/grid.svg";
|
||||
} else if (RegExp("projekt").hasMatch(name)) {
|
||||
return "$basePath/plain.svg";
|
||||
}
|
||||
|
||||
return "$basePath/plain.svg";
|
||||
}
|
||||
}
|
||||
|
||||
130
refilc/lib/helpers/uwu_helper.dart
Normal file
@@ -0,0 +1,130 @@
|
||||
import 'dart:math';
|
||||
|
||||
class Uwuifier {
|
||||
final Map<String, double> _spacesModifier;
|
||||
final double _wordsModifier;
|
||||
|
||||
final List<String> faces = [
|
||||
"OwO",
|
||||
"UwU",
|
||||
">w<",
|
||||
"^w^",
|
||||
"^-^",
|
||||
":3",
|
||||
];
|
||||
|
||||
final List<List<String>> uwuMap = [
|
||||
['(?:r|l)', 'w'],
|
||||
['(?:R|L)', 'W'],
|
||||
['na', 'nya'],
|
||||
['ne', 'nye'],
|
||||
['NA', 'NYA'],
|
||||
['NE', 'NYE'],
|
||||
['Na', 'Nya'],
|
||||
['Ne', 'Nye'],
|
||||
['no', 'nyo'],
|
||||
['NO', 'NYO'],
|
||||
['No', 'Nyo'],
|
||||
['nO', 'NYo'],
|
||||
['ove', 'uv'],
|
||||
['no', 'nwo'],
|
||||
];
|
||||
|
||||
final Map<String, String> _uwuCache = {};
|
||||
|
||||
Uwuifier({
|
||||
Map<String, double>? spaces,
|
||||
double? words,
|
||||
}) : _spacesModifier = spaces ?? {
|
||||
'faces': 0.05,
|
||||
'actions': 0.0,
|
||||
'stutters': 0.1,
|
||||
},
|
||||
_wordsModifier = words ?? 1.0;
|
||||
|
||||
String uwuifyWords(String sentence) {
|
||||
final words = sentence.split(' ');
|
||||
|
||||
final uwuifiedSentence = words.map((word) {
|
||||
if (isAt(word) || isUri(word)) return word;
|
||||
|
||||
var seed = Random().nextDouble();
|
||||
for (final uwuMapEntry in uwuMap) {
|
||||
final oldWord = RegExp(uwuMapEntry[0], caseSensitive: false);
|
||||
final newWord = uwuMapEntry[1];
|
||||
if (seed > _wordsModifier) continue;
|
||||
word = word.replaceAll(oldWord, newWord);
|
||||
}
|
||||
|
||||
return word;
|
||||
}).join(' ');
|
||||
|
||||
return uwuifiedSentence;
|
||||
}
|
||||
|
||||
String uwuifySpaces(String sentence) {
|
||||
final words = sentence.split(' ');
|
||||
|
||||
final faceThreshold = _spacesModifier['faces']!;
|
||||
final actionThreshold = _spacesModifier['actions']! + faceThreshold;
|
||||
final stutterThreshold = _spacesModifier['stutters']! + actionThreshold;
|
||||
|
||||
final uwuifiedSentence = words.map((word) {
|
||||
final seed = Random().nextDouble();
|
||||
final firstCharacter = word[0];
|
||||
|
||||
if (seed <= faceThreshold && faces.isNotEmpty) {
|
||||
word += ' ${faces[Random().nextInt(faces.length)]}';
|
||||
} else if (seed <= actionThreshold) {
|
||||
// Skip actions
|
||||
} else if (seed <= stutterThreshold && !isUri(word)) {
|
||||
if (Random().nextInt(10) == 0) {
|
||||
final stutter = Random().nextInt(3);
|
||||
return '${firstCharacter * (stutter + 1)}-$word';
|
||||
}
|
||||
}
|
||||
|
||||
return word;
|
||||
}).join(' ');
|
||||
|
||||
return uwuifiedSentence;
|
||||
}
|
||||
|
||||
String uwuifySentence(String sentence) {
|
||||
if (_uwuCache.containsKey(sentence)) {
|
||||
return _uwuCache[sentence]!;
|
||||
}
|
||||
|
||||
var uwuifiedSentence = uwuifyWords(sentence);
|
||||
uwuifiedSentence = uwuifySpaces(uwuifiedSentence);
|
||||
|
||||
_uwuCache[sentence] = uwuifiedSentence;
|
||||
return uwuifiedSentence;
|
||||
}
|
||||
|
||||
bool isAt(String value) {
|
||||
return value.startsWith('@');
|
||||
}
|
||||
|
||||
bool isUri(String? value) {
|
||||
if (value == null) return false;
|
||||
final split = RegExp(
|
||||
r'''(?:([^:/?#]+):)?(?:\/\/([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?''')
|
||||
.firstMatch(value);
|
||||
if (split == null) return false;
|
||||
final scheme = split.group(1);
|
||||
final authority = split.group(2);
|
||||
final path = split.group(3);
|
||||
if (!(scheme?.isNotEmpty == true && path?.isNotEmpty == true)) return false;
|
||||
if (authority != null && authority.isNotEmpty) {
|
||||
if (!(path?.isEmpty == true || path!.startsWith('/'))) return false;
|
||||
} else if (path?.startsWith('//') == true) {
|
||||
return false;
|
||||
}
|
||||
if (!RegExp(r'''^[a-z][a-z0-9+\-\.]*$''', caseSensitive: false)
|
||||
.hasMatch(scheme!.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -33,3 +33,37 @@ class SelfNote {
|
||||
'note_type': noteType == NoteType.image ? 'image' : 'text',
|
||||
};
|
||||
}
|
||||
|
||||
class TodoItem {
|
||||
String id;
|
||||
String title;
|
||||
String content;
|
||||
bool done;
|
||||
|
||||
Map? json;
|
||||
|
||||
TodoItem({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.content,
|
||||
required this.done,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory TodoItem.fromJson(Map json) {
|
||||
return TodoItem(
|
||||
id: json['id'],
|
||||
title: json['title'],
|
||||
content: json['content'],
|
||||
done: json['done'],
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
|
||||
get toJson => {
|
||||
'id': id,
|
||||
'title': title,
|
||||
'content': content,
|
||||
'done': done,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
// more
|
||||
bool _showBreaks;
|
||||
String _fontFamily;
|
||||
bool _titleOnlyFont;
|
||||
String _plusSessionId;
|
||||
String _calSyncRoomLocation;
|
||||
bool _calSyncShowExams;
|
||||
@@ -105,6 +106,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
bool _navShadow;
|
||||
bool _newColors;
|
||||
bool _uwuMode;
|
||||
bool _newPopups;
|
||||
// quick settings
|
||||
bool _qTimetableLessonNum;
|
||||
bool _qTimetableSubTiles;
|
||||
@@ -167,6 +169,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
required String pinSetNotify,
|
||||
required String pinSetExtras,
|
||||
required String fontFamily,
|
||||
required bool titleOnlyFont,
|
||||
required String plusSessionId,
|
||||
required String calSyncRoomLocation,
|
||||
required bool calSyncShowExams,
|
||||
@@ -176,6 +179,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
required bool navShadow,
|
||||
required bool newColors,
|
||||
required bool uwuMode,
|
||||
required bool newPopups,
|
||||
required bool qTimetableLessonNum,
|
||||
required bool qTimetableSubTiles,
|
||||
required bool qSubjectsSubTiles,
|
||||
@@ -235,6 +239,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
_pinSetNotify = pinSetNotify,
|
||||
_pinSetExtras = pinSetExtras,
|
||||
_fontFamily = fontFamily,
|
||||
_titleOnlyFont = titleOnlyFont,
|
||||
_plusSessionId = plusSessionId,
|
||||
_calSyncRoomLocation = calSyncRoomLocation,
|
||||
_calSyncShowExams = calSyncShowExams,
|
||||
@@ -244,6 +249,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
_navShadow = navShadow,
|
||||
_newColors = newColors,
|
||||
_uwuMode = uwuMode,
|
||||
_newPopups = newPopups,
|
||||
_qTimetableLessonNum = qTimetableLessonNum,
|
||||
_qTimetableSubTiles = qTimetableSubTiles,
|
||||
_qSubjectsSubTiles = qSubjectsSubTiles;
|
||||
@@ -322,6 +328,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
pinSetNotify: map['notify_s_pin'],
|
||||
pinSetExtras: map['extras_s_pin'],
|
||||
fontFamily: map['font_family'],
|
||||
titleOnlyFont: map['title_only_font'] == 1,
|
||||
plusSessionId: map['plus_session_id'],
|
||||
calSyncRoomLocation: map['cal_sync_room_location'],
|
||||
calSyncShowExams: map['cal_sync_show_exams'] == 1,
|
||||
@@ -331,6 +338,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
navShadow: map['nav_shadow'] == 1,
|
||||
newColors: map['new_colors'] == 1,
|
||||
uwuMode: map['uwu_mode'] == 1,
|
||||
newPopups: map['new_popups'] == 1,
|
||||
qTimetableLessonNum: map['q_timetable_lesson_num'] == 1,
|
||||
qTimetableSubTiles: map['q_timetable_sub_tiles'] == 1,
|
||||
qSubjectsSubTiles: map['q_subjects_sub_tiles'] == 1,
|
||||
@@ -397,6 +405,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
"notify_s_pin": _pinSetNotify,
|
||||
"extras_s_pin": _pinSetExtras,
|
||||
"font_family": _fontFamily,
|
||||
"title_only_font": _titleOnlyFont ? 1 : 0,
|
||||
"plus_session_id": _plusSessionId,
|
||||
"cal_sync_room_location": _calSyncRoomLocation,
|
||||
"cal_sync_show_exams": _calSyncShowExams ? 1 : 0,
|
||||
@@ -406,6 +415,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
"nav_shadow": _navShadow ? 1 : 0,
|
||||
"new_colors": _newColors ? 1 : 0,
|
||||
"uwu_mode": _uwuMode ? 1 : 0,
|
||||
"new_popups": _newPopups ? 1 : 0,
|
||||
"q_timetable_lesson_num": _qTimetableLessonNum ? 1 : 0,
|
||||
"q_timetable_sub_tiles": _qTimetableSubTiles ? 1 : 0,
|
||||
"q_subjects_sub_tiles": _qSubjectsSubTiles ? 1 : 0,
|
||||
@@ -476,6 +486,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
pinSetNotify: '',
|
||||
pinSetExtras: '',
|
||||
fontFamily: '',
|
||||
titleOnlyFont: false,
|
||||
plusSessionId: '',
|
||||
calSyncRoomLocation: 'location',
|
||||
calSyncShowExams: true,
|
||||
@@ -485,6 +496,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
navShadow: true,
|
||||
newColors: true,
|
||||
uwuMode: false,
|
||||
newPopups: true,
|
||||
qTimetableLessonNum: true,
|
||||
qTimetableSubTiles: true,
|
||||
qSubjectsSubTiles: true,
|
||||
@@ -546,6 +558,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
String get currentThemeCreator => _currentThemeCreator;
|
||||
bool get showBreaks => _showBreaks;
|
||||
String get fontFamily => _fontFamily;
|
||||
bool get titleOnlyFont => _titleOnlyFont;
|
||||
String get plusSessionId => _plusSessionId;
|
||||
String get calSyncRoomLocation => _calSyncRoomLocation;
|
||||
bool get calSyncShowExams => _calSyncShowExams;
|
||||
@@ -555,6 +568,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
bool get navShadow => _navShadow;
|
||||
bool get newColors => _newColors;
|
||||
bool get uwuMode => _uwuMode;
|
||||
bool get newPopups => _newPopups;
|
||||
bool get qTimetableLessonNum => _qTimetableLessonNum;
|
||||
bool get qTimetableSubTiles => _qTimetableSubTiles;
|
||||
bool get qSubjectsSubTiles => _qSubjectsSubTiles;
|
||||
@@ -612,6 +626,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
String? currentThemeCreator,
|
||||
bool? showBreaks,
|
||||
String? fontFamily,
|
||||
bool? titleOnlyFont,
|
||||
String? plusSessionId,
|
||||
String? calSyncRoomLocation,
|
||||
bool? calSyncShowExams,
|
||||
@@ -621,6 +636,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
bool? navShadow,
|
||||
bool? newColors,
|
||||
bool? uwuMode,
|
||||
bool? newPopups,
|
||||
bool? qTimetableLessonNum,
|
||||
bool? qTimetableSubTiles,
|
||||
bool? qSubjectsSubTiles,
|
||||
@@ -777,6 +793,9 @@ class SettingsProvider extends ChangeNotifier {
|
||||
if (fontFamily != null && fontFamily != _fontFamily) {
|
||||
_fontFamily = fontFamily;
|
||||
}
|
||||
if (titleOnlyFont != null && titleOnlyFont != _titleOnlyFont) {
|
||||
_titleOnlyFont = titleOnlyFont;
|
||||
}
|
||||
if (plusSessionId != null && plusSessionId != _plusSessionId) {
|
||||
_plusSessionId = plusSessionId;
|
||||
}
|
||||
@@ -806,6 +825,9 @@ class SettingsProvider extends ChangeNotifier {
|
||||
if (uwuMode != null && uwuMode != _uwuMode) {
|
||||
_uwuMode = uwuMode;
|
||||
}
|
||||
if (newPopups != null && newPopups != _newPopups) {
|
||||
_newPopups = newPopups;
|
||||
}
|
||||
if (qTimetableLessonNum != null &&
|
||||
qTimetableLessonNum != _qTimetableLessonNum) {
|
||||
_qTimetableLessonNum = qTimetableLessonNum;
|
||||
|
||||
@@ -16,8 +16,10 @@ class User {
|
||||
Role role;
|
||||
String nickname;
|
||||
String picture;
|
||||
int gradeStreak;
|
||||
|
||||
String get displayName => nickname != '' ? nickname : name;
|
||||
bool get hasStreak => gradeStreak > 0;
|
||||
|
||||
User({
|
||||
String? id,
|
||||
@@ -29,6 +31,7 @@ class User {
|
||||
required this.role,
|
||||
this.nickname = "",
|
||||
this.picture = "",
|
||||
this.gradeStreak = 0,
|
||||
}) {
|
||||
if (id != null) {
|
||||
this.id = id;
|
||||
@@ -57,6 +60,7 @@ class User {
|
||||
role: Role.values[map["role"] ?? 0],
|
||||
nickname: map["nickname"] ?? "",
|
||||
picture: map["picture"] ?? "",
|
||||
gradeStreak: map["grade_streak"] ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -104,9 +104,10 @@ class AppTheme {
|
||||
brightness: Brightness.light,
|
||||
useMaterial3: true,
|
||||
fontFamily: _defaultFontFamily,
|
||||
textTheme:
|
||||
googleFontsMap[settings.fontFamily]?.apply(bodyColor: textColor) ??
|
||||
const TextTheme().apply(bodyColor: textColor),
|
||||
textTheme: !settings.titleOnlyFont
|
||||
? (googleFontsMap[settings.fontFamily]?.apply(bodyColor: textColor) ??
|
||||
const TextTheme().apply(bodyColor: textColor))
|
||||
: null,
|
||||
scaffoldBackgroundColor: backgroundColor,
|
||||
primaryColor: lightColors.filc,
|
||||
dividerColor: const Color(0x00000000),
|
||||
@@ -229,8 +230,9 @@ class AppTheme {
|
||||
brightness: Brightness.dark,
|
||||
useMaterial3: true,
|
||||
fontFamily: _defaultFontFamily,
|
||||
textTheme:
|
||||
googleFontsMap[settings.fontFamily]?.apply(bodyColor: textColor),
|
||||
textTheme: !settings.titleOnlyFont
|
||||
? (googleFontsMap[settings.fontFamily]?.apply(bodyColor: textColor))
|
||||
: null,
|
||||
scaffoldBackgroundColor: backgroundColor,
|
||||
primaryColor: darkColors.filc,
|
||||
dividerColor: const Color(0x00000000),
|
||||
|
||||
@@ -192,6 +192,8 @@ class FilcColorPickerState extends State<FilcColorPicker> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool advOverride = widget.colorMode == CustomColorMode.grade ? true : false;
|
||||
|
||||
if (MediaQuery.of(context).orientation == Orientation.portrait ||
|
||||
widget.portraitOnly) {
|
||||
return Column(
|
||||
@@ -218,7 +220,7 @@ class FilcColorPickerState extends State<FilcColorPicker> {
|
||||
child: colorPickerSlider(TrackType.saturation),
|
||||
),
|
||||
),
|
||||
if (isAdvancedView)
|
||||
if (isAdvancedView || advOverride)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 12.0, right: 12.0),
|
||||
child: SizedBox(
|
||||
@@ -230,7 +232,7 @@ class FilcColorPickerState extends State<FilcColorPicker> {
|
||||
],
|
||||
),
|
||||
),
|
||||
if (isAdvancedView &&
|
||||
if ((isAdvancedView || advOverride) &&
|
||||
widget.colorMode != CustomColorMode.theme &&
|
||||
widget.colorMode != CustomColorMode.enterId)
|
||||
Padding(
|
||||
@@ -295,7 +297,8 @@ class FilcColorPickerState extends State<FilcColorPicker> {
|
||||
],
|
||||
),
|
||||
),
|
||||
if (widget.colorMode != CustomColorMode.enterId)
|
||||
if (widget.colorMode != CustomColorMode.enterId &&
|
||||
widget.colorMode != CustomColorMode.grade)
|
||||
SizedBox(
|
||||
height: 70 * (widget.colorMode == CustomColorMode.theme ? 2 : 1),
|
||||
child: BlockPicker(
|
||||
@@ -347,7 +350,8 @@ class FilcColorPickerState extends State<FilcColorPicker> {
|
||||
),
|
||||
),
|
||||
if (widget.colorMode != CustomColorMode.theme &&
|
||||
widget.colorMode != CustomColorMode.enterId)
|
||||
widget.colorMode != CustomColorMode.enterId &&
|
||||
!advOverride)
|
||||
Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:i18n_extension/i18n_extension.dart';
|
||||
import 'package:refilc/models/settings.dart';
|
||||
import 'package:refilc_kreta_api/providers/exam_provider.dart';
|
||||
import 'package:refilc_kreta_api/providers/homework_provider.dart';
|
||||
@@ -8,7 +9,8 @@ import 'package:refilc_kreta_api/models/lesson.dart';
|
||||
import 'package:refilc/utils/format.dart';
|
||||
import 'package:refilc_mobile_ui/common/panel/panel.dart';
|
||||
import 'package:refilc_mobile_ui/common/round_border_icon.dart';
|
||||
import 'package:refilc_mobile_ui/common/widgets/exam/exam_view.dart';
|
||||
// import 'package:refilc_mobile_ui/common/widgets/exam/exam_view.dart';
|
||||
import 'package:refilc_mobile_ui/common/widgets/exam/exam_viewable.dart';
|
||||
import 'package:refilc_mobile_ui/common/widgets/homework/homework_view.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||
@@ -109,7 +111,8 @@ class LessonTile extends StatelessWidget {
|
||||
title: exam.description != ""
|
||||
? exam.description
|
||||
: exam.mode?.description ?? "exam".i18n,
|
||||
onPressed: () => ExamView.show(exam, context: context),
|
||||
// onPressed: () => ExamView.show(exam, context: context),
|
||||
onPressed: () => ExamPopup.show(context: context, exam: exam),
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -190,7 +193,7 @@ class LessonTile extends StatelessWidget {
|
||||
: Transform.translate(
|
||||
offset: const Offset(0, -2.0),
|
||||
child: Text(
|
||||
"${DateFormat("H:mm").format(lesson.start)}-${DateFormat("H:mm").format(lesson.end)}",
|
||||
"${DateFormat("E, H:mm", I18n.of(context).locale.toString()).format(lesson.start)}-${DateFormat("H:mm").format(lesson.end)}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
|
||||
@@ -3,7 +3,7 @@ description: "Egy nem hivatalos e-KRÉTA kliens, diákoktól diákoknak."
|
||||
homepage: https://refilc.hu
|
||||
publish_to: "none"
|
||||
|
||||
version: 5.0.0+257
|
||||
version: 5.0.2+266
|
||||
|
||||
environment:
|
||||
sdk: ">=2.17.0 <=3.3.2"
|
||||
@@ -104,6 +104,7 @@ flutter:
|
||||
- assets/svg/menu_icons/
|
||||
- assets/other/dirtywords.xml
|
||||
- assets/svg/
|
||||
- assets/svg/cover_arts/
|
||||
|
||||
fonts:
|
||||
- family: FilcIcons
|
||||
|
||||
@@ -268,7 +268,7 @@ class GradesPageState extends State<GradesPage> {
|
||||
title: Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: Text(
|
||||
"Grades".i18n,
|
||||
"page_title_grades".i18n,
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text,
|
||||
fontSize: 32.0,
|
||||
|
||||
@@ -80,8 +80,8 @@ class KretaClient {
|
||||
_status.triggerRequest(res);
|
||||
|
||||
if (res.statusCode == 401) {
|
||||
await refreshLogin();
|
||||
headerMap.remove("authorization");
|
||||
await refreshLogin();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@@ -212,8 +212,8 @@ class KretaClient {
|
||||
res = await request.send();
|
||||
|
||||
if (res.statusCode == 401) {
|
||||
await refreshLogin();
|
||||
headerMap.remove("authorization");
|
||||
await refreshLogin();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// ignore_for_file: no_leading_underscores_for_local_identifiers
|
||||
|
||||
import 'package:refilc/utils/format.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
import 'category.dart';
|
||||
import 'subject.dart';
|
||||
import 'teacher.dart';
|
||||
@@ -75,6 +76,40 @@ class Grade {
|
||||
);
|
||||
}
|
||||
|
||||
factory Grade.fromExportJson(Map json) {
|
||||
return Grade(
|
||||
id: const Uuid().v4(),
|
||||
date: json["date"] != null ? DateTime.parse(json["date"]) : DateTime(0),
|
||||
value: GradeValue(
|
||||
json["value"] ?? 0,
|
||||
json["value_name"] ?? "",
|
||||
json["value_name"] ?? "",
|
||||
json["weight"] ?? 0,
|
||||
percentage: false,
|
||||
),
|
||||
teacher: Teacher.fromString((json["teacher"] ?? "").trim()),
|
||||
description: json["description"] ?? "",
|
||||
type: json["type"] != null
|
||||
? Category.getGradeType(json["type"]
|
||||
.replaceAll("midYear", "evkozi_jegy_ertekeles")
|
||||
.replaceAll("halfYear", "felevi_jegy_ertekeles")
|
||||
.replaceAll("endYear", "evvegi_jegy_ertekeles"))
|
||||
: GradeType.unknown,
|
||||
groupId: const Uuid().v4(),
|
||||
subject: GradeSubject(
|
||||
id: const Uuid().v4(),
|
||||
category: Category.fromJson({}),
|
||||
name: json["subject"] ?? ""),
|
||||
mode: Category.fromJson({}),
|
||||
writeDate:
|
||||
json["date"] != null ? DateTime.parse(json["date"]) : DateTime(0),
|
||||
seenDate:
|
||||
json["date"] != null ? DateTime.parse(json["date"]) : DateTime(0),
|
||||
form: "",
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
|
||||
bool compareTo(dynamic other) {
|
||||
if (runtimeType != other.runtimeType) return false;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ class Student {
|
||||
String? address;
|
||||
String? groupId;
|
||||
List<String> parents;
|
||||
// List<String> parentsPhone;
|
||||
String? className;
|
||||
|
||||
Student({
|
||||
@@ -21,6 +22,7 @@ class Student {
|
||||
required this.yearId,
|
||||
this.address,
|
||||
required this.parents,
|
||||
// required this.parentsPhone,
|
||||
this.json,
|
||||
});
|
||||
|
||||
|
||||
@@ -50,7 +50,8 @@ class GradeProvider with ChangeNotifier {
|
||||
String? userId = _user.id;
|
||||
if (userId != null) {
|
||||
final userStore = _database.userStore;
|
||||
userStore.storeLastSeen(DateTime.now(), userId: userId, category: LastSeenCategory.surprisegrade);
|
||||
userStore.storeLastSeen(DateTime.now(),
|
||||
userId: userId, category: LastSeenCategory.surprisegrade);
|
||||
_lastSeen = DateTime.now();
|
||||
}
|
||||
}
|
||||
@@ -59,7 +60,8 @@ class GradeProvider with ChangeNotifier {
|
||||
String? userId = _user.id;
|
||||
if (userId != null) {
|
||||
final userStore = _database.userStore;
|
||||
userStore.storeLastSeen(DateTime(1969), userId: userId, category: LastSeenCategory.surprisegrade);
|
||||
userStore.storeLastSeen(DateTime(1969),
|
||||
userId: userId, category: LastSeenCategory.surprisegrade);
|
||||
_lastSeen = DateTime(1969);
|
||||
}
|
||||
}
|
||||
@@ -73,9 +75,11 @@ class GradeProvider with ChangeNotifier {
|
||||
|
||||
_grades = await userQuery.getGrades(userId: userId);
|
||||
await convertBySettings();
|
||||
await getGradeStreak();
|
||||
_groupAvg = await userQuery.getGroupAverages(userId: userId);
|
||||
notifyListeners();
|
||||
DateTime lastSeenDB = await userQuery.lastSeen(userId: userId, category: LastSeenCategory.surprisegrade);
|
||||
DateTime lastSeenDB = await userQuery.lastSeen(
|
||||
userId: userId, category: LastSeenCategory.surprisegrade);
|
||||
if (lastSeenDB.millisecondsSinceEpoch == 0 ||
|
||||
lastSeenDB.year == 0 ||
|
||||
!_settings.gradeOpeningFun) {
|
||||
@@ -133,6 +137,28 @@ class GradeProvider with ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// get current grade streak and set it to the user
|
||||
Future<void> getGradeStreak() async {
|
||||
User? user = _user.user;
|
||||
if (user == null) throw "Cannot get Grade Streak for User null";
|
||||
|
||||
// streak magic
|
||||
int gradeStreak = 0;
|
||||
List<Grade> grs = _grades;
|
||||
grs.sort((a, b) => -a.date.compareTo(b.date));
|
||||
|
||||
for (Grade grade in grs) {
|
||||
if (grade.value.value == 5) {
|
||||
gradeStreak++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
user.gradeStreak = gradeStreak;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Fetches Grades from the Kreta API then stores them in the database
|
||||
Future<void> fetch() async {
|
||||
// test cucc
|
||||
@@ -173,6 +199,7 @@ class GradeProvider with ChangeNotifier {
|
||||
await _database.userStore.storeGrades(grades, userId: userId);
|
||||
_grades = grades;
|
||||
await convertBySettings();
|
||||
await getGradeStreak();
|
||||
}
|
||||
|
||||
Future<void> storeGroupAvg(List<GroupAverage> groupAvgs) async {
|
||||
|
||||
@@ -19,11 +19,13 @@ class ShareProvider extends ChangeNotifier {
|
||||
// }
|
||||
|
||||
// themes
|
||||
Future<SharedTheme> shareCurrentTheme(BuildContext context,
|
||||
{bool isPublic = false,
|
||||
bool shareNick = true,
|
||||
required SharedGradeColors gradeColors,
|
||||
String displayName = ''}) async {
|
||||
Future<SharedTheme> shareCurrentTheme(
|
||||
BuildContext context, {
|
||||
bool isPublic = false,
|
||||
bool shareNick = true,
|
||||
required SharedGradeColors gradeColors,
|
||||
String displayName = '',
|
||||
}) async {
|
||||
final SettingsProvider settings =
|
||||
Provider.of<SettingsProvider>(context, listen: false);
|
||||
|
||||
@@ -69,7 +71,25 @@ class ShareProvider extends ChangeNotifier {
|
||||
|
||||
if (gradeColorsJson != null) {
|
||||
SharedTheme theme = SharedTheme.fromJson(
|
||||
themeJson, SharedGradeColors.fromJson(gradeColorsJson));
|
||||
themeJson,
|
||||
SharedGradeColors.fromJson(gradeColorsJson["public_id"] != ''
|
||||
? gradeColorsJson
|
||||
: {
|
||||
"public_id": "0",
|
||||
"is_public": false,
|
||||
"nickname": "Anonymous",
|
||||
"five_color":
|
||||
SettingsProvider.defaultSettings().gradeColors[4].value,
|
||||
"four_color":
|
||||
SettingsProvider.defaultSettings().gradeColors[3].value,
|
||||
"three_color":
|
||||
SettingsProvider.defaultSettings().gradeColors[2].value,
|
||||
"two_color":
|
||||
SettingsProvider.defaultSettings().gradeColors[1].value,
|
||||
"one_color":
|
||||
SettingsProvider.defaultSettings().gradeColors[0].value,
|
||||
}),
|
||||
);
|
||||
return theme;
|
||||
}
|
||||
}
|
||||
@@ -93,7 +113,25 @@ class ShareProvider extends ChangeNotifier {
|
||||
|
||||
if (gradeColorsJson != null) {
|
||||
SharedTheme theme = SharedTheme.fromJson(
|
||||
t, SharedGradeColors.fromJson(gradeColorsJson));
|
||||
t,
|
||||
SharedGradeColors.fromJson(gradeColorsJson["public_id"] != ''
|
||||
? gradeColorsJson
|
||||
: {
|
||||
"public_id": "0",
|
||||
"is_public": false,
|
||||
"nickname": "Anonymous",
|
||||
"five_color":
|
||||
SettingsProvider.defaultSettings().gradeColors[4].value,
|
||||
"four_color":
|
||||
SettingsProvider.defaultSettings().gradeColors[3].value,
|
||||
"three_color":
|
||||
SettingsProvider.defaultSettings().gradeColors[2].value,
|
||||
"two_color":
|
||||
SettingsProvider.defaultSettings().gradeColors[1].value,
|
||||
"one_color":
|
||||
SettingsProvider.defaultSettings().gradeColors[0].value,
|
||||
}),
|
||||
);
|
||||
|
||||
themes.add(theme);
|
||||
}
|
||||
@@ -134,8 +172,25 @@ class ShareProvider extends ChangeNotifier {
|
||||
Map? gradeColorsJson = await FilcAPI.getSharedGradeColors(id);
|
||||
|
||||
if (gradeColorsJson != null) {
|
||||
SharedGradeColors gradeColors =
|
||||
SharedGradeColors.fromJson(gradeColorsJson);
|
||||
SharedGradeColors gradeColors = SharedGradeColors.fromJson(
|
||||
gradeColorsJson["public_id"] != ''
|
||||
? gradeColorsJson
|
||||
: {
|
||||
"public_id": "0",
|
||||
"is_public": false,
|
||||
"nickname": "Anonymous",
|
||||
"five_color":
|
||||
SettingsProvider.defaultSettings().gradeColors[4].value,
|
||||
"four_color":
|
||||
SettingsProvider.defaultSettings().gradeColors[3].value,
|
||||
"three_color":
|
||||
SettingsProvider.defaultSettings().gradeColors[2].value,
|
||||
"two_color":
|
||||
SettingsProvider.defaultSettings().gradeColors[1].value,
|
||||
"one_color":
|
||||
SettingsProvider.defaultSettings().gradeColors[0].value,
|
||||
},
|
||||
);
|
||||
return gradeColors;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
import 'package:dotted_border/dotted_border.dart';
|
||||
import 'package:refilc/theme/colors/colors.dart';
|
||||
import 'package:refilc/ui/widgets/grade/grade_tile.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:i18n_extension/i18n_extension.dart';
|
||||
|
||||
class AverageDisplay extends StatelessWidget {
|
||||
const AverageDisplay({super.key, this.average = 0.0, this.border = false});
|
||||
const AverageDisplay({
|
||||
super.key,
|
||||
this.average = 0.0,
|
||||
this.border = false,
|
||||
this.dashed = false,
|
||||
this.scale = 1.0,
|
||||
});
|
||||
|
||||
final double average;
|
||||
final bool border;
|
||||
final bool dashed;
|
||||
final double scale;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -20,25 +29,44 @@ class AverageDisplay extends StatelessWidget {
|
||||
averageText = averageText.replaceAll(".", ",");
|
||||
}
|
||||
|
||||
Widget txtWidget = Text(
|
||||
average == 0.0 ? "-" : averageText,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: color, fontWeight: FontWeight.w600, fontSize: scale * 15.0),
|
||||
maxLines: 1,
|
||||
);
|
||||
|
||||
return Container(
|
||||
width: border ? 57.0 : 54.0,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 6.0 - (border ? 2 : 0), vertical: 5.0 - (border ? 2 : 0)),
|
||||
width: (border ? 57.0 : 54.0) * scale,
|
||||
padding: (border && dashed)
|
||||
? null
|
||||
: EdgeInsets.symmetric(
|
||||
horizontal: (6.0 - (border ? 2 : 0)) * scale,
|
||||
vertical: (5.0 - (border ? 2 : 0))) *
|
||||
scale,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(45.0),
|
||||
border: border
|
||||
borderRadius:
|
||||
(border && dashed) ? null : BorderRadius.circular(45.0 * scale),
|
||||
border: border && !dashed
|
||||
? Border.fromBorderSide(
|
||||
BorderSide(color: color.withOpacity(.5), width: 1.0))
|
||||
BorderSide(color: color.withOpacity(.5), width: 1.0 * scale))
|
||||
: null,
|
||||
color: !border ? color.withOpacity(average == 0.0 ? .15 : .25) : null,
|
||||
),
|
||||
child: Text(
|
||||
average == 0.0 ? "-" : averageText,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: color, fontWeight: FontWeight.w600, fontSize: 15.0),
|
||||
maxLines: 1,
|
||||
),
|
||||
child: (border && dashed)
|
||||
? DottedBorder(
|
||||
strokeWidth: 1.0 * scale,
|
||||
padding: EdgeInsets.all(4.0 * scale),
|
||||
color: color.withOpacity(.5),
|
||||
dashPattern: const [6, 6],
|
||||
radius: Radius.circular(45.0 * scale),
|
||||
borderType: BorderType.RRect,
|
||||
child: Center(
|
||||
child: txtWidget,
|
||||
),
|
||||
)
|
||||
: txtWidget,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:refilc/helpers/subject.dart';
|
||||
import 'package:refilc/theme/colors/colors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:refilc/theme/colors/utils.dart';
|
||||
@@ -113,7 +114,9 @@ class HeroScrollViewState extends State<HeroScrollView> {
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 26.0),
|
||||
child: SvgPicture.asset(
|
||||
"assets/svg/mesh_bg.svg",
|
||||
// "assets/svg/mesh_bg.svg",
|
||||
SubjectBooklet.resolveVariant(
|
||||
context: context, subjectName: widget.title),
|
||||
// ignore: deprecated_member_use
|
||||
color: ColorsUtils()
|
||||
.darken(
|
||||
|
||||
@@ -49,6 +49,8 @@ extension Localization on String {
|
||||
"d_npc":
|
||||
"You're such a non-player character, we couldn't give you a personality.",
|
||||
"s_npc": "In-game playtime (hours)",
|
||||
// other
|
||||
"year_index": "Lesson Number",
|
||||
},
|
||||
"hu_hu": {
|
||||
// main
|
||||
@@ -96,6 +98,8 @@ extension Localization on String {
|
||||
"d_npc":
|
||||
"Egy akkora nagy non-player character vagy, hogy neked semmilyen személyiség nem jutott ezen kívül.",
|
||||
"s_npc": "In-game playtime (óra)",
|
||||
// other
|
||||
"year_index": "Éves óraszám",
|
||||
},
|
||||
"de_de": {
|
||||
// main
|
||||
@@ -144,6 +148,8 @@ extension Localization on String {
|
||||
"d_npc":
|
||||
"Du bist einfach so sehr wie ein Computer, dass wir dir nicht einmal eine Persönlichkeit geben konnten.",
|
||||
"s_npc": "Spielzeit (Stunden)",
|
||||
// other
|
||||
"year_index": "Ordinalzahl",
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ class ProfileButton extends StatelessWidget {
|
||||
radius: child.radius,
|
||||
badge: child.badge,
|
||||
role: child.role,
|
||||
gradeStreak: child.gradeStreak,
|
||||
profilePictureString: child.profilePictureString,
|
||||
onTap: () {
|
||||
showSlidingBottomSheet(
|
||||
|
||||
@@ -21,6 +21,7 @@ class ProfileImage extends StatefulWidget {
|
||||
this.censored = false,
|
||||
this.profilePictureString = "",
|
||||
this.isNotePfp = false,
|
||||
this.gradeStreak = false,
|
||||
});
|
||||
|
||||
final void Function()? onTap;
|
||||
@@ -35,6 +36,7 @@ class ProfileImage extends StatefulWidget {
|
||||
final bool censored;
|
||||
final String profilePictureString;
|
||||
final bool isNotePfp;
|
||||
final bool gradeStreak;
|
||||
|
||||
@override
|
||||
State<ProfileImage> createState() => _ProfileImageState();
|
||||
@@ -145,6 +147,20 @@ class _ProfileImageState extends State<ProfileImage> {
|
||||
color: roleColor, size: widget.radius / 1.3),
|
||||
),
|
||||
),
|
||||
|
||||
// streak indicator
|
||||
// if (widget.gradeStreak)
|
||||
// SizedBox(
|
||||
// height: widget.radius * 2,
|
||||
// width: widget.radius * 2,
|
||||
// child: Container(
|
||||
// alignment: Alignment.topLeft,
|
||||
// child: Text(
|
||||
// '🔥',
|
||||
// style: TextStyle(fontSize: widget.radius * 0.9),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -238,6 +254,29 @@ class _ProfileImageState extends State<ProfileImage> {
|
||||
),
|
||||
),
|
||||
|
||||
// streak indicator
|
||||
if (widget.gradeStreak)
|
||||
Hero(
|
||||
tag: "${widget.heroTag!}streak_indicator",
|
||||
child: FittedBox(
|
||||
fit: BoxFit.fitHeight,
|
||||
child: SizedBox(
|
||||
height: widget.radius * 2,
|
||||
width: widget.radius * 2,
|
||||
child: Transform.translate(
|
||||
offset: Offset(-widget.radius / 4, -widget.radius / 4),
|
||||
child: Container(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Text(
|
||||
'🔥',
|
||||
style: TextStyle(fontSize: widget.radius * 0.8),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Material(
|
||||
color: Colors.transparent,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
|
||||
@@ -9,7 +9,7 @@ extension Localization on String {
|
||||
"unexcused": "unexcused %s",
|
||||
"absence": "absence",
|
||||
"delay": "delay",
|
||||
"minute": " minutes of ".one(" minute of "),
|
||||
"minute": " minute(s) of ",
|
||||
},
|
||||
"hu_hu": {
|
||||
"excused": "igazolt %s",
|
||||
@@ -25,7 +25,7 @@ extension Localization on String {
|
||||
"unexcused": "unanerkannt %s",
|
||||
"absence": "Abwesenheit",
|
||||
"delay": "Verspätung",
|
||||
"minute": " Minuten ".one(" Minute "),
|
||||
"minute": " Minute(n) ",
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ extension Localization on String {
|
||||
"Mode": "Mode",
|
||||
"Submit date": "Submit Date",
|
||||
"show in timetable": "Show in timetable",
|
||||
"minutes": "minutes".one("minute"),
|
||||
"minutes": "minute(s)",
|
||||
"delay": "Delay",
|
||||
},
|
||||
"hu_hu": {
|
||||
@@ -27,7 +27,7 @@ extension Localization on String {
|
||||
"Mode": "Typ",
|
||||
"Submit date": "Datum einreichen",
|
||||
"show in timetable": "im Stundenplan anzeigen",
|
||||
"minutes": "Minuten".one("Minute"),
|
||||
"minutes": "Minute(n)",
|
||||
"delay": "Verspätung",
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:i18n_extension/i18n_extension.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:refilc/helpers/subject.dart';
|
||||
@@ -13,8 +14,11 @@ import 'package:refilc_kreta_api/models/exam.dart';
|
||||
import 'package:refilc_kreta_api/models/lesson.dart';
|
||||
import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
|
||||
import 'package:refilc_mobile_ui/common/round_border_icon.dart';
|
||||
import 'package:refilc_mobile_ui/common/viewable.dart';
|
||||
import 'package:refilc_mobile_ui/common/widgets/card_handle.dart';
|
||||
import 'package:refilc_mobile_ui/common/widgets/exam/exam_tile.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:refilc_mobile_ui/common/widgets/exam/exam_view.dart';
|
||||
|
||||
class ExamViewable extends StatelessWidget {
|
||||
const ExamViewable(this.exam,
|
||||
@@ -26,22 +30,25 @@ class ExamViewable extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () => ExamPopup.show(context: context, exam: exam),
|
||||
child: ExamTile(
|
||||
if (Provider.of<SettingsProvider>(context).newPopups) {
|
||||
return GestureDetector(
|
||||
onTap: () => ExamPopup.show(context: context, exam: exam),
|
||||
child: ExamTile(
|
||||
exam,
|
||||
showSubject: showSubject,
|
||||
padding: tilePadding,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Viewable(
|
||||
tile: ExamTile(
|
||||
exam,
|
||||
showSubject: showSubject,
|
||||
padding: tilePadding,
|
||||
),
|
||||
view: CardHandle(child: ExamView(exam)),
|
||||
);
|
||||
// return Viewable(
|
||||
// tile: ExamTile(
|
||||
// exam,
|
||||
// showSubject: showSubject,
|
||||
// padding: tilePadding,
|
||||
// ),
|
||||
// view: CardHandle(child: ExamView(exam)),
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +105,9 @@ class ExamPopup extends StatelessWidget {
|
||||
Stack(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
"assets/svg/mesh_bg.svg",
|
||||
// "assets/svg/mesh_bg.svg",
|
||||
SubjectBooklet.resolveVariant(
|
||||
context: context, subject: exam.subject),
|
||||
// ignore: deprecated_member_use
|
||||
color: ColorsUtils()
|
||||
.fade(context, Theme.of(context).colorScheme.secondary,
|
||||
@@ -210,13 +219,19 @@ class ExamPopup extends StatelessWidget {
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
exam.description.capital(),
|
||||
style: TextStyle(
|
||||
color:
|
||||
AppColors.of(context).text.withOpacity(0.9),
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width * 0.7,
|
||||
child: Text(
|
||||
exam.description.capital(),
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context)
|
||||
.text
|
||||
.withOpacity(0.9),
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
@@ -288,7 +303,7 @@ class ExamPopup extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
Text(
|
||||
'${DateFormat('H:mm').format(lesson!.start)} - ${DateFormat('H:mm').format(lesson!.end)}',
|
||||
'${DateFormat('MMM d, H:mm', I18n.locale.countryCode).format(lesson!.start).capital()} - ${DateFormat('H:mm').format(lesson!.end)}',
|
||||
style: TextStyle(
|
||||
color:
|
||||
AppColors.of(context).text.withOpacity(0.85),
|
||||
|
||||
@@ -12,6 +12,7 @@ extension Localization on String {
|
||||
"l_desc": "Description...",
|
||||
"done": "Done",
|
||||
"cancel": "Cancel",
|
||||
"year_index": "Lesson Number",
|
||||
},
|
||||
"hu_hu": {
|
||||
"Room": "Terem",
|
||||
@@ -22,6 +23,7 @@ extension Localization on String {
|
||||
"l_desc": "Leírás...",
|
||||
"done": "Kész",
|
||||
"cancel": "Mégse",
|
||||
"year_index": "Éves óraszám",
|
||||
},
|
||||
"de_de": {
|
||||
"Room": "Raum",
|
||||
@@ -32,6 +34,7 @@ extension Localization on String {
|
||||
"l_desc": "Beschreibung...",
|
||||
"done": "Erledigt",
|
||||
"cancel": "Abbrechen",
|
||||
"year_index": "Ordinalzahl",
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
@@ -8,11 +9,21 @@ import 'package:refilc/models/settings.dart';
|
||||
import 'package:refilc/theme/colors/colors.dart';
|
||||
import 'package:refilc/theme/colors/utils.dart';
|
||||
import 'package:refilc/utils/format.dart';
|
||||
import 'package:refilc_kreta_api/models/exam.dart';
|
||||
import 'package:refilc_kreta_api/models/lesson.dart';
|
||||
import 'package:refilc_kreta_api/providers/exam_provider.dart';
|
||||
import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
|
||||
import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
|
||||
import 'package:refilc_mobile_ui/common/round_border_icon.dart';
|
||||
import 'package:refilc/ui/widgets/lesson/lesson_tile.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:refilc_mobile_ui/common/viewable.dart';
|
||||
import 'package:refilc_mobile_ui/common/widgets/card_handle.dart';
|
||||
import 'package:refilc_mobile_ui/common/widgets/lesson/lesson_view.dart';
|
||||
import 'package:refilc_plus/models/premium_scopes.dart';
|
||||
import 'package:refilc_plus/providers/plus_provider.dart';
|
||||
import 'package:refilc_plus/ui/mobile/plus/upsell.dart';
|
||||
import 'lesson_view.i18n.dart';
|
||||
|
||||
class LessonViewable extends StatefulWidget {
|
||||
const LessonViewable(
|
||||
@@ -59,174 +70,169 @@ class LessonViewableState extends State<LessonViewable> {
|
||||
|
||||
if (lsn.subject.id == '' || tile.lesson.isEmpty) return tile;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => TimetableLessonPopup.show(
|
||||
context: context,
|
||||
lesson: lsn,
|
||||
),
|
||||
child: LessonTile(
|
||||
lsn,
|
||||
swapDesc: widget.swapDesc,
|
||||
showSubTiles: widget.showSubTiles,
|
||||
// onTap: () => TimetableLessonPopup.show(
|
||||
// context: context,
|
||||
// lesson: lsn,
|
||||
// ),
|
||||
),
|
||||
// check if new popup needed
|
||||
if (Provider.of<SettingsProvider>(context).newPopups) {
|
||||
return GestureDetector(
|
||||
onTap: () => TimetableLessonPopup.show(
|
||||
context: context,
|
||||
lesson: lsn,
|
||||
),
|
||||
child: tile,
|
||||
);
|
||||
}
|
||||
|
||||
return Viewable(
|
||||
tile: tile,
|
||||
view: CardHandle(child: LessonView(lsn)),
|
||||
actions: [
|
||||
PanelButton(
|
||||
background: true,
|
||||
title: Text(
|
||||
"edit_lesson".i18n,
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.of(context, rootNavigator: true).pop();
|
||||
|
||||
if (!Provider.of<PlusProvider>(context, listen: false)
|
||||
.hasScope(PremiumScopes.timetableNotes)) {
|
||||
PlusLockedFeaturePopup.show(
|
||||
context: context, feature: PremiumFeature.timetableNotes);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => StatefulBuilder(builder: (context, setS) {
|
||||
return AlertDialog(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(14.0))),
|
||||
title: Text("edit_lesson".i18n),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// description
|
||||
TextField(
|
||||
controller: _descTxt,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(
|
||||
borderSide: const BorderSide(
|
||||
color: Colors.grey, width: 1.5),
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: const BorderSide(
|
||||
color: Colors.grey, width: 1.5),
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
hintText: 'l_desc'.i18n,
|
||||
suffixIcon: IconButton(
|
||||
icon: const Icon(
|
||||
FeatherIcons.x,
|
||||
color: Colors.grey,
|
||||
size: 18.0,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_descTxt.text = '';
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
// const SizedBox(
|
||||
// height: 14.0,
|
||||
// ),
|
||||
// // class
|
||||
// TextField(
|
||||
// controller: _descTxt,
|
||||
// onEditingComplete: () async {
|
||||
// // SharedTheme? theme = await shareProvider.getThemeById(
|
||||
// // context,
|
||||
// // id: _paintId.text.replaceAll(' ', ''),
|
||||
// // );
|
||||
|
||||
// // if (theme != null) {
|
||||
// // // set theme variable
|
||||
// // newThemeByID = theme;
|
||||
|
||||
// // _paintId.clear();
|
||||
// // } else {
|
||||
// // ScaffoldMessenger.of(context).showSnackBar(
|
||||
// // CustomSnackBar(
|
||||
// // content: Text("theme_not_found".i18n,
|
||||
// // style: const TextStyle(color: Colors.white)),
|
||||
// // backgroundColor: AppColors.of(context).red,
|
||||
// // context: context,
|
||||
// // ),
|
||||
// // );
|
||||
// // }
|
||||
// },
|
||||
// decoration: InputDecoration(
|
||||
// border: OutlineInputBorder(
|
||||
// borderSide: const BorderSide(
|
||||
// color: Colors.grey, width: 1.5),
|
||||
// borderRadius: BorderRadius.circular(12.0),
|
||||
// ),
|
||||
// focusedBorder: OutlineInputBorder(
|
||||
// borderSide: const BorderSide(
|
||||
// color: Colors.grey, width: 1.5),
|
||||
// borderRadius: BorderRadius.circular(12.0),
|
||||
// ),
|
||||
// contentPadding:
|
||||
// const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
// hintText: 'l_desc'.i18n,
|
||||
// suffixIcon: IconButton(
|
||||
// icon: const Icon(
|
||||
// FeatherIcons.x,
|
||||
// color: Colors.grey,
|
||||
// size: 18.0,
|
||||
// ),
|
||||
// onPressed: () {
|
||||
// setState(() {
|
||||
// _descTxt.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: () async {
|
||||
saveLesson();
|
||||
|
||||
Navigator.of(context).pop();
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
// return Viewable(
|
||||
// tile: tile,
|
||||
// view: CardHandle(child: LessonView(lsn)),
|
||||
// actions: [
|
||||
// PanelButton(
|
||||
// background: true,
|
||||
// title: Text(
|
||||
// "edit_lesson".i18n,
|
||||
// textAlign: TextAlign.center,
|
||||
// maxLines: 2,
|
||||
// overflow: TextOverflow.ellipsis,
|
||||
// ),
|
||||
// onPressed: () {
|
||||
// Navigator.of(context, rootNavigator: true).pop();
|
||||
|
||||
// if (!Provider.of<PlusProvider>(context, listen: false)
|
||||
// .hasScope(PremiumScopes.timetableNotes)) {
|
||||
// PlusLockedFeaturePopup.show(
|
||||
// context: context, feature: PremiumFeature.timetableNotes);
|
||||
|
||||
// return;
|
||||
// }
|
||||
|
||||
// showDialog(
|
||||
// context: context,
|
||||
// builder: (context) => StatefulBuilder(builder: (context, setS) {
|
||||
// return AlertDialog(
|
||||
// shape: const RoundedRectangleBorder(
|
||||
// borderRadius: BorderRadius.all(Radius.circular(14.0))),
|
||||
// title: Text("edit_lesson".i18n),
|
||||
// content: Column(
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// children: [
|
||||
// // description
|
||||
// TextField(
|
||||
// controller: _descTxt,
|
||||
// decoration: InputDecoration(
|
||||
// border: OutlineInputBorder(
|
||||
// borderSide: const BorderSide(
|
||||
// color: Colors.grey, width: 1.5),
|
||||
// borderRadius: BorderRadius.circular(12.0),
|
||||
// ),
|
||||
// focusedBorder: OutlineInputBorder(
|
||||
// borderSide: const BorderSide(
|
||||
// color: Colors.grey, width: 1.5),
|
||||
// borderRadius: BorderRadius.circular(12.0),
|
||||
// ),
|
||||
// contentPadding:
|
||||
// const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
// hintText: 'l_desc'.i18n,
|
||||
// suffixIcon: IconButton(
|
||||
// icon: const Icon(
|
||||
// FeatherIcons.x,
|
||||
// color: Colors.grey,
|
||||
// size: 18.0,
|
||||
// ),
|
||||
// onPressed: () {
|
||||
// setState(() {
|
||||
// _descTxt.text = '';
|
||||
// });
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// // const SizedBox(
|
||||
// // height: 14.0,
|
||||
// // ),
|
||||
// // // class
|
||||
// // TextField(
|
||||
// // controller: _descTxt,
|
||||
// // onEditingComplete: () async {
|
||||
// // // SharedTheme? theme = await shareProvider.getThemeById(
|
||||
// // // context,
|
||||
// // // id: _paintId.text.replaceAll(' ', ''),
|
||||
// // // );
|
||||
|
||||
// // // if (theme != null) {
|
||||
// // // // set theme variable
|
||||
// // // newThemeByID = theme;
|
||||
|
||||
// // // _paintId.clear();
|
||||
// // // } else {
|
||||
// // // ScaffoldMessenger.of(context).showSnackBar(
|
||||
// // // CustomSnackBar(
|
||||
// // // content: Text("theme_not_found".i18n,
|
||||
// // // style: const TextStyle(color: Colors.white)),
|
||||
// // // backgroundColor: AppColors.of(context).red,
|
||||
// // // context: context,
|
||||
// // // ),
|
||||
// // // );
|
||||
// // // }
|
||||
// // },
|
||||
// // decoration: InputDecoration(
|
||||
// // border: OutlineInputBorder(
|
||||
// // borderSide: const BorderSide(
|
||||
// // color: Colors.grey, width: 1.5),
|
||||
// // borderRadius: BorderRadius.circular(12.0),
|
||||
// // ),
|
||||
// // focusedBorder: OutlineInputBorder(
|
||||
// // borderSide: const BorderSide(
|
||||
// // color: Colors.grey, width: 1.5),
|
||||
// // borderRadius: BorderRadius.circular(12.0),
|
||||
// // ),
|
||||
// // contentPadding:
|
||||
// // const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
// // hintText: 'l_desc'.i18n,
|
||||
// // suffixIcon: IconButton(
|
||||
// // icon: const Icon(
|
||||
// // FeatherIcons.x,
|
||||
// // color: Colors.grey,
|
||||
// // size: 18.0,
|
||||
// // ),
|
||||
// // onPressed: () {
|
||||
// // setState(() {
|
||||
// // _descTxt.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: () async {
|
||||
// saveLesson();
|
||||
|
||||
// Navigator.of(context).pop();
|
||||
// setState(() {});
|
||||
// },
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// }),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
}
|
||||
|
||||
void saveLesson() async {
|
||||
@@ -283,6 +289,18 @@ class TimetableLessonPopup extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Exam? lessonExam;
|
||||
|
||||
if (lesson.exam != "") {
|
||||
Exam exam = Provider.of<ExamProvider>(context, listen: false)
|
||||
.exams
|
||||
.firstWhere((t) => t.id == lesson.exam,
|
||||
orElse: () => Exam.fromJson({}));
|
||||
if (exam.id != "") {
|
||||
lessonExam = exam;
|
||||
}
|
||||
}
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).scaffoldBackgroundColor,
|
||||
@@ -295,7 +313,9 @@ class TimetableLessonPopup extends StatelessWidget {
|
||||
Stack(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
"assets/svg/mesh_bg.svg",
|
||||
// "assets/svg/mesh_bg.svg",
|
||||
SubjectBooklet.resolveVariant(
|
||||
context: context, subject: lesson.subject),
|
||||
// ignore: deprecated_member_use
|
||||
color: ColorsUtils()
|
||||
.fade(context, Theme.of(context).colorScheme.secondary,
|
||||
@@ -319,13 +339,13 @@ class TimetableLessonPopup extends StatelessWidget {
|
||||
.withOpacity(0.1),
|
||||
Theme.of(context).scaffoldBackgroundColor,
|
||||
],
|
||||
stops: const [0.1, 0.5, 0.7, 1.0],
|
||||
stops: const [0.0, 0.3, 0.6, 0.95],
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
),
|
||||
),
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: 175.0,
|
||||
height: 200.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -340,16 +360,27 @@ class TimetableLessonPopup extends StatelessWidget {
|
||||
width: 40,
|
||||
height: 4,
|
||||
decoration: BoxDecoration(
|
||||
color: ColorsUtils()
|
||||
.fade(
|
||||
context, Theme.of(context).colorScheme.secondary,
|
||||
darkenAmount: 0.1, lightenAmount: 0.1)
|
||||
.withOpacity(0.33),
|
||||
color: Theme.of(context).scaffoldBackgroundColor,
|
||||
borderRadius: BorderRadius.circular(
|
||||
2.0,
|
||||
),
|
||||
),
|
||||
child: Container(
|
||||
width: 40,
|
||||
height: 4,
|
||||
decoration: BoxDecoration(
|
||||
color: ColorsUtils()
|
||||
.fade(context,
|
||||
Theme.of(context).colorScheme.secondary,
|
||||
darkenAmount: 0.1, lightenAmount: 0.1)
|
||||
.withOpacity(0.33),
|
||||
borderRadius: BorderRadius.circular(
|
||||
2.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(
|
||||
height: 38.0,
|
||||
),
|
||||
@@ -387,11 +418,9 @@ class TimetableLessonPopup extends StatelessWidget {
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: const Radius.circular(12.0),
|
||||
bottom: (lesson.description.replaceAll(' ', '') != '')
|
||||
? const Radius.circular(6.0)
|
||||
: const Radius.circular(12.0),
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(12.0),
|
||||
bottom: Radius.circular(6.0),
|
||||
),
|
||||
),
|
||||
padding: const EdgeInsets.all(14.0),
|
||||
@@ -466,7 +495,15 @@ class TimetableLessonPopup extends StatelessWidget {
|
||||
height: 8.0,
|
||||
),
|
||||
Text(
|
||||
lesson.teacher.name,
|
||||
((lesson.substituteTeacher == null ||
|
||||
lesson.substituteTeacher!.name == "")
|
||||
? (lesson.teacher.isRenamed
|
||||
? lesson.teacher.renamedTo
|
||||
: lesson.teacher.name)
|
||||
: (lesson.substituteTeacher!.isRenamed
|
||||
? lesson.substituteTeacher!.renamedTo
|
||||
: lesson.substituteTeacher!.name)) ??
|
||||
'',
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text.withOpacity(0.9),
|
||||
fontSize: 14.0,
|
||||
@@ -487,7 +524,7 @@ class TimetableLessonPopup extends StatelessWidget {
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(6.0),
|
||||
bottom: Radius.circular(12.0),
|
||||
bottom: Radius.circular(6.0),
|
||||
),
|
||||
),
|
||||
padding: const EdgeInsets.all(14.0),
|
||||
@@ -506,6 +543,94 @@ class TimetableLessonPopup extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 6.0,
|
||||
),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: const Radius.circular(6.0),
|
||||
bottom: lesson.exam != ''
|
||||
? const Radius.circular(6.0)
|
||||
: const Radius.circular(12.0),
|
||||
),
|
||||
),
|
||||
padding: const EdgeInsets.all(14.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${'year_index'.i18n}: ${lesson.lessonYearIndex ?? '?'}',
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text.withOpacity(0.9),
|
||||
fontSize: 14.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (lesson.exam != '')
|
||||
const SizedBox(
|
||||
height: 6.0,
|
||||
),
|
||||
if (lesson.exam != '' && lessonExam != null)
|
||||
Container(
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(6.0),
|
||||
bottom: Radius.circular(12.0)),
|
||||
),
|
||||
padding: const EdgeInsets.all(14.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
const Icon(
|
||||
FeatherIcons.file,
|
||||
size: 20.0,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10.0,
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width * 0.5,
|
||||
child: Text(
|
||||
lessonExam.description.capital(),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context)
|
||||
.text
|
||||
.withOpacity(0.9),
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Flexible(
|
||||
child: Text(
|
||||
lessonExam.mode?.description ?? 'Dolgozat',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context)
|
||||
.text
|
||||
.withOpacity(0.85),
|
||||
fontSize: 14.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// const SizedBox(
|
||||
// height: 24.0,
|
||||
// ),
|
||||
|
||||
@@ -17,7 +17,7 @@ extension Localization on String {
|
||||
"Messages": "Messages",
|
||||
"Absences": "Absences",
|
||||
"update_available": "Update Available",
|
||||
"missed_exams": "You missed %s exams this week.".one("You missed an exam this week."),
|
||||
"missed_exams": "You missed %s exam(s) this week.",
|
||||
"missed_exam_contact": "Contact %s, to resolve it!",
|
||||
},
|
||||
"hu_hu": {
|
||||
@@ -34,7 +34,7 @@ extension Localization on String {
|
||||
"Messages": "Üzenetek",
|
||||
"Absences": "Hiányok",
|
||||
"update_available": "Frissítés elérhető",
|
||||
"missed_exams": "Ezen a héten hiányoztál %s dolgozatról.".one("Ezen a héten hiányoztál egy dolgozatról."),
|
||||
"missed_exams": "Ezen a héten hiányoztál %s dolgozatról.",
|
||||
"missed_exam_contact": "Keresd %s-t, ha pótolni szeretnéd!",
|
||||
},
|
||||
"de_de": {
|
||||
@@ -51,7 +51,7 @@ extension Localization on String {
|
||||
"Messages": "Nachrichten",
|
||||
"Absences": "Fehlen",
|
||||
"update_available": "Update verfügbar",
|
||||
"missed_exams": "Diese Woche haben Sie %s Prüfungen verpasst.".one("Diese Woche haben Sie eine Prüfung verpasst."),
|
||||
"missed_exams": "Diese Woche haben Sie %s Prüfungen verpasst.",
|
||||
"missed_exam_contact": "Wenden Sie sich an %s, um sie zu erneuern!",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -4,7 +4,9 @@ import 'dart:math';
|
||||
|
||||
import 'package:animations/animations.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:refilc/api/providers/update_provider.dart';
|
||||
import 'package:refilc/models/settings.dart';
|
||||
import 'package:refilc/theme/colors/utils.dart';
|
||||
import 'package:refilc/ui/date_widget.dart';
|
||||
import 'package:refilc_kreta_api/models/absence.dart';
|
||||
@@ -169,6 +171,7 @@ class AbsencesPageState extends State<AbsencesPage>
|
||||
badge: updateProvider.available,
|
||||
role: user.role,
|
||||
profilePictureString: user.picture,
|
||||
gradeStreak: (user.gradeStreak ?? 0) > 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -179,10 +182,22 @@ class AbsencesPageState extends State<AbsencesPage>
|
||||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: Text(
|
||||
"Absences".i18n,
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text,
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
style: Provider.of<SettingsProvider>(context).fontFamily !=
|
||||
'' &&
|
||||
Provider.of<SettingsProvider>(context).titleOnlyFont
|
||||
? GoogleFonts.getFont(
|
||||
Provider.of<SettingsProvider>(context).fontFamily,
|
||||
textStyle: TextStyle(
|
||||
color: AppColors.of(context).text,
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
)
|
||||
: TextStyle(
|
||||
color: AppColors.of(context).text,
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
bottom: FilterBar(
|
||||
@@ -504,7 +519,9 @@ class AbsencesPageState extends State<AbsencesPage>
|
||||
style: TextStyle(
|
||||
fontSize: 18.0,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: AppColors.of(context).green,
|
||||
color: value1 > 0
|
||||
? AppColors.of(context).green
|
||||
: AppColors.of(context).text,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
@@ -513,12 +530,14 @@ class AbsencesPageState extends State<AbsencesPage>
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 1.1,
|
||||
color: ColorsUtils().fade(
|
||||
context,
|
||||
AppColors.of(context).green,
|
||||
darkenAmount: 0.5,
|
||||
lightenAmount: 0.4,
|
||||
),
|
||||
color: value1 > 0
|
||||
? ColorsUtils().fade(
|
||||
context,
|
||||
AppColors.of(context).green,
|
||||
darkenAmount: 0.5,
|
||||
lightenAmount: 0.4,
|
||||
)
|
||||
: AppColors.of(context).text,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -535,7 +554,9 @@ class AbsencesPageState extends State<AbsencesPage>
|
||||
style: TextStyle(
|
||||
fontSize: 18.0,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: AppColors.of(context).red,
|
||||
color: value2 > 0
|
||||
? AppColors.of(context).red
|
||||
: AppColors.of(context).text,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
@@ -544,12 +565,14 @@ class AbsencesPageState extends State<AbsencesPage>
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 1.1,
|
||||
color: ColorsUtils().fade(
|
||||
context,
|
||||
AppColors.of(context).red,
|
||||
darkenAmount: 0.4,
|
||||
lightenAmount: 0.2,
|
||||
),
|
||||
color: value2 > 0
|
||||
? ColorsUtils().fade(
|
||||
context,
|
||||
AppColors.of(context).red,
|
||||
darkenAmount: 0.4,
|
||||
lightenAmount: 0.2,
|
||||
)
|
||||
: AppColors.of(context).text,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -597,8 +620,9 @@ class AbsencesPageState extends State<AbsencesPage>
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
const Icon(
|
||||
Icon(
|
||||
Icons.av_timer_rounded,
|
||||
color: value3 > 0 ? Colors.orange : null,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10.0,
|
||||
|
||||
@@ -34,7 +34,6 @@ import 'package:refilc_mobile_ui/pages/grades/calculator/grade_calculator_provid
|
||||
import 'package:refilc_mobile_ui/pages/grades/grades_count.dart';
|
||||
import 'package:refilc_mobile_ui/pages/grades/graph.dart';
|
||||
import 'package:refilc_mobile_ui/pages/grades/subject_grades_container.dart';
|
||||
import 'package:refilc_plus/ui/mobile/goal_planner/goal_planner_screen.dart';
|
||||
// import 'package:refilc_plus/models/premium_scopes.dart';
|
||||
// import 'package:refilc_plus/providers/plus_provider.dart';
|
||||
import 'package:refilc_plus/ui/mobile/goal_planner/goal_state_screen.dart';
|
||||
@@ -44,6 +43,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
|
||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:refilc_plus/ui/mobile/goal_planner/goal_track_popup.dart';
|
||||
import 'grades_page.i18n.dart';
|
||||
// import 'package:refilc_plus/ui/mobile/goal_planner/new_goal.dart';
|
||||
|
||||
@@ -425,9 +425,10 @@ class _GradeSubjectViewState extends State<GradeSubjectView>
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// const SnackBar(content: Text("Hamarosan...")));
|
||||
|
||||
Navigator.of(context).push(CupertinoPageRoute(
|
||||
builder: (context) =>
|
||||
GoalPlannerScreen(subject: widget.subject)));
|
||||
// Navigator.of(context).push(CupertinoPageRoute(
|
||||
// builder: (context) =>
|
||||
// GoalPlannerScreen(subject: widget.subject)));
|
||||
GoalTrackPopup.show(context, subject: widget.subject);
|
||||
},
|
||||
child: const Icon(FeatherIcons.flag, size: 20.0),
|
||||
),
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
// ignore_for_file: no_leading_underscores_for_local_identifiers
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:auto_size_text/auto_size_text.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:refilc/api/providers/update_provider.dart';
|
||||
import 'package:refilc/models/settings.dart';
|
||||
import 'package:refilc/ui/widgets/grade/grade_tile.dart';
|
||||
@@ -88,19 +92,18 @@ class GradesPageState extends State<GradesPage> {
|
||||
int avgDropValue = 0;
|
||||
|
||||
bool gradeCalcMode = false;
|
||||
bool importedViewMode = false;
|
||||
|
||||
List<Grade> jsonGrades = [];
|
||||
|
||||
List<Grade> getSubjectGrades(GradeSubject subject,
|
||||
{int days = 0}) =>
|
||||
!gradeCalcMode
|
||||
? gradeProvider
|
||||
.grades
|
||||
? (importedViewMode ? jsonGrades : gradeProvider.grades)
|
||||
.where((e) =>
|
||||
e
|
||||
.subject ==
|
||||
subject &&
|
||||
e.subject == subject &&
|
||||
e.type == GradeType.midYear &&
|
||||
(days ==
|
||||
0 ||
|
||||
(days == 0 ||
|
||||
e.date.isBefore(
|
||||
DateTime.now().subtract(Duration(days: days)))))
|
||||
.toList()
|
||||
@@ -109,18 +112,19 @@ class GradesPageState extends State<GradesPage> {
|
||||
.toList();
|
||||
|
||||
void generateTiles() {
|
||||
List<GradeSubject> subjects = gradeProvider.grades
|
||||
.map((e) => GradeSubject(
|
||||
category: e.subject.category,
|
||||
id: e.subject.id,
|
||||
name: e.subject.name,
|
||||
renamedTo: e.subject.renamedTo,
|
||||
customRounding: e.subject.customRounding,
|
||||
teacher: e.teacher,
|
||||
))
|
||||
.toSet()
|
||||
.toList()
|
||||
..sort((a, b) => a.name.compareTo(b.name));
|
||||
List<GradeSubject> subjects =
|
||||
(importedViewMode ? jsonGrades : gradeProvider.grades)
|
||||
.map((e) => GradeSubject(
|
||||
category: e.subject.category,
|
||||
id: e.subject.id,
|
||||
name: e.subject.name,
|
||||
renamedTo: e.subject.renamedTo,
|
||||
customRounding: e.subject.customRounding,
|
||||
teacher: e.teacher,
|
||||
))
|
||||
.toSet()
|
||||
.toList()
|
||||
..sort((a, b) => a.name.compareTo(b.name));
|
||||
List<Widget> tiles = [];
|
||||
|
||||
Map<GradeSubject, double> subjectAvgs = {};
|
||||
@@ -164,7 +168,8 @@ class GradesPageState extends State<GradesPage> {
|
||||
e.subject.id == subject.id && e.writeDate.isAfter(DateTime.now()));
|
||||
|
||||
bool hasUnder = (hasHomework || nearestExam != null) &&
|
||||
Provider.of<SettingsProvider>(context).qSubjectsSubTiles;
|
||||
Provider.of<SettingsProvider>(context, listen: false)
|
||||
.qSubjectsSubTiles;
|
||||
|
||||
return Padding(
|
||||
padding: i > 1 ? const EdgeInsets.only(top: 9.0) : EdgeInsets.zero,
|
||||
@@ -219,7 +224,8 @@ class GradesPageState extends State<GradesPage> {
|
||||
height: 6.0,
|
||||
),
|
||||
if (hasHomework &&
|
||||
Provider.of<SettingsProvider>(context).qSubjectsSubTiles)
|
||||
Provider.of<SettingsProvider>(context, listen: false)
|
||||
.qSubjectsSubTiles)
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
boxShadow: [
|
||||
@@ -267,6 +273,12 @@ class GradesPageState extends State<GradesPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (hasHomework &&
|
||||
nearestExam != null &&
|
||||
Provider.of<SettingsProvider>(context).qSubjectsSubTiles)
|
||||
const SizedBox(
|
||||
height: 6.0,
|
||||
),
|
||||
if (nearestExam != null &&
|
||||
Provider.of<SettingsProvider>(context).qSubjectsSubTiles)
|
||||
Container(
|
||||
@@ -441,25 +453,28 @@ class GradesPageState extends State<GradesPage> {
|
||||
.fold(0.0, (double a, double b) => a + b) /
|
||||
gradeProvider.groupAverages.length;
|
||||
|
||||
final now = gradeProvider.grades.isNotEmpty
|
||||
? gradeProvider.grades
|
||||
.reduce((v, e) => e.date.isAfter(v.date) ? e : v)
|
||||
.date
|
||||
: DateTime.now();
|
||||
final now =
|
||||
(importedViewMode ? jsonGrades : gradeProvider.grades).isNotEmpty
|
||||
? (importedViewMode ? jsonGrades : gradeProvider.grades)
|
||||
.reduce((v, e) => e.date.isAfter(v.date) ? e : v)
|
||||
.date
|
||||
: DateTime.now();
|
||||
|
||||
final currentStudentAvg = AverageHelper.averageEvals(!gradeCalcMode
|
||||
? gradeProvider.grades
|
||||
? (importedViewMode ? jsonGrades : gradeProvider.grades)
|
||||
.where((e) => e.type == GradeType.midYear)
|
||||
.toList()
|
||||
: calculatorProvider.grades);
|
||||
|
||||
final prevStudentAvg = AverageHelper.averageEvals(gradeProvider.grades
|
||||
final prevStudentAvg = AverageHelper.averageEvals((importedViewMode
|
||||
? jsonGrades
|
||||
: gradeProvider.grades)
|
||||
.where((e) => e.type == GradeType.midYear)
|
||||
.where((e) => e.date.isBefore(now.subtract(const Duration(days: 30))))
|
||||
.toList());
|
||||
|
||||
List<Grade> graphGrades = !gradeCalcMode
|
||||
? gradeProvider.grades
|
||||
? (importedViewMode ? jsonGrades : gradeProvider.grades)
|
||||
.where((e) =>
|
||||
e.type == GradeType.midYear &&
|
||||
(avgDropValue == 0 ||
|
||||
@@ -493,7 +508,7 @@ class GradesPageState extends State<GradesPage> {
|
||||
// const SizedBox(width: 4.0),
|
||||
TrendDisplay(
|
||||
previous: prevStudentAvg, current: currentStudentAvg),
|
||||
if (gradeProvider.grades
|
||||
if ((importedViewMode ? jsonGrades : gradeProvider.grades)
|
||||
.where((e) => e.type == GradeType.midYear)
|
||||
.isNotEmpty)
|
||||
AverageDisplay(average: currentStudentAvg),
|
||||
@@ -560,6 +575,7 @@ class GradesPageState extends State<GradesPage> {
|
||||
badge: updateProvider.available,
|
||||
role: user.role,
|
||||
profilePictureString: user.picture,
|
||||
gradeStreak: (user.gradeStreak ?? 0) > 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -568,11 +584,21 @@ class GradesPageState extends State<GradesPage> {
|
||||
title: Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: Text(
|
||||
"Grades".i18n,
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text,
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
"page_title_grades".i18n,
|
||||
style: Provider.of<SettingsProvider>(context).fontFamily !=
|
||||
'' &&
|
||||
Provider.of<SettingsProvider>(context).titleOnlyFont
|
||||
? GoogleFonts.getFont(
|
||||
Provider.of<SettingsProvider>(context).fontFamily,
|
||||
textStyle: TextStyle(
|
||||
color: AppColors.of(context).text,
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
)
|
||||
: TextStyle(
|
||||
color: AppColors.of(context).text,
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
shadowColor: Theme.of(context).shadowColor,
|
||||
@@ -614,7 +640,8 @@ class GradesPageState extends State<GradesPage> {
|
||||
|
||||
void gradeCalcTotal(BuildContext context) {
|
||||
calculatorProvider.clear();
|
||||
calculatorProvider.addAllGrades(gradeProvider.grades);
|
||||
calculatorProvider
|
||||
.addAllGrades((importedViewMode ? jsonGrades : gradeProvider.grades));
|
||||
|
||||
_sheetController = _scaffoldKey.currentState?.showBottomSheet(
|
||||
(context) => const RoundedBottomSheet(
|
||||
@@ -667,6 +694,66 @@ class GradesPageState extends State<GradesPage> {
|
||||
|
||||
// SoonAlert.show(context: context);
|
||||
gradeCalcTotal(context);
|
||||
|
||||
Navigator.of(context, rootNavigator: true).pop();
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10.0,
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
color: Theme.of(context).colorScheme.background),
|
||||
child: ListTile(
|
||||
title: Row(
|
||||
children: [
|
||||
const Icon(Icons.toll_rounded),
|
||||
const SizedBox(
|
||||
width: 10.0,
|
||||
),
|
||||
Text('import_grades'.i18n),
|
||||
],
|
||||
),
|
||||
trailing: importedViewMode ? const Icon(FeatherIcons.x) : null,
|
||||
onTap: () {
|
||||
if (importedViewMode) {
|
||||
importedViewMode = false;
|
||||
|
||||
generateTiles();
|
||||
setState(() {});
|
||||
|
||||
Navigator.of(context, rootNavigator: true).pop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Provider.of<PlusProvider>(context, listen: false)
|
||||
.hasScope(PremiumScopes.gradeExporting)) {
|
||||
PlusLockedFeaturePopup.show(
|
||||
context: context, feature: PremiumFeature.gradeExporting);
|
||||
return;
|
||||
}
|
||||
|
||||
// show file picker
|
||||
FilePicker.platform.pickFiles(
|
||||
type: FileType.custom,
|
||||
allowedExtensions: ['json'],
|
||||
).then((value) {
|
||||
if (value != null) {
|
||||
final File file = File(value.files.single.path!);
|
||||
final String content = file.readAsStringSync();
|
||||
final List<dynamic> json = jsonDecode(content);
|
||||
|
||||
jsonGrades = json.map((e) => Grade.fromJson(e)).toList();
|
||||
importedViewMode = true;
|
||||
|
||||
generateTiles();
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
|
||||
Navigator.of(context, rootNavigator: true).pop();
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
@@ -4,8 +4,9 @@ extension Localization on String {
|
||||
static final _t = Translations.byLocale("hu_hu") +
|
||||
{
|
||||
"en_en": {
|
||||
"Grades": "Subjects",
|
||||
"Ghost Grades": "Grades",
|
||||
"Grades": "Grades",
|
||||
"page_title_grades": "Subjects",
|
||||
"Ghost Grades": "Ghost Grades",
|
||||
"Subjects": "Your Subjects",
|
||||
"Subjects_changes": "Subject Differences",
|
||||
"empty": "You don't have any subjects.",
|
||||
@@ -17,8 +18,7 @@ extension Localization on String {
|
||||
"subjectavg": "Subject Average",
|
||||
"classavg": "Class Average",
|
||||
"fail_warning": "Failure warning",
|
||||
"fail_warning_description":
|
||||
"You are failing %d subjects!".one("You are failing a subject!"),
|
||||
"fail_warning_description": "You are failing %d subject(s)!",
|
||||
"data": "Data",
|
||||
"you_have_hw": "You have %s homework(s) to do",
|
||||
"grades_cnt": "Grade count: %s",
|
||||
@@ -29,9 +29,11 @@ extension Localization on String {
|
||||
"grades": "Grades",
|
||||
"show_exams_homework": "Exams and Homework",
|
||||
"grade_calc": "Grade Calculator",
|
||||
"import_grades": "Import Grades (JSON)",
|
||||
},
|
||||
"hu_hu": {
|
||||
"Grades": "Tantárgyak",
|
||||
"Grades": "Jegyek",
|
||||
"page_title_grades": "Tantárgyak",
|
||||
"Ghost Grades": "Szellem jegyek",
|
||||
"Subjects": "Tantárgyaid",
|
||||
"Subjects_changes": "Tantárgyi változások",
|
||||
@@ -55,9 +57,11 @@ extension Localization on String {
|
||||
"grades": "Jegyek",
|
||||
"show_exams_homework": "Dolgozatok és házik",
|
||||
"grade_calc": "Jegy kalkulátor",
|
||||
"import_grades": "Jegyek importálása (JSON)",
|
||||
},
|
||||
"de_de": {
|
||||
"Grades": "Fächer",
|
||||
"Grades": "Klassen",
|
||||
"page_title_grades": "Themen",
|
||||
"Ghost Grades": "Geist Noten",
|
||||
"Subjects": "Ihre Themen",
|
||||
"Subjects_changes": "Betreff Änderungen",
|
||||
@@ -81,6 +85,7 @@ extension Localization on String {
|
||||
"grades": "Noten",
|
||||
"show_exams_homework": "Referate und Hausaufgaben",
|
||||
"grade_calc": "Noten-Rechner",
|
||||
"import_grades": "Noten importieren (JSON)",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -248,11 +248,12 @@ class GradeGraphState extends State<GradeGraph> {
|
||||
),
|
||||
if (ghostData.isNotEmpty && ghostSpots.isNotEmpty)
|
||||
LineChartBarData(
|
||||
preventCurveOverShooting: true,
|
||||
preventCurveOverShooting: false,
|
||||
spots: ghostSpots,
|
||||
isCurved: true,
|
||||
colors: [AppColors.of(context).text],
|
||||
barWidth: 8,
|
||||
barWidth: 6,
|
||||
curveSmoothness: 0.2,
|
||||
isStrokeCapRound: true,
|
||||
dotData: FlDotData(show: false),
|
||||
belowBarData: BarAreaData(
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'dart:math';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:refilc/api/providers/live_card_provider.dart';
|
||||
import 'package:refilc/theme/colors/colors.dart';
|
||||
import 'package:refilc/ui/date_widget.dart';
|
||||
@@ -244,14 +245,34 @@ class HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
||||
greeting,
|
||||
overflow: TextOverflow.fade,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18.0,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium
|
||||
?.color,
|
||||
),
|
||||
style:
|
||||
Provider.of<SettingsProvider>(context)
|
||||
.fontFamily !=
|
||||
'' &&
|
||||
Provider.of<SettingsProvider>(
|
||||
context)
|
||||
.titleOnlyFont
|
||||
? GoogleFonts.getFont(
|
||||
Provider.of<SettingsProvider>(
|
||||
context)
|
||||
.fontFamily,
|
||||
textStyle: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18.0,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium
|
||||
?.color,
|
||||
),
|
||||
)
|
||||
: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18.0,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium
|
||||
?.color,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
DateFormat('EEEE, MMM d',
|
||||
@@ -317,6 +338,7 @@ class HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
||||
badge: updateProvider.available,
|
||||
role: user.role,
|
||||
profilePictureString: user.picture,
|
||||
gradeStreak: (user.gradeStreak ?? 0) > 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -355,7 +377,7 @@ class HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
||||
LiveCardState.duringLesson ||
|
||||
_liveCard.currentState ==
|
||||
LiveCardState.duringBreak)
|
||||
? 55.0
|
||||
? 62.0
|
||||
: 52.0),
|
||||
),
|
||||
child: Transform.scale(
|
||||
|
||||
@@ -19,8 +19,7 @@ extension Localization on String {
|
||||
"Messages": "Messages",
|
||||
"Absences": "Absences",
|
||||
"update_available": "Update Available",
|
||||
"missed_exams": "You missed %s exams this week."
|
||||
.one("You missed an exam this week."),
|
||||
"missed_exams": "You missed %s exam(s) this week.",
|
||||
"missed_exam_contact": "Contact %s to resolve it!",
|
||||
},
|
||||
"hu_hu": {
|
||||
@@ -39,8 +38,7 @@ extension Localization on String {
|
||||
"Messages": "Üzenetek",
|
||||
"Absences": "Hiányzások",
|
||||
"update_available": "Frissítés elérhető",
|
||||
"missed_exams": "Ezen a héten hiányoztál %s dolgozatról."
|
||||
.one("Ezen a héten hiányoztál egy dolgozatról."),
|
||||
"missed_exams": "Ezen a héten hiányoztál %s dolgozatról.",
|
||||
"missed_exam_contact": "Keresd %s tanár urat/hölgyet, hogy pótold!",
|
||||
},
|
||||
"de_de": {
|
||||
@@ -59,8 +57,7 @@ extension Localization on String {
|
||||
"Messages": "Nachrichten",
|
||||
"Absences": "Fehlen",
|
||||
"update_available": "Update verfügbar",
|
||||
"missed_exams": "Diese Woche haben Sie %s Prüfungen verpasst."
|
||||
.one("Diese Woche haben Sie eine Prüfung verpasst."),
|
||||
"missed_exams": "Diese Woche haben Sie %s Prüfungen verpasst.",
|
||||
"missed_exam_contact": "Wenden Sie sich an %s, um sie zu erneuern!",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -404,7 +404,7 @@ class LiveCardStateA extends State<LiveCard> {
|
||||
swapRoom: true,
|
||||
currentLessonIndicator: false,
|
||||
padding:
|
||||
const EdgeInsets.only(top: 6.0, bottom: 4.0),
|
||||
const EdgeInsets.only(top: 2.0, bottom: 4.0),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
showSubTiles: false,
|
||||
),
|
||||
@@ -911,6 +911,37 @@ class LiveCardStateA extends State<LiveCard> {
|
||||
Row(
|
||||
children: liveCard.nextLesson != null
|
||||
? [
|
||||
Container(
|
||||
width: (liveCard.nextLesson?.room
|
||||
.length ??
|
||||
0) >
|
||||
20
|
||||
? 111
|
||||
: null,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 5.5, vertical: 3.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.tertiary
|
||||
.withOpacity(.15),
|
||||
borderRadius:
|
||||
BorderRadius.circular(10.0),
|
||||
),
|
||||
child: Text(
|
||||
liveCard.nextLesson!.room,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
height: 1.1,
|
||||
fontSize: 12.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondary
|
||||
.withOpacity(.9),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
|
||||
@@ -5,8 +5,8 @@ extension Localization on String {
|
||||
{
|
||||
"en_en": {
|
||||
"next": "Next",
|
||||
"remaining min": "%d mins".one("%d min"),
|
||||
"remaining sec": "%d secs".one("%d sec"),
|
||||
"remaining min": "%d min(s)",
|
||||
"remaining sec": "%d sec(s)",
|
||||
"break": "Break",
|
||||
"go to room": "Go to room %s.",
|
||||
"go ground floor": "Go to the ground floor.",
|
||||
@@ -27,8 +27,8 @@ extension Localization on String {
|
||||
},
|
||||
"hu_hu": {
|
||||
"next": "Következő",
|
||||
"remaining min": "%d perc".one("%d perc"),
|
||||
"remaining sec": "%d másodperc".one("%d másodperc"),
|
||||
"remaining min": "%d perc",
|
||||
"remaining sec": "%d másodperc",
|
||||
"break": "Szünet",
|
||||
"go to room": "Menj a(z) %s terembe.",
|
||||
"go ground floor": "Menj a földszintre.",
|
||||
@@ -49,8 +49,8 @@ extension Localization on String {
|
||||
},
|
||||
"de_de": {
|
||||
"next": "Nächste",
|
||||
"remaining min": "%d Minuten".one("%d Minute"),
|
||||
"remaining sec": "%d Sekunden".one("%d Sekunden"),
|
||||
"remaining min": "%d Minute(n)",
|
||||
"remaining sec": "%d Sekunde(n)",
|
||||
"break": "Pause",
|
||||
"go to room": "Geh in den Raum %s.",
|
||||
"go ground floor": "Geh dir Treppe hinunter.",
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:refilc/api/providers/update_provider.dart';
|
||||
import 'package:refilc/models/settings.dart';
|
||||
import 'package:refilc/ui/date_widget.dart';
|
||||
import 'package:refilc_kreta_api/providers/message_provider.dart';
|
||||
import 'package:refilc/api/providers/user_provider.dart';
|
||||
@@ -109,6 +111,7 @@ class MessagesPageState extends State<MessagesPage>
|
||||
badge: updateProvider.available,
|
||||
role: user.role,
|
||||
profilePictureString: user.picture,
|
||||
gradeStreak: (user.gradeStreak ?? 0) > 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -128,10 +131,22 @@ class MessagesPageState extends State<MessagesPage>
|
||||
),
|
||||
Text(
|
||||
"Messages".i18n,
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text,
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
style: Provider.of<SettingsProvider>(context)
|
||||
.fontFamily !=
|
||||
'' &&
|
||||
Provider.of<SettingsProvider>(context)
|
||||
.titleOnlyFont
|
||||
? GoogleFonts.getFont(
|
||||
Provider.of<SettingsProvider>(context).fontFamily,
|
||||
textStyle: TextStyle(
|
||||
color: AppColors.of(context).text,
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
)
|
||||
: TextStyle(
|
||||
color: AppColors.of(context).text,
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'dart:math';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:refilc/api/providers/database_provider.dart';
|
||||
import 'package:refilc/api/providers/self_note_provider.dart';
|
||||
import 'package:refilc/api/providers/update_provider.dart';
|
||||
@@ -35,6 +36,7 @@ import 'package:refilc_plus/models/premium_scopes.dart';
|
||||
import 'package:refilc_plus/providers/plus_provider.dart';
|
||||
import 'package:refilc_plus/ui/mobile/plus/premium_inline.dart';
|
||||
import 'package:refilc_plus/ui/mobile/plus/upsell.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
import 'notes_page.i18n.dart';
|
||||
|
||||
enum AbsenceFilter { absences, delays, misses }
|
||||
@@ -65,9 +67,14 @@ class NotesPageState extends State<NotesPage> with TickerProviderStateMixin {
|
||||
|
||||
Map<String, bool> doneItems = {};
|
||||
List<Widget> noteTiles = [];
|
||||
List<TodoItem> todoItems = [];
|
||||
|
||||
final TextEditingController _taskName = TextEditingController();
|
||||
final TextEditingController _taskContent = TextEditingController();
|
||||
|
||||
void generateTiles() async {
|
||||
doneItems = await databaseProvider.userQuery.toDoItems(userId: user.id!);
|
||||
todoItems = await databaseProvider.userQuery.getTodoItems(userId: user.id!);
|
||||
|
||||
List<Widget> tiles = [];
|
||||
|
||||
@@ -82,7 +89,7 @@ class NotesPageState extends State<NotesPage> with TickerProviderStateMixin {
|
||||
List<Widget> toDoTiles = [];
|
||||
|
||||
if (hw.isNotEmpty &&
|
||||
!Provider.of<PlusProvider>(context, listen: false)
|
||||
Provider.of<PlusProvider>(context, listen: false)
|
||||
.hasScope(PremiumScopes.unlimitedSelfNotes)) {
|
||||
toDoTiles.addAll(hw.map((e) => TickTile(
|
||||
padding: EdgeInsets.zero,
|
||||
@@ -102,6 +109,21 @@ class NotesPageState extends State<NotesPage> with TickerProviderStateMixin {
|
||||
)));
|
||||
}
|
||||
|
||||
if (selfNoteProvider.todos.isNotEmpty) {
|
||||
toDoTiles.addAll(selfNoteProvider.todos.map((e) => TickTile(
|
||||
padding: EdgeInsets.zero,
|
||||
title: e.title,
|
||||
description: e.content,
|
||||
isTicked: e.done,
|
||||
onTap: (p0) async {
|
||||
todoItems.firstWhere((element) => element.id == e.id).done = p0;
|
||||
|
||||
await databaseProvider.userStore
|
||||
.storeSelfTodoItems(todoItems, userId: user.id!);
|
||||
},
|
||||
)));
|
||||
}
|
||||
|
||||
if (toDoTiles.isNotEmpty) {
|
||||
tiles.add(const SizedBox(
|
||||
height: 10.0,
|
||||
@@ -128,26 +150,31 @@ class NotesPageState extends State<NotesPage> with TickerProviderStateMixin {
|
||||
CupertinoPageRoute(
|
||||
builder: (context) => NoteViewScreen(note: e))),
|
||||
)
|
||||
: Container(
|
||||
height: MediaQuery.of(context).size.width / 2.42,
|
||||
width: MediaQuery.of(context).size.width / 2.42,
|
||||
decoration: BoxDecoration(
|
||||
boxShadow: [
|
||||
if (Provider.of<SettingsProvider>(context, listen: false)
|
||||
.shadowEffect)
|
||||
BoxShadow(
|
||||
offset: const Offset(0, 21),
|
||||
blurRadius: 23.0,
|
||||
color: Theme.of(context).shadowColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(16.0),
|
||||
child: Image.memory(
|
||||
const Base64Decoder().convert(e.content),
|
||||
fit: BoxFit.cover,
|
||||
gaplessPlayback: true,
|
||||
: GestureDetector(
|
||||
onTap: () => Navigator.of(context, rootNavigator: true).push(
|
||||
CupertinoPageRoute(
|
||||
builder: (context) => NoteViewScreen(note: e))),
|
||||
child: Container(
|
||||
height: MediaQuery.of(context).size.width / 2.42,
|
||||
width: MediaQuery.of(context).size.width / 2.42,
|
||||
decoration: BoxDecoration(
|
||||
boxShadow: [
|
||||
if (Provider.of<SettingsProvider>(context, listen: false)
|
||||
.shadowEffect)
|
||||
BoxShadow(
|
||||
offset: const Offset(0, 21),
|
||||
blurRadius: 23.0,
|
||||
color: Theme.of(context).shadowColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(16.0),
|
||||
child: Image.memory(
|
||||
const Base64Decoder().convert(e.content),
|
||||
fit: BoxFit.cover,
|
||||
gaplessPlayback: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -289,6 +316,7 @@ class NotesPageState extends State<NotesPage> with TickerProviderStateMixin {
|
||||
badge: updateProvider.available,
|
||||
role: user.role,
|
||||
profilePictureString: user.picture,
|
||||
gradeStreak: (user.gradeStreak ?? 0) > 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -299,10 +327,20 @@ class NotesPageState extends State<NotesPage> with TickerProviderStateMixin {
|
||||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: Text(
|
||||
"notes".i18n,
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text,
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
style: Provider.of<SettingsProvider>(context).fontFamily !=
|
||||
'' &&
|
||||
Provider.of<SettingsProvider>(context).titleOnlyFont
|
||||
? GoogleFonts.getFont(
|
||||
Provider.of<SettingsProvider>(context).fontFamily,
|
||||
textStyle: TextStyle(
|
||||
color: AppColors.of(context).text,
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
)
|
||||
: TextStyle(
|
||||
color: AppColors.of(context).text,
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -313,6 +351,8 @@ class NotesPageState extends State<NotesPage> with TickerProviderStateMixin {
|
||||
.fetch(
|
||||
from: DateTime.now().subtract(const Duration(days: 30)));
|
||||
Provider.of<SelfNoteProvider>(context, listen: false).restore();
|
||||
Provider.of<SelfNoteProvider>(context, listen: false)
|
||||
.restoreTodo();
|
||||
|
||||
generateTiles();
|
||||
|
||||
@@ -410,7 +450,159 @@ class NotesPageState extends State<NotesPage> with TickerProviderStateMixin {
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10.0,
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
color: Theme.of(context).colorScheme.background),
|
||||
child: ListTile(
|
||||
title: Row(
|
||||
children: [
|
||||
const Icon(Icons.task_outlined),
|
||||
const SizedBox(
|
||||
width: 10.0,
|
||||
),
|
||||
Text('new_task'.i18n),
|
||||
],
|
||||
),
|
||||
onTap: () {
|
||||
if (!Provider.of<PlusProvider>(context, listen: false)
|
||||
.hasScope(PremiumScopes.unlimitedSelfNotes)) {
|
||||
PlusLockedFeaturePopup.show(
|
||||
context: context, feature: PremiumFeature.selfNotes);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
showTaskCreation(context);
|
||||
},
|
||||
),
|
||||
),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
void showTaskCreation(context) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(14.0))),
|
||||
contentPadding: const EdgeInsets.only(top: 10.0),
|
||||
title: Text("new_task".i18n),
|
||||
content: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 10.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextField(
|
||||
controller: _taskName,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(
|
||||
borderSide:
|
||||
const BorderSide(color: Colors.grey, width: 1.5),
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide:
|
||||
const BorderSide(color: Colors.grey, width: 1.5),
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
hintText: "task_name".i18n,
|
||||
suffixIcon: IconButton(
|
||||
icon: const Icon(
|
||||
FeatherIcons.x,
|
||||
color: Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_taskName.text = "";
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10.0,
|
||||
),
|
||||
TextField(
|
||||
controller: _taskContent,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(
|
||||
borderSide:
|
||||
const BorderSide(color: Colors.grey, width: 1.5),
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide:
|
||||
const BorderSide(color: Colors.grey, width: 1.5),
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
hintText: "task_content".i18n,
|
||||
suffixIcon: IconButton(
|
||||
icon: const Icon(
|
||||
FeatherIcons.x,
|
||||
color: Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_taskContent.text = "";
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text(
|
||||
"cancel".i18n,
|
||||
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.of(context).maybePop();
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
child: Text(
|
||||
"next".i18n,
|
||||
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||
),
|
||||
onPressed: () async {
|
||||
todoItems.add(TodoItem.fromJson({
|
||||
'id': const Uuid().v4(),
|
||||
'title': _taskName.text.replaceAll(' ', '') != ""
|
||||
? _taskName.text
|
||||
: 'no_title'.i18n,
|
||||
'content': _taskContent.text,
|
||||
'done': false,
|
||||
}));
|
||||
|
||||
await databaseProvider.userStore
|
||||
.storeSelfTodoItems(todoItems, userId: user.id!);
|
||||
|
||||
setState(() {
|
||||
_taskName.text = "";
|
||||
_taskContent.text = "";
|
||||
});
|
||||
|
||||
Provider.of<SelfNoteProvider>(context, listen: false).restore();
|
||||
Provider.of<SelfNoteProvider>(context, listen: false)
|
||||
.restoreTodo();
|
||||
|
||||
generateTiles();
|
||||
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,10 @@ extension ScreensLocalization on String {
|
||||
"hint_t": "Note title...",
|
||||
"your_notes": "Your Notes",
|
||||
"new_image": "New Image",
|
||||
"no_title": "No title",
|
||||
"task_content": "Task content...",
|
||||
"task_name": "Task title...",
|
||||
"new_task": "New Task",
|
||||
},
|
||||
"hu_hu": {
|
||||
"notes": "Füzet",
|
||||
@@ -26,6 +30,10 @@ extension ScreensLocalization on String {
|
||||
"hint_t": "Jegyzet címe...",
|
||||
"your_notes": "Jegyzeteid",
|
||||
"new_image": "Új kép",
|
||||
"no_title": "Nincs cím",
|
||||
"task_content": "Feladat tartalma...",
|
||||
"task_name": "Feladat címe...",
|
||||
"new_task": "Új feladat",
|
||||
},
|
||||
"de_de": {
|
||||
"notes": "Broschüre",
|
||||
@@ -38,6 +46,10 @@ extension ScreensLocalization on String {
|
||||
"hint_t": "Titel notieren...",
|
||||
"your_notes": "Deine Noten",
|
||||
"new_image": "Neues Bild",
|
||||
"no_title": "Kein Titel",
|
||||
"task_content": "Aufgabeninhalt...",
|
||||
"task_name": "Aufgabentitel...",
|
||||
"new_task": "Neue Aufgabe",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -257,6 +257,8 @@ class AddNoteScreenState extends State<AddNoteScreen> {
|
||||
style: const TextStyle(fontSize: 16.0),
|
||||
),
|
||||
),
|
||||
if (MediaQuery.of(context).viewInsets.bottom != 0)
|
||||
const SizedBox(height: 60),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||
import 'package:image_crop/image_crop.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
@@ -27,6 +28,8 @@ class ImageNoteEditor extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _ImageNoteEditorState extends State<ImageNoteEditor> {
|
||||
final _title = TextEditingController();
|
||||
|
||||
final cropKey = GlobalKey<CropState>();
|
||||
File? _file;
|
||||
File? _sample;
|
||||
@@ -62,7 +65,7 @@ class _ImageNoteEditorState extends State<ImageNoteEditor> {
|
||||
child: Crop.file(
|
||||
_sample!,
|
||||
key: cropKey,
|
||||
aspectRatio: 1.0,
|
||||
// aspectRatio: 1.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -135,7 +138,8 @@ class _ImageNoteEditorState extends State<ImageNoteEditor> {
|
||||
selfNotes.add(SelfNote.fromJson({
|
||||
'id': const Uuid().v4(),
|
||||
'content': base64Image,
|
||||
'note_type': 'image'
|
||||
'note_type': 'image',
|
||||
'title': _title.text,
|
||||
}));
|
||||
|
||||
await Provider.of<DatabaseProvider>(context, listen: false)
|
||||
@@ -143,6 +147,7 @@ class _ImageNoteEditorState extends State<ImageNoteEditor> {
|
||||
.storeSelfNotes(selfNotes, userId: widget.u.id);
|
||||
|
||||
Provider.of<SelfNoteProvider>(context, listen: false).restore();
|
||||
Provider.of<SelfNoteProvider>(context, listen: false).restoreTodo();
|
||||
|
||||
debugPrint('$file');
|
||||
}
|
||||
@@ -170,6 +175,37 @@ class _ImageNoteEditorState extends State<ImageNoteEditor> {
|
||||
const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
|
||||
child: _sample == null ? openImageWidget() : cropImageWidget(),
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
|
||||
child: TextField(
|
||||
controller: _title,
|
||||
onEditingComplete: () async {},
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(
|
||||
borderSide: const BorderSide(color: Colors.grey, width: 1.5),
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: const BorderSide(color: Colors.grey, width: 1.5),
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
hintText: 'title'.i18n,
|
||||
suffixIcon: IconButton(
|
||||
icon: const Icon(
|
||||
FeatherIcons.x,
|
||||
color: Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_title.text = '';
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// if (widget.u.picture != "")
|
||||
// TextButton(
|
||||
// child: Text(
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||
import 'package:refilc/api/providers/self_note_provider.dart';
|
||||
import 'package:refilc/models/self_note.dart';
|
||||
@@ -8,6 +10,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:markdown/markdown.dart' as md;
|
||||
import 'notes_screen.i18n.dart';
|
||||
|
||||
class NoteViewScreen extends StatefulWidget {
|
||||
const NoteViewScreen({super.key, required this.note});
|
||||
@@ -30,7 +33,9 @@ class NoteViewScreenState extends State<NoteViewScreen> {
|
||||
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
leading: BackButton(color: AppColors.of(context).text),
|
||||
title: Text(
|
||||
widget.note.title ?? '${widget.note.content.split(' ')[0]}...',
|
||||
widget.note.noteType == NoteType.text
|
||||
? (widget.note.title ?? '${widget.note.content.split(' ')[0]}...')
|
||||
: 'image_note'.i18n,
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text,
|
||||
fontSize: 26.0,
|
||||
@@ -38,52 +43,55 @@ class NoteViewScreenState extends State<NoteViewScreen> {
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10.1),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
// handle tap
|
||||
Navigator.of(context, rootNavigator: true).push(
|
||||
CupertinoPageRoute(
|
||||
builder: (context) =>
|
||||
AddNoteScreen(initialNote: widget.note)));
|
||||
},
|
||||
child: Container(
|
||||
color: Theme.of(context).colorScheme.secondary.withOpacity(0.2),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Stack(
|
||||
children: [
|
||||
IconTheme(
|
||||
data: IconThemeData(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
if (widget.note.noteType == NoteType.text)
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10.1),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
// handle tap
|
||||
Navigator.of(context, rootNavigator: true).push(
|
||||
CupertinoPageRoute(
|
||||
builder: (context) =>
|
||||
AddNoteScreen(initialNote: widget.note)));
|
||||
},
|
||||
child: Container(
|
||||
color:
|
||||
Theme.of(context).colorScheme.secondary.withOpacity(0.2),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Stack(
|
||||
children: [
|
||||
IconTheme(
|
||||
data: IconThemeData(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
child: const Icon(
|
||||
FeatherIcons.edit,
|
||||
size: 20.0,
|
||||
),
|
||||
),
|
||||
child: const Icon(
|
||||
FeatherIcons.edit,
|
||||
size: 20.0,
|
||||
IconTheme(
|
||||
data: IconThemeData(
|
||||
color:
|
||||
Theme.of(context).brightness == Brightness.light
|
||||
? Colors.black.withOpacity(.5)
|
||||
: Colors.white.withOpacity(.3),
|
||||
),
|
||||
child: const Icon(
|
||||
FeatherIcons.edit,
|
||||
size: 20.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
IconTheme(
|
||||
data: IconThemeData(
|
||||
color:
|
||||
Theme.of(context).brightness == Brightness.light
|
||||
? Colors.black.withOpacity(.5)
|
||||
: Colors.white.withOpacity(.3),
|
||||
),
|
||||
child: const Icon(
|
||||
FeatherIcons.edit,
|
||||
size: 20.0,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
if (widget.note.noteType == NoteType.text)
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10.1),
|
||||
child: GestureDetector(
|
||||
@@ -140,21 +148,30 @@ class NoteViewScreenState extends State<NoteViewScreen> {
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: MarkdownBody(
|
||||
data: widget.note.content,
|
||||
extensionSet: md.ExtensionSet(
|
||||
md.ExtensionSet.gitHubFlavored.blockSyntaxes,
|
||||
<md.InlineSyntax>[
|
||||
md.EmojiSyntax(),
|
||||
...md.ExtensionSet.gitHubFlavored.inlineSyntaxes
|
||||
],
|
||||
),
|
||||
styleSheet: MarkdownStyleSheet(
|
||||
p: const TextStyle(
|
||||
fontSize: 15.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: widget.note.noteType == NoteType.text
|
||||
? MarkdownBody(
|
||||
data: widget.note.content,
|
||||
extensionSet: md.ExtensionSet(
|
||||
md.ExtensionSet.gitHubFlavored.blockSyntaxes,
|
||||
<md.InlineSyntax>[
|
||||
md.EmojiSyntax(),
|
||||
...md.ExtensionSet.gitHubFlavored.inlineSyntaxes
|
||||
],
|
||||
),
|
||||
styleSheet: MarkdownStyleSheet(
|
||||
p: const TextStyle(
|
||||
fontSize: 15.0,
|
||||
),
|
||||
),
|
||||
)
|
||||
: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10.0),
|
||||
child: Image.memory(
|
||||
const Base64Decoder().convert(widget.note.content),
|
||||
fit: BoxFit.contain,
|
||||
gaplessPlayback: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
// Expanded(
|
||||
// child: Text(
|
||||
|
||||
@@ -268,6 +268,7 @@ class NotesScreenState extends State<NotesScreen> {
|
||||
Provider.of<HomeworkProvider>(context, listen: false)
|
||||
.fetch(from: DateTime.now().subtract(const Duration(days: 30)));
|
||||
Provider.of<SelfNoteProvider>(context, listen: false).restore();
|
||||
Provider.of<SelfNoteProvider>(context, listen: false).restoreTodo();
|
||||
|
||||
return Future(() => null);
|
||||
},
|
||||
|
||||
@@ -18,6 +18,8 @@ extension SettingsLocalization on String {
|
||||
"click_here": "Click here",
|
||||
"select_image": "to select an image",
|
||||
"new_image": "New Image",
|
||||
"image_note": "Image",
|
||||
"title": "Image title...",
|
||||
},
|
||||
"hu_hu": {
|
||||
"notes": "Füzet",
|
||||
@@ -34,6 +36,8 @@ extension SettingsLocalization on String {
|
||||
"click_here": "Kattints ide",
|
||||
"select_image": "kép kiválasztásához",
|
||||
"new_image": "Új kép",
|
||||
"image_note": "Kép",
|
||||
"title": "Kép címe...",
|
||||
},
|
||||
"de_de": {
|
||||
"notes": "Broschüre",
|
||||
@@ -50,6 +54,8 @@ extension SettingsLocalization on String {
|
||||
"click_here": "Klicken Sie hier",
|
||||
"select_image": "um ein Bild auszuwählen",
|
||||
"new_image": "Neues Bild",
|
||||
"image_note": "Bild",
|
||||
"title": "Bildtitel...",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:refilc/models/settings.dart';
|
||||
import 'package:refilc/theme/colors/colors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:refilc/utils/format.dart';
|
||||
@@ -50,11 +53,26 @@ class _DayTitleState extends State<DayTitle> {
|
||||
width: MediaQuery.of(context).size.width / 1.5,
|
||||
child: Text(
|
||||
widget.dayTitle(index).capital(),
|
||||
style: TextStyle(
|
||||
color:
|
||||
AppColors.of(context).text.withOpacity(opacity),
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
style: Provider.of<SettingsProvider>(context)
|
||||
.fontFamily !=
|
||||
'' &&
|
||||
Provider.of<SettingsProvider>(context)
|
||||
.titleOnlyFont
|
||||
? GoogleFonts.getFont(
|
||||
Provider.of<SettingsProvider>(context).fontFamily,
|
||||
textStyle: TextStyle(
|
||||
color: AppColors.of(context)
|
||||
.text
|
||||
.withOpacity(opacity),
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
)
|
||||
: TextStyle(
|
||||
color: AppColors.of(context)
|
||||
.text
|
||||
.withOpacity(opacity),
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:math';
|
||||
import 'package:animations/animations.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:i18n_extension/i18n_extension.dart';
|
||||
import 'package:refilc/api/providers/database_provider.dart';
|
||||
import 'package:refilc/api/providers/update_provider.dart';
|
||||
@@ -19,7 +20,7 @@ import 'package:refilc_mobile_ui/common/empty.dart';
|
||||
import 'package:refilc_mobile_ui/common/profile_image/profile_button.dart';
|
||||
import 'package:refilc_mobile_ui/common/profile_image/profile_image.dart';
|
||||
import 'package:refilc_mobile_ui/common/system_chrome.dart';
|
||||
import 'package:refilc_mobile_ui/common/widgets/lesson/lesson_view.dart';
|
||||
// import 'package:refilc_mobile_ui/common/widgets/lesson/lesson_view.dart';
|
||||
import 'package:refilc_kreta_api/controllers/timetable_controller.dart';
|
||||
import 'package:refilc_mobile_ui/common/widgets/lesson/lesson_viewable.dart';
|
||||
import 'package:refilc_mobile_ui/pages/timetable/day_title.dart';
|
||||
@@ -60,7 +61,11 @@ class TimetablePage extends StatefulWidget {
|
||||
NavigationScreen.of(context)?.setPage("timetable");
|
||||
|
||||
// Show initial Lesson
|
||||
if (lesson != null) LessonView.show(lesson, context: context);
|
||||
// if (lesson != null) LessonView.show(lesson, context: context);
|
||||
// changed to new popup
|
||||
if (lesson != null) {
|
||||
TimetableLessonPopup.show(context: context, lesson: lesson);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -316,6 +321,7 @@ class TimetablePageState extends State<TimetablePage>
|
||||
badge: updateProvider.available,
|
||||
role: user.role,
|
||||
profilePictureString: user.picture,
|
||||
gradeStreak: (user.gradeStreak ?? 0) > 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -374,11 +380,25 @@ class TimetablePageState extends State<TimetablePage>
|
||||
} else {
|
||||
return Text(
|
||||
"timetable".i18n,
|
||||
style: TextStyle(
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColors.of(context).text,
|
||||
),
|
||||
style: Provider.of<SettingsProvider>(context)
|
||||
.fontFamily !=
|
||||
'' &&
|
||||
Provider.of<SettingsProvider>(context)
|
||||
.titleOnlyFont
|
||||
? GoogleFonts.getFont(
|
||||
Provider.of<SettingsProvider>(context)
|
||||
.fontFamily,
|
||||
textStyle: TextStyle(
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColors.of(context).text,
|
||||
),
|
||||
)
|
||||
: TextStyle(
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColors.of(context).text,
|
||||
),
|
||||
);
|
||||
}
|
||||
}(),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:refilc/models/settings.dart';
|
||||
import 'package:refilc_plus/providers/plus_provider.dart';
|
||||
import 'package:refilc_plus/ui/mobile/plus/activation_view/activation_view.dart';
|
||||
import 'package:refilc_mobile_ui/plus/plus_screen.i18n.dart';
|
||||
@@ -50,6 +51,20 @@ class PlusPlanCard extends StatelessWidget {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Provider.of<SettingsProvider>(context, listen: false).xFilcId ==
|
||||
"none") {
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
||||
content: Text(
|
||||
"Be kell kapcsolnod a Névtelen Analitikát a beállítások főoldalán, mielőtt reFilc+ előfizetést vásárolnál!",
|
||||
style:
|
||||
TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
|
||||
),
|
||||
backgroundColor: Colors.white,
|
||||
));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Provider.of<PlusProvider>(context, listen: false).hasPremium) {
|
||||
if (!active) {
|
||||
launchUrl(
|
||||
|
||||
@@ -225,6 +225,7 @@ class PlusScreenState extends State<PlusScreen> {
|
||||
['🎓', 'rfp_6'.i18n],
|
||||
['👕', 'rfp_14'.i18n],
|
||||
['👑', 'rfp_15'.i18n],
|
||||
['📩', 'rfp_17'.i18n],
|
||||
['🔜', 'more_soon'.i18n],
|
||||
],
|
||||
docsAccepted: docsAccepted,
|
||||
|
||||
@@ -45,6 +45,7 @@ extension SettingsLocalization on String {
|
||||
"rfp_14": "Discount in reFilc Shop (soon)",
|
||||
"rfp_15": "Subscriber role in our Discord community",
|
||||
"rfp_16": "Private leaks and informations about upcoming features",
|
||||
"rfp_17": "Grade exporting",
|
||||
// other
|
||||
"and": " and ",
|
||||
"every": "Every ",
|
||||
@@ -96,6 +97,7 @@ extension SettingsLocalization on String {
|
||||
"rfp_14": "Kedvezmény a reFilc Shop-ban (hamarosan)",
|
||||
"rfp_15": "Előfizetői rang a Discord szerverünkön",
|
||||
"rfp_16": "Privát betekintések és információk közelgő újításokról",
|
||||
"rfp_17": "Jegy exportálás",
|
||||
// other
|
||||
"and": " és ",
|
||||
"every": "Minden ",
|
||||
@@ -133,30 +135,32 @@ extension SettingsLocalization on String {
|
||||
"Der Preis wird in Euro angegeben im Bezug zum aktuellen Wechselkurs. 1 EUR ≈ 390 HUF",
|
||||
"active": "Aktiv",
|
||||
// benefits
|
||||
"rfp_1": "Előzetes hozzáférés új verziókhoz",
|
||||
"rfp_2": "2 fiók használata egyszerre",
|
||||
"rfp_3": "Egyedi üdvözlő üzenet",
|
||||
"rfp_4": "Korlátlan saját jegyzet és feladat a füzet oldalon",
|
||||
"rfp_5": "Egyedi jegy ritkaságok",
|
||||
"rfp_6": "Összesített átlagszámoló",
|
||||
"rfp_7": "Órarend jegyzetek",
|
||||
"rfp_8": "Egyedi betütípusok",
|
||||
"rfp_9": "Korlátlan fiók használata egyszerre",
|
||||
"rfp_10": "Alkalmazás ikonjának megváltoztatása (v5.1-től)",
|
||||
"rfp_11": "Live Activity szín",
|
||||
"rfp_12": "Fejlettebb cél kitűzés",
|
||||
"rfp_13": "Naptár szinkronizálás",
|
||||
"rfp_14": "Kedvezmény a reFilc Shop-ban (hamarosan)",
|
||||
"rfp_15": "Előfizetői rang a Discord szerverünkön",
|
||||
"rfp_16": "Privát betekintések és információk közelgő újításokról",
|
||||
"rfp_1": "Frühzeitiger Zugriff auf Updates",
|
||||
"rfp_2": "Verwendung von zwei Konten gleichzeitig",
|
||||
"rfp_3": "Individuelle Begrüßungsnachricht",
|
||||
"rfp_4":
|
||||
"Unbegrenzte eigene Notizen und Aufgaben auf der Notizbuchseite",
|
||||
"rfp_5": "Individuelle Notenraritäten",
|
||||
"rfp_6": "Gesamtdurchschnittsberechner",
|
||||
"rfp_7": "Stundenplan-Notizen",
|
||||
"rfp_8": "Individuelle Schriftarten",
|
||||
"rfp_9": "Unbegrenzte Konten",
|
||||
"rfp_10": "Anpassung des App-Symbols (ab v5.1)",
|
||||
"rfp_11": "Änderung der Live-Aktivitätsfarbe",
|
||||
"rfp_12": "Verbesserter Zielplaner",
|
||||
"rfp_13": "Importieren Sie Ihren Stundenplan in Ihre Kalender-App",
|
||||
"rfp_14": "Rabatt im reFilc Shop (bald)",
|
||||
"rfp_15": "Abonnentenrolle in unserer Discord-Community",
|
||||
"rfp_16": "Private Leaks und Informationen über kommende Funktionen",
|
||||
"rfp_17": "Notenexport",
|
||||
// other
|
||||
"and": " és ",
|
||||
"every": "Minden ",
|
||||
"benefit": " előny",
|
||||
"and": " und ",
|
||||
"every": "Jeder ",
|
||||
"benefit": " Vorteil",
|
||||
"show_lifetime": "Für immer Pakete",
|
||||
"more_soon": "Mehr folgt bald...",
|
||||
"faq_dc":
|
||||
"Az előnyök beváltásához írj nekünk Discord-on privát üzenetet!",
|
||||
"Um Ihre Vorteile einzulösen, schreiben Sie uns eine private Nachricht auf Discord!",
|
||||
"reactivate": "Bestehendes Abonnement reaktivieren",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@ extension SettingsLocalization on String {
|
||||
{
|
||||
"en_en": {
|
||||
"ekretaYou": "e-KRÉTA, you",
|
||||
"description": "An error occurred!",
|
||||
"description": "Unexpected error while using the application!",
|
||||
"submit": "Submit",
|
||||
"goback": "Go back",
|
||||
"details": "Details",
|
||||
@@ -15,11 +15,11 @@ extension SettingsLocalization on String {
|
||||
"stack": "Stack Trace",
|
||||
"done": "Done",
|
||||
"smth_went_wrong":
|
||||
"Something went wrong, it is of course the fault of Educational Development Informatikai Zrt. (e-KRÉTA) in any case! /s",
|
||||
"An unexpected error occurred while using the app.",
|
||||
},
|
||||
"hu_hu": {
|
||||
"ekretaYou": "e-KRÉTA, te",
|
||||
"description": "Fasz-emulátor hivatásos balfasz!",
|
||||
"description": "Váratlan hiba az alkalmazás használata közben!",
|
||||
"submit": "Hiba jelentése",
|
||||
"goback": "Vissza",
|
||||
"details": "Részletek",
|
||||
@@ -29,11 +29,11 @@ extension SettingsLocalization on String {
|
||||
"stack": "Stacktrace",
|
||||
"done": "Kész",
|
||||
"smth_went_wrong":
|
||||
"Valami probléma történt, ez természetesen az Educational Development Informatikai Zrt. (e-KRÉTA) hibája minden esetben! /s",
|
||||
"Nem várt hiba következett be az alkalmazás használata közben.",
|
||||
},
|
||||
"de_de": {
|
||||
"ekretaYou": "e-KRÉTA, du",
|
||||
"description": "Ein Fehler ist aufgetreten!",
|
||||
"description": "Unerwarteter Fehler bei der Benutzung der Anwendung!",
|
||||
"submit": "Abschicken",
|
||||
"goback": "Zurück",
|
||||
"details": "Details",
|
||||
@@ -43,7 +43,7 @@ extension SettingsLocalization on String {
|
||||
"stack": "Stack Trace",
|
||||
"done": "Fertig",
|
||||
"smth_went_wrong":
|
||||
"Irgendetwas ist schief gelaufen, es ist natürlich auf jeden Fall die Schuld der Educational Development Informatikai Zrt. (e-KRÉTA)! /s",
|
||||
"Bei der Benutzung der Anwendung ist ein unerwarteter Fehler aufgetreten.",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
183
refilc_mobile_ui/lib/screens/login/kreten_login.dart
Normal file
@@ -0,0 +1,183 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:refilc_kreta_api/client/api.dart';
|
||||
import 'package:refilc_kreta_api/client/client.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
|
||||
class KretenLoginScreen extends StatefulWidget {
|
||||
const KretenLoginScreen({super.key});
|
||||
|
||||
@override
|
||||
State<KretenLoginScreen> createState() => _KretenLoginScreenState();
|
||||
}
|
||||
|
||||
class _KretenLoginScreenState extends State<KretenLoginScreen> {
|
||||
late final WebViewController controller;
|
||||
var loadingPercentage = 0;
|
||||
var currentUrl = '';
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
controller = WebViewController()
|
||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||
..setNavigationDelegate(NavigationDelegate(
|
||||
onPageStarted: (url) async {
|
||||
setState(() {
|
||||
loadingPercentage = 0;
|
||||
currentUrl = url;
|
||||
});
|
||||
|
||||
List<String> requiredThings = url
|
||||
.replaceAll(
|
||||
'https://mobil.e-kreta.hu/ellenorzo-student/prod/oauthredirect?code=',
|
||||
'')
|
||||
.replaceAll(
|
||||
'&scope=openid email offline_access kreta-ellenorzo-webapi.public kreta-eugyintezes-webapi.public kreta-fileservice-webapi.public kreta-mobile-global-webapi.public kreta-dkt-webapi.public kreta-ier-webapi.public&state=refilc_student_mobile&session_state=',
|
||||
':')
|
||||
.split(':');
|
||||
|
||||
String code = requiredThings[0];
|
||||
// String sessionState = requiredThings[1];
|
||||
|
||||
debugPrint('url: $url');
|
||||
|
||||
// actual login (token grant) logic
|
||||
Map<String, String> headers = {
|
||||
"content-type": "application/x-www-form-urlencoded",
|
||||
"accept": "*/*",
|
||||
"user-agent":
|
||||
"eKretaStudent/264745 CFNetwork/1494.0.7 Darwin/23.4.0",
|
||||
"code_verifier": "THDUSddKOOndwCkqBtVHvRjh2LK0V2kMyLP2QirqVWQ",
|
||||
};
|
||||
|
||||
Map? res = await Provider.of<KretaClient>(context, listen: false)
|
||||
.postAPI(KretaAPI.login, headers: headers, body: {
|
||||
"code": code,
|
||||
"redirect_uri":
|
||||
"https://mobil.e-kreta.hu/ellenorzo-student/prod/oauthredirect",
|
||||
"client_id": "kreta-ellenorzo-student-mobile-ios",
|
||||
"grant_type": "authorization_code",
|
||||
});
|
||||
if (res != null) {
|
||||
if (kDebugMode) {
|
||||
print(res);
|
||||
}
|
||||
|
||||
// if (res.containsKey("error")) {
|
||||
// if (res["error"] == "invalid_grant") {
|
||||
// print("ERROR: invalid_grant");
|
||||
// return;
|
||||
// }
|
||||
// } else {
|
||||
// if (res.containsKey("access_token")) {
|
||||
// try {
|
||||
// Provider.of<KretaClient>(context, listen: false).accessToken =
|
||||
// res["access_token"];
|
||||
// Map? studentJson =
|
||||
// await Provider.of<KretaClient>(context, listen: false)
|
||||
// .getAPI(KretaAPI.student(instituteCode));
|
||||
// Student student = Student.fromJson(studentJson!);
|
||||
// var user = User(
|
||||
// username: username,
|
||||
// password: password,
|
||||
// instituteCode: instituteCode,
|
||||
// name: student.name,
|
||||
// student: student,
|
||||
// role: JwtUtils.getRoleFromJWT(res["access_token"])!,
|
||||
// );
|
||||
|
||||
// if (onLogin != null) onLogin(user);
|
||||
|
||||
// // Store User in the database
|
||||
// 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);
|
||||
|
||||
// // Get user data
|
||||
// try {
|
||||
// await Future.wait([
|
||||
// Provider.of<GradeProvider>(context, listen: false)
|
||||
// .fetch(),
|
||||
// Provider.of<TimetableProvider>(context, listen: false)
|
||||
// .fetch(week: Week.current()),
|
||||
// Provider.of<ExamProvider>(context, listen: false).fetch(),
|
||||
// Provider.of<HomeworkProvider>(context, listen: false)
|
||||
// .fetch(),
|
||||
// Provider.of<MessageProvider>(context, listen: false)
|
||||
// .fetchAll(),
|
||||
// Provider.of<MessageProvider>(context, listen: false)
|
||||
// .fetchAllRecipients(),
|
||||
// Provider.of<NoteProvider>(context, listen: false).fetch(),
|
||||
// Provider.of<EventProvider>(context, listen: false)
|
||||
// .fetch(),
|
||||
// Provider.of<AbsenceProvider>(context, listen: false)
|
||||
// .fetch(),
|
||||
// ]);
|
||||
// } catch (error) {
|
||||
// print("WARNING: failed to fetch user data: $error");
|
||||
// }
|
||||
|
||||
// if (onSuccess != null) onSuccess();
|
||||
|
||||
// return LoginState.success;
|
||||
// } catch (error) {
|
||||
// print("ERROR: loginAPI: $error");
|
||||
// // maybe check debug mode
|
||||
// // ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("ERROR: $error")));
|
||||
// return LoginState.failed;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
},
|
||||
onProgress: (progress) {
|
||||
setState(() {
|
||||
loadingPercentage = progress;
|
||||
});
|
||||
},
|
||||
onPageFinished: (url) {
|
||||
setState(() {
|
||||
loadingPercentage = 100;
|
||||
});
|
||||
},
|
||||
))
|
||||
..loadRequest(
|
||||
Uri.parse(
|
||||
'https://idp.e-kreta.hu/connect/authorize?prompt=login&nonce=refilc&response_type=code&code_challenge_method=S256&scope=openid%20email%20offline_access%20kreta-ellenorzo-webapi.public%20kreta-eugyintezes-webapi.public%20kreta-fileservice-webapi.public%20kreta-mobile-global-webapi.public%20kreta-dkt-webapi.public%20kreta-ier-webapi.public&code_challenge=Oj_aVMRJHYsv00mrtGJY72NJa7HY54lVnU2Cb4CWbWw&redirect_uri=https://mobil.e-kreta.hu/ellenorzo-student/prod/oauthredirect&client_id=kreta-ellenorzo-student-mobile-ios&state=refilc_student_mobile'),
|
||||
);
|
||||
}
|
||||
|
||||
// Future<void> loadLoginUrl() async {
|
||||
// String nonceStr = await Provider.of<KretaClient>(context, listen: false)
|
||||
// .getAPI(KretaAPI.nonce, json: false);
|
||||
|
||||
// Nonce nonce = getNonce(nonceStr, );
|
||||
// }
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: const BackButton(),
|
||||
title: const Text('e-KRÉTA Bejelentkezés'),
|
||||
),
|
||||
body: Stack(
|
||||
children: [
|
||||
WebViewWidget(
|
||||
controller: controller,
|
||||
),
|
||||
if (loadingPercentage < 100)
|
||||
LinearProgressIndicator(
|
||||
value: loadingPercentage / 100.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,9 @@ class AccountView extends StatelessWidget {
|
||||
Detail(
|
||||
title: "parents".plural(user.student.parents.length),
|
||||
description: user.student.parents.join(", ")),
|
||||
const SizedBox(
|
||||
height: 10.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -8,21 +8,22 @@ extension Localization on String {
|
||||
"school": "School",
|
||||
"class": "Class",
|
||||
"address": "Home address",
|
||||
"parents": "Parents".one("Parent"),
|
||||
"parents": "Parent(s)",
|
||||
"parents_phone": "Parents' phone number: ",
|
||||
},
|
||||
"hu_hu": {
|
||||
"birthdate": "Születési dátum",
|
||||
"school": "Iskola",
|
||||
"class": "Osztály",
|
||||
"address": "Lakcím",
|
||||
"parents": "Szülők".one("Szülő"),
|
||||
"parents": "Szülő(k)",
|
||||
},
|
||||
"de_de": {
|
||||
"birthdate": "Geburtsdatum",
|
||||
"school": "Schule",
|
||||
"class": "Klasse",
|
||||
"address": "Wohnanschrift",
|
||||
"parents": "Eltern",
|
||||
"parents": "Elter(n)",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -37,6 +37,9 @@ import 'package:flutter_material_color_picker/flutter_material_color_picker.dart
|
||||
import 'package:refilc/models/icon_pack.dart';
|
||||
import 'package:refilc/utils/format.dart';
|
||||
import 'package:refilc_mobile_ui/screens/settings/theme_screen.dart';
|
||||
import 'package:refilc_plus/models/premium_scopes.dart';
|
||||
import 'package:refilc_plus/providers/plus_provider.dart';
|
||||
import 'package:refilc_plus/ui/mobile/plus/upsell.dart';
|
||||
// import 'package:refilc_plus/models/premium_scopes.dart';
|
||||
// import 'package:refilc_plus/providers/plus_provider.dart';
|
||||
// import 'package:refilc_plus/ui/mobile/plus/upsell.dart';
|
||||
@@ -900,6 +903,15 @@ class _LiveActivityColorSettingState extends State<LiveActivityColorSetting> {
|
||||
allowShades: false,
|
||||
selectedColor: settings.liveActivityColor,
|
||||
onMainColorChange: (k) {
|
||||
if (!Provider.of<PlusProvider>(context, listen: false)
|
||||
.hasScope(PremiumScopes.liveActivityColor)) {
|
||||
PlusLockedFeaturePopup.show(
|
||||
context: context,
|
||||
feature: PremiumFeature.liveActivity,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
currentColor = k as Color;
|
||||
settings.update(
|
||||
|
||||
@@ -27,6 +27,7 @@ import 'package:refilc_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu.dart
|
||||
import 'package:refilc_mobile_ui/common/panel/panel.dart';
|
||||
import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
|
||||
import 'package:refilc_mobile_ui/common/profile_image/profile_image.dart';
|
||||
import 'package:refilc_mobile_ui/common/soon_alert/soon_alert.dart';
|
||||
// import 'package:refilc_mobile_ui/common/soon_alert/soon_alert.dart';
|
||||
import 'package:refilc_mobile_ui/common/splitted_panel/splitted_panel.dart';
|
||||
// import 'package:refilc_mobile_ui/common/system_chrome.dart';
|
||||
@@ -320,6 +321,7 @@ class SettingsScreenState extends State<SettingsScreen>
|
||||
badge: updateProvider.available,
|
||||
role: user.role,
|
||||
profilePictureString: user.picture,
|
||||
gradeStreak: (user.gradeStreak ?? 0) > 1,
|
||||
backgroundColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.tertiary, //!settings.presentationMode
|
||||
@@ -702,6 +704,46 @@ class SettingsScreenState extends State<SettingsScreen>
|
||||
],
|
||||
),
|
||||
|
||||
if ((user.gradeStreak ?? 0) > 1)
|
||||
SplittedPanel(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: 12.0, left: 24.0, right: 24.0),
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
SoonAlert.show(context: context);
|
||||
},
|
||||
child: ListTile(
|
||||
title: Text(
|
||||
"grade_streak".i18n,
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text.withOpacity(0.95),
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
"grade_streak_subtitle".i18n,
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text.withOpacity(0.75),
|
||||
),
|
||||
),
|
||||
leading: const Text(
|
||||
"🔥",
|
||||
style: TextStyle(fontSize: 22.0),
|
||||
),
|
||||
trailing: Text(
|
||||
"${user.gradeStreak}",
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text.withOpacity(0.95),
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 18.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
// plus subscribe inline
|
||||
const PlusSettingsInline(),
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ extension SettingsLocalization on String {
|
||||
static final _t = Translations.byLocale("hu_hu") +
|
||||
{
|
||||
"en_en": {
|
||||
"heads_up": "Heads up!",
|
||||
"export_warning": "Exported grades are currently not yet viewable in reFilc, you'll only be able to view them manually in JSON format. In the future, this functionality will be extended and you will be able to view the tickets in the app interface.",
|
||||
"personal_details": "Personal Details",
|
||||
"open_dkt": "Open DCS",
|
||||
"edit_nickname": "Edit Nickname",
|
||||
@@ -116,8 +118,18 @@ extension SettingsLocalization on String {
|
||||
"exp_settings": "Export Settings",
|
||||
"manage_subs": "Manage Subscription",
|
||||
"copy_plus_id": "Copy reFilc+ ID",
|
||||
// grade streak
|
||||
"grade_streak": "Grade 5 Streak",
|
||||
"grade_streak_subtitle": "So many 5s in a row?!",
|
||||
// other
|
||||
"only_ch_title_font": "Font Only for Titles",
|
||||
"new_popups": "New Popups",
|
||||
"export_method": "Export Method",
|
||||
"grade_exporting": "Grade Exporting",
|
||||
},
|
||||
"hu_hu": {
|
||||
"heads_up": "Figyelem!",
|
||||
"export_warning": "Az exportált jegyek jelenleg még nem megtekinthetők a reFilc-ben, csak te magad tudod átnézni őket JSON formátumban. A jövőben ez a funkció bővülni fog, és a jegyeket meg is tekintheted majd a reFilc felületén.",
|
||||
"personal_details": "Személyes információk",
|
||||
"open_dkt": "DKT megnyitása",
|
||||
"edit_nickname": "Becenév szerkesztése",
|
||||
@@ -230,8 +242,18 @@ extension SettingsLocalization on String {
|
||||
"exp_settings": "Beállítások exportálása",
|
||||
"manage_subs": "Előfizetés kezelése",
|
||||
"copy_plus_id": "reFilc+ ID másolása",
|
||||
// grade streak
|
||||
"grade_streak": "5-ös sorozat",
|
||||
"grade_streak_subtitle": "Egymás után ennyi 5-ös?!",
|
||||
// other
|
||||
"only_ch_title_font": "Betűtípus csak címekre",
|
||||
"new_popups": "Új felugró ablakok",
|
||||
"export_method": "Exportálási mód",
|
||||
"grade_exporting": "Jegy exportálás",
|
||||
},
|
||||
"de_de": {
|
||||
"heads_up": "Achtung!",
|
||||
"export_warning": "Exportierte Tickets sind derzeit noch nicht in reFilc einsehbar, Sie können sie nur selbst im JSON- Format überprüfen. In Zukunft wird diese Funktionalität erweitert und Sie werden die Tickets in der reFilc-Oberfläche anzeigen können",
|
||||
"personal_details": "Persönliche Angaben",
|
||||
"open_dkt": "Öffnen RDZ",
|
||||
"edit_nickname": "Spitznamen bearbeiten",
|
||||
@@ -344,6 +366,14 @@ extension SettingsLocalization on String {
|
||||
"exp_settings": "Einstellungen exportieren",
|
||||
"manage_subs": "Abonnement verwalten",
|
||||
"copy_plus_id": "reFilc+ ID kopieren",
|
||||
// grade streak
|
||||
"grade_streak": "5er-Streak",
|
||||
"grade_streak_subtitle": "So viele 5er in Folge?!",
|
||||
// other
|
||||
"only_ch_title_font": "Schriftart nur für Titel",
|
||||
"new_popups": "Neue Popups",
|
||||
"export_method": "Exportmethode",
|
||||
"grade_exporting": "Noten exportieren",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:refilc_plus/ui/mobile/settings/submenu/calendar_sync.dart';
|
||||
import 'package:refilc_plus/ui/mobile/settings/submenu/grade_exporting.dart';
|
||||
import 'package:refilc_plus/models/premium_scopes.dart';
|
||||
import 'package:refilc_plus/providers/plus_provider.dart';
|
||||
import 'package:refilc_plus/ui/mobile/plus/upsell.dart';
|
||||
@@ -158,6 +159,16 @@ class ExtrasSettingsScreenState extends State<ExtrasSettingsScreen> {
|
||||
),
|
||||
],
|
||||
),
|
||||
SplittedPanel(
|
||||
padding: const EdgeInsets.only(top: 9.0),
|
||||
cardPadding: const EdgeInsets.all(4.0),
|
||||
isSeparated: true,
|
||||
children: [
|
||||
MenuGradeExporting(
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
381
refilc_mobile_ui/lib/screens/settings/submenu/grade_colors.dart
Normal file
@@ -0,0 +1,381 @@
|
||||
import 'package:refilc/models/settings.dart';
|
||||
import 'package:refilc/theme/colors/colors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:refilc/ui/flutter_colorpicker/colorpicker.dart';
|
||||
import 'package:refilc/ui/widgets/grade/grade_tile.dart';
|
||||
import 'package:refilc_kreta_api/models/grade.dart';
|
||||
import 'package:refilc_mobile_ui/screens/settings/theme_screen.dart';
|
||||
import 'submenu_screen.i18n.dart';
|
||||
|
||||
enum SelectedGrade { one, two, three, four, five }
|
||||
|
||||
class GradeColorsSettingsScreen extends StatefulWidget {
|
||||
const GradeColorsSettingsScreen({super.key});
|
||||
|
||||
@override
|
||||
GradeColorsSettingsScreenState createState() =>
|
||||
GradeColorsSettingsScreenState();
|
||||
}
|
||||
|
||||
class GradeColorsSettingsScreenState extends State<GradeColorsSettingsScreen> {
|
||||
late SettingsProvider settingsProvider;
|
||||
|
||||
SelectedGrade currentEditGrade = SelectedGrade.one;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
leading: BackButton(
|
||||
color: AppColors.of(context).text,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
// made this cuz else it will be ugly
|
||||
currentEditGrade = SelectedGrade.one;
|
||||
});
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
title: Text(
|
||||
"grade_colors".i18n,
|
||||
style: TextStyle(color: AppColors.of(context).text),
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
List<Color> colors = List.castFrom(settingsProvider.gradeColors);
|
||||
var defaultColors =
|
||||
SettingsProvider.defaultSettings().gradeColors;
|
||||
colors[currentEditGrade.index] =
|
||||
defaultColors[currentEditGrade.index];
|
||||
settingsProvider.update(gradeColors: colors);
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.restore,
|
||||
size: 26.0,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
body: SizedBox(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).size.height * 0.14,
|
||||
),
|
||||
Stack(
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
borderRadius: BorderRadius.circular(75.0),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.shadow
|
||||
.withOpacity(.1),
|
||||
blurRadius: 10.0,
|
||||
offset: const Offset(0, 5),
|
||||
),
|
||||
],
|
||||
),
|
||||
padding: const EdgeInsets.all(6.0),
|
||||
child: GradeValueWidget(
|
||||
GradeValue(currentEditGrade.index + 1, '', '', 100),
|
||||
fill: true,
|
||||
size: 75.0,
|
||||
// color:
|
||||
// settingsProvider.gradeColors[currentEditGrade.index],
|
||||
),
|
||||
),
|
||||
// before grades
|
||||
if (currentEditGrade.index > 0)
|
||||
Transform.translate(
|
||||
offset: const Offset(-110, 16.5),
|
||||
child: GradeValueWidget(
|
||||
GradeValue(currentEditGrade.index, '', '', 100),
|
||||
fill: true,
|
||||
size: 60.0,
|
||||
// color:
|
||||
// settingsProvider.gradeColors[currentEditGrade.index],
|
||||
),
|
||||
),
|
||||
if (currentEditGrade.index > 1)
|
||||
Transform.translate(
|
||||
offset: const Offset(-200, 23),
|
||||
child: GradeValueWidget(
|
||||
GradeValue(currentEditGrade.index - 1, '', '', 100),
|
||||
fill: true,
|
||||
size: 50.0,
|
||||
// color:
|
||||
// settingsProvider.gradeColors[currentEditGrade.index],
|
||||
),
|
||||
),
|
||||
// after grades
|
||||
if (currentEditGrade.index < 4)
|
||||
Transform.translate(
|
||||
offset: const Offset(142, 16.5),
|
||||
child: GradeValueWidget(
|
||||
GradeValue(currentEditGrade.index + 2, '', '', 100),
|
||||
fill: true,
|
||||
size: 60.0,
|
||||
// color:
|
||||
// settingsProvider.gradeColors[currentEditGrade.index],
|
||||
),
|
||||
),
|
||||
if (currentEditGrade.index < 3)
|
||||
Transform.translate(
|
||||
offset: const Offset(245, 23),
|
||||
child: GradeValueWidget(
|
||||
GradeValue(currentEditGrade.index + 3, '', '', 100),
|
||||
fill: true,
|
||||
size: 50.0,
|
||||
// color:
|
||||
// settingsProvider.gradeColors[currentEditGrade.index],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).size.height * 0.14,
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
child: SafeArea(
|
||||
child: FilcColorPicker(
|
||||
colorMode: CustomColorMode.grade,
|
||||
pickerColor:
|
||||
settingsProvider.gradeColors[currentEditGrade.index],
|
||||
onColorChanged: (c) {
|
||||
setState(() {
|
||||
// update grade color
|
||||
settingsProvider.update(
|
||||
gradeColors: settingsProvider.gradeColors
|
||||
..[currentEditGrade.index] = c);
|
||||
});
|
||||
},
|
||||
onColorChangeEnd: (c, {adaptive}) {
|
||||
// update grade color
|
||||
},
|
||||
onThemeIdProvided: (t) {},
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 20.0, top: 16.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => setState(() {
|
||||
currentEditGrade = SelectedGrade.one;
|
||||
}),
|
||||
child: Container(
|
||||
width: 45.0,
|
||||
height: 45.0,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: currentEditGrade == SelectedGrade.one
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondary
|
||||
.withOpacity(.2),
|
||||
width: 1.0,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(50.0),
|
||||
color: currentEditGrade == SelectedGrade.one
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: null,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'1',
|
||||
style: TextStyle(
|
||||
fontSize: 14.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: currentEditGrade == SelectedGrade.one
|
||||
? Colors.white
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10.0),
|
||||
GestureDetector(
|
||||
onTap: () => setState(() {
|
||||
currentEditGrade = SelectedGrade.two;
|
||||
}),
|
||||
child: Container(
|
||||
width: 45.0,
|
||||
height: 45.0,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: currentEditGrade == SelectedGrade.two
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondary
|
||||
.withOpacity(.2),
|
||||
width: 1.0,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(50.0),
|
||||
color: currentEditGrade == SelectedGrade.two
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: null,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'2',
|
||||
style: TextStyle(
|
||||
fontSize: 14.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: currentEditGrade == SelectedGrade.two
|
||||
? Colors.white
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10.0),
|
||||
GestureDetector(
|
||||
onTap: () => setState(() {
|
||||
currentEditGrade = SelectedGrade.three;
|
||||
}),
|
||||
child: Container(
|
||||
width: 45.0,
|
||||
height: 45.0,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: currentEditGrade == SelectedGrade.three
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondary
|
||||
.withOpacity(.2),
|
||||
width: 1.0,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(50.0),
|
||||
color: currentEditGrade == SelectedGrade.three
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: null,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'3',
|
||||
style: TextStyle(
|
||||
fontSize: 14.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: currentEditGrade == SelectedGrade.three
|
||||
? Colors.white
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10.0),
|
||||
GestureDetector(
|
||||
onTap: () => setState(() {
|
||||
currentEditGrade = SelectedGrade.four;
|
||||
}),
|
||||
child: Container(
|
||||
width: 45.0,
|
||||
height: 45.0,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: currentEditGrade == SelectedGrade.four
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondary
|
||||
.withOpacity(.2),
|
||||
width: 1.0,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(50.0),
|
||||
color: currentEditGrade == SelectedGrade.four
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: null,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'4',
|
||||
style: TextStyle(
|
||||
fontSize: 14.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: currentEditGrade == SelectedGrade.four
|
||||
? Colors.white
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10.0),
|
||||
GestureDetector(
|
||||
onTap: () => setState(() {
|
||||
currentEditGrade = SelectedGrade.five;
|
||||
}),
|
||||
child: Container(
|
||||
width: 45.0,
|
||||
height: 45.0,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: currentEditGrade == SelectedGrade.five
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondary
|
||||
.withOpacity(.2),
|
||||
width: 1.0,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(50.0),
|
||||
color: currentEditGrade == SelectedGrade.five
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: null,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'5',
|
||||
style: TextStyle(
|
||||
fontSize: 14.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: currentEditGrade == SelectedGrade.five
|
||||
? Colors.white
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:refilc_mobile_ui/screens/settings/settings_screen.i18n.dart';
|
||||
import 'package:refilc_mobile_ui/screens/settings/submenu/share_theme_popup.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
class MenuPaintList extends StatelessWidget {
|
||||
@@ -251,18 +252,7 @@ class PaintListScreenState extends State<PaintListScreen>
|
||||
subject: 'share_subj_theme'.i18n,
|
||||
);
|
||||
} else {
|
||||
SharedGradeColors gradeColors = await shareProvider
|
||||
.shareCurrentGradeColors(context);
|
||||
SharedTheme theme =
|
||||
await shareProvider.shareCurrentTheme(
|
||||
context,
|
||||
gradeColors: gradeColors,
|
||||
);
|
||||
|
||||
Share.share(
|
||||
theme.id,
|
||||
subject: 'share_subj_theme'.i18n,
|
||||
);
|
||||
ShareThemeDialog.show(context);
|
||||
}
|
||||
},
|
||||
longPressInstead: true,
|
||||
|
||||
@@ -30,6 +30,8 @@ import 'package:refilc_plus/providers/plus_provider.dart';
|
||||
import 'package:refilc_plus/ui/mobile/plus/upsell.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
import 'grade_colors.dart';
|
||||
|
||||
class MenuPersonalizeSettings extends StatelessWidget {
|
||||
const MenuPersonalizeSettings({
|
||||
super.key,
|
||||
@@ -459,6 +461,49 @@ class PersonalizeSettingsScreenState extends State<PersonalizeSettingsScreen>
|
||||
),
|
||||
],
|
||||
),
|
||||
// new popup toggle
|
||||
SplittedPanel(
|
||||
padding: const EdgeInsets.only(top: 9.0),
|
||||
cardPadding: const EdgeInsets.all(4.0),
|
||||
isSeparated: true,
|
||||
children: [
|
||||
PanelButton(
|
||||
padding: const EdgeInsets.only(left: 14.0, right: 6.0),
|
||||
onPressed: () async {
|
||||
settingsProvider.update(
|
||||
newPopups: !settingsProvider.newPopups);
|
||||
|
||||
setState(() {});
|
||||
},
|
||||
title: Text(
|
||||
"new_popups".i18n,
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text.withOpacity(
|
||||
settingsProvider.newPopups ? .95 : .25),
|
||||
),
|
||||
),
|
||||
leading: Icon(
|
||||
FeatherIcons.alertOctagon,
|
||||
size: 22.0,
|
||||
color: AppColors.of(context).text.withOpacity(
|
||||
settingsProvider.newPopups ? .95 : .25),
|
||||
),
|
||||
trailing: Switch(
|
||||
onChanged: (v) async {
|
||||
settingsProvider.update(newPopups: v);
|
||||
|
||||
setState(() {});
|
||||
},
|
||||
value: settingsProvider.newPopups,
|
||||
activeColor: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(12.0),
|
||||
bottom: Radius.circular(12.0),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
// change subject icons
|
||||
// SplittedPanel(
|
||||
// padding: const EdgeInsets.only(top: 9.0),
|
||||
@@ -499,8 +544,14 @@ class PersonalizeSettingsScreenState extends State<PersonalizeSettingsScreen>
|
||||
children: [
|
||||
PanelButton(
|
||||
onPressed: () {
|
||||
SettingsHelper.gradeColors(context);
|
||||
setState(() {});
|
||||
// SettingsHelper.gradeColors(context);
|
||||
// setState(() {});
|
||||
Navigator.of(context, rootNavigator: true).push(
|
||||
CupertinoPageRoute(
|
||||
builder: (context) =>
|
||||
const GradeColorsSettingsScreen(),
|
||||
),
|
||||
);
|
||||
},
|
||||
title: Text(
|
||||
"grade_colors".i18n,
|
||||
@@ -670,16 +721,6 @@ class PersonalizeSettingsScreenState extends State<PersonalizeSettingsScreen>
|
||||
children: [
|
||||
PanelButton(
|
||||
onPressed: () {
|
||||
if (!Provider.of<PlusProvider>(context,
|
||||
listen: false)
|
||||
.hasScope(PremiumScopes.liveActivityColor)) {
|
||||
PlusLockedFeaturePopup.show(
|
||||
context: context,
|
||||
feature: PremiumFeature.liveActivity,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
SettingsHelper.liveActivityColor(context);
|
||||
setState(() {});
|
||||
},
|
||||
@@ -882,7 +923,7 @@ class PersonalizeSettingsScreenState extends State<PersonalizeSettingsScreen>
|
||||
title: Text('fonts'.i18n),
|
||||
padding: EdgeInsets.zero,
|
||||
cardPadding: const EdgeInsets.all(4.0),
|
||||
isSeparated: true,
|
||||
isSeparated: false,
|
||||
children: [
|
||||
PanelButton(
|
||||
onPressed: () {
|
||||
@@ -920,11 +961,72 @@ class PersonalizeSettingsScreenState extends State<PersonalizeSettingsScreen>
|
||||
),
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(12.0),
|
||||
bottom: Radius.circular(6.0),
|
||||
),
|
||||
),
|
||||
PanelButton(
|
||||
padding: const EdgeInsets.only(left: 14.0, right: 6.0),
|
||||
onPressed: () async {
|
||||
if (!Provider.of<PlusProvider>(context, listen: false)
|
||||
.hasScope(PremiumScopes.customFont)) {
|
||||
PlusLockedFeaturePopup.show(
|
||||
context: context,
|
||||
feature: PremiumFeature.fontChange);
|
||||
return;
|
||||
}
|
||||
|
||||
settingsProvider.update(
|
||||
titleOnlyFont: !settingsProvider.titleOnlyFont);
|
||||
Provider.of<ThemeModeObserver>(context, listen: false)
|
||||
.changeTheme(settingsProvider.theme,
|
||||
updateNavbarColor: false);
|
||||
setState(() {});
|
||||
},
|
||||
title: Text(
|
||||
"only_ch_title_font".i18n,
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text.withOpacity(
|
||||
settingsProvider.titleOnlyFont ? .95 : .25),
|
||||
),
|
||||
),
|
||||
leading: Icon(
|
||||
Icons.text_increase_rounded,
|
||||
size: 22.0,
|
||||
color: AppColors.of(context).text.withOpacity(
|
||||
settingsProvider.titleOnlyFont ? .95 : .25),
|
||||
),
|
||||
trailing: Switch(
|
||||
onChanged: (v) async {
|
||||
if (!Provider.of<PlusProvider>(context,
|
||||
listen: false)
|
||||
.hasScope(PremiumScopes.customFont)) {
|
||||
PlusLockedFeaturePopup.show(
|
||||
context: context,
|
||||
feature: PremiumFeature.fontChange);
|
||||
return;
|
||||
}
|
||||
|
||||
settingsProvider.update(titleOnlyFont: v);
|
||||
Provider.of<ThemeModeObserver>(context,
|
||||
listen: false)
|
||||
.changeTheme(settingsProvider.theme,
|
||||
updateNavbarColor: false);
|
||||
setState(() {});
|
||||
},
|
||||
value: settingsProvider.titleOnlyFont,
|
||||
activeColor: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(4.0),
|
||||
bottom: Radius.circular(12.0),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
// bottom padding
|
||||
const SizedBox(
|
||||
height: 20.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
// ignore_for_file: use_build_context_synchronously, deprecated_member_use
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
// import 'package:refilc/models/settings.dart';
|
||||
import 'package:refilc/models/shared_theme.dart';
|
||||
import 'package:refilc_kreta_api/providers/share_provider.dart';
|
||||
import 'package:refilc_mobile_ui/common/action_button.dart';
|
||||
import 'package:refilc_mobile_ui/common/splitted_panel/splitted_panel.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
import 'submenu_screen.i18n.dart';
|
||||
|
||||
class ShareThemeDialog extends StatefulWidget {
|
||||
const ShareThemeDialog({super.key});
|
||||
|
||||
static void show(BuildContext context) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => 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();
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => const ShareThemeDialog());
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
ShareThemeDialogState createState() => ShareThemeDialogState();
|
||||
}
|
||||
|
||||
class ShareThemeDialogState extends State<ShareThemeDialog> {
|
||||
final _title = TextEditingController();
|
||||
bool isPublic = false;
|
||||
|
||||
late ShareProvider shareProvider;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
shareProvider = Provider.of<ShareProvider>(context, listen: false);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(14.0))),
|
||||
contentPadding: const EdgeInsets.only(top: 10.0),
|
||||
title: Text("share_theme".i18n),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
|
||||
child: TextField(
|
||||
controller: _title,
|
||||
onEditingComplete: () async {},
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(
|
||||
borderSide: const BorderSide(color: Colors.grey, width: 1.5),
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: const BorderSide(color: Colors.grey, width: 1.5),
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
hintText: 'paint_title'.i18n,
|
||||
suffixIcon: IconButton(
|
||||
icon: const Icon(
|
||||
FeatherIcons.x,
|
||||
color: Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_title.text = '';
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SplittedPanel(
|
||||
children: [
|
||||
SwitchListTile(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16.0),
|
||||
),
|
||||
value: isPublic,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
isPublic = value;
|
||||
});
|
||||
},
|
||||
title: Text("is_public".i18n),
|
||||
contentPadding: const EdgeInsets.only(left: 15.0, right: 10.0),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text(
|
||||
"cancel".i18n,
|
||||
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.of(context).maybePop();
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
child: Text(
|
||||
"share_it".i18n,
|
||||
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||
),
|
||||
onPressed: () async {
|
||||
// share the fucking theme
|
||||
SharedGradeColors gradeColors =
|
||||
await shareProvider.shareCurrentGradeColors(context);
|
||||
SharedTheme theme = await shareProvider.shareCurrentTheme(
|
||||
context,
|
||||
gradeColors: gradeColors,
|
||||
isPublic: isPublic,
|
||||
displayName: _title.text,
|
||||
);
|
||||
|
||||
// save theme id in settings
|
||||
// Provider.of<SettingsProvider>(context, listen: false)
|
||||
// .update(currentThemeId: theme.id);
|
||||
|
||||
// close this popup shit
|
||||
Navigator.of(context).pop(true);
|
||||
|
||||
// show the share popup
|
||||
Share.share(
|
||||
theme.id,
|
||||
subject: 'share_subj_theme'.i18n,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,17 @@ extension SettingsLocalization on String {
|
||||
"rare": "Rare",
|
||||
"epic": "Epic",
|
||||
"legendary": "Legendary",
|
||||
// grade colors
|
||||
"grade_colors": "Grade Colors",
|
||||
// theme share popup
|
||||
"share_theme": "Share Paint",
|
||||
"paint_title": "Paint title...",
|
||||
"share_it": "Share it!",
|
||||
"is_public": "Public Paint",
|
||||
"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": {
|
||||
"general": "Általános",
|
||||
@@ -32,6 +43,17 @@ extension SettingsLocalization on String {
|
||||
"rare": "Ritka",
|
||||
"epic": "Epikus",
|
||||
"legendary": "Legendás",
|
||||
// grade colors
|
||||
"grade_colors": "Jegyek színei",
|
||||
// theme share popup
|
||||
"share_theme": "Téma megosztása",
|
||||
"paint_title": "Téma neve...",
|
||||
"share_it": "Megosztás!",
|
||||
"is_public": "Nyilvános téma",
|
||||
"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": {
|
||||
"general": "Allgemeine",
|
||||
@@ -47,6 +69,17 @@ extension SettingsLocalization on String {
|
||||
"rare": "Selten",
|
||||
"epic": "Episch",
|
||||
"legendary": "Legendär",
|
||||
// grade colors
|
||||
"grade_colors": "Notenfarben",
|
||||
// theme share popup
|
||||
"share_theme": "Thema teilen",
|
||||
"paint_title": "Thema Titel...",
|
||||
"share_it": "Teilen!",
|
||||
"is_public": "Öffentliches Thema",
|
||||
"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",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// ignore_for_file: use_build_context_synchronously, deprecated_member_use
|
||||
|
||||
import 'package:refilc/models/settings.dart';
|
||||
import 'package:refilc/models/shared_theme.dart';
|
||||
// import 'package:refilc/models/shared_theme.dart';
|
||||
import 'package:refilc/theme/colors/accent.dart';
|
||||
import 'package:refilc/theme/colors/colors.dart';
|
||||
import 'package:refilc/theme/observer.dart';
|
||||
@@ -10,7 +10,7 @@ import 'package:refilc/ui/widgets/message/message_tile.dart';
|
||||
import 'package:refilc_kreta_api/models/grade.dart';
|
||||
import 'package:refilc_kreta_api/models/homework.dart';
|
||||
import 'package:refilc_kreta_api/models/message.dart';
|
||||
import 'package:refilc_mobile_ui/common/action_button.dart';
|
||||
// import 'package:refilc_mobile_ui/common/action_button.dart';
|
||||
import 'package:refilc_mobile_ui/common/filter_bar.dart';
|
||||
import 'package:refilc_mobile_ui/common/panel/panel.dart';
|
||||
import 'package:refilc_mobile_ui/common/widgets/grade/new_grades.dart';
|
||||
@@ -24,6 +24,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:refilc_mobile_ui/screens/settings/submenu/share_theme_popup.dart';
|
||||
import 'theme_screen.i18n.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
@@ -44,6 +45,7 @@ enum CustomColorMode {
|
||||
text,
|
||||
icon,
|
||||
enterId,
|
||||
grade,
|
||||
}
|
||||
|
||||
class _PremiumCustomAccentColorSettingState
|
||||
@@ -158,6 +160,9 @@ class _PremiumCustomAccentColorSettingState
|
||||
case CustomColorMode.enterId:
|
||||
// do nothing here lol
|
||||
break;
|
||||
case CustomColorMode.grade:
|
||||
// do nothing here as well
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,6 +223,9 @@ class _PremiumCustomAccentColorSettingState
|
||||
settings.update(customAccentColor: accent, store: store);
|
||||
settings.update(customIconColor: icon, store: store);
|
||||
break;
|
||||
case CustomColorMode.grade:
|
||||
// do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,40 +305,48 @@ 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();
|
||||
// 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 =
|
||||
await shareProvider.shareCurrentTheme(
|
||||
context,
|
||||
gradeColors: gradeColors,
|
||||
);
|
||||
// SharedGradeColors gradeColors =
|
||||
// await shareProvider
|
||||
// .shareCurrentGradeColors(context);
|
||||
// SharedTheme theme =
|
||||
// await shareProvider.shareCurrentTheme(
|
||||
// context,
|
||||
// gradeColors: gradeColors,
|
||||
// );
|
||||
|
||||
Share.share(
|
||||
theme.id,
|
||||
subject: 'share_subj_theme'.i18n,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
// Share.share(
|
||||
// theme.id,
|
||||
// subject: 'share_subj_theme'.i18n,
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
if (settings.currentThemeId != '') {
|
||||
Share.share(
|
||||
settings.currentThemeId,
|
||||
subject: 'share_subj_theme'.i18n,
|
||||
);
|
||||
} else {
|
||||
ShareThemeDialog.show(context);
|
||||
}
|
||||
},
|
||||
icon: const Icon(
|
||||
FeatherIcons.share2,
|
||||
|
||||
@@ -24,26 +24,17 @@ extension SettingsLocalization on String {
|
||||
"dontfelt": "You didn't like this...",
|
||||
"youlate": "You're late!",
|
||||
// allsum page
|
||||
"test": "tests"
|
||||
.one("test"),
|
||||
"closingtest": "module tests"
|
||||
.one("module test"),
|
||||
"grade": "grades"
|
||||
.one("grade"),
|
||||
"hw": "homeworks"
|
||||
.one("homework"),
|
||||
"subject": "subjects"
|
||||
.one("subject"),
|
||||
"lesson": "lessons"
|
||||
.one("lesson"),
|
||||
"absence_sum": "absences"
|
||||
.one("absence"),
|
||||
"test": "test(s)",
|
||||
"closingtest": "module test(s)",
|
||||
"grade": "grade(s)",
|
||||
"hw": "homework(s)",
|
||||
"subject": "subject(s)",
|
||||
"lesson": "lesson(s)",
|
||||
"absence_sum": "absence(s)",
|
||||
"excused": "excused",
|
||||
"unexcused": "unexcused",
|
||||
"delay_sum": "delays"
|
||||
.one("delay"),
|
||||
"min": "minutes"
|
||||
.one("minute"),
|
||||
"delay_sum": "delay(s)",
|
||||
"min": "minute(s)",
|
||||
// personality page
|
||||
"click_reveal": "Click to reveal...",
|
||||
},
|
||||
|
||||
@@ -71,6 +71,8 @@ dependencies:
|
||||
markdown: ^7.2.2
|
||||
carousel_slider: ^4.2.1
|
||||
flutter_portal: ^1.1.4
|
||||
webview_flutter: ^4.8.0
|
||||
file_picker: ^6.2.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_lints: ^3.0.1
|
||||
|
||||