Compare commits

...

No commits in common. "master" and "main" have entirely different histories.
master ... main

293 changed files with 77 additions and 22973 deletions

3
.fvmrc
View File

@ -1,3 +0,0 @@
{
"flutter": "3.27.0-0.2.pre"
}

49
.gitignore vendored
View File

@ -1,49 +0,0 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
lib/core/services/constants.dart
# FVM Version Cache
.fvm/

View File

@ -1,30 +0,0 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "72432c3f15b26fe55f8fd822e5fb3581260f75dd"
channel: "master"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 72432c3f15b26fe55f8fd822e5fb3581260f75dd
base_revision: 72432c3f15b26fe55f8fd822e5fb3581260f75dd
- platform: android
create_revision: 72432c3f15b26fe55f8fd822e5fb3581260f75dd
base_revision: 72432c3f15b26fe55f8fd822e5fb3581260f75dd
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

View File

@ -1,3 +0,0 @@
{
"dart.flutterSdkPath": "C:\\tools\\flutter"
}

158
README.md
View File

@ -1,97 +1,93 @@
<p align="center"> # mobile-adaptive-learning
<img src="assets/logo.png" alt="SEALS Logo" width="200"/>
</p>
# SEALS - Smart English Adaptive Learning System
## Overview
SEALS refers to a personalized approach to language education that adjusts to the individual learner's needs, pace, and skill level. ## Getting started
## System Requirements To make it easy for you to get started with GitLab, here's a list of recommended next steps.
- Flutter version 3.19.0 or higher Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
- Dart version 3.3.0 or higher
- Android Studio / VS Code ## Add your files
- Android SDK version 23 (Android 7.0) or higher
- Minimum 2GB RAM - [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- 500MB free storage space - [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
```
cd existing_repo
git remote add origin https://gitlab.com/profile-image/kedaireka/polinema-adapative-learning/mobile-adaptive-learning.git
git branch -M main
git push -uf origin main
```
## Integrate with your tools
- [ ] [Set up project integrations](https://gitlab.com/profile-image/kedaireka/polinema-adapative-learning/mobile-adaptive-learning/-/settings/integrations)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation ## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
1. Clone the repository: ## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
```bash ## Support
git clone https://gitlab.com/profile-image/kedaireka/polinema-adapative-learning/mobile-adaptive-learning.git Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
```
2. Navigate to project directory: ## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
```bash ## Contributing
cd mobile-adaptive-learning State if you are open to contributions and what your requirements are for accepting them.
```
3. Install dependencies: For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
```bash You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
flutter pub get
```
4. Run the application: ## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
```bash ## License
flutter run For open source projects, say how it is licensed.
```
## Dependencies ## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
```yaml
dependencies:
audioplayers: ^6.1.0
bootstrap_icons: ^1.11.3
cached_network_image: ^3.4.1
carousel_slider: ^5.0.0
cupertino_icons: ^1.0.8
dio: ^5.7.0
flick_video_player: ^0.9.0
flutter:
sdk: flutter
flutter_inappwebview: ^6.0.0
flutter_secure_storage: ^9.2.2
flutter_svg: ^2.0.10+1
flutter_widget_from_html: ^0.15.2
google_fonts: ^6.2.1
google_nav_bar: ^5.0.6
html: ^0.15.4
image_picker: ^1.1.2
intl: ^0.19.0
jwt_decoder: ^2.0.1
provider: ^6.1.2
shared_preferences: ^2.3.2
shimmer: ^3.0.0
video_player: ^2.9.1
youtube_player_flutter: ^9.1.1
```
### Build Release
#### Android
```bash
# Generate Android App Bundle
flutter build appbundle --release
# Generate APK
flutter build apk --release
```
## Development Team
- Naresh Pratista - Mobile App Developer - [nareshpratista.contact@gmail.com](mailto:nareshpratista.contact@gmail.com)
- Diah Putri Nofianti - UI/UX Designer - [diahputrinofianti@gmail.com](mailto:diahputrinofianti@gmail.com)
- Elang Putra Adam - Backend Developer - [elangptra17@gmail.com](mailto:elangptra17@gmail.com)
## Acknowledgments
- [Flutter](https://flutter.dev/) - UI framework
- [Provider](https://pub.dev/packages/provider) - State management

View File

@ -1,28 +0,0 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at https://dart.dev/lints.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options

13
android/.gitignore vendored
View File

@ -1,13 +0,0 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/to/reference-keystore
key.properties
**/*.keystore
**/*.jks

View File

@ -1,44 +0,0 @@
plugins {
id "com.android.application"
id "kotlin-android"
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id "dev.flutter.flutter-gradle-plugin"
}
android {
namespace = "com.example.english_learning"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.english_learning"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = 24
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.debug
}
}
}
flutter {
source = "../.."
}

View File

@ -1,7 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@ -1,49 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<application
android:label="SEALS"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"
android:usesCleartextTraffic="true">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>

View File

@ -1,5 +0,0 @@
package com.example.english_learning
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground>
<inset
android:drawable="@drawable/ic_launcher_foreground"
android:inset="16%" />
</foreground>
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#FFFFFF</color>
</resources>

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -1,7 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@ -1,18 +0,0 @@
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = "../build"
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(":app")
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

View File

@ -1,3 +0,0 @@
org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
android.enableJetifier=true

View File

@ -1,5 +0,0 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip

View File

@ -1,25 +0,0 @@
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.3.2" apply false
id "org.jetbrains.kotlin.android" version "1.8.22" apply false
}
include ":app"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

View File

@ -1,3 +0,0 @@
description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:

34
ios/.gitignore vendored
View File

@ -1,34 +0,0 @@
**/dgph
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
</dict>
</plist>

View File

@ -1 +0,0 @@
#include "Generated.xcconfig"

View File

@ -1 +0,0 @@
#include "Generated.xcconfig"

View File

@ -1,616 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
proxyType = 1;
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
remoteInfo = Runner;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
331C8082294A63A400263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C807B294A618700263BE5 /* RunnerTests.swift */,
);
path = RunnerTests;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
);
path = Runner;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
331C8080294A63A400263BE5 /* RunnerTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
331C807D294A63A400263BE5 /* Sources */,
331C807F294A63A400263BE5 /* Resources */,
);
buildRules = (
);
dependencies = (
331C8086294A63A400263BE5 /* PBXTargetDependency */,
);
name = RunnerTests;
productName = RunnerTests;
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C8080294A63A400263BE5 = {
CreatedOnToolsVersion = 14.0;
TestTargetID = 97C146ED1CF9000F007C117D;
};
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 1100;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
331C8080294A63A400263BE5 /* RunnerTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
331C807F294A63A400263BE5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
331C807D294A63A400263BE5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 97C146ED1CF9000F007C117D /* Runner */;
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.englishLearning;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
331C8088294A63A400263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.englishLearning.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Debug;
};
331C8089294A63A400263BE5 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.englishLearning.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Release;
};
331C808A294A63A400263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.englishLearning.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.englishLearning;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.englishLearning;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
331C8088294A63A400263BE5 /* Debug */,
331C8089294A63A400263BE5 /* Release */,
331C808A294A63A400263BE5 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@ -1,98 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "331C8080294A63A400263BE5"
BuildableName = "RunnerTests.xctest"
BlueprintName = "RunnerTests"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@ -1,13 +0,0 @@
import Flutter
import UIKit
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}

