├── .gitignore ├── .metadata ├── .vscode └── launch.json ├── README.md ├── analysis_options.yaml ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── example │ │ │ │ ├── student_note │ │ │ │ └── MainActivity.kt │ │ │ │ └── yalda_students_notes │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable-v21 │ │ │ └── launch_background.xml │ │ │ ├── drawable │ │ │ └── launch_background.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── launcher_icon.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── launcher_icon.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── launcher_icon.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── launcher_icon.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── launcher_icon.png │ │ │ ├── values-night │ │ │ └── styles.xml │ │ │ └── values │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── asset ├── fonts │ ├── IRANMarker.ttf │ └── ic_font.ttf ├── icon │ └── icon.png ├── image │ ├── category.jpg │ ├── empty.jpg │ ├── error-404.png │ ├── lang.png │ ├── notes.jpg │ └── search.png └── translation │ ├── en.json │ └── fa.json ├── generate_js.bat ├── generate_js.sh ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Podfile ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-1024x1024@1x.png │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ └── Icon-App-83.5x83.5@2x.png │ └── LaunchImage.imageset │ │ ├── Contents.json │ │ ├── LaunchImage.png │ │ ├── LaunchImage@2x.png │ │ ├── LaunchImage@3x.png │ │ └── README.md │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h ├── lib ├── app │ ├── app.dart │ ├── app_prefs.dart │ ├── app_providers.dart │ ├── const.dart │ ├── di.dart │ ├── exception.dart │ ├── extensions.dart │ ├── functions.dart │ └── global.dart ├── data │ ├── datasource │ │ ├── connection │ │ │ ├── connection.dart │ │ │ ├── native.dart │ │ │ ├── unsupported.dart │ │ │ └── web.dart │ │ ├── database.dart │ │ ├── database.g.dart │ │ └── table │ │ │ ├── category_data.dart │ │ │ ├── note_data.dart │ │ │ └── reastore_data.dart │ ├── drift_config.dart │ ├── mapper │ │ └── mapper.dart │ └── repository │ │ ├── category_repository_impl.dart │ │ └── note_repository_impl.dart ├── domain │ ├── model │ │ ├── category_model.dart │ │ ├── country.dart │ │ └── note_model.dart │ └── repository │ │ ├── category_repository.dart │ │ └── note_repository.dart ├── gen │ ├── assets.gen.dart │ ├── fonts.gen.dart │ └── translation │ │ ├── codegen_loader.g.dart │ │ └── locale_keys.g.dart ├── main.dart ├── presentation │ ├── resources │ │ ├── color_manager.dart │ │ ├── font_manager.dart │ │ ├── language_manager.dart │ │ ├── style_manager.dart │ │ └── value_manager.dart │ ├── screen │ │ ├── about │ │ │ └── about_screen.dart │ │ ├── add_note │ │ │ ├── add_note_screen.dart │ │ │ └── bloc │ │ │ │ ├── addnote_bloc.dart │ │ │ │ ├── addnote_event.dart │ │ │ │ └── addnote_state.dart │ │ ├── category │ │ │ ├── bloc │ │ │ │ ├── category_bloc.dart │ │ │ │ ├── category_event.dart │ │ │ │ └── category_state.dart │ │ │ ├── category.dart │ │ │ └── ext.dart │ │ ├── category_notes │ │ │ ├── bloc │ │ │ │ ├── category_notes_bloc.dart │ │ │ │ ├── category_notes_event.dart │ │ │ │ └── category_notes_state.dart │ │ │ └── category_notes.dart │ │ ├── edit_note │ │ │ ├── bloc │ │ │ │ ├── editnote_bloc.dart │ │ │ │ ├── editnote_event.dart │ │ │ │ └── editnote_state.dart │ │ │ └── edit_note_screen.dart │ │ ├── favorite │ │ │ ├── bloc │ │ │ │ ├── starrednotes_bloc.dart │ │ │ │ ├── starrednotes_event.dart │ │ │ │ └── starrednotes_state.dart │ │ │ └── favorite.dart │ │ ├── home │ │ │ └── home_screen.dart │ │ ├── note │ │ │ ├── bloc │ │ │ │ ├── notelist_bloc.dart │ │ │ │ ├── notelist_event.dart │ │ │ │ └── notelist_state.dart │ │ │ └── note.dart │ │ ├── onboarding │ │ │ ├── bloc │ │ │ │ ├── language_bloc.dart │ │ │ │ ├── language_event.dart │ │ │ │ └── language_state.dart │ │ │ └── onboard_screen.dart │ │ ├── search │ │ │ ├── bloc │ │ │ │ ├── searchnote_bloc.dart │ │ │ │ ├── searchnote_event.dart │ │ │ │ └── searchnote_state.dart │ │ │ └── search_screen.dart │ │ └── setting │ │ │ ├── setting_dialog.dart │ │ │ └── setting_screen.dart │ ├── util │ │ ├── color_util.dart │ │ ├── language_util.dart │ │ └── theme_util.dart │ └── widgets │ │ ├── bottom_navigation.dart │ │ ├── bottom_sheet.dart │ │ ├── bouncing_spinner.dart │ │ ├── category_dialog.dart │ │ ├── category_item.dart │ │ ├── color_picker.dart │ │ ├── drawer.dart │ │ ├── empty_state.dart │ │ ├── invalid_state.dart │ │ ├── language_radio_button.dart │ │ ├── loading_state.dart │ │ ├── note_category_item.dart │ │ ├── note_grid.dart │ │ ├── note_grid_item.dart │ │ ├── note_item.dart │ │ ├── note_list.dart │ │ ├── note_list_item.dart │ │ ├── pop_menu_item.dart │ │ └── top_snackbar │ │ ├── custom_snack_bar.dart │ │ ├── safe_area_values.dart │ │ ├── tap_bounce_container.dart │ │ └── top_snack_bar.dart └── tranlation │ └── codegen_loader.g.dart ├── linux ├── .gitignore ├── CMakeLists.txt ├── flutter │ ├── CMakeLists.txt │ ├── generated_plugin_registrant.cc │ ├── generated_plugin_registrant.h │ └── generated_plugins.cmake ├── main.cc ├── my_application.cc └── my_application.h ├── macos ├── .gitignore ├── Flutter │ ├── Flutter-Debug.xcconfig │ ├── Flutter-Release.xcconfig │ ├── GeneratedPluginRegistrant.swift │ └── ephemeral │ │ ├── Flutter-Generated.xcconfig │ │ └── flutter_export_environment.sh ├── Podfile ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── app_icon_1024.png │ │ ├── app_icon_128.png │ │ ├── app_icon_16.png │ │ ├── app_icon_256.png │ │ ├── app_icon_32.png │ │ ├── app_icon_512.png │ │ └── app_icon_64.png │ ├── Base.lproj │ └── MainMenu.xib │ ├── Configs │ ├── AppInfo.xcconfig │ ├── Debug.xcconfig │ ├── Release.xcconfig │ └── Warnings.xcconfig │ ├── DebugProfile.entitlements │ ├── Info.plist │ ├── MainFlutterWindow.swift │ └── Release.entitlements ├── pictures ├── dark_note_list.jpg ├── dark_persian_note_list.png ├── dark_search.jpg ├── desktop.jpg ├── desktop_dark.jpg ├── light_categories.jpg ├── light_favorite.jpg ├── light_note_list.jpg ├── light_note_list.png └── light_search_404.jpg ├── pubspec.lock ├── pubspec.yaml ├── test └── widget_test.dart ├── web ├── favicon.png ├── icons │ ├── Icon-192.png │ ├── Icon-512.png │ ├── Icon-maskable-192.png │ └── Icon-maskable-512.png ├── index.html ├── manifest.json ├── shared_worker.dart.js ├── sql-wasm.js ├── sql-wasm.wasm ├── sqlite3.wasm ├── worker.dart ├── worker.dart.js └── worker.dart.min.js └── windows ├── .gitignore ├── CMakeLists.txt ├── flutter ├── CMakeLists.txt ├── generated_plugin_registrant.cc ├── generated_plugin_registrant.h └── generated_plugins.cmake └── runner ├── CMakeLists.txt ├── Runner.rc ├── flutter_window.cpp ├── flutter_window.h ├── main.cpp ├── resource.h ├── resources └── app_icon.ico ├── runner.exe.manifest ├── utils.cpp ├── utils.h ├── win32_window.cpp └── win32_window.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | .fvm/ 34 | 35 | lib/game_card.dart 36 | 37 | # Web related 38 | lib/generated_plugin_registrant.dart 39 | 40 | # Symbolication related 41 | app.*.symbols 42 | 43 | # Obfuscation related 44 | app.*.map.json 45 | 46 | # Android Studio will place build artifacts here 47 | /android/app/debug 48 | /android/app/profile 49 | /android/app/release 50 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: fc7015e35aac7ab785e7ae15a47db5c9e669ec7f 8 | channel: beta 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "yalda_students_notes", 9 | "request": "launch", 10 | "type": "dart", 11 | }, 12 | { 13 | "name": "yalda_students_notes (profile mode)", 14 | "request": "launch", 15 | "type": "dart", 16 | "flutterMode": "profile" 17 | }, 18 | { 19 | "name": "yalda_students_notes (release mode)", 20 | "request": "launch", 21 | "type": "dart", 22 | "flutterMode": "release" 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 📔 Note to Keep Application. 2 | 3 | 4 | 5 | ## ℹ️ Description 6 | 7 | - Develop by using Bloc library in clean architecture with Dependency injection 8 | 9 | - Note application; User can categorize their notes; star notes 10 | 11 | - This Note app is implemented with bloc and provider. It supports dark mode and user can switch between English or Persian language. 12 | 13 | - Run it on Mobile, Tablet, Desktop and your browser. 14 | 15 | - [UI design](https://dribbble.com/shots/16811788-Notes-app) 16 | 17 | 18 | 19 | ## ✅ Supported Platforms 20 | - Android 21 | - iOS 22 | - Desktop 23 | - Web 24 | - Linux 25 | 26 | 27 | 28 | ## 📦 Packages: 29 | - bloc 30 | - get_it 31 | - responsive framework 32 | - easy localization 33 | - drift 34 | - provider 35 | 36 | 37 | 38 | ## ⚜️ Features: 39 | - Adaptive and Responsive (mobile. web, windows) 40 | - dark mode 41 | - add, update and delete a note 42 | - star a note by double tapping on it 43 | - multi language 44 | - categorize notes 45 | - add, rename and delete(by long pressing on each category) a category 46 | 47 | 48 | 🔸 If you enjoy this project, ⭐ it ;) 49 | 50 | 51 | 52 | ## 🖼️ Screenshots: 53 | 54 | note list in dark 55 | favorite in light 56 | search in dark 57 | light categories 58 | desktop-windows 59 | desktop-dark-windows -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at 17 | # https://dart-lang.github.io/linter/lints/index.html. 18 | # 19 | # Instead of disabling a lint rule for the entire project in the 20 | # section below, it can also be suppressed for a single line of code 21 | # or a specific dart file by using the `// ignore: name_of_lint` and 22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 23 | # producing the lint. 24 | rules: 25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 27 | 28 | # Additional information about this file can be found at 29 | # https://dart.dev/guides/language/analysis-options 30 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new Exception("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 33 30 | 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_8 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | } 35 | 36 | kotlinOptions { 37 | jvmTarget = '1.8' 38 | } 39 | 40 | sourceSets { 41 | main.java.srcDirs += 'src/main/kotlin' 42 | } 43 | 44 | defaultConfig { 45 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 46 | applicationId "com.example.yalda_students_notes" 47 | minSdkVersion 21 48 | targetSdkVersion 33 49 | versionCode flutterVersionCode.toInteger() 50 | versionName flutterVersionName 51 | } 52 | 53 | buildTypes { 54 | release { 55 | // TODO: Add your own signing config for the release build. 56 | // Signing with the debug keys for now, so `flutter run --release` works. 57 | signingConfig signingConfigs.debug 58 | } 59 | } 60 | } 61 | 62 | flutter { 63 | source '../..' 64 | } 65 | 66 | dependencies { 67 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 68 | } 69 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 23 | 27 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/example/student_note/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.student_note 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/example/yalda_students_notes/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.yalda_students_notes 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/launcher_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/android/app/src/main/res/mipmap-hdpi/launcher_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/launcher_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/android/app/src/main/res/mipmap-mdpi/launcher_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/launcher_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.9.22' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:7.1.2' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | mavenCentral() 19 | } 20 | } 21 | 22 | rootProject.buildDir = '../build' 23 | subprojects { 24 | project.buildDir = "${rootProject.buildDir}/${project.name}" 25 | } 26 | subprojects { 27 | project.evaluationDependsOn(':app') 28 | } 29 | 30 | tasks.register("clean", Delete) { 31 | delete rootProject.buildDir 32 | } 33 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip 5 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip 7 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /asset/fonts/IRANMarker.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/asset/fonts/IRANMarker.ttf -------------------------------------------------------------------------------- /asset/fonts/ic_font.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/asset/fonts/ic_font.ttf -------------------------------------------------------------------------------- /asset/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/asset/icon/icon.png -------------------------------------------------------------------------------- /asset/image/category.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/asset/image/category.jpg -------------------------------------------------------------------------------- /asset/image/empty.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/asset/image/empty.jpg -------------------------------------------------------------------------------- /asset/image/error-404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/asset/image/error-404.png -------------------------------------------------------------------------------- /asset/image/lang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/asset/image/lang.png -------------------------------------------------------------------------------- /asset/image/notes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/asset/image/notes.jpg -------------------------------------------------------------------------------- /asset/image/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/asset/image/search.png -------------------------------------------------------------------------------- /asset/translation/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "profileTitle": "My Notes", 3 | "notes": "Notes", 4 | "notesList": "List Notes", 5 | "search": "Search", 6 | "categories": "Categories", 7 | "setting": "Setting", 8 | "startSearching": "Start Searching", 9 | "editNote": "Edit Note", 10 | "title": "Title", 11 | "content": "Content", 12 | "startTyping": "Start Typing", 13 | "listCategories": "List Categories", 14 | "language": "Language", 15 | "add_note": "Add Note", 16 | "content_Cannot_Be_Empty": "content Can not Be Empty.", 17 | "favorite_Notes": "Favorite Notes", 18 | "any_note": "You don't have any note.", 19 | "theme": "Theme", 20 | "about": "About us", 21 | "lets_go": "Let's go right away!", 22 | "Colorful_Notes": "Colorful Notes", 23 | "note_tutorial": "Write and Save whatever you want.\nDouble tap on each one to star it.", 24 | "find_quickly": "Find out Quickly", 25 | "search_easily": "You can easily search between notes \nand find what you want.", 26 | "Manage_Notes": "Manage Notes", 27 | "categorize_notes": "Make as many categories as you want and categorize your notes.\n\nYou can delete any category by long pressing on it.", 28 | "select_language": "Select your preferred language.", 29 | "done": "Done", 30 | "save": "Save", 31 | "move": "Move", 32 | "delete": "Delete", 33 | "select_category": "Select category", 34 | "category_count_1": "You have", 35 | "category_count_2": "categories.", 36 | "cancel": "Cancel", 37 | "create": "Create", 38 | "update": "Update", 39 | "note": "Note", 40 | "delete_none_category": "You can't delete None Category.", 41 | "home": "Home", 42 | "note_to_remember": "Note to Remember", 43 | "new_category": "New Category", 44 | "new_note": "New Note", 45 | "copy" : "Copied", 46 | "share" : "Share" 47 | } -------------------------------------------------------------------------------- /asset/translation/fa.json: -------------------------------------------------------------------------------- 1 | { 2 | "profileTitle": "یادداشت های من", 3 | "notes": "یادداشت ها", 4 | "notesList": "لیست یادداشت ها", 5 | "search": "جستجو", 6 | "categories": "دسته ها", 7 | "setting": "تنظیمات", 8 | "startSearching": "جستجو را آغاز کنید", 9 | "editNote": "ویرایش یادداشت", 10 | "title": "عنوان", 11 | "content": "محتوا", 12 | "startTyping": "تایپ کنید", 13 | "listCategories": "لیست دسته ها", 14 | "language": "زبان", 15 | "add_note": "اضافه کردن یادداشت", 16 | "content_Cannot_Be_Empty": "محتوا نمی تواند خال باشد", 17 | "favorite_Notes": "یادداشت های مورد علاقه", 18 | "any_note": "شما یادداشتی ندارید", 19 | "theme": "تم", 20 | "about": "درباره ما", 21 | "lets_go": "بزن بریم", 22 | "Colorful_Notes": "یادداشت های رنگی", 23 | "note_tutorial": "هر چیزی رو که میخوای بنویس و ذخیره اش کن.\n میتونی دوبار روش ضربه بزنی تا ستاره دار بشه.", 24 | "find_quickly": "سریع پیداش کن", 25 | "search_easily": "می تونی به راحتی بین یادداشت های جستجو کنی\nو هرچیزی رو که میخوای پیدا کنی.", 26 | "Manage_Notes": "مدیریت یادداشت ها", 27 | "categorize_notes": "هر تعداد که میخوای دسته بساز و یادداشت هات رو دسته بندی کن.\n\nبا دوبار ضربه روی اون میتونی حذفشون کنی.", 28 | "select_language": "زبان مورد نظر خود را انتخاب کنید.", 29 | "done": "تمام", 30 | "save": "ذخیره", 31 | "move": "انتقال", 32 | "delete": "حذف", 33 | "select_category": "دسته مورد نظر خود را انتخاب کنید.", 34 | "category_count_1": "شما", 35 | "category_count_2": "دسته دارید.", 36 | "cancel": "لغو", 37 | "create": "ایجاد", 38 | "update": "ذخیره", 39 | "note": "یادداشت", 40 | "delete_none_category": "شما نمی توانید دسته None را پاک کنید. ", 41 | "home": "خانه", 42 | "note_to_remember": "یادداشتی برای یادآوری", 43 | "new_category": "دسته جدید", 44 | "new_note": "یادداشت جدید", 45 | "copy" : "ک‍پی شد", 46 | "share" : "اشتراک گذاری" 47 | } -------------------------------------------------------------------------------- /generate_js.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | DEL "web\worker.dart.js" 4 | DEL "web\worker.dart.min.js" 5 | flutter "pub" "run" "build_runner" "build" "--delete-conflicting-outputs" "-o" "web:build\web\" 6 | COPY "build\web\worker.dart.js" "web\worker.dart.js" 7 | DEL /S "build\web" 8 | flutter "pub" "run" "build_runner" "build" "--release" "--delete-conflicting-outputs" "-o" "web:build\web\" 9 | COPY "build\web\worker.dart.js" "web\worker.dart.min.js" 10 | DEL /S "build\web" -------------------------------------------------------------------------------- /generate_js.sh: -------------------------------------------------------------------------------- 1 | rm -f web/worker.dart.js 2 | rm -f web/worker.dart.min.js 3 | flutter pub run build_runner build --delete-conflicting-outputs -o web:build/web/ 4 | cp -f build/web/worker.dart.js web/worker.dart.js 5 | rm -rf build/web 6 | flutter pub run build_runner build --release --delete-conflicting-outputs -o web:build/web/ 7 | cp -f build/web/worker.dart.js web/worker.dart.min.js 8 | rm -rf build/web 9 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '11.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | target 'RunnerTests' do 36 | inherit! :search_paths 37 | end 38 | end 39 | 40 | post_install do |installer| 41 | installer.pods_project.targets.each do |target| 42 | flutter_additional_ios_build_settings(target) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch presentation.screen with your own desired assets by replacing the image files in this directory. 4 | 5 | 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. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | Note to Remember 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | CFBundleLocalizations 45 | 46 | en 47 | fa 48 | 49 | LSApplicationQueriesSchemes 50 | 51 | https 52 | http 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /lib/app/app.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:drift/drift.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:yalda_students_notes/app/app_prefs.dart'; 6 | import 'package:yalda_students_notes/app/di.dart'; 7 | import 'package:yalda_students_notes/app/global.dart'; 8 | import 'package:yalda_students_notes/data/datasource/database.dart'; 9 | import 'package:yalda_students_notes/domain/model/category_model.dart'; 10 | import 'package:yalda_students_notes/domain/model/note_model.dart'; 11 | 12 | mixin FetchData { 13 | List fetchNoteData( 14 | AppDatabase database, List result) { 15 | final noteList = []; 16 | for (final row in result) { 17 | var noteData = row.readTable(database.note); 18 | var categoryData = row.readTable(database.category); 19 | 20 | final model = NoteModel( 21 | id: noteData.id, 22 | title: noteData.title ?? '', 23 | content: noteData.content, 24 | createdAt: noteData.createdAt, 25 | colorIndex: noteData.colorIndex, 26 | isFavorite: noteData.isFavorite, 27 | categoryId: categoryData.id, 28 | category: categoryData.title, 29 | ); 30 | noteList.add(model); 31 | } 32 | return noteList; 33 | } 34 | 35 | List fetchCategoryData(AppDatabase database, 36 | List result, Expression numberOfNotes) { 37 | final categories = []; 38 | for (final row in result) { 39 | var categoryData = row.readTable(database.category); 40 | final model = CategoryModel( 41 | id: categoryData.id, 42 | title: categoryData.title, 43 | color: categoryData.color, 44 | numberOfNotes: row.read(numberOfNotes)); 45 | categories.add(model); 46 | } 47 | 48 | return categories; 49 | } 50 | } 51 | 52 | mixin ExtractCategoryData { 53 | CategoryModel extractCategoryData(String data) { 54 | debugPrint(data); 55 | final split = data.split(','); 56 | List values = []; 57 | for (int i = 0; i < split.length; i++) { 58 | values.add(split[i]); 59 | } 60 | 61 | int id = int.parse(values[0]!); 62 | int color = int.parse(values[1]!); 63 | values.removeRange(0, 2); 64 | String title = values.join(); 65 | 66 | return CategoryModel(id: id, title: title, color: color); 67 | } 68 | } 69 | 70 | int generateColor() { 71 | return Color.fromRGBO(Random().nextInt(255), Random().nextInt(255), 72 | Random().nextInt(255), 1) 73 | .value; 74 | } 75 | 76 | bool isPersianLanguage() => 77 | appLocale.languageCode == const Locale('fa', 'IR').languageCode; 78 | 79 | Future isFirstTime() async { 80 | final appPref = instance(); 81 | 82 | var isFirstTime = await appPref.isFirstRun(); 83 | if (!isFirstTime) { 84 | return false; 85 | } else { 86 | appPref.setFirstRun(false); 87 | return true; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /lib/app/app_prefs.dart: -------------------------------------------------------------------------------- 1 | import 'package:shared_preferences/shared_preferences.dart'; 2 | 3 | const String firstRun = 'first_time'; 4 | const String darkMode = 'darkMode'; 5 | const String appLanguage = 'appLang'; 6 | 7 | class AppPreferences { 8 | final SharedPreferences _pref; 9 | 10 | AppPreferences(this._pref); 11 | 12 | Future setLanguage(String languageCode) async { 13 | return await _pref.setString(appLanguage, languageCode); 14 | } 15 | 16 | Future getLanguage() async { 17 | return _pref.getString(appLanguage) ?? ""; 18 | } 19 | 20 | Future setFirstRun(bool isFirstRun) async { 21 | return _pref.setBool(firstRun, isFirstRun); 22 | } 23 | 24 | Future isFirstRun() async { 25 | //check def value 26 | return _pref.getBool(firstRun) ?? true; 27 | } 28 | 29 | Future setTheme(bool isDark) async { 30 | return _pref.setBool(darkMode, isDark); 31 | } 32 | 33 | Future getTheme() async { 34 | //check def value 35 | return _pref.getBool(darkMode) ?? false; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/app/app_providers.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_bloc/flutter_bloc.dart'; 2 | import 'package:provider/provider.dart'; 3 | import 'package:yalda_students_notes/app/app.dart'; 4 | import 'package:yalda_students_notes/data/datasource/database.dart'; 5 | import 'package:yalda_students_notes/data/repository/category_repository_impl.dart'; 6 | import 'package:yalda_students_notes/data/repository/note_repository_impl.dart'; 7 | import 'package:yalda_students_notes/domain/model/category_model.dart'; 8 | import 'package:yalda_students_notes/presentation/screen/category/bloc/category_bloc.dart'; 9 | import 'package:yalda_students_notes/presentation/screen/category_notes/bloc/category_notes_bloc.dart'; 10 | import 'package:yalda_students_notes/presentation/screen/note/bloc/notelist_bloc.dart'; 11 | import 'package:yalda_students_notes/presentation/screen/onboarding/bloc/language_bloc.dart'; 12 | 13 | final providerList = [ 14 | ChangeNotifierProvider(create: (context) => AppDatabase()), 15 | BlocProvider( 16 | create: (context) => CategoryBloc( 17 | CategoryRepository(context.read()), 18 | CategoryModel(title: '', color: generateColor()))), 19 | BlocProvider( 20 | create: (context) => 21 | NoteListBloc(NoteRepository(context.read()))), 22 | BlocProvider(create: (context) => OnBoardingBloc()), 23 | BlocProvider( 24 | create: (context) => CategoryNotesBloc( 25 | categoryRepository: CategoryRepository(context.read()), 26 | noteRepository: NoteRepository(context.read())), 27 | ) 28 | ]; 29 | -------------------------------------------------------------------------------- /lib/app/const.dart: -------------------------------------------------------------------------------- 1 | class AppConstants { 2 | 3 | //config 4 | static const String appVersion = 'v1.0.0'; 5 | 6 | //app 7 | static const double bottomNavigationHeight = 65; 8 | static const int openAnimationDuration = 1000; 9 | 10 | //routes 11 | static const String homeRoute = '/'; 12 | static const String addNoteRoute = '/add_note'; 13 | static const String editNoteRoute = '/edit_note'; 14 | 15 | //URLs 16 | static const String githubUrl = 17 | 'https://github.com/yalda-student/student_note'; 18 | static const String linkedInUrl = 19 | 'https://www.linkedin.com/in/yalda-mohasseli-270049178/'; 20 | 21 | //messages 22 | static const String invalidDataType = 'Invalid data type'; 23 | } 24 | -------------------------------------------------------------------------------- /lib/app/di.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:shared_preferences/shared_preferences.dart'; 3 | import 'package:yalda_students_notes/app/app_prefs.dart'; 4 | 5 | final instance = GetIt.instance; 6 | 7 | Future initAppModule() async { 8 | final sharedPrefs = await SharedPreferences.getInstance(); 9 | instance.registerLazySingleton(() => sharedPrefs); 10 | 11 | instance.registerLazySingleton( 12 | () => AppPreferences(instance())); 13 | } 14 | -------------------------------------------------------------------------------- /lib/app/exception.dart: -------------------------------------------------------------------------------- 1 | class AppException{ 2 | final String message; 3 | 4 | AppException(this.message); 5 | } -------------------------------------------------------------------------------- /lib/app/extensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:yalda_students_notes/app/app_prefs.dart'; 3 | import 'package:yalda_students_notes/app/di.dart'; 4 | import 'package:yalda_students_notes/presentation/util/theme_util.dart'; 5 | 6 | extension BuildContextExts on BuildContext { 7 | bool screenIsHorizontal() { 8 | if (MediaQuery.of(this).size.width < MediaQuery.of(this).size.height) { 9 | //use horizontal | 10 | return true; 11 | } else { 12 | //use vertical __ 13 | return false; 14 | } 15 | } 16 | 17 | void changeTheme(bool value, ThemeNotifier themeNotifier) async { 18 | (value) 19 | ? themeNotifier.setTheme(darkTheme) 20 | : themeNotifier.setTheme(lightTheme); 21 | final appPref = instance(); 22 | await appPref.setTheme(value); 23 | } 24 | 25 | double get screenHeight => MediaQuery.of(this).size.height; 26 | 27 | double get screenWidth => MediaQuery.of(this).size.width; 28 | } 29 | 30 | extension StringExts on String { 31 | bool isLanguageRtl() { 32 | return this == (const Locale('fa', 'IR').languageCode); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/app/functions.dart: -------------------------------------------------------------------------------- 1 | import 'package:easy_localization/easy_localization.dart'; 2 | import 'package:shamsi_date/shamsi_date.dart'; 3 | 4 | String convertToJalaliDate(DateTime date){ 5 | Jalali g2j1 = Gregorian.fromDateTime(date).toJalali(); 6 | final jalaliDate = DateTime(g2j1.year, g2j1.month, g2j1.day); 7 | return DateFormat('yyyy/MM/dd').format(jalaliDate); 8 | } -------------------------------------------------------------------------------- /lib/app/global.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | Locale appLocale = const Locale('en', 'US'); -------------------------------------------------------------------------------- /lib/data/datasource/connection/connection.dart: -------------------------------------------------------------------------------- 1 | // We use a conditional export to expose the right connection factory depending 2 | // on the platform. 3 | export 'unsupported.dart' 4 | if (dart.library.js) 'web.dart' 5 | if (dart.library.ffi) 'native.dart'; 6 | -------------------------------------------------------------------------------- /lib/data/datasource/connection/native.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'dart:isolate'; 3 | 4 | import 'package:drift/drift.dart'; 5 | import 'package:drift/isolate.dart'; 6 | import 'package:drift/native.dart'; 7 | import 'package:path_provider/path_provider.dart'; 8 | import 'package:path/path.dart' as p; 9 | 10 | /// Obtains a database connection for running drift in a Dart VM. 11 | /// 12 | /// The [NativeDatabase] from drift will synchronously use sqlite3's C APIs. 13 | /// To move synchronous database work off the main thread, we use a 14 | /// [DriftIsolate], which can run queries in a background isolate under the 15 | /// hood. 16 | DatabaseConnection connect() { 17 | return DatabaseConnection.delayed(Future.sync(() async { 18 | // Background isolates can't use platform channels, so let's use 19 | // `path_provider` in the main isolate and just send the result containing 20 | // the path over to the background isolate. 21 | final appDir = await getApplicationDocumentsDirectory(); 22 | final dbPath = p.join(appDir.path, 'todos.db'); 23 | 24 | final receiveDriftIsolate = ReceivePort(); 25 | await Isolate.spawn(_entrypointForDriftIsolate, 26 | _IsolateStartRequest(receiveDriftIsolate.sendPort, dbPath)); 27 | 28 | final driftIsolate = await receiveDriftIsolate.first as DriftIsolate; 29 | return driftIsolate.connect(); 30 | })); 31 | } 32 | 33 | /// The entrypoint of isolates can only take a single message, but we need two 34 | /// (a send port to reach the originating isolate and the database's path that 35 | /// should be opened on the background isolate). So, we bundle this information 36 | /// in a single class. 37 | class _IsolateStartRequest { 38 | final SendPort talkToMain; 39 | final String databasePath; 40 | 41 | _IsolateStartRequest(this.talkToMain, this.databasePath); 42 | } 43 | 44 | /// The entrypoint for a background isolate launching a drift server. 45 | /// 46 | /// The main isolate can then connect to that isolate server to transparently 47 | /// run queries in the background. 48 | void _entrypointForDriftIsolate(_IsolateStartRequest request) { 49 | // The native database synchronously uses sqlite3's C API with `dart:ffi` for 50 | // a fast database implementation that doesn't require platform channels. 51 | final databaseImpl = NativeDatabase(File(request.databasePath)); 52 | 53 | // We can use DriftIsolate.inCurrent because this function is the entrypoint 54 | // of a background isolate itself. 55 | final driftServer = DriftIsolate.inCurrent( 56 | () => DatabaseConnection.fromExecutor(databaseImpl)); 57 | 58 | // Inform the main isolate about the server we just created. 59 | request.talkToMain.send(driftServer); 60 | } 61 | -------------------------------------------------------------------------------- /lib/data/datasource/connection/unsupported.dart: -------------------------------------------------------------------------------- 1 | import 'package:drift/drift.dart'; 2 | 3 | DatabaseConnection connect() { 4 | throw UnsupportedError( 5 | 'No suitable database implementation was found on this platform.'); 6 | } 7 | -------------------------------------------------------------------------------- /lib/data/datasource/connection/web.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | // ignore: avoid_web_libraries_in_flutter 3 | import 'dart:html'; 4 | 5 | import 'package:drift/drift.dart'; 6 | import 'package:drift/remote.dart'; 7 | import 'package:drift/web.dart'; 8 | import 'package:drift/wasm.dart'; 9 | import 'package:http/http.dart' as http; 10 | import 'package:sqlite3/wasm.dart'; 11 | 12 | const _useWorker = true; 13 | 14 | /// Obtains a database connection for running drift on the web. 15 | DatabaseConnection connect({bool isInWebWorker = false}) { 16 | if (_useWorker && !isInWebWorker) { 17 | final worker = SharedWorker('shared_worker.dart.js'); 18 | return remote(worker.port!.channel()); 19 | } else { 20 | return DatabaseConnection.delayed(Future.sync(() async { 21 | // We're using the experimental wasm support in Drift because this gives 22 | // us a recent sqlite3 version with fts5 support. 23 | // This is still experimental, so consider using the approach described in 24 | // https://drift.simonbinder.eu/web/ instead. 25 | 26 | final response = await http.get(Uri.parse('sqlite3.wasm')); 27 | final fs = await IndexedDbFileSystem.open(dbName: 'my_app'); 28 | final sqlite3 = await WasmSqlite3.load( 29 | response.bodyBytes, 30 | SqliteEnvironment(fileSystem: fs), 31 | ); 32 | 33 | final databaseImpl = WasmDatabase(sqlite3: sqlite3, path: 'app.db'); 34 | return DatabaseConnection.fromExecutor(databaseImpl); 35 | })); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/data/datasource/table/category_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:drift/drift.dart'; 2 | 3 | class Category extends Table { 4 | IntColumn get id => integer().autoIncrement()(); 5 | 6 | TextColumn get title => text().withLength(max: 255)(); 7 | 8 | DateTimeColumn get createdAt => dateTime()(); 9 | 10 | IntColumn get color => integer()(); 11 | } -------------------------------------------------------------------------------- /lib/data/datasource/table/note_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:drift/drift.dart'; 2 | import 'package:yalda_students_notes/data/datasource/table/category_data.dart'; 3 | 4 | class Note extends Table { 5 | IntColumn get id => integer().autoIncrement()(); 6 | 7 | TextColumn get title => text().withLength(max: 255).nullable()(); 8 | 9 | TextColumn get content => text().named('body')(); 10 | 11 | DateTimeColumn get createdAt => dateTime()(); 12 | 13 | IntColumn get colorIndex => integer()(); 14 | 15 | BoolColumn get isFavorite => boolean().withDefault(const Constant(false))(); 16 | 17 | IntColumn get categoryId => 18 | integer().withDefault(const Constant(1)).references(Category, #id, 19 | onDelete: KeyAction.setDefault, onUpdate: KeyAction.cascade)(); 20 | } -------------------------------------------------------------------------------- /lib/data/datasource/table/reastore_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:drift/drift.dart'; 2 | import 'package:yalda_students_notes/data/datasource/table/category_data.dart'; 3 | 4 | class Note extends Table { 5 | IntColumn get id => integer().autoIncrement()(); 6 | TextColumn get title => text().withLength(max: 255).nullable()(); 7 | TextColumn get content => text().named('body')(); 8 | DateTimeColumn get deletedAt => dateTime()(); 9 | IntColumn get color => integer()(); 10 | BoolColumn get isFavorite => boolean().withDefault(const Constant(false))(); 11 | IntColumn get categoryId => integer() 12 | .nullable() 13 | .withDefault(const Constant(1)) 14 | .references(Category, #id, 15 | onDelete: KeyAction.setDefault, onUpdate: KeyAction.cascade)(); 16 | } 17 | -------------------------------------------------------------------------------- /lib/data/drift_config.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:yalda_students_notes/data/datasource/database.dart'; 3 | 4 | class DriftConfig { 5 | static late AppDatabase appDatabase; 6 | 7 | static init() { 8 | appDatabase = AppDatabase(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /lib/data/mapper/mapper.dart: -------------------------------------------------------------------------------- 1 | import 'package:drift/drift.dart'; 2 | import 'package:yalda_students_notes/data/datasource/database.dart'; 3 | import 'package:yalda_students_notes/domain/model/category_model.dart'; 4 | import 'package:yalda_students_notes/domain/model/note_model.dart'; 5 | 6 | extension CategoryModelMapper on CategoryModel { 7 | CategoryCompanion toCategoryCompanion() { 8 | return CategoryCompanion( 9 | id: const Value.absent(), 10 | title: Value(title), 11 | createdAt: Value(DateTime.now()), 12 | color: Value(color)); 13 | } 14 | 15 | CategoryData toCategoryData() { 16 | return CategoryData( 17 | id: id, title: title, createdAt: DateTime.now(), color: color); 18 | } 19 | } 20 | 21 | extension NoteModelMapper on NoteModel { 22 | NoteData toNoteDate() { 23 | return NoteData( 24 | id: id, 25 | title: title, 26 | content: content, 27 | createdAt: createdAt, 28 | colorIndex: colorIndex, 29 | categoryId: categoryId, 30 | isFavorite: isFavorite); 31 | } 32 | 33 | NoteCompanion toNoteCompanion() { 34 | return NoteCompanion( 35 | id: const Value.absent(), 36 | title: Value(title), 37 | content: Value(content), 38 | createdAt: Value(createdAt), 39 | colorIndex: Value(colorIndex), 40 | isFavorite: Value(isFavorite), 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/data/repository/category_repository_impl.dart: -------------------------------------------------------------------------------- 1 | import 'package:yalda_students_notes/data/datasource/database.dart'; 2 | import 'package:yalda_students_notes/domain/model/category_model.dart'; 3 | import 'package:yalda_students_notes/domain/repository/category_repository.dart'; 4 | 5 | class CategoryRepository implements ICategoryRepository { 6 | final AppDatabase datasource; 7 | 8 | CategoryRepository(this.datasource); 9 | 10 | @override 11 | Future insertCategory(CategoryModel category) { 12 | return datasource.addCategory(category); 13 | } 14 | 15 | @override 16 | Future updateCategory(CategoryModel category) { 17 | return datasource.updateCategory(category); 18 | } 19 | 20 | @override 21 | Future deleteCategory(int id) { 22 | return datasource.deleteCategory(id); 23 | } 24 | 25 | @override 26 | Future> getAllCategories() { 27 | return datasource.getAllCategories(); 28 | } 29 | 30 | @override 31 | Future getCategoryTitle(int id) { 32 | return datasource.getCategoryTitle(id); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/data/repository/note_repository_impl.dart: -------------------------------------------------------------------------------- 1 | import 'package:yalda_students_notes/data/datasource/database.dart'; 2 | import 'package:yalda_students_notes/domain/model/note_model.dart'; 3 | import 'package:yalda_students_notes/domain/repository/note_repository.dart'; 4 | 5 | class NoteRepository implements INoteRepository { 6 | final AppDatabase datasource; 7 | 8 | NoteRepository(this.datasource); 9 | 10 | @override 11 | Future insertNote(NoteModel note) { 12 | return datasource.insertNote(note); 13 | } 14 | 15 | @override 16 | Future updateNote(NoteModel note) async { 17 | return datasource.updateNote(note); 18 | } 19 | 20 | @override 21 | Future deleteNote(int id) { 22 | return datasource.deleteNote(id); 23 | } 24 | 25 | @override 26 | Future> getAllNotes({String searchKeyword = ''}) { 27 | return datasource.getAllNotes(searchKeyword); 28 | } 29 | 30 | @override 31 | Future getNoteById(int id) { 32 | return datasource.getNoteById(id); 33 | } 34 | 35 | @override 36 | Future> getNotesInCategory(int categoryId) async { 37 | return datasource.getNotesInCategory(categoryId); 38 | } 39 | 40 | @override 41 | Future> getStarredNotes() { 42 | return datasource.getStarNotes(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/domain/model/category_model.dart: -------------------------------------------------------------------------------- 1 | class CategoryModel { 2 | final int id; 3 | final String title; 4 | int color; 5 | int numberOfNotes; 6 | 7 | CategoryModel({ 8 | this.id = -1, 9 | required this.title, 10 | required this.color, 11 | this.numberOfNotes = 0, 12 | }); 13 | 14 | @override 15 | String toString() { 16 | return 'CategoryModel{id: $id, title: $title, color: $color, numberOfNotes: $numberOfNotes}'; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/domain/model/country.dart: -------------------------------------------------------------------------------- 1 | import 'package:flag/flag.dart'; 2 | import 'package:flutter/cupertino.dart'; 3 | 4 | class Country { 5 | final String name; 6 | final Widget flag; 7 | final Locale locale; 8 | 9 | Country({required this.name, required this.flag, required this.locale}); 10 | } 11 | 12 | final countries = [ 13 | Country( 14 | name: 'English', 15 | locale: const Locale('en', 'US'), 16 | flag: Row( 17 | children: [ 18 | SizedBox( 19 | width: 30, 20 | height: 30, 21 | child: Flag.fromCode(FlagsCode.US, height: 20)), 22 | const SizedBox(width: 8), 23 | const Text('English') 24 | ], 25 | )), 26 | Country( 27 | name: 'فارسی', 28 | locale: const Locale('fa', 'IR'), 29 | flag: Row( 30 | children: [ 31 | SizedBox( 32 | width: 30, 33 | height: 30, 34 | child: Flag.fromCode(FlagsCode.IR, height: 20)), 35 | const SizedBox(width: 8), 36 | const Text('فارسی') 37 | ], 38 | )), 39 | ]; 40 | -------------------------------------------------------------------------------- /lib/domain/model/note_model.dart: -------------------------------------------------------------------------------- 1 | import 'package:yalda_students_notes/data/datasource/database.dart'; 2 | 3 | class NoteModel { 4 | int id; 5 | String title; 6 | String content; 7 | DateTime createdAt; 8 | int colorIndex; 9 | bool isFavorite; 10 | int categoryId; 11 | String category; 12 | 13 | NoteModel( 14 | {this.id = -1, 15 | required this.title, 16 | required this.content, 17 | required this.createdAt, 18 | required this.colorIndex, 19 | required this.isFavorite, 20 | this.categoryId = 1, 21 | this.category = 'None'}); 22 | 23 | NoteModel.fromNoteData(NoteData noteData) 24 | : id = noteData.id, 25 | title = noteData.title ?? '', 26 | content = noteData.content, 27 | createdAt = noteData.createdAt, 28 | colorIndex = noteData.colorIndex, 29 | isFavorite = noteData.isFavorite, 30 | category = '', 31 | categoryId = noteData.categoryId; 32 | 33 | @override 34 | String toString() { 35 | return 'NoteModel{id: $id, title: $title, content: $content, createdAt: $createdAt, color: $colorIndex, isFavorite: $isFavorite, categoryId: $categoryId, category: $category}'; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/domain/repository/category_repository.dart: -------------------------------------------------------------------------------- 1 | import 'package:yalda_students_notes/domain/model/category_model.dart'; 2 | 3 | abstract class ICategoryRepository { 4 | Future insertCategory(CategoryModel category); 5 | 6 | Future updateCategory(CategoryModel category); 7 | 8 | Future deleteCategory(int id); 9 | 10 | Future> getAllCategories(); 11 | 12 | Future getCategoryTitle(int id); 13 | } -------------------------------------------------------------------------------- /lib/domain/repository/note_repository.dart: -------------------------------------------------------------------------------- 1 | import 'package:yalda_students_notes/domain/model/note_model.dart'; 2 | 3 | abstract class INoteRepository { 4 | Future insertNote(NoteModel note); 5 | 6 | Future updateNote(NoteModel note); 7 | 8 | Future deleteNote(int id); 9 | 10 | Future getNoteById(int id); 11 | 12 | Future> getAllNotes({String searchKeyword = ''}); 13 | 14 | Future> getStarredNotes(); 15 | 16 | Future> getNotesInCategory(int categoryId); 17 | } -------------------------------------------------------------------------------- /lib/gen/fonts.gen.dart: -------------------------------------------------------------------------------- 1 | /// GENERATED CODE - DO NOT MODIFY BY HAND 2 | /// ***************************************************** 3 | /// FlutterGen 4 | /// ***************************************************** 5 | 6 | // coverage:ignore-file 7 | // ignore_for_file: type=lint 8 | // ignore_for_file: directives_ordering,unnecessary_import 9 | 10 | class FontFamily { 11 | FontFamily._(); 12 | 13 | /// Font family: IRANMarker 14 | static const String iRANMarker = 'IRANMarker'; 15 | 16 | /// Font family: ic_font 17 | static const String icFont = 'ic_font'; 18 | } 19 | -------------------------------------------------------------------------------- /lib/gen/translation/locale_keys.g.dart: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT. This is code generated via package:easy_localization/generate.dart 2 | 3 | abstract class LocaleKeys { 4 | static const profileTitle = 'profileTitle'; 5 | static const notes = 'notes'; 6 | static const notesList = 'notesList'; 7 | static const search = 'search'; 8 | static const categories = 'categories'; 9 | static const setting = 'setting'; 10 | static const startSearching = 'startSearching'; 11 | static const editNote = 'editNote'; 12 | static const title = 'title'; 13 | static const content = 'content'; 14 | static const startTyping = 'startTyping'; 15 | static const listCategories = 'listCategories'; 16 | static const language = 'language'; 17 | static const add_note = 'add_note'; 18 | static const content_Cannot_Be_Empty = 'content_Cannot_Be_Empty'; 19 | static const favorite_Notes = 'favorite_Notes'; 20 | static const any_note = 'any_note'; 21 | static const theme = 'theme'; 22 | static const about = 'about'; 23 | static const lets_go = 'lets_go'; 24 | static const Colorful_Notes = 'Colorful_Notes'; 25 | static const note_tutorial = 'note_tutorial'; 26 | static const find_quickly = 'find_quickly'; 27 | static const search_easily = 'search_easily'; 28 | static const Manage_Notes = 'Manage_Notes'; 29 | static const categorize_notes = 'categorize_notes'; 30 | static const select_language = 'select_language'; 31 | static const done = 'done'; 32 | static const save = 'save'; 33 | static const move = 'move'; 34 | static const delete = 'delete'; 35 | static const select_category = 'select_category'; 36 | static const category_count_1 = 'category_count_1'; 37 | static const category_count_2 = 'category_count_2'; 38 | static const cancel = 'cancel'; 39 | static const create = 'create'; 40 | static const update = 'update'; 41 | static const note = 'note'; 42 | static const delete_none_category = 'delete_none_category'; 43 | static const home = 'home'; 44 | static const note_to_remember = 'note_to_remember'; 45 | static const new_category = 'new_category'; 46 | static const new_note = 'new_note'; 47 | static const copy = 'copy'; 48 | static const share = 'share'; 49 | 50 | } 51 | -------------------------------------------------------------------------------- /lib/presentation/resources/font_manager.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:responsive_framework/responsive_framework.dart'; 3 | 4 | class FontConstants { 5 | static const String icFont = 'ic_font'; 6 | static const String iranMarkerFont = 'IRANMarker'; 7 | } 8 | 9 | class FontSize { 10 | static const double s11 = 11.0; 11 | static const double s12 = 12.0; 12 | static const double s13 = 13.0; 13 | static const double s14 = 14.0; 14 | static const double s15 = 15.0; 15 | static const double s16 = 16.0; 16 | static const double s17 = 17.0; 17 | static const double s18 = 18.0; 18 | static const double s19 = 19.0; 19 | static const double s20 = 20.0; 20 | static const double s22 = 22.0; 21 | static const double s28 = 28.0; 22 | 23 | static double alertDialogTitle(BuildContext context) => 24 | ResponsiveValue(context, defaultValue: s19, valueWhen: [ 25 | const Condition.equals(name: TABLET, value: s17), 26 | ]).value!; 27 | 28 | static double alertDialogContent(BuildContext context) => 29 | ResponsiveValue(context, defaultValue: s16, valueWhen: [ 30 | const Condition.equals(name: TABLET, value: s15), 31 | ]).value!; 32 | 33 | static double onBoardTitle(BuildContext context) => 34 | ResponsiveValue(context, defaultValue: s28, valueWhen: [ 35 | const Condition.equals(name: TABLET, value: s20), 36 | ]).value!; 37 | 38 | static double onBoardBody(BuildContext context) => 39 | ResponsiveValue(context, defaultValue: s19, valueWhen: [ 40 | const Condition.equals(name: TABLET, value: s16), 41 | ]).value!; 42 | 43 | static double body1(BuildContext context) => 44 | ResponsiveValue(context, defaultValue: s16, valueWhen: [ 45 | const Condition.equals(name: TABLET, value: s12), 46 | ]).value!; 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /lib/presentation/resources/language_manager.dart: -------------------------------------------------------------------------------- 1 | import 'package:easy_localization/easy_localization.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:yalda_students_notes/app/app_prefs.dart'; 4 | import 'package:yalda_students_notes/app/di.dart'; 5 | 6 | mixin AppLanguage { 7 | void onLanguageChange(BuildContext context, Locale locale) async { 8 | await context.setLocale(locale); 9 | // EasyLocalization.of(context)!.setLocale(locale); 10 | final appPref = instance(); 11 | 12 | if (locale == const Locale('en', 'US')) { 13 | appPref.setLanguage(const Locale('en', 'US').languageCode); 14 | } else { 15 | appPref.setLanguage(const Locale('fa', 'IR').languageCode); 16 | } 17 | } 18 | } 19 | 20 | Future getLanguageCode() async { 21 | final appPref = instance(); 22 | return await appPref.getLanguage(); 23 | } 24 | 25 | Map languagesMap = { 26 | const Locale('en', 'US'): "English", 27 | const Locale('fa', 'IR'): "فارسی", 28 | }; 29 | 30 | List languagesList = ['English', 'فارسی']; 31 | -------------------------------------------------------------------------------- /lib/presentation/resources/style_manager.dart: -------------------------------------------------------------------------------- 1 | import 'package:easy_localization/easy_localization.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:responsive_framework/responsive_framework.dart'; 4 | import 'package:yalda_students_notes/presentation/resources/color_manager.dart'; 5 | import 'package:yalda_students_notes/presentation/resources/font_manager.dart'; 6 | 7 | class StyleManager { 8 | static TextStyle drawerTextStyle(BuildContext context) { 9 | return TextStyle( 10 | fontSize: ResponsiveValue( 11 | context, 12 | defaultValue: 15.0, 13 | valueWhen: const [ 14 | Condition.equals(name: TABLET, value: 12.0), 15 | ], 16 | ).value, 17 | ); 18 | } 19 | 20 | static TextStyle tabBarTextStyle(BuildContext context) { 21 | var isEn = 22 | EasyLocalization.of(context)!.currentLocale == const Locale('en', 'US'); 23 | return Theme.of(context) 24 | .textTheme 25 | .bodyText1! 26 | .apply(fontSizeDelta: isEn ? 0.0 : -4.0); 27 | } 28 | 29 | static TextStyle headerTextStyle(BuildContext context) { 30 | var isEn = 31 | EasyLocalization.of(context)!.currentLocale == const Locale('en', 'US'); 32 | return Theme.of(context) 33 | .textTheme 34 | .headline6! 35 | .apply(fontSizeDelta: isEn ? -2.0 : -5.0, fontWeightDelta: 5); 36 | } 37 | 38 | static TextStyle noteTitleTextStyle(ThemeData theme) { 39 | return TextStyle( 40 | overflow: TextOverflow.ellipsis, 41 | fontWeight: FontWeight.w800, 42 | fontSize: 18, 43 | color: theme.colorScheme.onSurface.withOpacity(0.85)); 44 | } 45 | 46 | static TextStyle noteContentTextStyle(ThemeData theme) { 47 | return TextStyle( 48 | overflow: TextOverflow.ellipsis, 49 | fontWeight: FontWeight.w700, 50 | fontSize: 16, 51 | color: theme.colorScheme.onSurface.withOpacity(0.7)); 52 | } 53 | 54 | static TextStyle noteCategoryTextStyle(ThemeData theme) { 55 | return TextStyle( 56 | overflow: TextOverflow.ellipsis, 57 | fontWeight: FontWeight.w400, 58 | fontSize: 10, 59 | color: theme.colorScheme.onSurface); 60 | } 61 | 62 | static TextStyle counterTextStyle(ThemeData theme) => 63 | TextStyle(color: ColorManager.getNoteEditorTextColor(theme)); 64 | 65 | static TextStyle dialogTitlePersianDarkTextStyle() => const TextStyle( 66 | fontFamily: FontConstants.iranMarkerFont, 67 | fontSize: 16, 68 | fontWeight: FontWeight.w500, 69 | color: Colors.white); 70 | 71 | static TextStyle dialogTitlePersianLightTextStyle() => const TextStyle( 72 | fontSize: 16, 73 | fontFamily: FontConstants.iranMarkerFont, 74 | fontWeight: FontWeight.w500, 75 | color: ColorManager.primaryDark); 76 | 77 | static TextStyle dialogTitleEnglishDarkTextStyle() => const TextStyle( 78 | fontFamily: FontConstants.icFont, 79 | fontSize: FontSize.s18, 80 | fontWeight: FontWeight.w600, 81 | color: Colors.white); 82 | 83 | static TextStyle dialogTitleEnglishLightTextStyle() => const TextStyle( 84 | fontFamily: FontConstants.icFont, 85 | fontSize: FontSize.s18, 86 | fontWeight: FontWeight.w600, 87 | color: ColorManager.primaryDark); 88 | } 89 | -------------------------------------------------------------------------------- /lib/presentation/resources/value_manager.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:responsive_framework/responsive_framework.dart'; 3 | 4 | class ValueManager { 5 | static const double gridSpacing = 20.0; 6 | } 7 | 8 | class AppPadding { 9 | static const double p0 = 0.0; 10 | static const double p4 = 4.0; 11 | static const double p6 = 6.0; 12 | static const double p8 = 8.0; 13 | static const double p10 = 10.0; 14 | static const double p12 = 12.0; 15 | static const double p16 = 16.0; 16 | } 17 | 18 | class AppSize { 19 | static const double s0 = 0.0; 20 | static const double s6 = 6.0; 21 | static const double s8 = 8.0; 22 | static const double s10 = 10.0; 23 | static const double s12 = 12.0; 24 | static const double s14 = 14.0; 25 | static const double s15 = 15.0; 26 | static const double s16 = 16.0; 27 | static const double s18 = 18.0; 28 | static const double s20 = 20.0; 29 | static const double s22 = 22.0; 30 | static const double s24 = 24.0; 31 | static const double s30 = 30.0; 32 | 33 | static double iconSize(BuildContext context) => 34 | ResponsiveValue(context, defaultValue: s22, valueWhen: [ 35 | const Condition.equals(name: TABLET, value: s20), 36 | ]).value!; 37 | 38 | static double colorPickerIconSize(BuildContext context) => 39 | ResponsiveValue(context, defaultValue: s30, valueWhen: [ 40 | const Condition.equals(name: TABLET, value: 24), 41 | ]).value!; 42 | 43 | static double checkIconSize(BuildContext context) => 44 | ResponsiveValue(context, defaultValue: s18, valueWhen: [ 45 | const Condition.equals(name: TABLET, value: s15), 46 | ]).value!; 47 | } 48 | 49 | const breakPoints = [ 50 | ResponsiveBreakpoint.resize(300, name: MOBILE), 51 | ResponsiveBreakpoint.autoScale(650, name: TABLET), 52 | ResponsiveBreakpoint.resize(850, name: DESKTOP), 53 | ResponsiveBreakpoint.autoScale(1700, name: 'XL'), 54 | ]; 55 | -------------------------------------------------------------------------------- /lib/presentation/screen/add_note/bloc/addnote_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'package:bloc/bloc.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:yalda_students_notes/data/repository/note_repository_impl.dart'; 4 | import 'package:yalda_students_notes/domain/model/category_model.dart'; 5 | import 'package:yalda_students_notes/domain/model/note_model.dart'; 6 | 7 | part 'addnote_event.dart'; 8 | part 'addnote_state.dart'; 9 | 10 | class AddNoteBloc extends Bloc { 11 | final NoteModel _noteData; 12 | final NoteRepository repository; 13 | 14 | AddNoteBloc(this.repository, this._noteData) 15 | : super(AddNoteInitial(_noteData)) { 16 | on((event, emit) async { 17 | if (event is AddNoteSave) { 18 | if (_noteData.title.isEmpty) { 19 | _noteData.title = getFirstWord(_noteData.content); 20 | } 21 | await repository.insertNote(_noteData); 22 | } else if (event is AddNoteColorChange) { 23 | _noteData.colorIndex = event.colorIndex; 24 | 25 | emit(AddNoteInitial(_noteData)); 26 | } else if (event is AddNoteTitleChange) { 27 | _noteData.title = event.title; 28 | 29 | emit(AddNoteInitial(_noteData)); 30 | } else if (event is AddNoteCategoryChange) { 31 | _noteData.category = event.category.title; 32 | _noteData.categoryId = event.category.id; 33 | 34 | emit(AddNoteInitial(_noteData)); 35 | } else if (event is AddNoteContentChange) { 36 | _noteData.content = event.content; 37 | 38 | emit(AddNoteInitial(_noteData)); 39 | } 40 | }); 41 | } 42 | 43 | String getFirstWord(String inputString) { 44 | List wordList = inputString.split(' '); 45 | if (wordList.isNotEmpty) { 46 | return wordList[0]; 47 | } else { 48 | return ' '; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/presentation/screen/add_note/bloc/addnote_event.dart: -------------------------------------------------------------------------------- 1 | part of 'addnote_bloc.dart'; 2 | 3 | @immutable 4 | abstract class AddNoteEvent {} 5 | 6 | class AddNoteSave extends AddNoteEvent {} 7 | 8 | class AddNoteColorChange extends AddNoteEvent { 9 | final int colorIndex; 10 | 11 | AddNoteColorChange(this.colorIndex); 12 | } 13 | 14 | class AddNoteContentChange extends AddNoteEvent { 15 | final String content; 16 | 17 | AddNoteContentChange(this.content); 18 | } 19 | 20 | class AddNoteTitleChange extends AddNoteEvent { 21 | final String title; 22 | 23 | AddNoteTitleChange(this.title); 24 | } 25 | 26 | class AddNoteCategoryChange extends AddNoteEvent{ 27 | 28 | final CategoryModel category; 29 | 30 | AddNoteCategoryChange(this.category); 31 | } -------------------------------------------------------------------------------- /lib/presentation/screen/add_note/bloc/addnote_state.dart: -------------------------------------------------------------------------------- 1 | part of 'addnote_bloc.dart'; 2 | 3 | @immutable 4 | abstract class AddNoteState { 5 | final NoteModel noteData; 6 | 7 | const AddNoteState(this.noteData); 8 | } 9 | 10 | class AddNoteInitial extends AddNoteState { 11 | const AddNoteInitial(NoteModel noteData) : super(noteData); 12 | } 13 | -------------------------------------------------------------------------------- /lib/presentation/screen/category/bloc/category_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'package:bloc/bloc.dart'; 2 | import 'package:equatable/equatable.dart'; 3 | import 'package:yalda_students_notes/app/app.dart'; 4 | import 'package:yalda_students_notes/data/repository/category_repository_impl.dart'; 5 | import 'package:yalda_students_notes/domain/model/category_model.dart'; 6 | 7 | part 'category_event.dart'; 8 | part 'category_state.dart'; 9 | 10 | class CategoryBloc extends Bloc { 11 | final CategoryRepository repository; 12 | CategoryModel _category; 13 | 14 | CategoryBloc(this.repository, this._category) : super(CategoryInitial()) { 15 | on((event, emit) async { 16 | if (event is CategoryStart) { 17 | final data = await repository.getAllCategories(); 18 | emit(CategorySuccess(data)); 19 | } else if (event is CategoryInsert) { 20 | _category.color = generateColor(); 21 | repository.insertCategory(_category); 22 | } 23 | if (event is CategoryDelete) { 24 | await repository.deleteCategory(event.categoryId); 25 | } else if (event is CategoryTextFieldChange) { 26 | _category = 27 | CategoryModel(title: event.categoryName, color: _category.color); 28 | } 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/presentation/screen/category/bloc/category_event.dart: -------------------------------------------------------------------------------- 1 | part of 'category_bloc.dart'; 2 | 3 | abstract class CategoryEvent extends Equatable { 4 | const CategoryEvent(); 5 | } 6 | 7 | class CategoryStart extends CategoryEvent { 8 | @override 9 | List get props => []; 10 | } 11 | 12 | class CategoryTextFieldChange extends CategoryEvent { 13 | final String categoryName; 14 | 15 | const CategoryTextFieldChange(this.categoryName); 16 | 17 | @override 18 | List get props => []; 19 | } 20 | 21 | class CategoryInsert extends CategoryEvent { 22 | @override 23 | List get props => []; 24 | } 25 | 26 | class CategoryDelete extends CategoryEvent { 27 | final int categoryId; 28 | 29 | const CategoryDelete(this.categoryId); 30 | 31 | @override 32 | List get props => []; 33 | } 34 | -------------------------------------------------------------------------------- /lib/presentation/screen/category/bloc/category_state.dart: -------------------------------------------------------------------------------- 1 | part of 'category_bloc.dart'; 2 | 3 | abstract class CategoryState extends Equatable { 4 | const CategoryState(); 5 | } 6 | 7 | class CategoryInitial extends CategoryState { 8 | @override 9 | List get props => []; 10 | } 11 | 12 | class CategoryLoading extends CategoryState { 13 | @override 14 | List get props => []; 15 | } 16 | 17 | class CategorySuccess extends CategoryState { 18 | final List data; 19 | 20 | const CategorySuccess(this.data); 21 | 22 | @override 23 | List get props => [data]; 24 | } 25 | 26 | class CategoryError extends CategoryState { 27 | final String message; 28 | 29 | const CategoryError(this.message); 30 | 31 | @override 32 | List get props => [message]; 33 | } 34 | -------------------------------------------------------------------------------- /lib/presentation/screen/category/ext.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | extension ScreenSizeGameCardExt on BuildContext{ 4 | double singleChildScrollViewDynamicHeight(){ 5 | if(MediaQuery.of(this).size.width < MediaQuery.of(this).size.height){ 6 | //use horizontal | 7 | return MediaQuery.of(this).size.height - 100; 8 | } else { 9 | //use vertical __ 10 | return MediaQuery.of(this).size.height; 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /lib/presentation/screen/category_notes/bloc/category_notes_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'package:bloc/bloc.dart'; 2 | import 'package:equatable/equatable.dart'; 3 | import 'package:yalda_students_notes/data/repository/category_repository_impl.dart'; 4 | import 'package:yalda_students_notes/data/repository/note_repository_impl.dart'; 5 | import 'package:yalda_students_notes/domain/model/category_model.dart'; 6 | import 'package:yalda_students_notes/domain/model/note_model.dart'; 7 | 8 | part 'category_notes_event.dart'; 9 | part 'category_notes_state.dart'; 10 | 11 | class CategoryNotesBloc extends Bloc { 12 | late int categoryId; 13 | late CategoryModel categoryData; 14 | final NoteRepository noteRepository; 15 | final CategoryRepository categoryRepository; 16 | 17 | CategoryNotesBloc( 18 | {required this.categoryRepository, required this.noteRepository}) 19 | : super(CategoryNotesInitial()) { 20 | on((event, emit) async { 21 | if (event is CategoryNoteStart) { 22 | categoryId = event.categoryId; 23 | 24 | final title = await categoryRepository.getCategoryTitle(categoryId); 25 | emit(CategoryNotesName(title)); 26 | final list = await noteRepository.getNotesInCategory(categoryId); 27 | if (list.isNotEmpty) { 28 | emit(CategoryNotesSuccess(list)); 29 | } else { 30 | emit(CategoryNotesEmptyState()); 31 | } 32 | } else if (event is CategoryNoteTextFieldChange) { 33 | categoryData = CategoryModel( 34 | id: categoryId, 35 | title: event.categoryTitle, 36 | color: categoryData.color); 37 | } else if (event is CategoryNoteRename) { 38 | await categoryRepository.updateCategory(categoryData); 39 | } 40 | }); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/presentation/screen/category_notes/bloc/category_notes_event.dart: -------------------------------------------------------------------------------- 1 | part of 'category_notes_bloc.dart'; 2 | 3 | abstract class CategoryNotesEvent extends Equatable { 4 | const CategoryNotesEvent(); 5 | } 6 | 7 | class CategoryNoteStart extends CategoryNotesEvent { 8 | final int categoryId; 9 | 10 | const CategoryNoteStart(this.categoryId); 11 | 12 | @override 13 | List get props => []; 14 | } 15 | 16 | class CategoryNoteTextFieldChange extends CategoryNotesEvent { 17 | final String categoryTitle; 18 | 19 | const CategoryNoteTextFieldChange(this.categoryTitle); 20 | 21 | @override 22 | List get props => [categoryTitle]; 23 | } 24 | 25 | class CategoryNoteRename extends CategoryNotesEvent { 26 | @override 27 | List get props => []; 28 | } 29 | -------------------------------------------------------------------------------- /lib/presentation/screen/category_notes/bloc/category_notes_state.dart: -------------------------------------------------------------------------------- 1 | part of 'category_notes_bloc.dart'; 2 | 3 | abstract class CategoryNotesState extends Equatable { 4 | const CategoryNotesState(); 5 | } 6 | 7 | class CategoryNotesInitial extends CategoryNotesState { 8 | @override 9 | List get props => []; 10 | } 11 | 12 | class CategoryNotesLoading extends CategoryNotesState { 13 | @override 14 | List get props => []; 15 | } 16 | 17 | class CategoryNotesEmptyState extends CategoryNotesState { 18 | @override 19 | List get props => []; 20 | } 21 | 22 | class CategoryNotesSuccess extends CategoryNotesState { 23 | final List data; 24 | 25 | const CategoryNotesSuccess(this.data); 26 | 27 | @override 28 | List get props => [data]; 29 | } 30 | 31 | class CategoryNotesName extends CategoryNotesState{ 32 | final String title; 33 | 34 | const CategoryNotesName(this.title); 35 | @override 36 | List get props => [title]; 37 | } -------------------------------------------------------------------------------- /lib/presentation/screen/edit_note/bloc/editnote_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'package:bloc/bloc.dart'; 2 | import 'package:flutter/cupertino.dart'; 3 | import 'package:share_plus/share_plus.dart'; 4 | import 'package:yalda_students_notes/data/repository/note_repository_impl.dart'; 5 | import 'package:yalda_students_notes/domain/model/category_model.dart'; 6 | import 'package:yalda_students_notes/domain/model/note_model.dart'; 7 | 8 | part 'editnote_event.dart'; 9 | part 'editnote_state.dart'; 10 | 11 | class EditNoteBloc extends Bloc { 12 | final NoteModel _noteData; 13 | final NoteRepository repository; 14 | 15 | EditNoteBloc(this.repository, this._noteData) 16 | : super(EditNoteInitial(_noteData)) { 17 | on((event, emit) async { 18 | if (event is EditNoteUpdate) { 19 | await repository.updateNote(_noteData); 20 | } else if (event is EditNoteDelete) { 21 | await repository.deleteNote(_noteData.id); 22 | } else if (event is EditNoteCategoryChange) { 23 | _noteData.categoryId = event.category.id; 24 | _noteData.category = event.category.title; 25 | 26 | emit(EditNoteInitial(_noteData)); 27 | } else if (event is EditNoteColorChange) { 28 | _noteData.colorIndex = event.colorIndex; 29 | 30 | emit(EditNoteInitial(_noteData)); 31 | } else if (event is EditNoteTitleChange) { 32 | _noteData.title = event.title; 33 | 34 | emit(EditNoteInitial(_noteData)); 35 | } else if (event is EditNoteContentChange) { 36 | _noteData.content = event.content; 37 | 38 | emit(EditNoteInitial(_noteData)); 39 | } else if (event is EditNoteShare) { 40 | debugPrint('EditNoteShare'); 41 | Share.share('${_noteData.title}\n\n${_noteData.content}'); 42 | } 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/presentation/screen/edit_note/bloc/editnote_event.dart: -------------------------------------------------------------------------------- 1 | part of 'editnote_bloc.dart'; 2 | 3 | @immutable 4 | abstract class EditNoteEvent {} 5 | 6 | class EditNoteStart extends EditNoteEvent {} 7 | 8 | class EditNoteUpdate extends EditNoteEvent {} 9 | 10 | class EditNoteDelete extends EditNoteEvent {} 11 | 12 | class EditNoteShare extends EditNoteEvent {} 13 | 14 | class EditNoteTitleChange extends EditNoteEvent { 15 | final String title; 16 | 17 | EditNoteTitleChange(this.title); 18 | } 19 | 20 | class EditNoteContentChange extends EditNoteEvent { 21 | final String content; 22 | 23 | EditNoteContentChange(this.content); 24 | } 25 | 26 | class EditNoteColorChange extends EditNoteEvent { 27 | final int colorIndex; 28 | 29 | EditNoteColorChange(this.colorIndex); 30 | } 31 | 32 | class EditNoteCategoryChange extends EditNoteEvent { 33 | final CategoryModel category; 34 | 35 | EditNoteCategoryChange(this.category); 36 | } 37 | -------------------------------------------------------------------------------- /lib/presentation/screen/edit_note/bloc/editnote_state.dart: -------------------------------------------------------------------------------- 1 | part of 'editnote_bloc.dart'; 2 | 3 | @immutable 4 | abstract class EditNoteState { 5 | final NoteModel noteData; 6 | 7 | const EditNoteState(this.noteData); 8 | } 9 | 10 | class EditNoteInitial extends EditNoteState { 11 | const EditNoteInitial(NoteModel noteData) : super(noteData); 12 | } 13 | 14 | class EditNoteLoading extends EditNoteState { 15 | const EditNoteLoading(NoteModel noteData) : super(noteData); 16 | } 17 | -------------------------------------------------------------------------------- /lib/presentation/screen/favorite/bloc/starrednotes_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'package:bloc/bloc.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:yalda_students_notes/data/repository/note_repository_impl.dart'; 4 | import 'package:yalda_students_notes/domain/model/note_model.dart'; 5 | 6 | part 'starrednotes_event.dart'; 7 | part 'starrednotes_state.dart'; 8 | 9 | class StarredNotesBloc extends Bloc { 10 | final NoteRepository repository; 11 | 12 | StarredNotesBloc(this.repository) : super(StarredNotesInitial()) { 13 | on((event, emit) async { 14 | if (event is StarredNotesStart) { 15 | emit(StarredNotesLoading()); 16 | await _initialList(emit); 17 | } 18 | }); 19 | } 20 | 21 | Future _initialList(Emitter emit) async { 22 | try { 23 | final data = await repository.getStarredNotes(); 24 | 25 | if (data.isEmpty) { 26 | emit(StarredNotesEmpty()); 27 | } else { 28 | emit(StarredNotesSuccess(data)); 29 | } 30 | } catch (e) { 31 | emit(StarredNotesError('Error')); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/presentation/screen/favorite/bloc/starrednotes_event.dart: -------------------------------------------------------------------------------- 1 | part of 'starrednotes_bloc.dart'; 2 | 3 | @immutable 4 | abstract class StarredNotesEvent {} 5 | 6 | class StarredNotesStart extends StarredNotesEvent{ 7 | 8 | } 9 | -------------------------------------------------------------------------------- /lib/presentation/screen/favorite/bloc/starrednotes_state.dart: -------------------------------------------------------------------------------- 1 | part of 'starrednotes_bloc.dart'; 2 | 3 | @immutable 4 | abstract class StarredNotesState {} 5 | 6 | class StarredNotesInitial extends StarredNotesState {} 7 | 8 | class StarredNotesSuccess extends StarredNotesState { 9 | final List noteList; 10 | 11 | StarredNotesSuccess(this.noteList); 12 | } 13 | 14 | class StarredNotesEmpty extends StarredNotesState {} 15 | 16 | class StarredNotesError extends StarredNotesState { 17 | final String message; 18 | 19 | StarredNotesError(this.message); 20 | } 21 | 22 | class StarredNotesLoading extends StarredNotesState {} 23 | -------------------------------------------------------------------------------- /lib/presentation/screen/favorite/favorite.dart: -------------------------------------------------------------------------------- 1 | import 'package:easy_localization/easy_localization.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:iconsax/iconsax.dart'; 5 | import 'package:provider/provider.dart'; 6 | import 'package:responsive_framework/responsive_framework.dart'; 7 | import 'package:yalda_students_notes/data/datasource/database.dart'; 8 | import 'package:yalda_students_notes/data/repository/note_repository_impl.dart'; 9 | import 'package:yalda_students_notes/gen/translation/locale_keys.g.dart'; 10 | import 'package:yalda_students_notes/presentation/resources/value_manager.dart'; 11 | import 'package:yalda_students_notes/presentation/screen/favorite/bloc/starrednotes_bloc.dart'; 12 | import 'package:yalda_students_notes/presentation/widgets/empty_state.dart'; 13 | import 'package:yalda_students_notes/presentation/widgets/loading_state.dart'; 14 | import 'package:yalda_students_notes/presentation/widgets/note_grid.dart'; 15 | import 'package:yalda_students_notes/presentation/widgets/note_list.dart'; 16 | 17 | class FavoriteScreen extends StatelessWidget { 18 | const FavoriteScreen({Key? key}) : super(key: key); 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | final theme = Theme.of(context); 23 | 24 | return BlocProvider( 25 | create: (context) => 26 | StarredNotesBloc(NoteRepository(context.read())), 27 | child: Padding( 28 | padding: const EdgeInsets.only(top: AppPadding.p12), 29 | child: Column( 30 | children: [ 31 | ListTile( 32 | title: const Text( 33 | LocaleKeys.favorite_Notes, 34 | style: TextStyle(fontWeight: FontWeight.bold, fontSize: 17), 35 | ).tr(), 36 | leading: Icon( 37 | Iconsax.note_favorite, 38 | color: theme.colorScheme.onSurface, 39 | ), 40 | ), 41 | Consumer( 42 | builder: (context, value, child) { 43 | context.read().add(StarredNotesStart()); 44 | return BlocBuilder( 45 | builder: (context, state) { 46 | return _handleStates(state); 47 | }, 48 | ); 49 | }, 50 | ), 51 | ], 52 | ), 53 | ), 54 | ); 55 | } 56 | 57 | Widget _handleStates(StarredNotesState state) { 58 | if (state is StarredNotesSuccess) { 59 | return ResponsiveVisibility( 60 | hiddenWhen: const [Condition.largerThan(name: MOBILE)], 61 | child: NoteList(data: state.noteList), 62 | replacement: NoteGrid(data: state.noteList), 63 | ); 64 | } else if (state is StarredNotesEmpty) { 65 | return const EmptyState(); 66 | } else if (state is StarredNotesLoading || state is StarredNotesInitial) { 67 | return const LoadingState(); 68 | } else if (state is StarredNotesError) { 69 | return Center(child: Text(state.message)); 70 | } else { 71 | throw Exception('Invalid State'); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /lib/presentation/screen/home/home_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:contained_tab_bar_view/contained_tab_bar_view.dart'; 2 | import 'package:easy_localization/easy_localization.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:iconsax/iconsax.dart'; 5 | import 'package:responsive_framework/responsive_framework.dart'; 6 | import 'package:yalda_students_notes/app/extensions.dart'; 7 | import 'package:yalda_students_notes/gen/translation/locale_keys.g.dart'; 8 | import 'package:yalda_students_notes/presentation/resources/font_manager.dart'; 9 | import 'package:yalda_students_notes/presentation/resources/style_manager.dart'; 10 | import 'package:yalda_students_notes/presentation/resources/value_manager.dart'; 11 | import 'package:yalda_students_notes/presentation/screen/favorite/favorite.dart'; 12 | import 'package:yalda_students_notes/presentation/screen/note/note.dart'; 13 | 14 | class HomeScreen extends StatelessWidget { 15 | const HomeScreen({Key? key}) : super(key: key); 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | final theme = Theme.of(context); 20 | 21 | return ResponsiveVisibility( 22 | hiddenWhen: const [Condition.largerThan(name: MOBILE)], 23 | replacement: const NoteScreen(), 24 | child: Padding( 25 | padding: const EdgeInsets.all(AppPadding.p12), 26 | child: Column( 27 | children: [ 28 | AppBar( 29 | title: Text(LocaleKeys.profileTitle.tr(), 30 | style: theme.appBarTheme.titleTextStyle!.copyWith( 31 | color: theme.colorScheme.onSurface, 32 | fontSize: FontSize.onBoardBody(context), 33 | fontWeight: FontWeight.w600)), 34 | leading: 35 | Icon(Iconsax.note_text, color: theme.colorScheme.onSurface), 36 | ), 37 | const Divider(), 38 | const SizedBox(height: AppSize.s8), 39 | Expanded( 40 | child: ContainedTabBarView( 41 | tabs: [ 42 | const Text(LocaleKeys.notes).tr(), 43 | const Text(LocaleKeys.favorite_Notes).tr() 44 | ], 45 | views: const [NoteScreen(), FavoriteScreen()], 46 | tabBarViewProperties: const TabBarViewProperties( 47 | physics: BouncingScrollPhysics()), 48 | tabBarProperties: TabBarProperties( 49 | height: 49, 50 | width: context.screenWidth * 0.7, 51 | background: Container( 52 | decoration: BoxDecoration( 53 | color: theme.colorScheme.surface.withOpacity(0.3), 54 | borderRadius: 55 | const BorderRadius.all(Radius.circular(AppSize.s12)), 56 | ), 57 | ), 58 | indicatorPadding: const EdgeInsets.fromLTRB(AppPadding.p12, 59 | AppPadding.p6, AppPadding.p12, AppPadding.p6), 60 | position: TabBarPosition.top, 61 | alignment: TabBarAlignment.center, 62 | indicatorColor: Colors.transparent, 63 | labelColor: theme.colorScheme.primary, 64 | labelStyle: StyleManager.tabBarTextStyle(context), 65 | unselectedLabelColor: theme.colorScheme.onPrimary, 66 | indicator: ContainerTabIndicator( 67 | color: theme.colorScheme.onSurface, 68 | radius: BorderRadius.circular(AppSize.s12), 69 | ), 70 | ), 71 | ), 72 | ), 73 | ], 74 | ), 75 | ), 76 | ); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /lib/presentation/screen/note/bloc/notelist_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'package:bloc/bloc.dart'; 2 | import 'package:flutter/cupertino.dart'; 3 | import 'package:yalda_students_notes/data/repository/note_repository_impl.dart'; 4 | import 'package:yalda_students_notes/domain/model/note_model.dart'; 5 | 6 | part 'notelist_event.dart'; 7 | part 'notelist_state.dart'; 8 | 9 | class NoteListBloc extends Bloc { 10 | final NoteRepository repository; 11 | 12 | NoteListBloc(this.repository) : super(NoteListInitial()) { 13 | on((event, emit) async { 14 | if (event is NoteListStar) { 15 | await repository.updateNote(event.noteData); 16 | } 17 | 18 | if (event is NoteListStart) { 19 | emit(NoteListLoading()); 20 | await _initialList(emit); 21 | } 22 | }); 23 | } 24 | 25 | Future _initialList(Emitter emit) async { 26 | try { 27 | final data = await repository.getAllNotes(searchKeyword: ''); 28 | if (data.isEmpty) { 29 | emit(NoteListEmpty()); 30 | } else { 31 | emit(NoteListSuccess(data)); 32 | } 33 | } catch (e) { 34 | debugPrint('$e'); 35 | emit(NoteListError(e.toString())); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/presentation/screen/note/bloc/notelist_event.dart: -------------------------------------------------------------------------------- 1 | part of 'notelist_bloc.dart'; 2 | 3 | @immutable 4 | abstract class NoteListEvent {} 5 | 6 | class NoteListStart extends NoteListEvent {} 7 | 8 | class NoteListStar extends NoteListEvent { 9 | final NoteModel noteData; 10 | 11 | NoteListStar(this.noteData); 12 | } 13 | -------------------------------------------------------------------------------- /lib/presentation/screen/note/bloc/notelist_state.dart: -------------------------------------------------------------------------------- 1 | part of 'notelist_bloc.dart'; 2 | 3 | @immutable 4 | abstract class NoteListState {} 5 | 6 | class NoteListInitial extends NoteListState {} 7 | 8 | class NoteListEmpty extends NoteListState {} 9 | 10 | class NoteListLoading extends NoteListState {} 11 | 12 | class NoteListSuccess extends NoteListState { 13 | final List noteList; 14 | 15 | NoteListSuccess(this.noteList); 16 | } 17 | 18 | class NoteListError extends NoteListState { 19 | final String errorMessage; 20 | 21 | NoteListError(this.errorMessage); 22 | } 23 | -------------------------------------------------------------------------------- /lib/presentation/screen/onboarding/bloc/language_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'package:bloc/bloc.dart'; 2 | 3 | part 'language_event.dart'; 4 | part 'language_state.dart'; 5 | 6 | class OnBoardingBloc extends Bloc { 7 | OnBoardingBloc() : super(OnBoardingInitial()) { 8 | on((event, emit) { 9 | if (event is OnBoardingLanguageChangeEvent) { 10 | emit(OnBoardingInitial()); 11 | } 12 | }); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/presentation/screen/onboarding/bloc/language_event.dart: -------------------------------------------------------------------------------- 1 | part of 'language_bloc.dart'; 2 | 3 | abstract class OnBoardingEvent {} 4 | 5 | class OnBoardingLanguageChangeEvent extends OnBoardingEvent {} 6 | -------------------------------------------------------------------------------- /lib/presentation/screen/onboarding/bloc/language_state.dart: -------------------------------------------------------------------------------- 1 | part of 'language_bloc.dart'; 2 | 3 | abstract class OnBoardingState {} 4 | 5 | class OnBoardingInitial extends OnBoardingState {} 6 | -------------------------------------------------------------------------------- /lib/presentation/screen/search/bloc/searchnote_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'package:bloc/bloc.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:yalda_students_notes/data/repository/note_repository_impl.dart'; 4 | import 'package:yalda_students_notes/domain/model/note_model.dart'; 5 | 6 | part 'searchnote_event.dart'; 7 | part 'searchnote_state.dart'; 8 | 9 | class SearchNoteBloc extends Bloc { 10 | final NoteRepository _repository; 11 | 12 | SearchNoteBloc(this._repository) : super(SearchNoteInitial()) { 13 | on((event, emit) async { 14 | if (event is SearchNoteTextChange) { 15 | emit(SearchNoteLoading()); 16 | await _initialList(emit, event.expression); 17 | } else if (event is SearchNoteClearText) { 18 | emit(SearchNoteInitial()); 19 | } 20 | }); 21 | } 22 | 23 | Future _initialList( 24 | Emitter emit, String expression) async { 25 | try { 26 | final data = await _repository.getAllNotes(searchKeyword: expression); 27 | if (data.isEmpty) { 28 | emit(SearchNoteEmpty()); 29 | } else { 30 | emit(SearchNoteSuccess(data)); 31 | } 32 | } catch (e) { 33 | emit(SearchNoteError('Error')); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/presentation/screen/search/bloc/searchnote_event.dart: -------------------------------------------------------------------------------- 1 | part of 'searchnote_bloc.dart'; 2 | 3 | @immutable 4 | abstract class SearchNoteEvent {} 5 | 6 | class SearchNoteTextChange extends SearchNoteEvent { 7 | final String expression; 8 | 9 | SearchNoteTextChange(this.expression); 10 | } 11 | 12 | class SearchNoteClearText extends SearchNoteEvent {} 13 | -------------------------------------------------------------------------------- /lib/presentation/screen/search/bloc/searchnote_state.dart: -------------------------------------------------------------------------------- 1 | part of 'searchnote_bloc.dart'; 2 | 3 | @immutable 4 | abstract class SearchNoteState {} 5 | 6 | class SearchNoteInitial extends SearchNoteState {} 7 | 8 | class SearchNoteSuccess extends SearchNoteState { 9 | final List list; 10 | 11 | SearchNoteSuccess(this.list); 12 | } 13 | 14 | class SearchNoteEmpty extends SearchNoteState {} 15 | 16 | class SearchNoteError extends SearchNoteState { 17 | final String errorMessage; 18 | 19 | SearchNoteError(this.errorMessage); 20 | } 21 | 22 | class SearchNoteLoading extends SearchNoteState {} 23 | -------------------------------------------------------------------------------- /lib/presentation/screen/setting/setting_dialog.dart: -------------------------------------------------------------------------------- 1 | import 'package:easy_localization/easy_localization.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:iconsax/iconsax.dart'; 4 | import 'package:provider/provider.dart'; 5 | import 'package:yalda_students_notes/app/const.dart'; 6 | import 'package:yalda_students_notes/app/extensions.dart'; 7 | import 'package:yalda_students_notes/gen/translation/locale_keys.g.dart'; 8 | import 'package:yalda_students_notes/presentation/resources/color_manager.dart'; 9 | import 'package:yalda_students_notes/presentation/resources/font_manager.dart'; 10 | import 'package:yalda_students_notes/presentation/resources/language_manager.dart'; 11 | import 'package:yalda_students_notes/presentation/resources/value_manager.dart'; 12 | import 'package:yalda_students_notes/presentation/util/theme_util.dart'; 13 | import 'package:yalda_students_notes/presentation/widgets/language_radio_button.dart'; 14 | 15 | AlertDialog settingDialog(BuildContext context, ThemeData theme) { 16 | final themeNotifier = Provider.of(context); 17 | final _isDark = (themeNotifier.getTheme() == darkTheme); 18 | 19 | final appLanguage = 20 | EasyLocalization.of(context)!.currentLocale == const Locale('en', 'US'); 21 | return AlertDialog( 22 | title: Text(LocaleKeys.setting.tr(), 23 | style: TextStyle(fontSize: FontSize.alertDialogTitle(context))), 24 | content: SingleChildScrollView( 25 | child: Column( 26 | children: [ 27 | ListTile( 28 | onTap: () => showDialog( 29 | context: context, 30 | barrierDismissible: false, 31 | builder: (BuildContext context) => languageDialog(context, theme), 32 | ), 33 | title: Text( 34 | LocaleKeys.language.tr(), 35 | style: TextStyle(fontSize: FontSize.alertDialogContent(context)), 36 | ), 37 | trailing: Text( 38 | appLanguage ? languagesList[0] : languagesList[1], 39 | style: TextStyle( 40 | color: ColorManager.radioButtonColor, 41 | fontSize: FontSize.alertDialogContent(context)), 42 | ), 43 | ), 44 | ListTile( 45 | title: Text(LocaleKeys.theme.tr(), 46 | style: 47 | TextStyle(fontSize: FontSize.alertDialogContent(context))), 48 | trailing: Icon( 49 | _isDark ? Iconsax.moon5 : Iconsax.sun_15, 50 | color: _isDark ? Colors.white : Colors.amber, 51 | size: AppSize.iconSize(context), 52 | ), 53 | onTap: () => context.changeTheme(!_isDark, themeNotifier), 54 | ), 55 | SizedBox(height: context.screenHeight * 0.02), 56 | const Text( 57 | AppConstants.appVersion, 58 | style: TextStyle( 59 | fontSize: FontSize.s12, 60 | color: ColorManager.unselectedTabLabelDarkColor, 61 | ), 62 | ), 63 | ], 64 | ), 65 | ), 66 | ); 67 | } 68 | 69 | AlertDialog languageDialog(BuildContext context, ThemeData theme) { 70 | return AlertDialog( 71 | title: Text(LocaleKeys.language.tr()), 72 | content: const LanguageRadioButton(), 73 | actions: [ 74 | TextButton( 75 | child: Text( 76 | LocaleKeys.cancel.tr(), 77 | style: TextStyle(color: theme.colorScheme.secondary.withOpacity(0.7)), 78 | ), 79 | onPressed: () => Navigator.of(context).pop(), 80 | ), 81 | ], 82 | ); 83 | } 84 | -------------------------------------------------------------------------------- /lib/presentation/util/color_util.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:provider/provider.dart'; 3 | import 'package:yalda_students_notes/presentation/resources/color_manager.dart'; 4 | import 'package:yalda_students_notes/presentation/util/theme_util.dart'; 5 | 6 | Color getNoteColor(BuildContext context, int colorIndex) { 7 | final isDark = Provider.of(context, listen: false).isDark(); 8 | final noteColor = ColorManager.noteColors.elementAt(colorIndex); 9 | return isDark ? noteColor.darkColor : noteColor.lightColor; 10 | } 11 | -------------------------------------------------------------------------------- /lib/presentation/util/language_util.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:yalda_students_notes/app/global.dart'; 3 | 4 | class LanguageNotifier with ChangeNotifier { 5 | Locale locale; 6 | 7 | LanguageNotifier(this.locale); 8 | 9 | Locale getLocale() => locale; 10 | 11 | void setLocale(Locale newLocale) { 12 | locale = newLocale; 13 | appLocale = newLocale; 14 | notifyListeners(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lib/presentation/widgets/bottom_navigation.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:iconsax/iconsax.dart'; 3 | import 'package:yalda_students_notes/app/const.dart'; 4 | import 'package:yalda_students_notes/main.dart'; 5 | import 'package:yalda_students_notes/presentation/resources/color_manager.dart'; 6 | import 'package:yalda_students_notes/presentation/resources/value_manager.dart'; 7 | 8 | class CustomBottomNavigation extends StatelessWidget { 9 | final int selectedIndex; 10 | final Function(int index) onTap; 11 | 12 | const CustomBottomNavigation({ 13 | Key? key, 14 | required this.selectedIndex, 15 | required this.onTap, 16 | }) : super(key: key); 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | final theme = Theme.of(context); 21 | 22 | return Container( 23 | width: MediaQuery.of(context).size.width, 24 | height: AppConstants.bottomNavigationHeight, 25 | decoration: BoxDecoration( 26 | color: theme.colorScheme.onBackground, 27 | borderRadius: const BorderRadius.only( 28 | topRight: Radius.circular(18), 29 | topLeft: Radius.circular(18), 30 | ), 31 | ), 32 | child: Row( 33 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 34 | crossAxisAlignment: CrossAxisAlignment.center, 35 | children: [ 36 | BottomNavigationItem( 37 | icon: Iconsax.home, 38 | isActive: selectedIndex == homeIndex, 39 | onTap: () => onTap(homeIndex), 40 | ), 41 | BottomNavigationItem( 42 | icon: Iconsax.search_status, 43 | isActive: selectedIndex == searchIndex, 44 | onTap: () => onTap(searchIndex), 45 | ), 46 | BottomNavigationItem( 47 | icon: Iconsax.category_2, 48 | isActive: selectedIndex == categoryIndex, 49 | onTap: () => onTap(categoryIndex), 50 | ), 51 | BottomNavigationItem( 52 | icon: Iconsax.setting_2, 53 | isActive: selectedIndex == settingIndex, 54 | onTap: () => onTap(settingIndex), 55 | ), 56 | ], 57 | ), 58 | ); 59 | } 60 | } 61 | 62 | class BottomNavigationItem extends StatelessWidget { 63 | const BottomNavigationItem({ 64 | Key? key, 65 | required this.icon, 66 | required this.isActive, 67 | required this.onTap, 68 | }) : super(key: key); 69 | 70 | final IconData icon; 71 | final bool isActive; 72 | final Function() onTap; 73 | 74 | @override 75 | Widget build(BuildContext context) { 76 | final theme = Theme.of(context); 77 | return InkWell( 78 | onTap: onTap, 79 | child: Container( 80 | padding: const EdgeInsets.all(AppPadding.p16), 81 | child: Icon( 82 | icon, 83 | color: isActive ? ColorManager.activeColor : theme.dividerColor, 84 | ), 85 | ), 86 | ); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /lib/presentation/widgets/bottom_sheet.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:easy_localization/easy_localization.dart'; 4 | import 'package:yalda_students_notes/gen/translation/locale_keys.g.dart'; 5 | import 'package:yalda_students_notes/presentation/screen/category/bloc/category_bloc.dart'; 6 | import 'package:yalda_students_notes/presentation/widgets/loading_state.dart'; 7 | 8 | class CategoryBottomSheet extends StatelessWidget { 9 | const CategoryBottomSheet({Key? key}) : super(key: key); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | context.read().add(CategoryStart()); 14 | return BlocBuilder( 15 | builder: (context, state) { 16 | if (state is CategoryLoading || state is CategoryInitial) { 17 | return const LoadingState(); 18 | } else if (state is CategorySuccess) { 19 | return SizedBox( 20 | height: MediaQuery.of(context).size.height * 0.3, 21 | child: ListView.separated( 22 | itemCount: state.data.length + 1, 23 | physics: const BouncingScrollPhysics(), 24 | itemBuilder: (context, index) { 25 | if (index == 0) { 26 | return Padding( 27 | padding: const EdgeInsets.all(12.0), 28 | child: Align( 29 | alignment: Alignment.center, 30 | child: Text(LocaleKeys.select_category.tr(), 31 | style: const TextStyle( 32 | fontSize: 19, fontWeight: FontWeight.bold))), 33 | ); 34 | } else { 35 | final category = state.data[index - 1]; 36 | return GestureDetector( 37 | onTap: () { 38 | //send category back to EditNoteBloc 39 | Navigator.pop(context, 40 | '${category.id},${category.color},${category.title}'); 41 | }, 42 | child: Container( 43 | margin: const EdgeInsets.only(top: 12, left: 12), 44 | child: Text( 45 | category.title, 46 | style: const TextStyle(fontSize: 16), 47 | ), 48 | ), 49 | ); 50 | } 51 | }, 52 | separatorBuilder: (context, index) => 53 | index != 0 ? const Divider() : const SizedBox(), 54 | ), 55 | ); 56 | } else { 57 | return const Center( 58 | child: Text('Invalid state'), 59 | ); 60 | } 61 | }, 62 | ); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /lib/presentation/widgets/bouncing_spinner.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class BouncingSpinner extends StatefulWidget { 4 | final int length; 5 | final double radius; 6 | final Color color1; 7 | Color? color2; 8 | double? offset; 9 | Duration? duration; 10 | 11 | BouncingSpinner( 12 | {Key? key, 13 | required this.length, 14 | required this.radius, 15 | required this.color1, 16 | this.color2, 17 | this.offset, 18 | this.duration}) 19 | : super(key: key) { 20 | offset ??= radius / 2; 21 | color2 ??= color1; 22 | duration ??= const Duration(milliseconds: 1500); 23 | } 24 | 25 | @override 26 | State createState() => _BouncingSpinnerState(); 27 | } 28 | 29 | class _BouncingSpinnerState extends State 30 | with SingleTickerProviderStateMixin { 31 | late final Animation animation; 32 | late final AnimationController controller; 33 | 34 | @override 35 | void initState() { 36 | super.initState(); 37 | 38 | controller = AnimationController(vsync: this, duration: widget.duration); 39 | animation = Tween(begin: 0.4, end: 0.6).animate(controller) 40 | ..addListener(() => setState(() {})) 41 | ..addStatusListener((status) { 42 | if (status == AnimationStatus.dismissed) { 43 | controller.forward(); 44 | } else if (status == AnimationStatus.completed) { 45 | controller.reverse(); 46 | } 47 | }); 48 | controller.forward(); 49 | } 50 | 51 | @override 52 | void dispose() { 53 | controller.dispose(); 54 | super.dispose(); 55 | } 56 | 57 | @override 58 | Widget build(BuildContext context) { 59 | return Center( 60 | child: Container( 61 | alignment: Alignment.center, 62 | width: (widget.radius*0.6) * widget.length , 63 | child: Stack( 64 | alignment: Alignment.topCenter, 65 | children: List.generate(widget.length, (index) { 66 | final isEven = index % 2 == 0; 67 | final offset = widget.offset! * index; 68 | final color = isEven ? widget.color2 : widget.color1; 69 | final scale = 70 | isEven ? animation.value : (1 - animation.value as double); 71 | 72 | return Positioned( 73 | left: offset, 74 | top: 50, 75 | child: Transform.scale( 76 | scale: scale, 77 | child: Container( 78 | width: widget.radius, 79 | height: widget.radius, 80 | decoration: BoxDecoration( 81 | shape: BoxShape.circle, 82 | color: color, 83 | ), 84 | ), 85 | ), 86 | ); 87 | }), 88 | ), 89 | ), 90 | ); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /lib/presentation/widgets/category_dialog.dart: -------------------------------------------------------------------------------- 1 | import 'package:easy_localization/easy_localization.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:yalda_students_notes/gen/translation/locale_keys.g.dart'; 5 | import 'package:yalda_students_notes/presentation/screen/category/bloc/category_bloc.dart'; 6 | 7 | class CategoryDialog extends StatelessWidget { 8 | const CategoryDialog({ 9 | Key? key, 10 | required this.outlineInputBorder, 11 | }) : super(key: key); 12 | 13 | final OutlineInputBorder outlineInputBorder; 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | final theme = Theme.of(context); 18 | return ListBody( 19 | children: [ 20 | TextFormField( 21 | maxLength: 255, 22 | decoration: InputDecoration( 23 | hintText: LocaleKeys.title.tr(), 24 | filled: true, 25 | fillColor: theme.colorScheme.surface.withOpacity(0.1), 26 | enabledBorder: outlineInputBorder, 27 | focusedBorder: outlineInputBorder, 28 | contentPadding: const EdgeInsets.all(10.0)), 29 | onChanged: (value) { 30 | context.read().add(CategoryTextFieldChange(value)); 31 | }, 32 | ), 33 | ], 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/presentation/widgets/color_picker.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:provider/provider.dart'; 3 | import 'package:yalda_students_notes/presentation/resources/color_manager.dart'; 4 | import 'package:yalda_students_notes/presentation/resources/value_manager.dart'; 5 | import 'package:yalda_students_notes/presentation/util/theme_util.dart'; 6 | 7 | class ColorPicker extends StatelessWidget { 8 | final int selectedIndex; 9 | final Function(int) onTap; 10 | 11 | const ColorPicker( 12 | {Key? key, required this.onTap, required this.selectedIndex}) 13 | : super(key: key); 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return Container( 18 | height: 38, 19 | padding: const EdgeInsets.only(left: 6, right: 10), 20 | child: ListView.builder( 21 | physics: const BouncingScrollPhysics(), 22 | itemCount: ColorManager.noteColors.length, 23 | scrollDirection: Axis.horizontal, 24 | itemBuilder: (context, index) { 25 | final itemSize = AppSize.colorPickerIconSize(context); 26 | final themeNotifier = Provider.of(context); 27 | final _isDark = (themeNotifier.getTheme() == darkTheme); 28 | 29 | final color = ColorManager.noteColors[index]; 30 | 31 | return GestureDetector( 32 | onTap: () => onTap(index), 33 | child: Stack( 34 | clipBehavior: Clip.antiAlias, 35 | alignment: Alignment.center, 36 | children: [ 37 | Container( 38 | height: itemSize, 39 | width: itemSize, 40 | margin: const EdgeInsets.fromLTRB(6, 4, 0, 4), 41 | decoration: BoxDecoration( 42 | color: _isDark ? color.darkColor : color.lightColor, 43 | shape: BoxShape.circle, 44 | border: Border.all( 45 | color: Colors.grey.withOpacity(0.8), width: 1), 46 | ), 47 | ), 48 | selectedIndex == index 49 | ? Icon(Icons.check, 50 | size: AppSize.checkIconSize(context), 51 | color: _isDark 52 | ? Colors.white.withOpacity(0.8) 53 | : Colors.black.withOpacity(0.8)) 54 | : const SizedBox() 55 | ], 56 | ), 57 | ); 58 | }, 59 | ), 60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /lib/presentation/widgets/empty_state.dart: -------------------------------------------------------------------------------- 1 | import 'package:easy_localization/easy_localization.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:yalda_students_notes/gen/assets.gen.dart'; 4 | import 'package:yalda_students_notes/gen/translation/locale_keys.g.dart'; 5 | 6 | class EmptyState extends StatelessWidget { 7 | const EmptyState({ 8 | Key? key, 9 | }) : super(key: key); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return Expanded( 14 | child: Column( 15 | children: [ 16 | const SizedBox(height: 100), 17 | Assets.image.error404.image(width: 180, color: Theme.of(context).colorScheme.onSurface), 18 | Text( 19 | LocaleKeys.any_note.tr(), 20 | style: const TextStyle(fontStyle: FontStyle.italic, fontSize: 16), 21 | ) 22 | ], 23 | ), 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/presentation/widgets/invalid_state.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class InvalidState extends StatelessWidget { 4 | const InvalidState({Key? key}) : super(key: key); 5 | 6 | @override 7 | Widget build(BuildContext context) { 8 | return const Center( 9 | child: Text('Invalid State'), 10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/presentation/widgets/language_radio_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:easy_localization/easy_localization.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:yalda_students_notes/presentation/resources/language_manager.dart'; 4 | 5 | enum Language { english, persian } 6 | 7 | class LanguageRadioButton extends StatefulWidget { 8 | const LanguageRadioButton({Key? key}) : super(key: key); 9 | 10 | @override 11 | _LanguageRadioButtonState createState() => _LanguageRadioButtonState(); 12 | } 13 | 14 | class _LanguageRadioButtonState extends State 15 | with AppLanguage { 16 | @override 17 | Widget build(BuildContext context) { 18 | final appLanguage = 19 | EasyLocalization.of(context)!.currentLocale == const Locale('en', 'US') 20 | ? Language.english 21 | : Language.persian; 22 | 23 | return SingleChildScrollView( 24 | child: Column( 25 | children: [ 26 | ListTile( 27 | title: Text(languagesList[0]), 28 | leading: Radio( 29 | value: Language.english, 30 | groupValue: appLanguage, 31 | onChanged: (Language? value) => 32 | onLanguageChange(context, const Locale('en', 'US')), 33 | ), 34 | ), 35 | ListTile( 36 | title: Text(languagesList[1]), 37 | leading: Radio( 38 | value: Language.persian, 39 | groupValue: appLanguage, 40 | onChanged: (Language? value) => 41 | onLanguageChange(context, const Locale('fa', 'IR')), 42 | ), 43 | ), 44 | ], 45 | ), 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/presentation/widgets/loading_state.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:yalda_students_notes/presentation/resources/color_manager.dart'; 3 | import 'package:yalda_students_notes/presentation/widgets/bouncing_spinner.dart'; 4 | 5 | class LoadingState extends StatelessWidget { 6 | const LoadingState({Key? key}) : super(key: key); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return Center( 11 | child: SizedBox( 12 | height: 100, 13 | child: BouncingSpinner( 14 | length: 5, 15 | radius: 25, 16 | duration: const Duration(seconds: 1), 17 | color1: Theme.of(context).colorScheme.secondary, 18 | color2: ColorManager.radioButtonColor, 19 | ), 20 | )); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/presentation/widgets/note_category_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:detectable_text_field/detector/sample_regular_expressions.dart'; 2 | import 'package:detectable_text_field/widgets/detectable_text.dart'; 3 | import 'package:easy_localization/easy_localization.dart'; 4 | import 'package:expandable/expandable.dart'; 5 | import 'package:flutter/material.dart'; 6 | import 'package:flutter/services.dart'; 7 | import 'package:yalda_students_notes/domain/model/note_model.dart'; 8 | import 'package:yalda_students_notes/gen/translation/locale_keys.g.dart'; 9 | import 'package:yalda_students_notes/presentation/resources/color_manager.dart'; 10 | import 'package:yalda_students_notes/presentation/resources/font_manager.dart'; 11 | import 'package:yalda_students_notes/presentation/resources/value_manager.dart'; 12 | import 'package:yalda_students_notes/presentation/util/color_util.dart'; 13 | import 'package:yalda_students_notes/presentation/widgets/top_snackbar/custom_snack_bar.dart'; 14 | import 'package:yalda_students_notes/presentation/widgets/top_snackbar/top_snack_bar.dart'; 15 | 16 | class NoteCategoryItem extends StatelessWidget { 17 | final NoteModel note; 18 | 19 | const NoteCategoryItem({ 20 | Key? key, 21 | required this.note, 22 | }) : super(key: key); 23 | 24 | @override 25 | Widget build(BuildContext context) { 26 | final theme = Theme.of(context); 27 | 28 | final noteColor = getNoteColor(context, note.colorIndex); 29 | 30 | return Container( 31 | width: 170, 32 | padding: const EdgeInsets.all(AppPadding.p16), 33 | decoration: BoxDecoration( 34 | color: noteColor, borderRadius: BorderRadius.circular(AppSize.s15)), 35 | child: ExpandablePanel( 36 | theme: ExpandableThemeData(iconColor: theme.colorScheme.onSurface), 37 | header: Text( 38 | note.title, 39 | style: TextStyle( 40 | overflow: TextOverflow.ellipsis, 41 | fontWeight: FontWeight.w800, 42 | fontSize: FontSize.s19, 43 | color: theme.colorScheme.onSurface), 44 | ), 45 | collapsed: Text( 46 | note.content, 47 | maxLines: 1, 48 | overflow: TextOverflow.ellipsis, 49 | style: TextStyle( 50 | fontWeight: FontWeight.normal, 51 | fontSize: FontSize.s15, 52 | color: theme.colorScheme.onSurface), 53 | ), 54 | expanded: DetectableText( 55 | text: note.content, 56 | softWrap: true, 57 | detectionRegExp: detectionRegExp(atSign: false, hashtag: false)!, 58 | basicStyle: TextStyle( 59 | fontWeight: FontWeight.w500, 60 | fontSize: FontSize.s16, 61 | color: theme.colorScheme.onSurface), 62 | onTap: (text) async { 63 | await Clipboard.setData(ClipboardData(text: text)); 64 | showTopSnackBar( 65 | context, CustomSnackBar.info(message: LocaleKeys.copy.tr())); 66 | }, 67 | detectedStyle: const TextStyle( 68 | decoration: TextDecoration.underline, 69 | fontWeight: FontWeight.w500, 70 | fontSize: FontSize.s16, 71 | color: ColorManager.radioButtonColor), 72 | ), 73 | ), 74 | ); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /lib/presentation/widgets/note_grid.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:responsive_framework/responsive_framework.dart'; 3 | import 'package:yalda_students_notes/domain/model/note_model.dart'; 4 | import 'package:yalda_students_notes/presentation/resources/value_manager.dart'; 5 | import 'package:yalda_students_notes/presentation/widgets/note_grid_item.dart'; 6 | import 'package:yalda_students_notes/presentation/widgets/note_item.dart'; 7 | 8 | class NoteGrid extends StatelessWidget { 9 | final List data; 10 | 11 | const NoteGrid({Key? key, required this.data}) : super(key: key); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return Expanded( 16 | child: ResponsiveGridView.builder( 17 | itemCount: data.length, 18 | physics: const BouncingScrollPhysics(), 19 | padding: const EdgeInsets.fromLTRB(16, 8, 16, 8), 20 | gridDelegate: const ResponsiveGridDelegate( 21 | maxCrossAxisExtent: 160, 22 | crossAxisSpacing: ValueManager.gridSpacing, 23 | mainAxisSpacing: ValueManager.gridSpacing), 24 | itemBuilder: (context, index) => NoteItem( 25 | noteItem: NoteGridItem(data: data[index]), 26 | data: data[index], 27 | ), 28 | )); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/presentation/widgets/note_grid_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:iconsax/iconsax.dart'; 3 | import 'package:yalda_students_notes/app/app_prefs.dart'; 4 | import 'package:yalda_students_notes/app/di.dart'; 5 | import 'package:yalda_students_notes/app/extensions.dart'; 6 | import 'package:yalda_students_notes/domain/model/note_model.dart'; 7 | import 'package:yalda_students_notes/presentation/resources/style_manager.dart'; 8 | import 'package:yalda_students_notes/presentation/resources/value_manager.dart'; 9 | import 'package:yalda_students_notes/presentation/util/color_util.dart'; 10 | 11 | class NoteGridItem extends StatelessWidget { 12 | final NoteModel data; 13 | 14 | const NoteGridItem({Key? key, required this.data}) : super(key: key); 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | final theme = Theme.of(context); 19 | final appPref = instance(); 20 | 21 | return Container( 22 | padding: const EdgeInsets.all(AppPadding.p12), 23 | decoration: BoxDecoration( 24 | color: getNoteColor(context, data.colorIndex), 25 | borderRadius: BorderRadius.circular(15), 26 | ), 27 | child: FutureBuilder( 28 | future: appPref.getLanguage(), 29 | initialData: const Locale('en', 'US').languageCode, 30 | builder: (context, snapshot) { 31 | return Align( 32 | alignment: snapshot.data!.isLanguageRtl() 33 | ? Alignment.topRight 34 | : Alignment.topLeft, 35 | child: Column( 36 | crossAxisAlignment: CrossAxisAlignment.stretch, 37 | children: [ 38 | Text(data.title, 39 | style: StyleManager.noteTitleTextStyle(theme), 40 | textAlign: TextAlign.start), 41 | const SizedBox(height: AppSize.s12), 42 | Expanded( 43 | child: Text( 44 | data.content, 45 | maxLines: 3, 46 | overflow: TextOverflow.fade, 47 | textAlign: TextAlign.start, 48 | style: StyleManager.noteContentTextStyle(theme), 49 | ), 50 | ), 51 | Row( 52 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 53 | children: [ 54 | Text(data.category, 55 | style: StyleManager.noteCategoryTextStyle(theme)), 56 | if (data.isFavorite) 57 | Align( 58 | alignment: Alignment.bottomRight, 59 | child: Icon(Iconsax.heart5, 60 | color: theme.errorColor, size: AppSize.s16), 61 | ) 62 | ], 63 | ), 64 | ], 65 | ), 66 | ); 67 | }), 68 | ); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /lib/presentation/widgets/note_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:animations/animations.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:yalda_students_notes/app/const.dart'; 5 | import 'package:yalda_students_notes/data/datasource/database.dart'; 6 | import 'package:yalda_students_notes/data/repository/note_repository_impl.dart'; 7 | import 'package:yalda_students_notes/domain/model/note_model.dart'; 8 | import 'package:yalda_students_notes/presentation/screen/edit_note/bloc/editnote_bloc.dart'; 9 | import 'package:yalda_students_notes/presentation/screen/edit_note/edit_note_screen.dart'; 10 | import 'package:yalda_students_notes/presentation/screen/note/bloc/notelist_bloc.dart'; 11 | 12 | class NoteItem extends StatelessWidget { 13 | const NoteItem({Key? key, required this.noteItem, required this.data}) 14 | : super(key: key); 15 | 16 | final NoteModel data; 17 | final Widget noteItem; 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return OpenContainer( 22 | tappable: true, 23 | closedElevation: 0, 24 | openElevation: 0, 25 | clipBehavior: Clip.antiAliasWithSaveLayer, 26 | closedColor: Theme.of(context).scaffoldBackgroundColor, 27 | transitionType: ContainerTransitionType.fade, 28 | closedShape: 29 | RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)), 30 | transitionDuration: 31 | const Duration(milliseconds: AppConstants.openAnimationDuration), 32 | openBuilder: (context, openContainer) { 33 | return BlocProvider( 34 | create: (context) => 35 | EditNoteBloc(NoteRepository(context.read()), data), 36 | child: const EditNoteScreen(), 37 | ); 38 | }, 39 | closedBuilder: (context, openContainer) { 40 | return InkWell( 41 | child: noteItem, 42 | onTap: () => openContainer.call(), 43 | onDoubleTap: () => starNote(context), 44 | ); 45 | }, 46 | ); 47 | } 48 | 49 | void starNote(BuildContext context) { 50 | final note = data; 51 | context.read().add( 52 | NoteListStar( 53 | NoteModel( 54 | id: note.id, 55 | title: note.title, 56 | content: note.content, 57 | createdAt: note.createdAt, 58 | colorIndex: note.colorIndex, 59 | isFavorite: !note.isFavorite, 60 | categoryId: note.categoryId), 61 | ), 62 | ); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /lib/presentation/widgets/note_list.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:yalda_students_notes/domain/model/note_model.dart'; 3 | import 'package:yalda_students_notes/presentation/widgets/note_item.dart'; 4 | import 'package:yalda_students_notes/presentation/widgets/note_list_item.dart'; 5 | 6 | class NoteList extends StatelessWidget { 7 | final List data; 8 | const NoteList({Key? key, required this.data}) : super(key: key); 9 | 10 | @override 11 | Widget build(BuildContext context) { 12 | return Expanded( 13 | child: ListView.builder( 14 | itemCount: data.length, 15 | physics: const BouncingScrollPhysics(), 16 | itemBuilder: (context, index) { 17 | return NoteItem( 18 | noteItem: NoteListItem(data: data[index]), 19 | data: data[index], 20 | ); 21 | }, 22 | ), 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/presentation/widgets/note_list_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:easy_localization/easy_localization.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:iconsax/iconsax.dart'; 4 | import 'package:yalda_students_notes/app/functions.dart'; 5 | import 'package:yalda_students_notes/domain/model/note_model.dart'; 6 | import 'package:yalda_students_notes/presentation/resources/font_manager.dart'; 7 | import 'package:yalda_students_notes/presentation/resources/style_manager.dart'; 8 | import 'package:yalda_students_notes/presentation/resources/value_manager.dart'; 9 | import 'package:yalda_students_notes/presentation/util/color_util.dart'; 10 | 11 | class NoteListItem extends StatelessWidget { 12 | const NoteListItem({Key? key, required this.data}) : super(key: key); 13 | 14 | final NoteModel data; 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | final theme = Theme.of(context); 19 | 20 | String date; 21 | if (EasyLocalization.of(context)!.currentLocale != 22 | const Locale('en', 'US')) { 23 | date = convertToJalaliDate(data.createdAt); 24 | } else { 25 | date = DateFormat('dd/MM/yyyy').format(data.createdAt); 26 | } 27 | 28 | return Container( 29 | height: 100, 30 | margin: const EdgeInsets.fromLTRB(2, 12, 2, 0), 31 | padding: const EdgeInsets.all(AppPadding.p12), 32 | decoration: BoxDecoration( 33 | color: getNoteColor(context, data.colorIndex), 34 | borderRadius: BorderRadius.circular(15), 35 | ), 36 | child: Padding( 37 | padding: 38 | const EdgeInsets.only(left: AppPadding.p8, right: AppPadding.p8), 39 | child: Column( 40 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 41 | crossAxisAlignment: CrossAxisAlignment.start, 42 | children: [ 43 | Row( 44 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 45 | crossAxisAlignment: CrossAxisAlignment.start, 46 | children: [ 47 | Expanded( 48 | child: Text(data.title, 49 | maxLines: 1, 50 | style: StyleManager.noteTitleTextStyle(theme)), 51 | ), 52 | if (data.isFavorite) 53 | Icon(Iconsax.heart5, 54 | color: theme.errorColor, size: AppSize.s20) 55 | ], 56 | ), 57 | Row( 58 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 59 | children: [ 60 | Text( 61 | data.category, 62 | style: TextStyle( 63 | fontWeight: FontWeight.normal, 64 | fontSize: FontSize.s13, 65 | color: theme.colorScheme.onSurface), 66 | ), 67 | Text( 68 | date, 69 | textAlign: TextAlign.start, 70 | style: TextStyle( 71 | fontWeight: FontWeight.normal, 72 | fontSize: FontSize.s13, 73 | color: theme.colorScheme.onSurface), 74 | ), 75 | ], 76 | ) 77 | ], 78 | ), 79 | ), 80 | ); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /lib/presentation/widgets/pop_menu_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:yalda_students_notes/presentation/resources/font_manager.dart'; 3 | import 'package:yalda_students_notes/presentation/resources/value_manager.dart'; 4 | 5 | class AppPopupMenuItem extends StatelessWidget { 6 | final IconData icon; 7 | final String title; 8 | 9 | const AppPopupMenuItem({Key? key, required this.title, required this.icon}) 10 | : super(key: key); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return Row( 15 | children: [ 16 | const SizedBox(width: AppSize.s6), 17 | Icon(icon, color: Colors.black, size: AppSize.s20), 18 | const SizedBox(width: AppSize.s6), 19 | Text(title, 20 | style: 21 | const TextStyle(color: Colors.black, fontSize: FontSize.s13)), 22 | ], 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/presentation/widgets/top_snackbar/safe_area_values.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | class SafeAreaValues { 4 | const SafeAreaValues({ 5 | this.left = true, 6 | this.right = true, 7 | this.top = true, 8 | this.bottom = true, 9 | this.minimum = EdgeInsets.zero, 10 | this.maintainBottomViewPadding = false, 11 | }); 12 | 13 | final bool left; 14 | final bool top; 15 | final bool right; 16 | final bool bottom; 17 | final EdgeInsets minimum; 18 | final bool maintainBottomViewPadding; 19 | } 20 | -------------------------------------------------------------------------------- /lib/presentation/widgets/top_snackbar/tap_bounce_container.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class TapBounceContainer extends StatefulWidget { 4 | final Widget child; 5 | final VoidCallback? onTap; 6 | 7 | const TapBounceContainer({ 8 | Key? key, 9 | required this.child, 10 | this.onTap, 11 | }) : super(key: key); 12 | 13 | @override 14 | _TapBounceContainerState createState() => _TapBounceContainerState(); 15 | } 16 | 17 | class _TapBounceContainerState extends State 18 | with SingleTickerProviderStateMixin { 19 | late double _scale; 20 | late AnimationController _controller; 21 | 22 | final animationDuration = Duration(milliseconds: 200); 23 | 24 | @override 25 | void initState() { 26 | _controller = AnimationController( 27 | vsync: this, 28 | duration: animationDuration, 29 | lowerBound: 0.0, 30 | upperBound: 0.04, 31 | )..addListener(() { 32 | if (mounted) { 33 | setState(() {}); 34 | } 35 | }); 36 | super.initState(); 37 | } 38 | 39 | @override 40 | void dispose() { 41 | _controller.dispose(); 42 | super.dispose(); 43 | } 44 | 45 | @override 46 | Widget build(BuildContext context) { 47 | _scale = 1 - _controller.value; 48 | 49 | return GestureDetector( 50 | onTapDown: _onTapDown, 51 | onTapUp: _onTapUp, 52 | onPanEnd: _onPanEnd, 53 | child: Transform.scale( 54 | scale: _scale, 55 | child: widget.child, 56 | ), 57 | ); 58 | } 59 | 60 | void _onTapDown(TapDownDetails details) { 61 | if (mounted) { 62 | _controller.forward(); 63 | } 64 | } 65 | 66 | void _onTapUp(TapUpDetails details) async { 67 | await _closeSnackBar(); 68 | } 69 | 70 | void _onPanEnd(DragEndDetails details) async { 71 | await _closeSnackBar(); 72 | } 73 | 74 | Future _closeSnackBar() async { 75 | if (mounted) { 76 | _controller.reverse(); 77 | await Future.delayed(animationDuration); 78 | widget.onTap?.call(); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /linux/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral 2 | -------------------------------------------------------------------------------- /linux/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 4 | 5 | # Configuration provided via flutter tool. 6 | include(${EPHEMERAL_DIR}/generated_config.cmake) 7 | 8 | # TODO: Move the rest of this into files in ephemeral. See 9 | # https://github.com/flutter/flutter/issues/57146. 10 | 11 | # Serves the same purpose as list(TRANSFORM ... PREPEND ...), 12 | # which isn't available in 3.10. 13 | function(list_prepend LIST_NAME PREFIX) 14 | set(NEW_LIST "") 15 | foreach(element ${${LIST_NAME}}) 16 | list(APPEND NEW_LIST "${PREFIX}${element}") 17 | endforeach(element) 18 | set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) 19 | endfunction() 20 | 21 | # === Flutter Library === 22 | # System-level dependencies. 23 | find_package(PkgConfig REQUIRED) 24 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 25 | pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) 26 | pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) 27 | 28 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") 29 | 30 | # Published to parent scope for install step. 31 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 32 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 33 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 34 | set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) 35 | 36 | list(APPEND FLUTTER_LIBRARY_HEADERS 37 | "fl_basic_message_channel.h" 38 | "fl_binary_codec.h" 39 | "fl_binary_messenger.h" 40 | "fl_dart_project.h" 41 | "fl_engine.h" 42 | "fl_json_message_codec.h" 43 | "fl_json_method_codec.h" 44 | "fl_message_codec.h" 45 | "fl_method_call.h" 46 | "fl_method_channel.h" 47 | "fl_method_codec.h" 48 | "fl_method_response.h" 49 | "fl_plugin_registrar.h" 50 | "fl_plugin_registry.h" 51 | "fl_standard_message_codec.h" 52 | "fl_standard_method_codec.h" 53 | "fl_string_codec.h" 54 | "fl_value.h" 55 | "fl_view.h" 56 | "flutter_linux.h" 57 | ) 58 | list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") 59 | add_library(flutter INTERFACE) 60 | target_include_directories(flutter INTERFACE 61 | "${EPHEMERAL_DIR}" 62 | ) 63 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") 64 | target_link_libraries(flutter INTERFACE 65 | PkgConfig::GTK 66 | PkgConfig::GLIB 67 | PkgConfig::GIO 68 | ) 69 | add_dependencies(flutter flutter_assemble) 70 | 71 | # === Flutter tool backend === 72 | # _phony_ is a non-existent file to force this command to run every time, 73 | # since currently there's no way to get a full input/output list from the 74 | # flutter tool. 75 | add_custom_command( 76 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 77 | ${CMAKE_CURRENT_BINARY_DIR}/_phony_ 78 | COMMAND ${CMAKE_COMMAND} -E env 79 | ${FLUTTER_TOOL_ENVIRONMENT} 80 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" 81 | ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} 82 | VERBATIM 83 | ) 84 | add_custom_target(flutter_assemble DEPENDS 85 | "${FLUTTER_LIBRARY}" 86 | ${FLUTTER_LIBRARY_HEADERS} 87 | ) 88 | -------------------------------------------------------------------------------- /linux/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | void fl_register_plugins(FlPluginRegistry* registry) { 14 | g_autoptr(FlPluginRegistrar) flutter_platform_alert_registrar = 15 | fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterPlatformAlertPlugin"); 16 | flutter_platform_alert_plugin_register_with_registrar(flutter_platform_alert_registrar); 17 | g_autoptr(FlPluginRegistrar) sqlite3_flutter_libs_registrar = 18 | fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin"); 19 | sqlite3_flutter_libs_plugin_register_with_registrar(sqlite3_flutter_libs_registrar); 20 | g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = 21 | fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); 22 | url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); 23 | } 24 | -------------------------------------------------------------------------------- /linux/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void fl_register_plugins(FlPluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /linux/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | flutter_platform_alert 7 | sqlite3_flutter_libs 8 | url_launcher_linux 9 | ) 10 | 11 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 12 | ) 13 | 14 | set(PLUGIN_BUNDLED_LIBRARIES) 15 | 16 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 17 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) 18 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 19 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 20 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 21 | endforeach(plugin) 22 | 23 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 24 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) 25 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 26 | endforeach(ffi_plugin) 27 | -------------------------------------------------------------------------------- /linux/main.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | int main(int argc, char** argv) { 4 | g_autoptr(MyApplication) app = my_application_new(); 5 | return g_application_run(G_APPLICATION(app), argc, argv); 6 | } 7 | -------------------------------------------------------------------------------- /linux/my_application.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUTTER_MY_APPLICATION_H_ 2 | #define FLUTTER_MY_APPLICATION_H_ 3 | 4 | #include 5 | 6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, 7 | GtkApplication) 8 | 9 | /** 10 | * my_application_new: 11 | * 12 | * Creates a new Flutter-based application. 13 | * 14 | * Returns: a new #MyApplication. 15 | */ 16 | MyApplication* my_application_new(); 17 | 18 | #endif // FLUTTER_MY_APPLICATION_H_ 19 | -------------------------------------------------------------------------------- /macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | import flutter_platform_alert 9 | import path_provider_foundation 10 | import share_plus 11 | import shared_preferences_foundation 12 | import sqlite3_flutter_libs 13 | import url_launcher_macos 14 | 15 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 16 | FlutterPlatformAlertPlugin.register(with: registry.registrar(forPlugin: "FlutterPlatformAlertPlugin")) 17 | PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) 18 | SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) 19 | SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) 20 | Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) 21 | UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) 22 | } 23 | -------------------------------------------------------------------------------- /macos/Flutter/ephemeral/Flutter-Generated.xcconfig: -------------------------------------------------------------------------------- 1 | // This is a generated file; do not edit or check into version control. 2 | FLUTTER_ROOT=/Users/yalda/Flutter/flutter 3 | FLUTTER_APPLICATION_PATH=/Users/yalda/StudioProjects/note_to_remember 4 | COCOAPODS_PARALLEL_CODE_SIGN=true 5 | FLUTTER_BUILD_DIR=build 6 | FLUTTER_BUILD_NAME=1.0.0 7 | FLUTTER_BUILD_NUMBER=1 8 | DART_OBFUSCATION=false 9 | TRACK_WIDGET_CREATION=true 10 | TREE_SHAKE_ICONS=false 11 | PACKAGE_CONFIG=.dart_tool/package_config.json 12 | -------------------------------------------------------------------------------- /macos/Flutter/ephemeral/flutter_export_environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This is a generated file; do not edit or check into version control. 3 | export "FLUTTER_ROOT=/Users/yalda/Flutter/flutter" 4 | export "FLUTTER_APPLICATION_PATH=/Users/yalda/StudioProjects/note_to_remember" 5 | export "COCOAPODS_PARALLEL_CODE_SIGN=true" 6 | export "FLUTTER_BUILD_DIR=build" 7 | export "FLUTTER_BUILD_NAME=1.0.0" 8 | export "FLUTTER_BUILD_NUMBER=1" 9 | export "DART_OBFUSCATION=false" 10 | export "TRACK_WIDGET_CREATION=true" 11 | export "TREE_SHAKE_ICONS=false" 12 | export "PACKAGE_CONFIG=.dart_tool/package_config.json" 13 | -------------------------------------------------------------------------------- /macos/Podfile: -------------------------------------------------------------------------------- 1 | platform :osx, '10.14' 2 | 3 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 4 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 5 | 6 | project 'Runner', { 7 | 'Debug' => :debug, 8 | 'Profile' => :release, 9 | 'Release' => :release, 10 | } 11 | 12 | def flutter_root 13 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) 14 | unless File.exist?(generated_xcode_build_settings_path) 15 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" 16 | end 17 | 18 | File.foreach(generated_xcode_build_settings_path) do |line| 19 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 20 | return matches[1].strip if matches 21 | end 22 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" 23 | end 24 | 25 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 26 | 27 | flutter_macos_podfile_setup 28 | 29 | target 'Runner' do 30 | use_frameworks! 31 | use_modular_headers! 32 | 33 | flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) 34 | target 'RunnerTests' do 35 | inherit! :search_paths 36 | end 37 | end 38 | 39 | post_install do |installer| 40 | installer.pods_project.targets.each do |target| 41 | flutter_additional_macos_build_settings(target) 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @NSApplicationMain 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = student_note 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.studentNote 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2022 com.example. All rights reserved. 15 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController.init() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /pictures/dark_note_list.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/pictures/dark_note_list.jpg -------------------------------------------------------------------------------- /pictures/dark_persian_note_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/pictures/dark_persian_note_list.png -------------------------------------------------------------------------------- /pictures/dark_search.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/pictures/dark_search.jpg -------------------------------------------------------------------------------- /pictures/desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/pictures/desktop.jpg -------------------------------------------------------------------------------- /pictures/desktop_dark.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/pictures/desktop_dark.jpg -------------------------------------------------------------------------------- /pictures/light_categories.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/pictures/light_categories.jpg -------------------------------------------------------------------------------- /pictures/light_favorite.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/pictures/light_favorite.jpg -------------------------------------------------------------------------------- /pictures/light_note_list.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/pictures/light_note_list.jpg -------------------------------------------------------------------------------- /pictures/light_note_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/pictures/light_note_list.png -------------------------------------------------------------------------------- /pictures/light_search_404.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/pictures/light_search_404.jpg -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: yalda_students_notes 2 | description: A new Flutter project. 3 | 4 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 5 | 6 | version: 1.0.0+1 7 | 8 | environment: 9 | sdk: '>=2.19.6 <3.0.0' 10 | 11 | dependencies: 12 | flutter: 13 | sdk: flutter 14 | 15 | flutter_localizations: # Add this line 16 | sdk: flutter 17 | 18 | cupertino_icons: ^1.0.2 19 | flutter_svg: ^2.0.9 20 | iconsax: ^0.0.8 21 | google_fonts: ^2.2.0 22 | provider: ^6.0.2 23 | theme_provider: ^0.5.0 24 | flutter_bloc: ^8.0.1 25 | intl: ^0.18.0 26 | 27 | drift: ^1.6.0 28 | http: ^0.13.4 # used to load sqlite3 wasm files on the web 29 | sqlite3_flutter_libs: ^0.5.5 30 | sqlite3: ^1.7.0 31 | path_provider: ^2.0.9 32 | path: ^1.8.0 33 | 34 | day_night_switcher: ^0.2.0+1 35 | shared_preferences: ^2.0.12 36 | equatable: ^2.0.3 37 | easy_localization: ^3.0.1 38 | toggle_switch: ^2.0.1 39 | expandable: ^5.0.1 40 | modal_bottom_sheet: ^2.0.1 41 | contained_tab_bar_view: ^0.8.0 42 | flutter_feather_icons: ^2.0.0+1 43 | url_launcher: ^6.0.20 44 | introduction_screen: ^3.0.2 45 | dropdown_button2: ^1.9.4 46 | flag: ^7.0.0 47 | 48 | universal_platform: ^1.0.0-nullsafety 49 | responsive_framework: ^0.1.7 50 | animations: ^2.0.2 51 | flutter_staggered_grid_view: ^0.6.1 52 | flutter_platform_alert: ^0.2.6 53 | get_it: ^7.2.0 54 | shamsi_date: ^1.0.1 55 | auto_direction: ^0.0.7 56 | flutter_social_textfield: ^0.1.0 57 | detectable_text_field: ^3.0.2 58 | share_plus: ^7.2.1 59 | 60 | dev_dependencies: 61 | flutter_test: 62 | sdk: flutter 63 | flutter_gen_runner: 4.1.6 64 | drift_dev: ^1.4.0 65 | build_runner: ^2.1.11 66 | flutter_launcher_icons: ^0.9.2 67 | build_web_compilers: ^3.2.1 68 | flutter_lints: ^1.0.4 69 | 70 | dependency_overrides: 71 | js: ^0.6.4 # temporarily added because sqlite3 depends on this, and flutter hasn't caught up yet. 72 | # drift: 73 | # path: ../../drift 74 | # drift_dev: 75 | # path: ../../drift_dev 76 | # sqlparser: 77 | # path: ../../sqlparser 78 | 79 | flutter_lints: ^1.0.0 80 | 81 | flutter_icons: 82 | android: "launcher_icon" 83 | ios: true 84 | image_path_ios: "asset/icon/icon.png" 85 | image_path_android: "asset/icon/icon.png" 86 | 87 | flutter: 88 | 89 | uses-material-design: true 90 | generate: true 91 | 92 | assets: 93 | - asset/image/ 94 | - asset/icon/ 95 | - asset/translation/ 96 | 97 | fonts: 98 | - family: ic_font 99 | fonts: 100 | - asset: asset/fonts/ic_font.ttf 101 | - family: IRANMarker 102 | fonts: 103 | - asset: asset/fonts/IRANMarker.ttf -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child presentation.widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:yalda_students_notes/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(const MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/web/favicon.png -------------------------------------------------------------------------------- /web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/web/icons/Icon-192.png -------------------------------------------------------------------------------- /web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/web/icons/Icon-512.png -------------------------------------------------------------------------------- /web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "short_name": "app", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /web/sql-wasm.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/web/sql-wasm.wasm -------------------------------------------------------------------------------- /web/sqlite3.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/web/sqlite3.wasm -------------------------------------------------------------------------------- /web/worker.dart: -------------------------------------------------------------------------------- 1 | // ignore: avoid_web_libraries_in_flutter 2 | import 'dart:html'; 3 | 4 | import 'package:yalda_students_notes/data/datasource/connection/web.dart'; 5 | import 'package:drift/web.dart'; 6 | import 'package:drift/remote.dart'; 7 | 8 | void main() { 9 | final self = SharedWorkerGlobalScope.instance; 10 | final server = DriftServer(connect(isInWebWorker: true)); 11 | 12 | self.onConnect.listen((event) { 13 | final msg = event as MessageEvent; 14 | server.serve(msg.ports.first.channel()); 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /web/worker.dart.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var _currentDirectory = (function () { 3 | var _url; 4 | var lines = new Error().stack.split('\n'); 5 | function lookupUrl() { 6 | if (lines.length > 2) { 7 | var match = lines[1].match(/^\s+at (.+):\d+:\d+$/); 8 | // Chrome. 9 | if (match) return match[1]; 10 | // Chrome nested eval case. 11 | match = lines[1].match(/^\s+at eval [(](.+):\d+:\d+[)]$/); 12 | if (match) return match[1]; 13 | // Edge. 14 | match = lines[1].match(/^\s+at.+\((.+):\d+:\d+\)$/); 15 | if (match) return match[1]; 16 | // Firefox. 17 | match = lines[0].match(/[<][@](.+):\d+:\d+$/) 18 | if (match) return match[1]; 19 | } 20 | // Safari. 21 | return lines[0].match(/(.+):\d+:\d+$/)[1]; 22 | } 23 | _url = lookupUrl(); 24 | var lastSlash = _url.lastIndexOf('/'); 25 | if (lastSlash == -1) return _url; 26 | var currentDirectory = _url.substring(0, lastSlash + 1); 27 | return currentDirectory; 28 | })(); 29 | 30 | var baseUrl = (function () { 31 | // Attempt to detect --precompiled mode for tests, and set the base url 32 | // appropriately, otherwise set it to '/'. 33 | var pathParts = location.pathname.split("/"); 34 | if (pathParts[0] == "") { 35 | pathParts.shift(); 36 | } 37 | if (pathParts.length > 1 && pathParts[1] == "test") { 38 | return "/" + pathParts.slice(0, 2).join("/") + "/"; 39 | } 40 | // Attempt to detect base url using html tag 41 | // base href should start and end with "/" 42 | if (typeof document !== 'undefined') { 43 | var el = document.getElementsByTagName('base'); 44 | if (el && el[0] && el[0].getAttribute("href") && el[0].getAttribute 45 | ("href").startsWith("/") && el[0].getAttribute("href").endsWith("/")){ 46 | return el[0].getAttribute("href"); 47 | } 48 | } 49 | // return default value 50 | return "/"; 51 | }()); 52 | 53 | 54 | var mapperUri = baseUrl + "packages/build_web_compilers/src/" + 55 | "dev_compiler_stack_trace/stack_trace_mapper.dart.js"; 56 | var requireUri = baseUrl + 57 | "packages/build_web_compilers/src/dev_compiler/require.js"; 58 | var mainUri = _currentDirectory + "worker.dart.bootstrap"; 59 | 60 | if (typeof document != 'undefined') { 61 | var el = document.createElement("script"); 62 | el.defer = true; 63 | el.async = false; 64 | el.src = mapperUri; 65 | document.head.appendChild(el); 66 | 67 | el = document.createElement("script"); 68 | el.defer = true; 69 | el.async = false; 70 | el.src = requireUri; 71 | el.setAttribute("data-main", mainUri); 72 | document.head.appendChild(el); 73 | } else { 74 | importScripts(mapperUri, requireUri); 75 | require.config({ 76 | baseUrl: baseUrl, 77 | }); 78 | // TODO: update bootstrap code to take argument - dart-lang/build#1115 79 | window = self; 80 | require([mainUri + '.js']); 81 | } 82 | })(); 83 | -------------------------------------------------------------------------------- /windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | void RegisterPlugins(flutter::PluginRegistry* registry) { 15 | FlutterPlatformAlertPluginRegisterWithRegistrar( 16 | registry->GetRegistrarForPlugin("FlutterPlatformAlertPlugin")); 17 | SharePlusWindowsPluginCApiRegisterWithRegistrar( 18 | registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); 19 | Sqlite3FlutterLibsPluginRegisterWithRegistrar( 20 | registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin")); 21 | UrlLauncherWindowsRegisterWithRegistrar( 22 | registry->GetRegistrarForPlugin("UrlLauncherWindows")); 23 | } 24 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void RegisterPlugins(flutter::PluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | flutter_platform_alert 7 | share_plus 8 | sqlite3_flutter_libs 9 | url_launcher_windows 10 | ) 11 | 12 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 13 | ) 14 | 15 | set(PLUGIN_BUNDLED_LIBRARIES) 16 | 17 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 18 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) 19 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 20 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 21 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 22 | endforeach(plugin) 23 | 24 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 25 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) 26 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 27 | endforeach(ffi_plugin) 28 | -------------------------------------------------------------------------------- /windows/runner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | project(runner LANGUAGES CXX) 3 | 4 | add_executable(${BINARY_NAME} WIN32 5 | "flutter_window.cpp" 6 | "main.cpp" 7 | "utils.cpp" 8 | "win32_window.cpp" 9 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 10 | "Runner.rc" 11 | "runner.exe.manifest" 12 | ) 13 | apply_standard_settings(${BINARY_NAME}) 14 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") 15 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) 16 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") 17 | add_dependencies(${BINARY_NAME} flutter_assemble) 18 | -------------------------------------------------------------------------------- /windows/runner/Runner.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #pragma code_page(65001) 4 | #include "resource.h" 5 | 6 | #define APSTUDIO_READONLY_SYMBOLS 7 | ///////////////////////////////////////////////////////////////////////////// 8 | // 9 | // Generated from the TEXTINCLUDE 2 resource. 10 | // 11 | #include "winres.h" 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | #undef APSTUDIO_READONLY_SYMBOLS 15 | 16 | ///////////////////////////////////////////////////////////////////////////// 17 | // English (United States) resources 18 | 19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""winres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // 50 | // Icon 51 | // 52 | 53 | // Icon with lowest ID value placed first to ensure application icon 54 | // remains consistent on all systems. 55 | IDI_APP_ICON ICON "resources\\app_icon.ico" 56 | 57 | 58 | ///////////////////////////////////////////////////////////////////////////// 59 | // 60 | // Version 61 | // 62 | 63 | #ifdef FLUTTER_BUILD_NUMBER 64 | #define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER 65 | #else 66 | #define VERSION_AS_NUMBER 1,0,0 67 | #endif 68 | 69 | #ifdef FLUTTER_BUILD_NAME 70 | #define VERSION_AS_STRING #FLUTTER_BUILD_NAME 71 | #else 72 | #define VERSION_AS_STRING "1.0.0" 73 | #endif 74 | 75 | VS_VERSION_INFO VERSIONINFO 76 | FILEVERSION VERSION_AS_NUMBER 77 | PRODUCTVERSION VERSION_AS_NUMBER 78 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 79 | #ifdef _DEBUG 80 | FILEFLAGS VS_FF_DEBUG 81 | #else 82 | FILEFLAGS 0x0L 83 | #endif 84 | FILEOS VOS__WINDOWS32 85 | FILETYPE VFT_APP 86 | FILESUBTYPE 0x0L 87 | BEGIN 88 | BLOCK "StringFileInfo" 89 | BEGIN 90 | BLOCK "040904e4" 91 | BEGIN 92 | VALUE "CompanyName", "com.example" "\0" 93 | VALUE "FileDescription", "yalda_students_notes" "\0" 94 | VALUE "FileVersion", VERSION_AS_STRING "\0" 95 | VALUE "InternalName", "yalda_students_notes" "\0" 96 | VALUE "LegalCopyright", "Copyright (C) 2022 com.example. All rights reserved." "\0" 97 | VALUE "OriginalFilename", "yalda_students_notes.exe" "\0" 98 | VALUE "ProductName", "yalda_students_notes" "\0" 99 | VALUE "ProductVersion", VERSION_AS_STRING "\0" 100 | END 101 | END 102 | BLOCK "VarFileInfo" 103 | BEGIN 104 | VALUE "Translation", 0x409, 1252 105 | END 106 | END 107 | 108 | #endif // English (United States) resources 109 | ///////////////////////////////////////////////////////////////////////////// 110 | 111 | 112 | 113 | #ifndef APSTUDIO_INVOKED 114 | ///////////////////////////////////////////////////////////////////////////// 115 | // 116 | // Generated from the TEXTINCLUDE 3 resource. 117 | // 118 | 119 | 120 | ///////////////////////////////////////////////////////////////////////////// 121 | #endif // not APSTUDIO_INVOKED 122 | -------------------------------------------------------------------------------- /windows/runner/flutter_window.cpp: -------------------------------------------------------------------------------- 1 | #include "flutter_window.h" 2 | 3 | #include 4 | 5 | #include "flutter/generated_plugin_registrant.h" 6 | 7 | FlutterWindow::FlutterWindow(const flutter::DartProject& project) 8 | : project_(project) {} 9 | 10 | FlutterWindow::~FlutterWindow() {} 11 | 12 | bool FlutterWindow::OnCreate() { 13 | if (!Win32Window::OnCreate()) { 14 | return false; 15 | } 16 | 17 | RECT frame = GetClientArea(); 18 | 19 | // The size here must match the window dimensions to avoid unnecessary surface 20 | // creation / destruction in the startup path. 21 | flutter_controller_ = std::make_unique( 22 | frame.right - frame.left, frame.bottom - frame.top, project_); 23 | // Ensure that basic setup of the controller was successful. 24 | if (!flutter_controller_->engine() || !flutter_controller_->view()) { 25 | return false; 26 | } 27 | RegisterPlugins(flutter_controller_->engine()); 28 | SetChildContent(flutter_controller_->view()->GetNativeWindow()); 29 | return true; 30 | } 31 | 32 | void FlutterWindow::OnDestroy() { 33 | if (flutter_controller_) { 34 | flutter_controller_ = nullptr; 35 | } 36 | 37 | Win32Window::OnDestroy(); 38 | } 39 | 40 | LRESULT 41 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message, 42 | WPARAM const wparam, 43 | LPARAM const lparam) noexcept { 44 | // Give Flutter, including plugins, an opportunity to handle window messages. 45 | if (flutter_controller_) { 46 | std::optional result = 47 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, 48 | lparam); 49 | if (result) { 50 | return *result; 51 | } 52 | } 53 | 54 | switch (message) { 55 | case WM_FONTCHANGE: 56 | flutter_controller_->engine()->ReloadSystemFonts(); 57 | break; 58 | } 59 | 60 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam); 61 | } 62 | -------------------------------------------------------------------------------- /windows/runner/flutter_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_FLUTTER_WINDOW_H_ 2 | #define RUNNER_FLUTTER_WINDOW_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "win32_window.h" 10 | 11 | // A window that does nothing but host a Flutter view. 12 | class FlutterWindow : public Win32Window { 13 | public: 14 | // Creates a new FlutterWindow hosting a Flutter view running |project|. 15 | explicit FlutterWindow(const flutter::DartProject& project); 16 | virtual ~FlutterWindow(); 17 | 18 | protected: 19 | // Win32Window: 20 | bool OnCreate() override; 21 | void OnDestroy() override; 22 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, 23 | LPARAM const lparam) noexcept override; 24 | 25 | private: 26 | // The project to run. 27 | flutter::DartProject project_; 28 | 29 | // The Flutter instance hosted by this window. 30 | std::unique_ptr flutter_controller_; 31 | }; 32 | 33 | #endif // RUNNER_FLUTTER_WINDOW_H_ 34 | -------------------------------------------------------------------------------- /windows/runner/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "flutter_window.h" 6 | #include "utils.h" 7 | 8 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, 9 | _In_ wchar_t *command_line, _In_ int show_command) { 10 | // Attach to console when present (e.g., 'flutter run') or create a 11 | // new console when running with a debugger. 12 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { 13 | CreateAndAttachConsole(); 14 | } 15 | 16 | // Initialize COM, so that it is available for use in the library and/or 17 | // plugins. 18 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); 19 | 20 | flutter::DartProject project(L"data"); 21 | 22 | std::vector command_line_arguments = 23 | GetCommandLineArguments(); 24 | 25 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); 26 | 27 | FlutterWindow window(project); 28 | Win32Window::Point origin(10, 10); 29 | Win32Window::Size size(1280, 720); 30 | if (!window.CreateAndShow(L"yalda_students_notes", origin, size)) { 31 | return EXIT_FAILURE; 32 | } 33 | window.SetQuitOnClose(true); 34 | 35 | ::MSG msg; 36 | while (::GetMessage(&msg, nullptr, 0, 0)) { 37 | ::TranslateMessage(&msg); 38 | ::DispatchMessage(&msg); 39 | } 40 | 41 | ::CoUninitialize(); 42 | return EXIT_SUCCESS; 43 | } 44 | -------------------------------------------------------------------------------- /windows/runner/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Runner.rc 4 | // 5 | #define IDI_APP_ICON 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /windows/runner/resources/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yalda-student/note_to_remember/9cee70f4efb4d2f0555a0c84aae4ecfefe9639f8/windows/runner/resources/app_icon.ico -------------------------------------------------------------------------------- /windows/runner/runner.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PerMonitorV2 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /windows/runner/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | void CreateAndAttachConsole() { 11 | if (::AllocConsole()) { 12 | FILE *unused; 13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) { 14 | _dup2(_fileno(stdout), 1); 15 | } 16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) { 17 | _dup2(_fileno(stdout), 2); 18 | } 19 | std::ios::sync_with_stdio(); 20 | FlutterDesktopResyncOutputStreams(); 21 | } 22 | } 23 | 24 | std::vector GetCommandLineArguments() { 25 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. 26 | int argc; 27 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); 28 | if (argv == nullptr) { 29 | return std::vector(); 30 | } 31 | 32 | std::vector command_line_arguments; 33 | 34 | // Skip the first argument as it's the binary name. 35 | for (int i = 1; i < argc; i++) { 36 | command_line_arguments.push_back(Utf8FromUtf16(argv[i])); 37 | } 38 | 39 | ::LocalFree(argv); 40 | 41 | return command_line_arguments; 42 | } 43 | 44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) { 45 | if (utf16_string == nullptr) { 46 | return std::string(); 47 | } 48 | int target_length = ::WideCharToMultiByte( 49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 50 | -1, nullptr, 0, nullptr, nullptr); 51 | if (target_length == 0) { 52 | return std::string(); 53 | } 54 | std::string utf8_string; 55 | utf8_string.resize(target_length); 56 | int converted_length = ::WideCharToMultiByte( 57 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 58 | -1, utf8_string.data(), 59 | target_length, nullptr, nullptr); 60 | if (converted_length == 0) { 61 | return std::string(); 62 | } 63 | return utf8_string; 64 | } 65 | -------------------------------------------------------------------------------- /windows/runner/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_UTILS_H_ 2 | #define RUNNER_UTILS_H_ 3 | 4 | #include 5 | #include 6 | 7 | // Creates a console for the process, and redirects stdout and stderr to 8 | // it for both the runner and the Flutter library. 9 | void CreateAndAttachConsole(); 10 | 11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string 12 | // encoded in UTF-8. Returns an empty std::string on failure. 13 | std::string Utf8FromUtf16(const wchar_t* utf16_string); 14 | 15 | // Gets the command line arguments passed in as a std::vector, 16 | // encoded in UTF-8. Returns an empty std::vector on failure. 17 | std::vector GetCommandLineArguments(); 18 | 19 | #endif // RUNNER_UTILS_H_ 20 | -------------------------------------------------------------------------------- /windows/runner/win32_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_WIN32_WINDOW_H_ 2 | #define RUNNER_WIN32_WINDOW_H_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | // A class abstraction for a high DPI-aware Win32 Window. Intended to be 11 | // inherited from by classes that wish to specialize with custom 12 | // rendering and input handling 13 | class Win32Window { 14 | public: 15 | struct Point { 16 | unsigned int x; 17 | unsigned int y; 18 | Point(unsigned int x, unsigned int y) : x(x), y(y) {} 19 | }; 20 | 21 | struct Size { 22 | unsigned int width; 23 | unsigned int height; 24 | Size(unsigned int width, unsigned int height) 25 | : width(width), height(height) {} 26 | }; 27 | 28 | Win32Window(); 29 | virtual ~Win32Window(); 30 | 31 | // Creates and shows a win32 window with |title| and position and size using 32 | // |origin| and |size|. New windows are created on the default monitor. Window 33 | // sizes are specified to the OS in physical pixels, hence to ensure a 34 | // consistent size to will treat the width height passed in to this function 35 | // as logical pixels and scale to appropriate for the default monitor. Returns 36 | // true if the window was created successfully. 37 | bool CreateAndShow(const std::wstring& title, 38 | const Point& origin, 39 | const Size& size); 40 | 41 | // Release OS resources associated with window. 42 | void Destroy(); 43 | 44 | // Inserts |content| into the window tree. 45 | void SetChildContent(HWND content); 46 | 47 | // Returns the backing Window handle to enable clients to set icon and other 48 | // window properties. Returns nullptr if the window has been destroyed. 49 | HWND GetHandle(); 50 | 51 | // If true, closing this window will quit the application. 52 | void SetQuitOnClose(bool quit_on_close); 53 | 54 | // Return a RECT representing the bounds of the current client area. 55 | RECT GetClientArea(); 56 | 57 | protected: 58 | // Processes and route salient window messages for mouse handling, 59 | // size change and DPI. Delegates handling of these to member overloads that 60 | // inheriting classes can handle. 61 | virtual LRESULT MessageHandler(HWND window, 62 | UINT const message, 63 | WPARAM const wparam, 64 | LPARAM const lparam) noexcept; 65 | 66 | // Called when CreateAndShow is called, allowing subclass window-related 67 | // setup. Subclasses should return false if setup fails. 68 | virtual bool OnCreate(); 69 | 70 | // Called when Destroy is called. 71 | virtual void OnDestroy(); 72 | 73 | private: 74 | friend class WindowClassRegistrar; 75 | 76 | // OS callback called by message pump. Handles the WM_NCCREATE message which 77 | // is passed when the non-client area is being created and enables automatic 78 | // non-client DPI scaling so that the non-client area automatically 79 | // responsponds to changes in DPI. All other messages are handled by 80 | // MessageHandler. 81 | static LRESULT CALLBACK WndProc(HWND const window, 82 | UINT const message, 83 | WPARAM const wparam, 84 | LPARAM const lparam) noexcept; 85 | 86 | // Retrieves a class instance pointer for |window| 87 | static Win32Window* GetThisFromHandle(HWND const window) noexcept; 88 | 89 | bool quit_on_close_ = false; 90 | 91 | // window handle for top level window. 92 | HWND window_handle_ = nullptr; 93 | 94 | // window handle for hosted content. 95 | HWND child_content_ = nullptr; 96 | }; 97 | 98 | #endif // RUNNER_WIN32_WINDOW_H_ 99 | --------------------------------------------------------------------------------