View File

@ -1 +0,0 @@
{"images":[{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@3x.png","scale":"3x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 787 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -1,23 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

View File

@ -1,5 +0,0 @@
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.

View File

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

View File

@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>English Learning</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>english_learning</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>

View File

@ -1 +0,0 @@
#import "GeneratedPluginRegistrant.h"

View File

@ -1,12 +0,0 @@
import Flutter
import UIKit
import XCTest
class RunnerTests: XCTestCase {
func testExample() {
// If you add code to the Runner application, consider adding tests here.
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
}
}

View File

@ -1,3 +0,0 @@
const String baseUrl = 'http://labai.polinema.ac.id:3001/';
const String mediaUrl = 'http://labai.polinema.ac.id:3001/api/uploads/';

View File

@ -1,415 +0,0 @@
// ignore_for_file: avoid_print
import 'package:dio/dio.dart';
import 'package:english_learning/core/services/constants.dart';
class DioClient {
final Dio _dio = Dio();
DioClient() {
_dio.options.baseUrl = baseUrl;
_dio.options.connectTimeout = const Duration(seconds: 10);
_dio.options.receiveTimeout = const Duration(seconds: 30);
}
Future<Response> refreshAccessToken(String refreshToken) async {
try {
final response = await _dio.post(
'/api/refreshToken',
data: {'REFRESH_TOKEN': refreshToken},
options: Options(
headers: {
'Content-Type': 'application/json',
},
),
);
return response;
} catch (e) {
print('Refresh Token error: $e');
rethrow;
}
}
Future<Response> post(String path, {dynamic data, Options? options}) async {
try {
final response = await _dio.post(
path,
data: data,
options:
options ?? Options(headers: {'Content-Type': 'application/json'}),
);
return response;
} on DioException catch (e) {
print('DioError: ${e.response?.data ?? e.message}');
rethrow;
} catch (e) {
print('Unexpected error: $e');
rethrow;
}
}
Future<Response> updateUserProfile(
String id, FormData formData, String token) async {
try {
final response = await _dio.put(
'/api/user/update/$id',
data: formData,
options: Options(
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'multipart/form-data',
},
),
);
return response;
} catch (e) {
print('Update Profile error: $e');
rethrow;
}
}
Future<Response> updatePassword(
String id,
Map<String, dynamic> data,
String token,
) async {
try {
final response = await _dio.put(
'/api/user/update/password/$id',
data: data,
options: Options(
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
),
);
return response;
} catch (e) {
print('Update Password error: $e');
rethrow;
}
}
Future<Response> reportIssue(
Map<String, dynamic> data,
String token,
) async {
try {
final response = await _dio.post(
'/api/report',
data: data,
options: Options(
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
),
);
return response;
} catch (e) {
print('Update Password error: $e');
rethrow;
}
}
Future<Response> registerStudent(Map<String, dynamic> data) async {
try {
// Send POST request to the registration endpoint
final response = await _dio.post(
'/api/register/student',
data: data,
options: Options(
headers: {
'Content-Type': 'application/json',
},
),
);
return response;
} catch (e) {
// Handle the error
rethrow;
}
}
Future<Response> loginStudent(Map<String, dynamic> data) async {
try {
final response = await _dio.post(
'/api/login',
data: data,
options: Options(
headers: {
'Content-Type': 'application/json',
},
),
);
return response;
} catch (e) {
rethrow;
}
}
Future<Response> forgotPassword(Map<String, dynamic> data) async {
try {
final response = await _dio.post(
'/api/forgotPassword',
data: data,
options: Options(
headers: {
'Content-Type': 'application/json',
},
),
);
return response;
} catch (e) {
rethrow;
}
}
Future<Response> getMe(String token) async {
try {
print('Sending getMe request with token: Bearer $token');
final response = await _dio.get(
'/api/getMe',
options: Options(
headers: {
'Authorization': 'Bearer $token', // Add 'Bearer ' prefix here
},
),
);
print('getMe response: ${response.data}');
return response;
} catch (e) {
print('GetMe error: $e');
rethrow;
}
}
Future<Response> getSections(String token) async {
try {
final response = await _dio.get(
'/api/section',
options: Options(
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
),
);
print('getSections response: ${response.data}');
return response;
} catch (e) {
print('GetSections error: $e');
rethrow;
}
}
Future<Response> getTopics(String sectionId, String token) async {
try {
final response = await _dio.get(
'/api/topic/section/$sectionId',
options: Options(
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
),
);
print('getTopics response: ${response.data}');
return response;
} catch (e) {
print('GetTopics error: $e');
rethrow;
}
}
Future<Response> getLevels(String topicsId, String token) async {
try {
final response = await _dio.get(
'/api/level/topic/$topicsId',
options: Options(
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
),
);
print('getLevels response: ${response.data}');
return response;
} catch (e) {
print('GetLevels error: $e');
rethrow;
}
}
Future<Response> createStudentLearning(String idLevel, String token) async {
try {
final response = await _dio.post(
'/api/stdLearning',
data: {'ID_LEVEL': idLevel},
options: Options(
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
),
);
return response;
} catch (e) {
print('Create Student Learning error: $e');
rethrow;
}
}
Future<Response> getExercises(String levelId, String token) async {
try {
final response = await _dio.get(
'/api/exercise/level/$levelId',
options: Options(
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
),
);
print('getExercises response: ${response.data}');
return response;
} on DioException catch (e) {
print(
'DioError: ${e.response?.statusCode} - ${e.response?.data ?? e.message}');
rethrow;
} catch (e) {
print('Unexpected error: $e');
rethrow;
}
}
Future<Response> submitExerciseAnswers(
List<Map<String, dynamic>> answers, String token) async {
try {
final response = await _dio.post(
'/api/stdExercise',
data: {'answers': answers},
options: Options(
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
),
);
print('submitExerciseAnswers response: ${response.data}');
return response;
} catch (e) {
print('SubmitExerciseAnswers error: $e');
rethrow;
}
}
Future<Response> getScore(String stdLearningId, String token) async {
try {
final response = await _dio.get(
'/api/stdLearning/score/$stdLearningId',
options: Options(
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
),
);
print('getScore response: ${response.data}');
return response;
} catch (e) {
print('GetScore error: $e');
rethrow;
}
}
Future<Response> getLearningHistory(
String sectionId,
String token, {
int page = 1,
int limit = 5,
}) async {
try {
final response = await _dio.get(
'/api/learningHistory/section/$sectionId',
queryParameters: {
'page': page,
'limit': limit,
},
options: Options(
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
),
);
print('getLearningHistory response: ${response.data}');
return response;
} catch (e) {
print('GetLearningHistory error: $e');
rethrow;
}
}
Future<Response> getCompletedTopics(String token) async {
try {
final response = await _dio.get(
'/api/topic/complete',
options: Options(
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
),
);
print('getCompletedTopics response: ${response.data}');
return response;
} catch (e) {
print('GetCompletedTopics error: $e');
rethrow;
}
}
Future<Response> studentFeedback(
String stdLearningId,
String feedback,
String token,
) async {
try {
final response = await _dio.put(
'/api/stdLearning/$stdLearningId',
data: {'FEEDBACK_STUDENT': feedback},
options: Options(
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
),
);
return response;
} catch (e) {
print('Submit Feedback error: $e');
rethrow;
}
}
Future<Response> getStudentAnswers(String stdLearningId, String token) async {
try {
final response = await _dio.get(
'/api/studentAnswers/$stdLearningId',
options: Options(
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
),
);
print('studentAnswers response: ${response.data}');
return response;
} catch (e) {
print('StudentAnswers error: $e');
rethrow;
}
}
}

View File

@ -1,34 +0,0 @@
import 'package:english_learning/core/services/dio_client.dart';
import 'package:english_learning/features/home/models/completed_topics_model.dart';
class CompletedTopicsRepository {
final DioClient _dioClient;
CompletedTopicsRepository(this._dioClient);
Future<List<CompletedTopic>> getCompletedTopics(String token) async {
final response = await _dioClient.getCompletedTopics(token);
// Tambahkan pengecekan status code dan payload
if (response.statusCode == 200) {
// Cek apakah payload null atau bukan list
if (response.data['payload'] == null) {
return []; // Kembalikan list kosong jika payload null
}
// Pastikan payload adalah list
final dynamic payloadData = response.data['payload'];
if (payloadData is List) {
return payloadData
.map((data) => CompletedTopic.fromJson(data))
.toList();
} else {
return []; // Kembalikan list kosong jika payload bukan list
}
} else {
// Tangani status code selain 200
return [];
}
}
}

View File

@ -1,77 +0,0 @@
import 'package:english_learning/core/services/dio_client.dart';
import 'package:english_learning/features/learning/modules/feedback/models/feedback_model.dart';
class ExerciseRepository {
final DioClient _dioClient;
ExerciseRepository(this._dioClient);
Future<Map<String, dynamic>> getExercises(
String levelId, String token) async {
try {
final response = await _dioClient.getExercises(levelId, token);
if (response.statusCode == 200) {
return response.data['payload'];
} else {
throw Exception('Failed to load exercises');
}
} catch (e) {
throw Exception('Error fetching exercises: $e');
}
}
Future<Map<String, dynamic>> getStudentAnswers(
String stdLearningId, String token) async {
try {
final response = await _dioClient.getStudentAnswers(stdLearningId, token);
if (response.statusCode == 200) {
return response.data;
} else {
throw Exception('Failed to load student answers');
}
} catch (e) {
throw Exception('Error fetching student answers: $e');
}
}
Future<Map<String, dynamic>> submitAnswersAndGetScore(
List<Map<String, dynamic>> answers,
String studentLearningId,
String token) async {
try {
// Submit answers
await _dioClient.submitExerciseAnswers(answers, token);
// Get score
final response = await _dioClient.getScore(studentLearningId, token);
if (response.statusCode == 200) {
return response.data['payload'];
} else {
throw Exception('Failed to get score');
}
} catch (e) {
throw Exception('Error submitting answers and getting score: $e');
}
}
Future<FeedbackModel> submitFeedback(
String stdLearningId,
String feedback,
String token,
) async {
try {
final response = await _dioClient.studentFeedback(
stdLearningId,
feedback,
token,
);
if (response.statusCode == 200) {
return FeedbackModel.fromJson(response.data['payload']);
} else {
throw Exception('Failed to submit feedback');
}
} catch (e) {
throw Exception('Error submitting feedback: $e');
}
}
}

View File

@ -1,53 +0,0 @@
import 'package:dio/dio.dart';
import 'package:english_learning/core/services/dio_client.dart';
import 'package:english_learning/features/history/models/history_model.dart';
class HistoryRepository {
final DioClient _dioClient;
HistoryRepository(this._dioClient);
Future<List<HistoryModel>> getLearningHistory(
String sectionId,
String token,
) async {
try {
final response = await _dioClient.getLearningHistory(
sectionId,
token,
page: 1,
limit: 10,
);
if (response.statusCode == 200) {
final responseData = response.data;
if (responseData == null ||
responseData['payload'] == null ||
responseData['payload']['history'] == null) {
return [];
}
final List<dynamic> historyData = responseData['payload']['history'];
if (historyData.isEmpty) {
return [];
}
return historyData.map((json) => HistoryModel.fromJson(json)).toList();
} else {
return [];
}
} on DioException catch (e) {
if (e.response?.statusCode == 404) {
return [];
} else if (e.response != null) {
throw Exception('Server error: ${e.response?.statusMessage}');
} else {
throw Exception('Network error: ${e.message}');
}
} catch (e) {
throw Exception('Unexpected error: $e');
}
}
}

View File

@ -1,34 +0,0 @@
import 'package:english_learning/core/services/dio_client.dart';
import 'package:english_learning/features/learning/modules/level/models/level_model.dart';
class LevelRepository {
final DioClient _dioClient = DioClient();
Future<Map<String, dynamic>> getLevels(String topicId, String token) async {
try {
final response = await _dioClient.getLevels(topicId, token);
if (response.statusCode == 200 && response.data != null) {
final Map<String, dynamic> responseData = response.data;
if (responseData.containsKey('data')) {
final Map<String, dynamic> data = responseData['data'] ?? {};
final List<dynamic> levelsData = data['levels'] ?? [];
final List<Level> levels =
levelsData.map((json) => Level.fromJson(json)).toList();
final Map<String, dynamic>? lastCompletedLevel =
data['lastCompletedLevel'] ?? {};
return {
'levels': levels,
'lastCompletedLevel': lastCompletedLevel,
};
} else {
throw Exception('Invalid response structure: missing "data" key');
}
} else {
throw Exception('Failed to load levels: ${response.statusCode}');
}
} catch (e) {
rethrow;
}
}
}

View File

@ -1,21 +0,0 @@
import 'package:english_learning/core/services/dio_client.dart';
import 'package:english_learning/features/learning/modules/model/section_model.dart';
class SectionRepository {
final DioClient _dioClient = DioClient();
Future<List<Section>> getSections(String token) async {
try {
final response = await _dioClient.getSections(token);
if (response.statusCode == 200) {
final Map<String, dynamic> responseData = response.data;
final List<dynamic> data = responseData['payload'];
return data.map((json) => Section.fromJson(json)).toList();
} else {
throw Exception('Failed to load sections: ${response.statusCode}');
}
} catch (e) {
rethrow;
}
}
}

View File

@ -1,17 +0,0 @@
import 'package:english_learning/core/services/dio_client.dart';
class StudentLearningRepository {
final DioClient _dioClient;
StudentLearningRepository(this._dioClient);
Future<Map<String, dynamic>> createStudentLearning(
String idLevel, String token) async {
try {
final response = await _dioClient.createStudentLearning(idLevel, token);
return response.data;
} catch (e) {
throw Exception('Failed to create student learning: $e');
}
}
}

View File

@ -1,21 +0,0 @@
import 'package:english_learning/core/services/dio_client.dart';
import 'package:english_learning/features/learning/modules/topics/models/topic_model.dart';
class TopicRepository {
final DioClient _dioClient = DioClient();
Future<List<Topic>> getTopics(String sectionId, String token) async {
try {
final response = await _dioClient.getTopics(sectionId, token);
if (response.statusCode == 200) {
final Map<String, dynamic> responseData = response.data;
final List<dynamic> data = responseData['payload'];
return data.map((json) => Topic.fromJson(json)).toList();
} else {
throw Exception('Failed to load topics: ${response.statusCode}');
}
} catch (e) {
rethrow;
}
}
}

View File

@ -1,117 +0,0 @@
import 'dart:convert';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:english_learning/core/services/dio_client.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class UserRepository {
final DioClient dioClient = DioClient();
final FlutterSecureStorage _secureStorage = const FlutterSecureStorage();
// Authentication methods
Future<Response> registerUser(Map<String, dynamic> data) async {
return await dioClient.registerStudent(data);
}
Future<Response> loginUser(Map<String, dynamic> data) async {
return await dioClient.loginStudent(data);
}
Future<Response> logoutUser() async {
return await dioClient.post('/api/logout');
}
Future<Response> forgotPassword(String email) async {
return await dioClient.forgotPassword({'EMAIL': email});
}
// User data methods
Future<Response> getMe(String token) async {
return await dioClient.getMe(token);
}
Future<Response> updateUserProfile(
String id,
Map<String, dynamic> data,
String token, {
File? imageFile,
}) async {
try {
FormData formData = FormData.fromMap(data);
if (imageFile != null) {
formData.files.add(MapEntry(
'PICTURE',
await MultipartFile.fromFile(imageFile.path,
filename: imageFile.path.split('/').last),
));
}
return await dioClient.updateUserProfile(id, formData, token);
} catch (e) {
rethrow;
}
}
Future<Response> updatePassword(
String id,
String oldPassword,
String newPassword,
String confirmPassword,
String token,
) async {
try {
final data = {
"OLD_PASSWORD": oldPassword,
"PASSWORD": newPassword,
"CONFIRM_PASSWORD": confirmPassword
};
return await dioClient.updatePassword(id, data, token);
} catch (e) {
rethrow;
}
}
Future<Response> reportIssue(String report, String token) async {
return await dioClient.reportIssue({'REPORTS': report}, token);
}
// Token management methods
Future<void> saveRefreshToken(String refreshToken) async {
await _secureStorage.write(key: 'refreshToken', value: refreshToken);
}
Future<String?> getRefreshToken() async {
return await _secureStorage.read(key: 'refreshToken');
}
Future<void> deleteRefreshToken() async {
await _secureStorage.delete(key: 'refreshToken');
}
Future<void> saveToken(String token) async {
await _secureStorage.write(key: 'jwtToken', value: token);
}
Future<String?> getToken() async {
return await _secureStorage.read(key: 'jwtToken');
}
Future<void> deleteToken() async {
await _secureStorage.delete(key: 'jwtToken');
}
// User data storage methods
Future<void> saveUserData(Map<String, dynamic> userData) async {
await _secureStorage.write(key: 'userData', value: json.encode(userData));
}
Future<Map<String, dynamic>?> getUserData() async {
String? cachedUserData = await _secureStorage.read(key: 'userData');
return cachedUserData != null
? Map<String, dynamic>.from(json.decode(cachedUserData))
: null;
}
Future<void> deleteUserData() async {
await _secureStorage.delete(key: 'userData');
}
}

View File

@ -1,94 +0,0 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
class AppColors {
static const Color whiteColor = Color(0xFFFFFFFF);
static const Color blackColor = Color(0xFF262626);
static const Color blackButtonColor = Color(0xFF404040);
static const Color darkColor = Color(0xFF526071);
static const Color greyColor = Color(0xFF737373);
static const Color cardDisabledColor = Color(0xFFF2F2F2);
static const Color cardButtonColor = Color(0xFFE0E0E0);
static const Color yellowColor = Color(0xFFFDE047);
static const Color tetriaryColor = Color(0xFF959EA9);
static const Color blueColor = Color(0xFF0090FF);
static const Color redColor = Color(0xFFE9342C);
static const Color disableColor = Color(0xFFBDBDBD);
static const Color bgSoftColor = Color(0xFFF1F5FC);
static const Color sliderInActive = Color(0xFFBFDBFE);
static const Color secondaryColor = Color(0xFF5674ED);
static const Color primaryColor = Color(0xFF34C3F9);
static const Color yellowButtonColor = Color(0xFFFACC15);
static const Color greenColor = Color(0xFF00BC65);
static LinearGradient get gradientTheme => const LinearGradient(
colors: [secondaryColor, primaryColor],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
);
}
class AppTextStyles {
static TextStyle blackTextStyle = GoogleFonts.inter(
color: AppColors.blackColor,
);
static TextStyle logoTextStyle = GoogleFonts.comfortaa(
color: AppColors.whiteColor,
fontSize: 30,
fontWeight: FontWeight.bold,
);
static TextStyle greyTextStyle = GoogleFonts.inter(
color: AppColors.greyColor,
);
static TextStyle yellowTextStyle = GoogleFonts.inter(
color: AppColors.yellowColor,
);
static TextStyle redTextStyle = GoogleFonts.inter(
color: AppColors.redColor,
);
static TextStyle disableTextStyle = GoogleFonts.inter(
color: AppColors.disableColor,
);
static TextStyle primaryTextStyle = GoogleFonts.inter(
color: AppColors.primaryColor,
);
static TextStyle blueTextStyle = GoogleFonts.inter(
color: AppColors.blueColor,
);
static TextStyle secondaryTextStyle = GoogleFonts.inter(
color: AppColors.secondaryColor,
);
static TextStyle whiteTextStyle = GoogleFonts.inter(
color: AppColors.whiteColor,
);
static TextStyle tetriaryTextStyle = GoogleFonts.inter(
color: AppColors.tetriaryColor,
);
static TextStyle blackButtonTextStyle = GoogleFonts.inter(
color: AppColors.blackButtonColor,
);
}
ThemeData appTheme() {
return ThemeData(
textSelectionTheme: const TextSelectionThemeData(
cursorColor: AppColors.blackColor,
selectionColor: AppColors.blueColor,
selectionHandleColor: AppColors.blueColor,
),
textTheme: GoogleFonts.interTextTheme(),
fontFamily: GoogleFonts.inter().fontFamily,
scaffoldBackgroundColor: AppColors.whiteColor,
);
}

View File

@ -1,37 +0,0 @@
import 'package:flutter/material.dart';
mixin BackHandlerMixin<T extends StatefulWidget> on State<T> {
DateTime? currentBackPressTime;
Future<bool> onWillPop() async {
DateTime now = DateTime.now();
if (currentBackPressTime == null ||
now.difference(currentBackPressTime!) > const Duration(seconds: 2)) {
currentBackPressTime = now;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Press back again to exit'),
duration: Duration(seconds: 2),
backgroundColor: Colors.black87,
behavior: SnackBarBehavior.floating,
margin: EdgeInsets.all(16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
),
),
);
return false;
}
return true;
}
Widget wrapWithBackHandler({required Widget child}) {
return WillPopScope(
onWillPop: onWillPop,
child: child,
);
}
}

View File

@ -1,103 +0,0 @@
import 'package:english_learning/features/auth/provider/validator_provider.dart';
import 'package:english_learning/core/utils/styles/theme.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class ConfirmPasswordFieldWidget extends StatefulWidget {
final String labelText;
final String hintText;
const ConfirmPasswordFieldWidget({
super.key,
required this.labelText,
required this.hintText,
});
@override
ConfirmPasswordFieldWidgetState createState() =>
ConfirmPasswordFieldWidgetState();
}
class ConfirmPasswordFieldWidgetState
extends State<ConfirmPasswordFieldWidget> {
late FocusNode _focusNode;
@override
void initState() {
super.initState();
_focusNode = FocusNode();
_focusNode.addListener(() {
if (!_focusNode.hasFocus) {
final validatorProvider =
Provider.of<ValidatorProvider>(context, listen: false);
validatorProvider.validateField(
'confirmPassword', validatorProvider.getError('confirmPassword'),
validator: validatorProvider.confirmPasswordValidator);
}
});
}
@override
void dispose() {
_focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final validatorProvider = Provider.of<ValidatorProvider>(context);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.labelText,
style: AppTextStyles.blackTextStyle.copyWith(
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
TextField(
focusNode: _focusNode,
obscureText: validatorProvider.isObscure('confirmPassword'),
onChanged: (value) {
validatorProvider.validateField('confirmPassword', value,
validator: validatorProvider.confirmPasswordValidator);
},
decoration: InputDecoration(
hintText: widget.hintText,
hintStyle: AppTextStyles.disableTextStyle.copyWith(
fontSize: 12,
),
suffixIcon: GestureDetector(
onTap: () =>
validatorProvider.toggleVisibility('confirmPassword'),
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
transitionBuilder: (Widget child, Animation<double> animation) {
return ScaleTransition(scale: animation, child: child);
},
child: Icon(
validatorProvider.isObscure('confirmPassword')
? BootstrapIcons.eye_slash
: BootstrapIcons.eye,
color: AppColors.greyColor,
),
),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(
width: 1,
color: AppColors.disableColor,
),
),
errorText: validatorProvider.getError('confirmPassword'),
),
),
],
);
}
}

View File

@ -1,62 +0,0 @@
import 'package:english_learning/core/utils/styles/theme.dart';
import 'package:flutter/material.dart';
class CustomButton extends StatelessWidget {
final String text;
final double width;
final double height;
final Color color;
final VoidCallback onPressed;
final TextStyle? textStyle;
const CustomButton({
super.key,
required this.text,
required this.width,
required this.height,
required this.color,
required this.onPressed,
this.textStyle,
});
@override
Widget build(BuildContext context) {
final mediaQuery = MediaQuery.of(context);
final screenWidth = mediaQuery.size.width;
return SizedBox(
width: width,
height: height,
child: DecoratedBox(
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(8),
),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.transparent,
shadowColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
),
),
onPressed: onPressed,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
text,
style: textStyle ??
AppTextStyles.blackButtonTextStyle.copyWith(
fontSize: screenWidth * 0.036,
fontWeight: FontWeight.w900,
),
),
],
),
),
),
);
}
}

View File

@ -1,56 +0,0 @@
import 'package:flutter/material.dart';
class CustomSnackBar {
static void show(
BuildContext context, {
required String message,
bool isError = false,
Duration duration = const Duration(seconds: 3),
}) {
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
message,
style: const TextStyle(color: Colors.white),
),
backgroundColor: isError ? Colors.red : Colors.green,
behavior: SnackBarBehavior.floating,
margin: const EdgeInsets.all(16),
duration: duration,
dismissDirection: DismissDirection.vertical,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
);
}
// Versi dengan custom styling
static void showCustom(
BuildContext context, {
required String message,
Color? backgroundColor,
Color? textColor,
Duration duration = const Duration(seconds: 3),
SnackBarBehavior behavior = SnackBarBehavior.floating,
}) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
message,
style: TextStyle(color: textColor ?? Colors.white),
),
backgroundColor: backgroundColor ?? Colors.black,
behavior: behavior,
margin: const EdgeInsets.all(16),
duration: duration,
dismissDirection: DismissDirection.vertical,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
);
}
}

View File

@ -1,81 +0,0 @@
import 'package:english_learning/features/auth/provider/validator_provider.dart';
import 'package:english_learning/core/utils/styles/theme.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class EmailFieldWidget extends StatefulWidget {
final String labelText;
final String hintText;
const EmailFieldWidget(
{super.key, required this.labelText, required this.hintText});
@override
EmailFieldWidgetState createState() => EmailFieldWidgetState();
}
class EmailFieldWidgetState extends State<EmailFieldWidget> {
late FocusNode _focusNode;
@override
void initState() {
super.initState();
_focusNode = FocusNode();
_focusNode.addListener(() {
if (!_focusNode.hasFocus) {
final validatorProvider =
Provider.of<ValidatorProvider>(context, listen: false);
validatorProvider.validateField(
'email', validatorProvider.getError('email'),
validator: validatorProvider.emailValidator);
}
});
}
@override
void dispose() {
_focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final validatorProvider = Provider.of<ValidatorProvider>(context);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.labelText,
style: AppTextStyles.blackTextStyle.copyWith(
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
TextField(
focusNode: _focusNode,
keyboardType: TextInputType.emailAddress,
onChanged: (value) {
validatorProvider.validateField('email', value,
validator: validatorProvider.emailValidator);
},
decoration: InputDecoration(
hintText: widget.hintText,
hintStyle: AppTextStyles.disableTextStyle.copyWith(
fontSize: 12,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(
width: 1,
color: AppColors.disableColor,
),
),
errorText: validatorProvider.getError('email'),
),
),
],
);
}
}

View File

@ -1,95 +0,0 @@
import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/material.dart';
import 'package:english_learning/core/utils/styles/theme.dart';
class ClassFieldWidget extends StatefulWidget {
final bool isRequired;
final String labelText;
final String hintText;
const ClassFieldWidget({
super.key,
required this.labelText,
required this.hintText,
this.isRequired = false,
});
@override
State<ClassFieldWidget> createState() => _ClassFieldWidgetState();
}
class _ClassFieldWidgetState extends State<ClassFieldWidget> {
String? selectedClass;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text.rich(
TextSpan(
children: [
TextSpan(
text: widget.labelText,
style: AppTextStyles.blackTextStyle.copyWith(
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
if (widget.isRequired)
TextSpan(
text: ' *',
style: AppTextStyles.blackTextStyle.copyWith(
fontSize: 12,
fontWeight: FontWeight.bold,
color: AppColors.redColor, // Red color for asterisk
),
),
],
),
),
const SizedBox(height: 8),
DropdownButtonFormField(
value: selectedClass,
hint: Text(
widget.hintText,
style: AppTextStyles.disableTextStyle.copyWith(
fontSize: 12,
),
),
decoration: InputDecoration(
contentPadding:
const EdgeInsets.symmetric(vertical: 12, horizontal: 12),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(
color: AppColors.disableColor,
width: 1,
),
),
),
icon: const Icon(
BootstrapIcons.chevron_down,
color: AppColors.greyColor,
size: 16,
),
items: <String>['Class 1', 'Class 2', 'Class 3', 'Class 4']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: AppTextStyles.greyTextStyle.copyWith(
fontSize: 12,
),
),
);
}).toList(),
onChanged: (String? newValue) {
setState(() {
selectedClass = newValue;
});
},
),
],
);
}
}

View File

@ -1,173 +0,0 @@
import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:english_learning/features/auth/provider/validator_provider.dart';
import 'package:flutter/material.dart';
import 'package:english_learning/core/utils/styles/theme.dart';
import 'package:provider/provider.dart';
class CustomFieldWidget extends StatefulWidget {
final String fieldName;
final String labelText;
final dynamic hintText;
final String? Function(String?)? validator;
final bool obscureText;
final TextEditingController? controller;
final IconButton? suffixIcon;
final TextInputAction textInputAction;
final TextInputType? keyboardType;
final bool? isError;
final FocusNode? focusNode;
final Function(String?)? onChanged;
final String? errorText;
final Function()? onSuffixIconTap;
final bool isRequired;
final bool isEnabled;
final Function(String?)? onFieldSubmitted;
const CustomFieldWidget({
super.key,
required this.fieldName,
required this.labelText,
required this.textInputAction,
this.hintText,
this.validator,
this.obscureText = false,
this.controller,
this.suffixIcon,
this.focusNode,
this.keyboardType,
this.isError = false,
this.errorText,
this.onChanged,
this.onSuffixIconTap,
this.isRequired = false,
this.isEnabled = true,
this.onFieldSubmitted,
});
@override
State<CustomFieldWidget> createState() => _CustomFieldWidgetState();
}
class _CustomFieldWidgetState extends State<CustomFieldWidget> {
late TextEditingController _controller;
late ValidatorProvider _validatorProvider;
@override
void initState() {
super.initState();
_controller = widget.controller ?? TextEditingController();
// Simpan referensi provider di initState
_validatorProvider = context.read<ValidatorProvider>();
_validatorProvider.setController(widget.fieldName, _controller);
}
@override
void dispose() {
// Gunakan referensi yang disimpan sebelumnya
_validatorProvider.removeController(widget.fieldName);
if (widget.controller == null) {
_controller.dispose();
}
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text.rich(
TextSpan(
children: [
TextSpan(
text: widget.labelText,
style: AppTextStyles.blackTextStyle.copyWith(
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
if (widget.isRequired)
TextSpan(
text: ' *',
style: AppTextStyles.blackTextStyle.copyWith(
fontSize: 12,
fontWeight: FontWeight.bold,
color: AppColors.redColor, // Red color for asterisk
),
),
],
),
),
const SizedBox(height: 8),
TextFormField(
controller: widget.controller,
keyboardType: widget.keyboardType,
textInputAction: widget.textInputAction,
obscureText: widget.obscureText,
focusNode: widget.focusNode,
onChanged: widget.onChanged,
onFieldSubmitted: widget.onFieldSubmitted,
enabled: widget.isEnabled,
decoration: InputDecoration(
hintText: widget.hintText,
hintStyle: AppTextStyles.disableTextStyle.copyWith(
fontSize: 12,
),
fillColor: widget.isEnabled
? AppColors.whiteColor
: AppColors.cardDisabledColor,
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(
width: 1,
color: AppColors.cardDisabledColor,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(
width: 1,
color: AppColors.cardDisabledColor,
),
),
disabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(
width: 1,
color: AppColors
.cardDisabledColor, // Adjust this color if necessary
),
),
suffixIcon: widget.onSuffixIconTap != null
? GestureDetector(
onTap: widget.onSuffixIconTap,
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
transitionBuilder:
(Widget child, Animation<double> animation) {
return ScaleTransition(scale: animation, child: child);
},
child: Icon(
widget.obscureText
? BootstrapIcons.eye_slash
: BootstrapIcons.eye,
color: AppColors.greyColor,
size: 20,
),
),
)
: null,
errorText: widget.errorText,
),
validator: widget.validator,
),
],
);
}
}

View File

@ -1,83 +0,0 @@
import 'package:english_learning/features/auth/provider/validator_provider.dart';
import 'package:english_learning/core/utils/styles/theme.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class FullNameFieldWidget extends StatefulWidget {
final String labelText;
final String hintText;
const FullNameFieldWidget({
super.key,
required this.labelText,
required this.hintText,
});
@override
FullNameFieldWidgetState createState() => FullNameFieldWidgetState();
}
class FullNameFieldWidgetState extends State<FullNameFieldWidget> {
late FocusNode _focusNode;
@override
void initState() {
super.initState();
_focusNode = FocusNode();
_focusNode.addListener(() {
if (!_focusNode.hasFocus) {
final validatorProvider =
Provider.of<ValidatorProvider>(context, listen: false);
validatorProvider.validateField(
'fullName', validatorProvider.getError('fullName'),
validator: validatorProvider.fullNameValidator);
}
});
}
@override
void dispose() {
_focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final validatorProvider = Provider.of<ValidatorProvider>(context);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.labelText,
style: AppTextStyles.blackTextStyle.copyWith(
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
TextField(
focusNode: _focusNode,
onChanged: (value) {
validatorProvider.validateField('fullName', value,
validator: validatorProvider.fullNameValidator);
},
decoration: InputDecoration(
hintText: widget.hintText,
hintStyle: AppTextStyles.disableTextStyle.copyWith(
fontSize: 12,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(
width: 1,
color: AppColors.disableColor,
),
),
errorText: validatorProvider.getError('fullName'),
),
),
],
);
}
}

View File

@ -1,128 +0,0 @@
import 'package:english_learning/core/utils/styles/theme.dart';
import 'package:flutter/material.dart';
class GlobalButton extends StatelessWidget {
final String text;
final VoidCallback? onPressed;
final double? width;
final double? height;
final IconData? icon;
final double? iconSize;
final bool spaceBetween;
final Gradient? gradient;
final Color? textColor;
final Color? backgroundColor;
final Color? borderColor;
final double borderWidth;
final bool transparentBackground;
final bool isLoading;
const GlobalButton({
super.key,
required this.text,
required this.onPressed,
this.width = double.infinity,
this.height = 49.0,
this.icon,
this.iconSize = 24.0,
this.spaceBetween = false,
this.gradient,
this.textColor = Colors.white,
this.backgroundColor,
this.borderColor,
this.borderWidth = 1.0,
this.transparentBackground = false,
this.isLoading = false,
});
@override
Widget build(BuildContext context) {
return SizedBox(
width: width,
height: height,
child: DecoratedBox(
decoration: BoxDecoration(
gradient: transparentBackground
? null
: (gradient ??
(backgroundColor != null ? null : AppColors.gradientTheme)),
color: gradient == null
? backgroundColor
: null, // Use solid color if no gradient
borderRadius: BorderRadius.circular(12),
border: borderColor != null
? Border.all(color: borderColor!, width: borderWidth)
: null,
),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.transparent,
shadowColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
),
),
onPressed: onPressed,
child: isLoading ? _buildLoadingIndicator() : _buildButtonContent(),
),
),
);
}
Widget _buildLoadingIndicator() {
return SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(textColor ?? Colors.white),
strokeWidth: 2.0,
),
);
}
Widget _buildButtonContent() {
if (spaceBetween && icon != null) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
text,
style: AppTextStyles.whiteTextStyle.copyWith(
fontSize: 14,
fontWeight: FontWeight.bold,
color: textColor,
),
),
Icon(
icon,
size: iconSize,
color: textColor ?? Colors.white,
),
],
);
} else {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
text,
style: AppTextStyles.whiteTextStyle.copyWith(
fontSize: 14,
fontWeight: FontWeight.bold,
color: textColor,
),
),
if (icon != null)
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Icon(
icon,
size: iconSize,
color: textColor ?? Colors.white,
),
),
],
);
}
}
}

Some files were not shown because too many files have changed in this diff Show More