diff --git a/.gitignore b/.gitignore index 5be27ae..24476c5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ # Miscellaneous *.class -*.lock *.log *.pyc *.swp @@ -9,6 +8,7 @@ .buildlog/ .history .svn/ +migrate_working_dir/ # IntelliJ related *.iml @@ -16,56 +16,29 @@ *.iws .idea/ -# Visual Studio Code related -.vscode/ +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ # Flutter/Dart/Pub related **/doc/api/ +**/ios/Flutter/.last_build_id .dart_tool/ .flutter-plugins +.flutter-plugins-dependencies .packages .pub-cache/ .pub/ -build/ +/build/ -# Android related -**/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java +# Symbolication related +app.*.symbols -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/flutter_assets/ -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* +# Obfuscation related +app.*.map.json -# Exceptions to above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 -!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages \ No newline at end of file +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index ed83ee2..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "shared_preferences_suite_name"] - path = shared_preferences_suite_name - url = git://github.com/CoolONEOfficial/shared_preferences_suite_name.git diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..14f5fc9 --- /dev/null +++ b/.metadata @@ -0,0 +1,33 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled. + +version: + revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 + channel: stable + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 + base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 + - platform: android + create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 + base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 + - platform: ios + create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 + base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 86f83bc..0000000 --- a/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -os: - - linux -sudo: false -addons: - apt: - # Flutter depends on /usr/lib/x86_64-linux-gnu/libstdc++.so.6 version GLIBCXX_3.4.18 - sources: - - ubuntu-toolchain-r-test # if we don't specify this, the libstdc++6 we get is the wrong version - packages: - - libstdc++6 - - fonts-droid-fallback -before_script: - - git clone https://github.com/flutter/flutter.git -b master - - ./flutter/bin/flutter doctor -script: - - ./flutter/bin/flutter test -cache: - directories: - - $HOME/.pub-cache \ No newline at end of file diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..61b6c4d --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..6f56801 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/android/app/build.gradle b/android/app/build.gradle index 1a1f2e8..93eec8c 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -22,46 +22,43 @@ if (flutterVersionName == null) { } apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" -def keystoreProperties = new Properties() -def keystorePropertiesFile = rootProject.file('key.properties') -if (keystorePropertiesFile.exists()) { - keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) -} - android { - compileSdkVersion 28 + namespace "ru.coolone.ranepatimetable" + compileSdkVersion flutter.compileSdkVersion + ndkVersion flutter.ndkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } - lintOptions { - disable 'InvalidPackage' + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' } defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "ru.coolone.ranepatimetable" - minSdkVersion 19 - targetSdkVersion 28 + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. + minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } - signingConfigs { - release { - keyAlias keystoreProperties['keyAlias'] - keyPassword keystoreProperties['keyPassword'] - storeFile file(keystoreProperties['storeFile']) - storePassword keystoreProperties['storePassword'] - } - } buildTypes { release { - signingConfig signingConfigs.release - - minifyEnabled true - useProguard false - - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug } } } @@ -71,14 +68,12 @@ flutter { } dependencies { - def room_version = "2.2.3" - implementation "androidx.room:room-runtime:$room_version" - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - annotationProcessor "androidx.room:room-compiler:$room_version" - compileOnly 'org.projectlombok:lombok:1.18.6' - annotationProcessor 'org.projectlombok:lombok:1.18.6' - implementation 'com.google.code.gson:gson:2.8.5' - implementation 'com.nabinbhandari.android:permissions:3.8' - implementation 'com.jakewharton.threetenabp:threetenabp:1.1.1' - testImplementation 'junit:junit:4.12' + constraints { + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0") { + because("kotlin-stdlib-jdk7 is now a part of kotlin-stdlib") + } + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0") { + because("kotlin-stdlib-jdk8 is now a part of kotlin-stdlib") + } + } } diff --git a/android/app/gradle.properties b/android/app/gradle.properties deleted file mode 100644 index 646c51b..0000000 --- a/android/app/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -android.useAndroidX=true -android.enableJetifier=true diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro deleted file mode 100644 index dc15837..0000000 --- a/android/app/proguard-rules.pro +++ /dev/null @@ -1,9 +0,0 @@ -#Flutter Wrapper --keep class io.flutter.app.** { *; } --keep class io.flutter.plugin.** { *; } --keep class io.flutter.util.** { *; } --keep class io.flutter.view.** { *; } --keep class io.flutter.** { *; } --keep class io.flutter.plugins.** { *; } --keep class com.builttoroam.devicecalendar.** { *; } --keep class ru.coolone.ranepatimetable.** { *; } \ No newline at end of file diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 9b38f7f..6856f8f 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,77 +1,33 @@ - - - - - - - - - - + + android:label="ranepatimetable" + android:name="${applicationName}" + android:icon="@mipmap/ic_launcher"> - - + - + android:name="io.flutter.embedding.android.NormalTheme" + android:resource="@style/NormalTheme" + /> - - - + + - - - - - - - - - - - - + + - diff --git a/android/app/src/main/assets/fonts/TimetableIcons.ttf b/android/app/src/main/assets/fonts/TimetableIcons.ttf deleted file mode 100644 index 9f1582d..0000000 Binary files a/android/app/src/main/assets/fonts/TimetableIcons.ttf and /dev/null differ diff --git a/android/app/src/main/ic_launcher-web.png b/android/app/src/main/ic_launcher-web.png deleted file mode 100644 index 6a1cfc1..0000000 Binary files a/android/app/src/main/ic_launcher-web.png and /dev/null differ diff --git a/android/app/src/main/icicc-web.png b/android/app/src/main/icicc-web.png deleted file mode 100644 index 6a1cfc1..0000000 Binary files a/android/app/src/main/icicc-web.png and /dev/null differ diff --git a/android/app/src/main/java/ru/coolone/ranepatimetable/MainActivity.java b/android/app/src/main/java/ru/coolone/ranepatimetable/MainActivity.java deleted file mode 100644 index 7f86329..0000000 --- a/android/app/src/main/java/ru/coolone/ranepatimetable/MainActivity.java +++ /dev/null @@ -1,43 +0,0 @@ -package ru.coolone.ranepatimetable; - -import android.appwidget.AppWidgetManager; -import android.content.ComponentName; -import android.content.Intent; -import android.os.Bundle; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import io.flutter.app.FlutterActivity; -import io.flutter.plugin.common.MethodCall; -import io.flutter.plugin.common.MethodChannel; -import io.flutter.plugins.GeneratedPluginRegistrant; -import lombok.var; - -@lombok.extern.java.Log -public class MainActivity extends FlutterActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - GeneratedPluginRegistrant.registerWith(this); - - new MethodChannel(getFlutterView(), "ru.coolone.ranepatimetable/methodChannel").setMethodCallHandler( - (methodCall, result) -> { - if ("refreshWidget".equals(methodCall.method)) { - var intent = new Intent(MainActivity.this, WidgetProvider.class); - intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); - var ids = AppWidgetManager.getInstance(getApplication()) - .getAppWidgetIds(new ComponentName(getApplication(), WidgetProvider.class)); - intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids); - sendBroadcast(intent); - result.success(null); - } else { - result.notImplemented(); - } - } - ); - } - -} diff --git a/android/app/src/main/java/ru/coolone/ranepatimetable/Timeline.java b/android/app/src/main/java/ru/coolone/ranepatimetable/Timeline.java deleted file mode 100644 index a79c5b7..0000000 --- a/android/app/src/main/java/ru/coolone/ranepatimetable/Timeline.java +++ /dev/null @@ -1,219 +0,0 @@ -package ru.coolone.ranepatimetable; - -import android.content.ContentValues; -import android.provider.BaseColumns; - -import java.util.Date; - -import androidx.room.ColumnInfo; -import androidx.room.Embedded; -import androidx.room.Entity; -import androidx.room.PrimaryKey; -import androidx.room.TypeConverter; -import androidx.room.TypeConverters; -import lombok.AllArgsConstructor; -import lombok.NoArgsConstructor; - -/** - * Represents one record of the Timeline table. - */ -@NoArgsConstructor -@AllArgsConstructor -@Entity(tableName = Timeline.TABLE_NAME) -public class Timeline { - - @NoArgsConstructor - @AllArgsConstructor - public enum Location { - Academy(0xe81b), - Hotel(0xe801), - StudyHostel(0xe802); - - int iconCodePoint; - } - - @NoArgsConstructor - @AllArgsConstructor - static public class TeacherModel { - public static final String COLUMN_TEACHER_NAME = "name"; - public static final String COLUMN_TEACHER_SURNAME = "surname"; - public static final String COLUMN_TEACHER_PATRONYMIC = "patronymic"; - - String name, surname, patronymic; - - public static TeacherModel fromContentValues(ContentValues values, String prefix) { - return new TeacherModel( - values.getAsString(prefix + COLUMN_TEACHER_NAME), - values.getAsString(prefix + COLUMN_TEACHER_SURNAME), - values.getAsString(prefix + COLUMN_TEACHER_PATRONYMIC) - ); - } - } - - @NoArgsConstructor - @AllArgsConstructor - static public class TimeOfDayModel { - public static final String COLUMN_TIMEOFDAY_HOUR = "hour"; - public static final String COLUMN_TIMEOFDAY_MINUTE = "minute"; - - int hour, minute; - - public static TimeOfDayModel fromContentValues(ContentValues values, String prefix) { - return new TimeOfDayModel( - values.getAsInteger(prefix + COLUMN_TIMEOFDAY_HOUR), - values.getAsInteger(prefix + COLUMN_TIMEOFDAY_MINUTE) - ); - } - } - - @NoArgsConstructor - @AllArgsConstructor - static public class LessonAction { - public static final String COLUMN_LESSON_TYPE_TITLE = "title"; - - String title; - } - - @AllArgsConstructor - @NoArgsConstructor - static public class LessonModel { - public static final String PREFIX_LESSON_ACTION = "action_"; - - public static final String COLUMN_LESSON_TITLE = "title"; - public static final String COLUMN_LESSON_FULL_TITLE = "fullTitle"; - public static final String COLUMN_LESSON_ICON = "iconCodePoint"; - - String title, fullTitle; - int iconCodePoint; - @Embedded(prefix = PREFIX_LESSON_ACTION) - LessonAction action; - - public static LessonModel fromContentValues(ContentValues values, String prefix) { - return new LessonModel( - values.getAsString(prefix + COLUMN_LESSON_TITLE), - values.getAsString(prefix + COLUMN_LESSON_FULL_TITLE), - values.getAsInteger(prefix + COLUMN_LESSON_ICON), - new LessonAction( - values.getAsString( - prefix - + PREFIX_LESSON_ACTION - + LessonAction.COLUMN_LESSON_TYPE_TITLE - ) - ) - ); - } - } - - @NoArgsConstructor - @AllArgsConstructor - static public class RoomModel { - public static final String COLUMN_ROOM_NUMBER = "number"; - public static final String COLUMN_ROOM_LOCATION = "location"; - - String number; - - @TypeConverters(RoomModel.class) - Location location; - - public static RoomModel fromContentValues(ContentValues values, String prefix) { - return new RoomModel( - values.getAsString(prefix + COLUMN_ROOM_NUMBER), - Location.values()[values.getAsInteger(prefix + COLUMN_ROOM_LOCATION)] - ); - } - - @TypeConverter - public static Location toLocation(int numeral) { - return Location.values()[numeral]; - } - - @TypeConverter - public static int fromLocation(Location status) { - return status.ordinal(); - } - - } - - /** - * The name of the Timeline table. - */ - public static final String TABLE_NAME = "lessons"; - - public static final String COLUMN_ID = BaseColumns._ID; - public static final String COLUMN_DATE = "date"; - public static final String COLUMN_GROUP = "group"; - public static final String COLUMN_FIRST = "first"; - public static final String COLUMN_LAST = "last"; - public static final String COLUMN_MERGE_BOTTOM = "mergeBottom"; - public static final String COLUMN_MERGE_TOP = "mergeTop"; - - public static final String PREFIX_LESSON = "lesson_"; - public static final String PREFIX_ROOM = "room_"; - public static final String PREFIX_TEACHER = "teacher_"; - public static final String PREFIX_START = "start_"; - public static final String PREFIX_FINISH = "finish_"; - - @PrimaryKey(autoGenerate = true) - @ColumnInfo(index = true, name = COLUMN_ID) - public long id; - - @Embedded(prefix = PREFIX_LESSON) - LessonModel lesson; - - @Embedded(prefix = PREFIX_ROOM) - RoomModel room; - - @ColumnInfo(name = COLUMN_DATE) - @TypeConverters(Timeline.class) - Date date; - - @ColumnInfo(name = COLUMN_GROUP) - String group; - - @ColumnInfo(name = COLUMN_FIRST) - boolean first; - - @ColumnInfo(name = COLUMN_LAST) - boolean last; - - @ColumnInfo(name = COLUMN_MERGE_BOTTOM) - boolean mergeBottom; - - @ColumnInfo(name = COLUMN_MERGE_TOP) - boolean mergeTop; - - @Embedded(prefix = PREFIX_TEACHER) - TeacherModel teacher; - - @Embedded(prefix = PREFIX_START) - TimeOfDayModel start; - - @Embedded(prefix = PREFIX_FINISH) - TimeOfDayModel finish; - - @TypeConverter - public static Date toDate(Long dateLong) { - return dateLong == null ? null : new Date(dateLong); - } - - @TypeConverter - public static Long fromDate(Date date) { - return date == null ? null : date.getTime(); - } - -// public static Timeline fromContentValues(ContentValues values) { -// return new Timeline( -// values.getAsLong(COLUMN_ID), -// LessonModel.fromContentValues(values, PREFIX_LESSON), -// RoomModel.fromContentValues(values, PREFIX_ROOM), -// new Date(values.getAsLong(COLUMN_DATE)), -// Timeline.User.values() -// values.getAsString(COLUMN_GROUP), -// values.getAsInteger(COLUMN_FIRST) == 1, -// values.getAsInteger(COLUMN_LAST) == 1, -// TeacherModel.fromContentValues(values, PREFIX_TEACHER), -// TimeOfDayModel.fromContentValues(values, PREFIX_START), -// TimeOfDayModel.fromContentValues(values, PREFIX_FINISH) -// ); -// } -} \ No newline at end of file diff --git a/android/app/src/main/java/ru/coolone/ranepatimetable/TimelineDao.java b/android/app/src/main/java/ru/coolone/ranepatimetable/TimelineDao.java deleted file mode 100644 index cd94f93..0000000 --- a/android/app/src/main/java/ru/coolone/ranepatimetable/TimelineDao.java +++ /dev/null @@ -1,117 +0,0 @@ -package ru.coolone.ranepatimetable; - -import android.database.Cursor; - -import java.util.Calendar; -import java.util.List; - -import androidx.room.Dao; -import androidx.room.Insert; -import androidx.room.Query; -import androidx.room.Update; - -import static ru.coolone.ranepatimetable.WidgetProvider.getTodayMidnight; - -@Dao -public interface TimelineDao { - - /** - * Counts the number of timetables in the table. - * - * @return The number of timetables. - */ - @Query("SELECT COUNT(*) FROM " + Timeline.TABLE_NAME) - public int count(); - - /** - * Inserts a timeline into the table. - * - * @param timeline A new timeline. - * @return The row ID of the newly inserted timeline. - */ - @Insert - public long insert(Timeline timeline); - - /** - * Inserts multiple timelines into the database - * - * @param timelines An array of new timelines. - * @return The row IDs of the newly inserted timelines. - */ - @Insert - public long[] insertAll(Timeline[] timelines); - - @Query("DELETE FROM " + Timeline.TABLE_NAME + " WHERE strftime('%Y-%m-%d', date) < strftime('%Y-%m-%d', 'now')") - public int deleteOld(); - - /** - * Get all timetables. - * - * @return A {@link List} of all the timetables in the table. - */ - @Query("SELECT * FROM " + Timeline.TABLE_NAME) - public Timeline[] getAll(); - - /** - * Select all timetables. - * - * @return A {@link Cursor} of all the timetables in the table. - */ - @Query("SELECT * FROM " + Timeline.TABLE_NAME) - public Cursor selectAll(); - - /** - * Select a timetable by the ID. - * - * @param id The row ID. - * @return A {@link Cursor} of the selected timetable. - */ - @Query("SELECT * FROM " + Timeline.TABLE_NAME + " WHERE " + Timeline.COLUMN_ID + " = :id") - public Cursor selectById(long id); - - /** - * Select a timetable by the Date. - * - * @param date The row Date. - * @return A {@link Cursor} of the selected timetable. - */ - @Query("SELECT * FROM " + Timeline.TABLE_NAME + " WHERE " + Timeline.COLUMN_DATE + " = :date") - public Cursor selectByDate(long date); - - //SELECT * FROM NAMES WHERE date == (SELECT date FROM NAMES WHERE date >= '1900-02-01 00:00:00' LIMIT 1) - - @Query("SELECT * FROM " + Timeline.TABLE_NAME + " WHERE " + Timeline.COLUMN_DATE + " == " + - "(" + - "SELECT " + Timeline.COLUMN_DATE + - " FROM " + Timeline.TABLE_NAME + - " WHERE " + Timeline.COLUMN_DATE + " >= :now LIMIT 1" + - ")" - ) - public Cursor selectWeekday(long now); - - /** - * Delete a timetable by the ID. - * - * @param id The row ID. - * @return A number of timetables deleted. This should always be {@code 1}. - */ - @Query("DELETE FROM " + Timeline.TABLE_NAME + " WHERE " + Timeline.COLUMN_ID + " = :id") - public int deleteById(long id); - - /** - * Delete all timetables. - * - * @return A number of timetables deleted. This should always be {@code 1}. - */ - @Query("DELETE FROM " + Timeline.TABLE_NAME) - public int delete(); - - /** - * Update the timeline. The timeline is identified by the row ID. - * - * @param timeline The timeline to update. - * @return A number of timetables updated. This should always be {@code 1}. - */ - @Update - public int update(Timeline timeline); -} \ No newline at end of file diff --git a/android/app/src/main/java/ru/coolone/ranepatimetable/TimetableDataProvider.java b/android/app/src/main/java/ru/coolone/ranepatimetable/TimetableDataProvider.java deleted file mode 100644 index 9b61b8e..0000000 --- a/android/app/src/main/java/ru/coolone/ranepatimetable/TimetableDataProvider.java +++ /dev/null @@ -1,97 +0,0 @@ -package ru.coolone.ranepatimetable; - -import android.content.ContentProvider; -import android.content.ContentUris; -import android.content.ContentValues; -import android.content.UriMatcher; -import android.database.Cursor; -import android.net.Uri; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import lombok.var; - - -public class TimetableDataProvider extends ContentProvider { - - /** The authority of this content provider. */ - public static final String AUTHORITY = "ru.coolone.ranepatimetable.provider"; - - /** The URI for the Timeline table. */ - public static final Uri URI_TIMELINE = Uri.parse( - "content://" + AUTHORITY + "/" + Timeline.TABLE_NAME); - - /** The match code for some items in the Timeline table. */ - private static final int CODE_TIMELINE_DIR = 1; - - /** The match code for an item in the Timeline table. */ - private static final int CODE_TIMELINE_ITEM = 2; - - /** The URI matcher. */ - private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH); - - static { - MATCHER.addURI(AUTHORITY, Timeline.TABLE_NAME, CODE_TIMELINE_DIR); - MATCHER.addURI(AUTHORITY, Timeline.TABLE_NAME + "/*", CODE_TIMELINE_ITEM); - } - - @Override - public boolean onCreate() { - return true; - } - - @Nullable - @Override - public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, - @Nullable String[] selectionArgs, @Nullable String sortOrder) { - final int code = MATCHER.match(uri); - if (code == CODE_TIMELINE_DIR || code == CODE_TIMELINE_ITEM) { - var ctx = getContext(); - if (ctx == null) return null; - - var timetable = TimetableDatabase.getInstance(ctx).timetable(); - - final Cursor cursor; - if (code == CODE_TIMELINE_DIR) { - cursor = timetable.selectAll(); - } else { - cursor = timetable.selectById(ContentUris.parseId(uri)); - } - cursor.setNotificationUri(ctx.getContentResolver(), uri); - - return cursor; - } else { - throw new IllegalArgumentException("Unknown URI: " + uri); - } - } - - @Nullable - @Override - public String getType(@NonNull Uri uri) { - switch (MATCHER.match(uri)) { - case CODE_TIMELINE_DIR: - return "vnd.android.cursor.dir/" + AUTHORITY + "." + Timeline.TABLE_NAME; - case CODE_TIMELINE_ITEM: - return "vnd.android.cursor.item/" + AUTHORITY + "." + Timeline.TABLE_NAME; - default: - throw new IllegalArgumentException("Unknown URI: " + uri); - } - } - - @Nullable - @Override - public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { - return null; - } - - @Override - public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { - return 0; - } - - @Override - public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { - return 0; - } - -} \ No newline at end of file diff --git a/android/app/src/main/java/ru/coolone/ranepatimetable/TimetableDatabase.java b/android/app/src/main/java/ru/coolone/ranepatimetable/TimetableDatabase.java deleted file mode 100644 index 2539636..0000000 --- a/android/app/src/main/java/ru/coolone/ranepatimetable/TimetableDatabase.java +++ /dev/null @@ -1,45 +0,0 @@ -package ru.coolone.ranepatimetable; - -import android.content.Context; - -import androidx.room.Database; -import androidx.room.Room; -import androidx.room.RoomDatabase; - -@Database(entities = {Timeline.class}, version = 1, exportSchema = false) -public abstract class TimetableDatabase extends RoomDatabase { - - public static final String FILENAME = "timetable.db"; - - /** - * @return The DAO for the Timeline table. - */ - @SuppressWarnings("WeakerAccess") - public abstract TimelineDao timetable(); - - /** - * The only instance - */ - private static TimetableDatabase sInstance; - - /** - * Gets the singleton instance of TimetableDatabase. - * - * @param ctx The ctx. - * @return The singleton instance of TimetableDatabase. - */ - public static synchronized TimetableDatabase getInstance(Context ctx) { - if (sInstance == null) { - sInstance = Room - .databaseBuilder( - ctx, - TimetableDatabase.class, - FILENAME - ) - .createFromAsset("database/" + FILENAME) - .allowMainThreadQueries() - .build(); - } - return sInstance; - } -} \ No newline at end of file diff --git a/android/app/src/main/java/ru/coolone/ranepatimetable/WidgetProvider.java b/android/app/src/main/java/ru/coolone/ranepatimetable/WidgetProvider.java deleted file mode 100644 index 85fcd26..0000000 --- a/android/app/src/main/java/ru/coolone/ranepatimetable/WidgetProvider.java +++ /dev/null @@ -1,848 +0,0 @@ -package ru.coolone.ranepatimetable; - -import android.Manifest; -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.appwidget.AppWidgetManager; -import android.appwidget.AppWidgetProvider; -import android.appwidget.AppWidgetProviderInfo; -import android.content.ComponentName; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Typeface; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.provider.AlarmClock; -import android.provider.CalendarContract; -import android.util.Pair; -import android.view.View; -import android.widget.RemoteViews; -import android.widget.Toast; - -import com.jakewharton.threetenabp.AndroidThreeTen; -import com.nabinbhandari.android.permissions.PermissionHandler; -import com.nabinbhandari.android.permissions.Permissions; - -import org.threeten.bp.Duration; - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.Locale; -import java.util.Objects; -import java.util.TimeZone; - -import androidx.core.app.ActivityCompat; - -import lombok.AllArgsConstructor; -import lombok.NoArgsConstructor; -import lombok.extern.java.Log; -import lombok.val; -import lombok.var; - -import static ru.coolone.ranepatimetable.WidgetRemoteViewsFactory.dpScale; - -/** - * The widget's AppWidgetProvider. - */ -@Log -@NoArgsConstructor -public class WidgetProvider extends AppWidgetProvider { - enum IntentAction { - DeleteOld("DELETE_OLD"), - CreateAlarmClock("CREATE_ALARM_CLOCK"), - CreateCalendarEvents("CREATE_CALENDAR_EVENTS"), - DayNext("DAY_NEXT"), - DayPrev("DAY_PREV"); - final String action; - - IntentAction(String action) { - this.action = "ru.coolone.ranepatimetable." + action; - } - } - - enum Brightness { - Dark, - Light - } - - enum RoomLocationStyle { - Text, - Icon - } - - enum DayStyle { - Weekday, - Date - } - - AlarmManager manager; - PendingIntent updatePendingIntent, deleteOldPendingIntent; - - static private int dateOffset; - - enum SearchItemTypeId { - Group, - Teacher - } - - private static SharedPreferences _prefs; - - public static SharedPreferences getPrefs(Context ctx) { - if (_prefs == null) - _prefs = ctx.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE); - return _prefs; - } - - @Override - public void onDisabled(Context ctx) { - if (manager != null && updatePendingIntent != null) - manager.cancel(updatePendingIntent); - } - - @Override - public void onEnabled(Context ctx) { - AndroidThreeTen.init(ctx); - - _widgetSize = Pair.create( - getPrefs(ctx).getInt(PrefsIds.WidgetSizeWidth.prefId, 1), - getPrefs(ctx).getInt(PrefsIds.WidgetSizeHeight.prefId, 1) - ); - - log.info("Create widget size from prefs: \n" - + "w: " + _widgetSize.first + "\n" - + "h: " + _widgetSize.second + "\n" - ); - - manager = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE); - - updatePendingIntent = PendingIntent.getBroadcast( - ctx, - 0, - new Intent(ctx, WidgetProvider.class), - PendingIntent.FLAG_UPDATE_CURRENT - ); - manager.setRepeating( - AlarmManager.RTC, - getTodayMidnight().getTimeInMillis(), - 1000 * 60 * 60 * 24, - updatePendingIntent - ); - - deleteOldPendingIntent = PendingIntent.getBroadcast( - ctx, - 0, - new Intent(IntentAction.DeleteOld.action), - PendingIntent.FLAG_UPDATE_CURRENT - ); - manager.setRepeating( - AlarmManager.RTC, - getTodayMidnight().getTimeInMillis(), - 1000 * 60 * 60 * 24, - deleteOldPendingIntent - ); - } - - private int getCalendarId(Context ctx) { - String projection[] = { - CalendarContract.Calendars._ID, CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL - }; - - var contentResolver = ctx.getContentResolver(); - var managedCursor = contentResolver.query( - Uri.parse("content://com.android.calendar/calendars"), - projection, - null, - null, - null - ); - - if (managedCursor != null && managedCursor.moveToFirst()) { - var idIndex = managedCursor.getColumnIndex(projection[0]); - var accessIndex = managedCursor.getColumnIndex(projection[1]); - do { - if (managedCursor.getInt(accessIndex) == 700) - return managedCursor.getInt(idIndex); - } while (managedCursor.moveToNext()); - managedCursor.close(); - } - return -1; - } - - private void createAlarmClock(Context ctx) { - var firstLesson = TimetableDatabase.getInstance(ctx).timetable().selectByDate(showDate); - if (firstLesson.moveToFirst()) { - var duration = Duration.ofMinutes(getPrefs(ctx).getLong(PrefsIds.BeforeAlarmClock.prefId, 0)); - - if (duration.isZero()) - Toast.makeText(ctx, R.string.noBeforeAlarmClock, Toast.LENGTH_LONG).show(); - else { - var date = GregorianCalendar.getInstance(); - date.setTimeInMillis(firstLesson.getLong(firstLesson.getColumnIndex(Timeline.COLUMN_DATE))); - date.add(Calendar.HOUR, firstLesson.getInt(firstLesson.getColumnIndex( - Timeline.PREFIX_START - + Timeline.TimeOfDayModel.COLUMN_TIMEOFDAY_HOUR - )) - - ((int) duration.toHours())); - date.add(Calendar.MINUTE, firstLesson.getInt(firstLesson.getColumnIndex( - Timeline.PREFIX_START - + Timeline.TimeOfDayModel.COLUMN_TIMEOFDAY_MINUTE - )) - - ((int) duration.toMinutes())); - - var alarmIntent = new Intent(AlarmClock.ACTION_SET_ALARM); - alarmIntent.putExtra(AlarmClock.EXTRA_MESSAGE, firstLesson.getString( - firstLesson.getColumnIndex( - Timeline.PREFIX_LESSON - + Timeline.LessonModel.COLUMN_LESSON_TITLE - ))); - alarmIntent.putExtra(AlarmClock.EXTRA_HOUR, date.get(Calendar.HOUR)); - alarmIntent.putExtra(AlarmClock.EXTRA_MINUTES, date.get(Calendar.MINUTE)); - alarmIntent.putExtra(AlarmClock.EXTRA_SKIP_UI, true); - alarmIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - ctx.startActivity(alarmIntent); - } - } else - Toast.makeText(ctx, R.string.noLessons, Toast.LENGTH_LONG).show(); - } - - private void createCalendarEvents(final Context ctx) { - var mLesson = TimetableDatabase.getInstance(ctx).timetable().selectByDate(showDate); - - if (mLesson.getCount() == 0) - Toast.makeText(ctx, R.string.noLessons, Toast.LENGTH_LONG).show(); - else { - while (mLesson.moveToNext()) { - var mDate = GregorianCalendar.getInstance(); - mDate.setTimeInMillis(mLesson.getLong(mLesson.getColumnIndex(Timeline.COLUMN_DATE))); - - var mStartDate = new GregorianCalendar(); - mStartDate.setTimeInMillis(mDate.getTimeInMillis()); - mStartDate.add(Calendar.HOUR, mLesson.getInt(mLesson.getColumnIndex( - Timeline.PREFIX_START - + Timeline.TimeOfDayModel.COLUMN_TIMEOFDAY_HOUR - ))); - mStartDate.add(Calendar.MINUTE, mLesson.getInt(mLesson.getColumnIndex( - Timeline.PREFIX_START - + Timeline.TimeOfDayModel.COLUMN_TIMEOFDAY_MINUTE - ))); - - var mFinishDate = new GregorianCalendar(); - mFinishDate.setTimeInMillis(mDate.getTimeInMillis()); - mFinishDate.add(Calendar.HOUR, mLesson.getInt(mLesson.getColumnIndex( - Timeline.PREFIX_FINISH - + Timeline.TimeOfDayModel.COLUMN_TIMEOFDAY_HOUR - ))); - mFinishDate.add(Calendar.MINUTE, mLesson.getInt(mLesson.getColumnIndex( - Timeline.PREFIX_FINISH - + Timeline.TimeOfDayModel.COLUMN_TIMEOFDAY_MINUTE - ))); - - ContentResolver cr = ctx.getContentResolver(); - ContentValues values = new ContentValues(); - values.put(CalendarContract.Events.DTSTART, mStartDate.getTimeInMillis()); - values.put(CalendarContract.Events.DTEND, mFinishDate.getTimeInMillis()); - values.put(CalendarContract.Events.TITLE, mLesson.getString(mLesson.getColumnIndex( - Timeline.PREFIX_LESSON - + Timeline.LessonModel.COLUMN_LESSON_TITLE - ))); - values.put(CalendarContract.Events.DESCRIPTION, mLesson.getString(mLesson.getColumnIndex( - Timeline.PREFIX_LESSON - + Timeline.LessonModel.COLUMN_LESSON_FULL_TITLE - ))); - values.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID()); - if (ActivityCompat.checkSelfPermission(ctx, android.Manifest.permission.WRITE_CALENDAR) - == PackageManager.PERMISSION_GRANTED - && ActivityCompat.checkSelfPermission(ctx, Manifest.permission.READ_CALENDAR) - == PackageManager.PERMISSION_GRANTED) { - values.put(CalendarContract.Events.CALENDAR_ID, getCalendarId(ctx)); - Toast.makeText(ctx, cr.insert(CalendarContract.Events.CONTENT_URI, values) == null - ? R.string.createCalendarEventsFailed - : R.string.createCalendarEventsSuccess, - Toast.LENGTH_LONG - ).show(); - } else - Permissions.check( - ctx, - new String[]{ - Manifest.permission.WRITE_CALENDAR, - Manifest.permission.READ_CALENDAR - }, - null, - null, - new PermissionHandler() { - @Override - public void onGranted() { - createCalendarEvents(ctx); - } - - @Override - public void onDenied(Context ctx, ArrayList deniedPermissions) { - super.onDenied(ctx, deniedPermissions); - Toast.makeText(ctx, R.string.noCalendarPermissions, - Toast.LENGTH_LONG - ).show(); - } - } - ); - } - } - } - - private void refreshWidget(Context ctx) { - ComponentName name = new ComponentName(ctx, WidgetProvider.class); - int[] ids = AppWidgetManager.getInstance(ctx).getAppWidgetIds(name); - - for (var mId : ids) - AppWidgetManager.getInstance(ctx) - .updateAppWidget( - new ComponentName( - ctx.getPackageName(), - WidgetProvider.class.getName() - ), - buildLayout( - ctx, - mId, - AppWidgetManager.getInstance(ctx), - false - ) - ); - } - - @Override - public void onReceive(Context ctx, Intent intent) { - log.info("onReceive: " + intent.getAction()); - - if (Objects.equals(intent.getAction(), IntentAction.DeleteOld.action)) { - TimetableDatabase.getInstance(ctx).timetable().deleteOld(); - } else if (Objects.equals(intent.getAction(), IntentAction.CreateAlarmClock.action)) { - createAlarmClock(ctx); - } else if (Objects.equals(intent.getAction(), IntentAction.CreateCalendarEvents.action)) { - createCalendarEvents(ctx); - } else if (Objects.equals(intent.getAction(), IntentAction.DayNext.action) - || Objects.equals(intent.getAction(), IntentAction.DayPrev.action)) { - Calendar now; - do { - dateOffset += Objects.equals(intent.getAction(), IntentAction.DayNext.action) - ? 1 - : -1; - - now = GregorianCalendar.getInstance(); - now.add(Calendar.DATE, dateOffset); - } - while (now.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY); - refreshWidget(ctx); - } - - super.onReceive(ctx, intent); - } - - public Theme theme; - - @AllArgsConstructor - static class Theme { - final int primary, accent, - textPrimary, textAccent, - background; - final Brightness brightness; - } - - public static final Theme defaultTheme = new Theme( - 0xFF2196F3, - 0xFF2196F3, - Color.BLACK, - Color.WHITE, - 0xFF90CAF9, - Brightness.Light - ); - - private static final String FLUTTER_PREFIX = "flutter."; - - enum PrefsIds { - OptimizedLessonTitles("optimized_lesson_titles"), - - RoomLocationStyle("room_location_style"), - - WidgetTranslucent("widget_translucent"), - - ThemePrimary("theme_primary"), - ThemeAccent("theme_accent"), - ThemeTextPrimary("theme_text_primary"), - ThemeTextAccent("theme_text_accent"), - ThemeBackground("theme_background"), - - ThemeBrightness("theme_brightness"), - - BeforeAlarmClock("before_alarm_clock"), - EndCache("end_cache"), - WidgetSizeWidth("widget_size_width"), - WidgetSizeHeight("widget_size_height"), - - PrimarySearchItemPrefix("primary_search_item_"), - ItemType("type", PrimarySearchItemPrefix.prefId), - ItemId("id", PrimarySearchItemPrefix.prefId), - ItemTitle("title", PrimarySearchItemPrefix.prefId), - - DayStyle("day_style"); - - final String prefId; - - PrefsIds(String prefId) { - this(prefId, FLUTTER_PREFIX); - } - - PrefsIds(String prefId, String prefix) { - this.prefId = prefix.concat(prefId); - } - } - - private static Calendar getMidnight(Calendar calendar) { - calendar.set(Calendar.HOUR_OF_DAY, 0); - calendar.set(Calendar.MINUTE, 0); - calendar.set(Calendar.SECOND, 0); - calendar.set(Calendar.MILLISECOND, 0); - return calendar; - } - - public static Calendar getTodayMidnight() { - return getMidnight(Calendar.getInstance()); - } - - static long showDate; - - static Bitmap buildEmptyViewBitmap(Context ctx, Theme theme) { - var type = SearchItemTypeId.values()[ - (int) getPrefs(ctx).getLong( - PrefsIds.ItemType.prefId, - 0 - ) - ]; - - var BEER = '\ue838'; - var CONFETTI = '\ue839'; - - return buildNotificationBitmap( - ctx, - theme, - type == SearchItemTypeId.Teacher - ? CONFETTI - : BEER, - ctx.getString(R.string.freeDay), - 9f - ); - } - - static Bitmap buildNoCacheImageBitmap(Context ctx, Theme theme) { - var NO_CACHE = '\ue826'; - - return buildNotificationBitmap( - ctx, - theme, - NO_CACHE, - ctx.getString(R.string.noCache), - 14f, - 0 - ); - } - - static Bitmap buildNotificationBitmap( - Context ctx, - Theme theme, - char icon, - String notification, - float textScale - ) { - return buildNotificationBitmap( - ctx, - theme, - icon, - notification, - textScale, - ctx.getResources().getDimension(R.dimen.widget_head_height) / dpScale(ctx) - ); - } - - static Bitmap buildNotificationBitmap( - Context ctx, - Theme theme, - char icon, - String notification, - float textScale, - float headHeight - ) { - var dpScale = dpScale(ctx); - var widgetSize = widgetSize(ctx); - - var bitmap = Bitmap.createBitmap((int) (widgetSize.first * dpScale), (int) (widgetSize.second * dpScale), Bitmap.Config.ARGB_8888); - var canvas = new Canvas(bitmap); - - var iconPaint = new Paint(); - iconPaint.setAntiAlias(true); - iconPaint.setSubpixelText(true); - iconPaint.setTextAlign(Paint.Align.CENTER); - iconPaint.setTypeface( - Typeface.createFromAsset( - ctx.getAssets(), - "fonts/TimetableIcons.ttf" - ) - ); - - iconPaint.setTextSize(dpScale * (Math.min(widgetSize.first, widgetSize.second) / 3f)); - iconPaint.setColor(theme.textPrimary); - - canvas.drawText( - String.valueOf(icon), - (widgetSize.first / 2f) * dpScale, - (headHeight + (widgetSize.second - headHeight) / 2) * dpScale, - iconPaint - ); - - var textPaint = new Paint(); - textPaint.setAntiAlias(true); - textPaint.setSubpixelText(true); - textPaint.setTextAlign(Paint.Align.CENTER); - - textPaint.setTextSize(dpScale * (Math.min(widgetSize.first, widgetSize.second) / textScale)); - textPaint.setColor(theme.textPrimary); - - var mTextY = ( - headHeight + - ( - widgetSize.second - headHeight - ) / 2 + - ( - Math.min(widgetSize.first, widgetSize.second) / 4f - ) - ) * dpScale; - for (var line : notification.split("\n")) { - canvas.drawText( - line, - (widgetSize.first / 2f) * dpScale, - mTextY, - textPaint - ); - mTextY += textPaint.descent() - textPaint.ascent(); - } - - return bitmap; - } - - private Pair getWidgetSize( - Context ctx, - int appWidgetId, - AppWidgetManager manager - ) { - AppWidgetProviderInfo providerInfo = AppWidgetManager.getInstance( - ctx.getApplicationContext() - ).getAppWidgetInfo(appWidgetId); - - // Since min and max is usually the same, just take min - var mWidgetLandSize = new Pair<>(providerInfo.minWidth, providerInfo.minHeight); - var mWidgetPortSize = new Pair<>(providerInfo.minWidth, providerInfo.minHeight); - var mNewWidgetLandSize = new Pair<>(0, 0); - var mNewWidgetPortSize = new Pair<>(0, 0); - - Bundle mAppWidgetOptions = manager.getAppWidgetOptions(appWidgetId); - - if (mAppWidgetOptions - .getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH) > 0) { - - mNewWidgetPortSize = new Pair<>( - mAppWidgetOptions - .getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH), - mAppWidgetOptions - .getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT) - ); - - mNewWidgetLandSize = new Pair<>( - mAppWidgetOptions - .getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH), - mAppWidgetOptions - .getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT) - ); - } - - log.info( - "Dimensions of the Widget in DIP: \n" - + "landWidth = " + mWidgetLandSize.first - + ",\nlandHeight = " + mWidgetLandSize.second - + ",\nportWidth = " + mWidgetPortSize.first - + ",\nportHeight = " + mWidgetPortSize.second - + ",\nnew landWidth = " + mNewWidgetLandSize.first - + ",\nnew landHeight = " + mNewWidgetLandSize.second - + ",\nnew portWidth = " + mNewWidgetPortSize.first - + ",\nnew portHeight = " + mNewWidgetPortSize.second - ); - - return ctx.getResources().getBoolean(R.bool.isPort) - ? mNewWidgetPortSize.first != 0 || mNewWidgetPortSize.second != 0 - ? mNewWidgetPortSize - : mWidgetPortSize - : mNewWidgetLandSize.first != 0 || mNewWidgetLandSize.second != 0 - ? mNewWidgetLandSize - : mWidgetLandSize; - } - - public static Pair _widgetSize; - - public static Pair widgetSize(Context ctx) { - if (_widgetSize == null) - _widgetSize = Pair.create( - getPrefs(ctx).getInt(PrefsIds.WidgetSizeWidth.prefId, 1), - getPrefs(ctx).getInt(PrefsIds.WidgetSizeHeight.prefId, 1) - ); - return _widgetSize; - } - - Locale getCurrentLocale(Context context){ - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){ - return context.getResources().getConfiguration().getLocales().get(0); - } else{ - //noinspection deprecation - return context.getResources().getConfiguration().locale; - } - } - - private RemoteViews buildLayout(Context ctx, int appWidgetId, AppWidgetManager manager, boolean updateSize) { - val prefs = getPrefs(ctx); - - log.severe("prefs color: " + prefs.getString(PrefsIds.ThemePrimary.prefId, Integer.toHexString(defaultTheme.primary))); - - theme = new Theme( - Color.parseColor('#' + prefs.getString(PrefsIds.ThemePrimary.prefId, Integer.toHexString(defaultTheme.primary))), - Color.parseColor('#' + prefs.getString(PrefsIds.ThemeAccent.prefId, Integer.toHexString(defaultTheme.accent))), - Color.parseColor('#' + prefs.getString(PrefsIds.ThemeTextPrimary.prefId, Integer.toHexString(defaultTheme.textPrimary))), - Color.parseColor('#' + prefs.getString(PrefsIds.ThemeTextAccent.prefId, Integer.toHexString(defaultTheme.textAccent))), - Color.parseColor('#' + prefs.getString(PrefsIds.ThemeBackground.prefId, Integer.toHexString(defaultTheme.background))), - Brightness.values()[(int) prefs.getLong(PrefsIds.ThemeBrightness.prefId, defaultTheme.brightness.ordinal())] - ); - - // Set the size - if (updateSize) { - _widgetSize = getWidgetSize(ctx, appWidgetId, manager); - getPrefs(ctx).edit() - .putInt(PrefsIds.WidgetSizeWidth.prefId, _widgetSize.first) - .putInt(PrefsIds.WidgetSizeHeight.prefId, _widgetSize.second) - .apply(); - } - - // Get rounded background layout ids - - int bodyLayoutResId = -1; - int headLayoutResId = -1; - int layoutResId = -1; - - var translucent = getPrefs(ctx).getBoolean(PrefsIds.WidgetTranslucent.prefId, true); - - switch (theme.brightness) { - case Dark: - bodyLayoutResId = translucent - ? R.drawable.rounded_body_layout_dark_translucent - : R.drawable.rounded_body_layout_dark; - headLayoutResId = translucent - ? R.drawable.rounded_head_layout_dark_translucent - : R.drawable.rounded_head_layout_dark; - layoutResId = translucent - ? R.drawable.rounded_layout_dark_translucent - : R.drawable.rounded_layout_dark; - break; - case Light: - bodyLayoutResId = translucent - ? R.drawable.rounded_body_layout_light_translucent - : R.drawable.rounded_body_layout_light; - headLayoutResId = translucent - ? R.drawable.rounded_head_layout_light_translucent - : R.drawable.rounded_head_layout_light; - layoutResId = translucent - ? R.drawable.rounded_layout_light_translucent - : R.drawable.rounded_layout_light; - break; - } - - RemoteViews rv; - - var test = TimetableDatabase.getInstance(ctx).timetable(); - - var data = test.getAll(); - - var firstDate = data[0].date; - - Calendar cal = new GregorianCalendar(); - cal.setTimeInMillis(firstDate.getTime()*1000); - - if (TimetableDatabase.getInstance(ctx).timetable().count() != 0) { - - rv = new RemoteViews(ctx.getPackageName(), R.layout.widget_layout); - - var futureLessonFindDate = getTodayMidnight(); - futureLessonFindDate.add(Calendar.DATE, dateOffset); - - var dayStyle = DayStyle.values()[ - (int) getPrefs(ctx).getLong(PrefsIds.DayStyle.prefId, 0) - ]; - - String dayTitle = null; - switch (dayStyle) { - case Date: - dayTitle = futureLessonFindDate.get(Calendar.DAY_OF_MONTH) - + " " - + futureLessonFindDate.getDisplayName( - Calendar.MONTH, - Calendar.SHORT, - getCurrentLocale(ctx) - ); - break; - case Weekday: - dayTitle = futureLessonFindDate.getDisplayName( - Calendar.DAY_OF_WEEK, - Calendar.SHORT, - getCurrentLocale(ctx) - ); - dayTitle = dayTitle.substring(0, 1).toUpperCase() + dayTitle.substring(1); - break; - } - - int dayDescId; - switch (dateOffset) { - case 0: - dayDescId = R.string.widget_title_today; - break; - case 1: - dayDescId = R.string.widget_title_tomorrow; - break; - case 2: - dayDescId = R.string.widget_title_after_tomorrow; - break; - default: - dayDescId = R.string.widget_title_after_days; - } - - var dayDescStr = ctx.getString(dayDescId); - if (dateOffset > 2) - dayDescStr = String.format(dayDescStr, dateOffset); - - rv.setTextViewText(R.id.widget_title, - dayTitle != null ? dayTitle + ", " + dayDescStr : dayDescStr - ); - rv.setTextColor(R.id.widget_title, theme.textPrimary); - - // Specify the service to provide data for the collection widget. Note that we need to - // embed the appWidgetId via the data otherwise it will be ignored. - var intent = new Intent(ctx, WidgetService.class); - intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); - var futureLessonDate = GregorianCalendar.getInstance(); - futureLessonDate.setTimeInMillis( - futureLessonFindDate.getTimeInMillis() - ); - showDate = getMidnight(futureLessonDate).getTimeInMillis(); - intent.putExtra(WidgetRemoteViewsFactory.DATE, showDate); - intent.putExtra(WidgetRemoteViewsFactory.THEME_PRIMARY, theme.primary); - intent.putExtra(WidgetRemoteViewsFactory.THEME_ACCENT, theme.accent); - intent.putExtra(WidgetRemoteViewsFactory.THEME_TEXT_PRIMARY, theme.textPrimary); - intent.putExtra(WidgetRemoteViewsFactory.THEME_TEXT_ACCENT, theme.textAccent); - intent.putExtra(WidgetRemoteViewsFactory.THEME_BACKGROUND, theme.background); - intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME))); - - rv.setInt(R.id.widget_body, "setBackgroundResource", bodyLayoutResId); - rv.setInt(R.id.widget_head, "setBackgroundResource", headLayoutResId); - rv.setInt(R.id.create_calendar_events, "setColorFilter", theme.textPrimary); - rv.setInt(R.id.create_alarm_clock, "setColorFilter", theme.textPrimary); - rv.setInt(R.id.day_next, "setColorFilter", theme.textPrimary); - rv.setInt(R.id.day_prev, "setColorFilter", theme.textPrimary); - - rv.setOnClickPendingIntent(R.id.create_alarm_clock, getPendingSelfIntent(ctx, IntentAction.CreateAlarmClock.action)); - rv.setOnClickPendingIntent(R.id.create_calendar_events, getPendingSelfIntent(ctx, IntentAction.CreateCalendarEvents.action)); - rv.setOnClickPendingIntent(R.id.day_next, getPendingSelfIntent(ctx, IntentAction.DayNext.action)); - rv.setOnClickPendingIntent(R.id.day_prev, getPendingSelfIntent(ctx, IntentAction.DayPrev.action)); - - rv.setViewPadding( - R.id.widget_title, dateOffset == 0 - ? (int) WidgetRemoteViewsFactory.dpToPixel(ctx, 16) - : 0, 0, 0, 0 - ); - rv.setViewVisibility(R.id.day_prev, dateOffset > 0 ? View.VISIBLE : View.GONE); - rv.setViewVisibility(R.id.day_next, dateOffset < 6 ? View.VISIBLE : View.GONE); - - rv.setRemoteAdapter(R.id.timeline_list, intent); - rv.setImageViewBitmap( - R.id.empty_view, - buildEmptyViewBitmap(ctx, theme) - ); - rv.setEmptyView(R.id.timeline_list, R.id.empty_view); - - } else { - rv = new RemoteViews(ctx.getPackageName(), R.layout.widget_no_cache_layout); - - rv.setInt(R.id.widget_no_cache_image, "setBackgroundResource", layoutResId); - rv.setOnClickPendingIntent(R.id.widget_no_cache_image, - PendingIntent.getActivity( - ctx, - 0, - new Intent( - ctx, - MainActivity.class - ), - 0 - ) - ); - rv.setImageViewBitmap( - R.id.widget_no_cache_image, - buildNoCacheImageBitmap(ctx, theme) - ); - } - - return rv; - } - - protected PendingIntent getPendingSelfIntent(Context ctx, String action) { - var intent = new Intent(ctx, getClass()); - intent.setAction(action); - return PendingIntent.getBroadcast(ctx, 0, intent, 0); - } - - @Override - public void onUpdate(Context ctx, AppWidgetManager appWidgetManager, int[] appWidgetIds) { - log.info("widget onUpdate"); - - // Update each of the widgets with the remote adapter - for (int appWidgetId : appWidgetIds) { - appWidgetManager.updateAppWidget( - appWidgetId, - buildLayout( - ctx, - appWidgetId, - appWidgetManager, - true - ) - ); - } - super.onUpdate(ctx, appWidgetManager, appWidgetIds); - } - - @Override - public void onAppWidgetOptionsChanged(Context ctx, AppWidgetManager appWidgetManager, - int appWidgetId, Bundle newOptions) { - log.info("widget onAppWidgetOptionsChanged"); - - appWidgetManager.updateAppWidget( - appWidgetId, - buildLayout( - ctx, - appWidgetId, - appWidgetManager, - true - ) - ); - - appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.timeline_list); - } -} \ No newline at end of file diff --git a/android/app/src/main/java/ru/coolone/ranepatimetable/WidgetService.java b/android/app/src/main/java/ru/coolone/ranepatimetable/WidgetService.java deleted file mode 100644 index 3ec6ce8..0000000 --- a/android/app/src/main/java/ru/coolone/ranepatimetable/WidgetService.java +++ /dev/null @@ -1,433 +0,0 @@ -package ru.coolone.ranepatimetable; - -import android.content.Context; -import android.content.Intent; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.RectF; -import android.graphics.Typeface; -import android.os.Build; -import android.util.DisplayMetrics; -import android.view.View; -import android.widget.RemoteViews; -import android.widget.RemoteViewsService; - -import java.util.GregorianCalendar; -import java.util.Locale; - -import lombok.extern.java.Log; -import lombok.var; - -import static ru.coolone.ranepatimetable.Timeline.COLUMN_DATE; -import static ru.coolone.ranepatimetable.Timeline.COLUMN_FIRST; -import static ru.coolone.ranepatimetable.Timeline.COLUMN_GROUP; -import static ru.coolone.ranepatimetable.Timeline.COLUMN_LAST; -import static ru.coolone.ranepatimetable.Timeline.COLUMN_MERGE_TOP; -import static ru.coolone.ranepatimetable.Timeline.LessonAction; -import static ru.coolone.ranepatimetable.Timeline.LessonModel; -import static ru.coolone.ranepatimetable.Timeline.Location; -import static ru.coolone.ranepatimetable.Timeline.PREFIX_FINISH; -import static ru.coolone.ranepatimetable.Timeline.PREFIX_LESSON; -import static ru.coolone.ranepatimetable.Timeline.PREFIX_ROOM; -import static ru.coolone.ranepatimetable.Timeline.PREFIX_START; -import static ru.coolone.ranepatimetable.Timeline.PREFIX_TEACHER; -import static ru.coolone.ranepatimetable.Timeline.RoomModel; -import static ru.coolone.ranepatimetable.Timeline.TeacherModel; -import static ru.coolone.ranepatimetable.Timeline.TimeOfDayModel; -import static ru.coolone.ranepatimetable.WidgetProvider.RoomLocationStyle.Icon; -import static ru.coolone.ranepatimetable.WidgetProvider.defaultTheme; -import static ru.coolone.ranepatimetable.WidgetProvider.getPrefs; -import static ru.coolone.ranepatimetable.WidgetProvider.widgetSize; - -/** - * This is the service that provides the factory to be bound to the collection service. - */ -public class WidgetService extends RemoteViewsService { - @Override - public RemoteViewsFactory onGetViewFactory(Intent intent) { - return new WidgetRemoteViewsFactory(this.getApplicationContext(), intent); - } -} - -/** - * This is the factory that will provide data to the collection widget. - */ -@Log -class WidgetRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory { - private Context ctx; - private Cursor cursor; - private long dateMillis; - private WidgetProvider.Theme theme; - - public static final String DATE = "date"; - public static final String THEME_PRIMARY = "themePrimary"; - public static final String THEME_ACCENT = "themeAccent"; - public static final String THEME_TEXT_PRIMARY = "themeTextPrimary"; - public static final String THEME_TEXT_ACCENT = "themeTextAccent"; - public static final String THEME_BACKGROUND = "themeBackground"; - public static final String THEME_BRIGHTNESS = "themeBrightness"; - - public WidgetRemoteViewsFactory(Context ctx, Intent intent) { - this.ctx = ctx; - var intentDateMillis = intent.getLongExtra(DATE, -1); - if (intentDateMillis != -1) dateMillis = intentDateMillis; - theme = new WidgetProvider.Theme( - intent.getIntExtra(THEME_PRIMARY, defaultTheme.primary), - intent.getIntExtra(THEME_ACCENT, defaultTheme.accent), - intent.getIntExtra(THEME_TEXT_PRIMARY, defaultTheme.textPrimary), - intent.getIntExtra(THEME_TEXT_ACCENT, defaultTheme.textAccent), - intent.getIntExtra(THEME_BACKGROUND, defaultTheme.background), - WidgetProvider.Brightness.values()[intent.getIntExtra(THEME_BRIGHTNESS, defaultTheme.brightness.ordinal())] - ); - } - - @Override - public void onCreate() { - // Since we reload the cursor in onDataSetChanged() which gets called immediately after - // onCreate(), we do nothing here. - } - - @Override - public void onDestroy() { - if (cursor != null) { - cursor.close(); - } - } - - @Override - public int getCount() { - log.info("Widget columns count: " + cursor.getCount()); - return cursor.getCount(); - } - - /** - * This method converts dp unit to equivalent pixels, depending on device density. - * - * @param dp A value in dp (density independent pixels) unit. Which we need to convert into pixels - * @return A float value to represent px equivalent to dp depending on device density - */ - static float dpToPixel(Context ctx, float dp) { - var metrics = ctx.getResources().getDisplayMetrics(); - return dp * ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT); - } - - private static float _dpScale = -1; - - static float dpScale(Context ctx) { - if (_dpScale == -1) _dpScale = dpToPixel(ctx, 1); - return _dpScale; - } - - private static final int rectMargins = 8, - iconSize = 29, - circleRadius = 23, - rectCornersRadius = 10, - circleMargin = 5, - circleRadiusAdd = 3; - - private Bitmap buildItemBitmap(Context ctx) { - var dpScale = dpScale(ctx); - var widgetSize = widgetSize(ctx); - - var w = (widgetSize.first > 0 ? widgetSize.first : 100) * dpScale; - var h = 80 * dpScale; - - log.info("w: " + w + ", h: " + h); - - var bitmap = Bitmap.createBitmap((int) w, (int) h, Bitmap.Config.ARGB_8888); - var canvas = new Canvas(bitmap); - - // Background rect draw - var rect = new RectF(dpScale * rectMargins, dpScale * rectMargins, - w - rectMargins * dpScale, h); - var bgRectPaint = new Paint(); - bgRectPaint.setAntiAlias(true); - bgRectPaint.setColor(theme.background); - canvas.drawRoundRect(rect, dpScale * rectCornersRadius, dpScale * rectCornersRadius, bgRectPaint); - - var mergeTop = cursor.getInt(cursor.getColumnIndex(COLUMN_MERGE_TOP)) != 0; - if (mergeTop) { - var mergePaint = new Paint(); - mergePaint.setAntiAlias(true); - mergePaint.setColor(Color.argb( - Color.alpha(theme.background) / 2, - Color.red(theme.background), - Color.green(theme.background), - Color.blue(theme.background - )) - ); - canvas.drawRect( - new RectF( - dpScale * rectCornersRadius * 2, - 0, - w - (dpScale * rectCornersRadius * 2), - dpScale * rectMargins - ), - mergePaint - ); - } - - var first = cursor.getInt(cursor.getColumnIndex(COLUMN_FIRST)) != 0; - var last = cursor.getInt(cursor.getColumnIndex(COLUMN_LAST)) != 0; - - var circleX = dpScale * (rectMargins * 2 + circleRadius + 68); - var circleY = h / 2 + dpScale * (rectMargins / 2f); - - var translateIcon = 0.0f; - - if (!(first && last)) { - var rectPaint = new Paint(); - rectPaint.setAntiAlias(true); - rectPaint.setColor(theme.accent); - - // Rect round - if (first || !last) { - translateIcon = circleMargin; - circleY -= circleMargin; - canvas.drawRect( - circleX - circleRadius * dpScale, circleY - 1, - circleX + circleRadius * dpScale, dpScale * h + 1, - rectPaint - ); - } - if (last || !first) { - translateIcon = -circleMargin; - circleY += circleMargin; - canvas.drawRect( - circleX - circleRadius * dpScale, -1, - circleX + circleRadius * dpScale, circleY + 1, - rectPaint - ); - } - - // Arc draw - var arcRect = new RectF( - circleX - circleRadius * dpScale, circleY - circleRadius * dpScale, - circleX + circleRadius * dpScale, circleY + circleRadius * dpScale - ); - var arcPaint = new Paint(); - arcPaint.setAntiAlias(true); - arcPaint.setColor(theme.accent); - - if (first) - canvas.drawArc( - arcRect, - 180f, - 180f, - false, - arcPaint - ); - else if (last) - canvas.drawArc( - arcRect, - 0f, - 180f, - false, - arcPaint - ); - } else { - // Draw circle - var circlePaint = new Paint(); - circlePaint.setAntiAlias(true); - circlePaint.setColor(theme.accent); - circlePaint.setStyle(Paint.Style.FILL); - - canvas.drawCircle( - circleX, - circleY, - dpScale * (circleRadius + circleRadiusAdd), - circlePaint - ); - } - - // Draw icons - var iconPaint = new Paint(); - iconPaint.setAntiAlias(true); - iconPaint.setSubpixelText(true); - iconPaint.setTextAlign(Paint.Align.CENTER); - iconPaint.setTypeface( - Typeface.createFromAsset( - ctx.getAssets(), - "fonts/TimetableIcons.ttf" - ) - ); - - // Draw lesson icon - iconPaint.setTextSize(dpScale * iconSize); - iconPaint.setColor(theme.textAccent); - canvas.drawText( - String.valueOf( - Character.toChars( - cursor.getInt( - cursor.getColumnIndex( - PREFIX_LESSON - + LessonModel.COLUMN_LESSON_ICON) - ) - ) - ), circleX, circleY + dpScale * (10 + translateIcon), iconPaint - ); - - // Draw room location icon - if (WidgetProvider.RoomLocationStyle.values()[ - (int) getPrefs(ctx).getLong(WidgetProvider.PrefsIds.RoomLocationStyle.prefId, 0) - ] == Icon) { - var roomLocation = Location.values()[cursor.getInt(cursor.getColumnIndex( - PREFIX_ROOM - + RoomModel.COLUMN_ROOM_LOCATION) - )]; - iconPaint.setColor(theme.textPrimary); - iconPaint.setTextSize(dpScale * 20); - canvas.drawText( - String.valueOf( - Character.toChars(roomLocation.iconCodePoint) - ), dpScale * 25, dpScale * 70, iconPaint - ); - } - - return bitmap; - } - - private Locale getCurrentLocale() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - return ctx.getResources().getConfiguration().getLocales().get(0); - } else { - //noinspection deprecation - return ctx.getResources().getConfiguration().locale; - } - } - - @Override - public RemoteViews getViewAt(int position) { - var rv = new RemoteViews(ctx.getPackageName(), R.layout.widget_item); - - // Get the data for this position from the content provider - if (cursor.moveToPosition(position)) { - var date = new GregorianCalendar(); - date.setTimeInMillis(cursor.getLong(cursor.getColumnIndex(COLUMN_DATE))); - - var start = new TimeOfDayModel( - cursor.getInt(cursor.getColumnIndex(PREFIX_START + TimeOfDayModel.COLUMN_TIMEOFDAY_HOUR)), - cursor.getInt(cursor.getColumnIndex(PREFIX_START + TimeOfDayModel.COLUMN_TIMEOFDAY_MINUTE)) - ); - var finish = new TimeOfDayModel( - cursor.getInt(cursor.getColumnIndex(PREFIX_FINISH + TimeOfDayModel.COLUMN_TIMEOFDAY_HOUR)), - cursor.getInt(cursor.getColumnIndex(PREFIX_FINISH + TimeOfDayModel.COLUMN_TIMEOFDAY_MINUTE)) - ); - - rv.setTextViewText(R.id.widget_item_lesson_title, - cursor.getString( - cursor.getColumnIndex( - PREFIX_LESSON + ( - getPrefs(ctx).getBoolean( - WidgetProvider.PrefsIds.OptimizedLessonTitles.prefId, - true - ) - ? LessonModel.COLUMN_LESSON_TITLE - : LessonModel.COLUMN_LESSON_FULL_TITLE - )))); - var teacherName = cursor.getString(cursor.getColumnIndex(PREFIX_TEACHER + TeacherModel.COLUMN_TEACHER_NAME)); - var teacherSurname = cursor.getString(cursor.getColumnIndex(PREFIX_TEACHER + TeacherModel.COLUMN_TEACHER_SURNAME)); - var teacherPatronymic = cursor.getString(cursor.getColumnIndex(PREFIX_TEACHER + TeacherModel.COLUMN_TEACHER_PATRONYMIC)); - var group = cursor.getString(cursor.getColumnIndex(COLUMN_GROUP)); - var user = WidgetProvider.SearchItemTypeId.values()[(int) getPrefs(ctx).getLong( - WidgetProvider.PrefsIds.ItemType.prefId, - -1 - )]; - rv.setTextViewText(R.id.widget_item_teacher_or_group, - user == WidgetProvider.SearchItemTypeId.Group - ? teacherSurname + ' ' + teacherName.charAt(0) + ". " + teacherPatronymic.charAt(0) + '.' - : group); - rv.setTextViewText(R.id.widget_item_start, String.format(getCurrentLocale(), "%d:%02d", start.hour, start.minute)); - rv.setTextViewText(R.id.widget_item_finish, String.format(getCurrentLocale(), "%d:%02d", finish.hour, finish.minute)); - - var prefix = ""; - var roomLocationStyle = WidgetProvider.RoomLocationStyle.values()[ - (int) getPrefs(ctx).getLong(WidgetProvider.PrefsIds.RoomLocationStyle.prefId, 0) - ]; - switch (roomLocationStyle) { - case Icon: - rv.setViewPadding(R.id.widget_item_room_number, - (int) dpToPixel(ctx, 22), - 0, 0, 0 - ); - break; - case Text: - switch (Location.values()[cursor.getInt(cursor.getColumnIndex( - PREFIX_ROOM - + RoomModel.COLUMN_ROOM_LOCATION))]) { - case Hotel: - prefix = "П8-"; - break; - case StudyHostel: - prefix = "СО-"; - break; - } - break; - } - rv.setTextViewText(R.id.widget_item_room_number, - prefix + cursor.getString(cursor.getColumnIndex( - PREFIX_ROOM - + RoomModel.COLUMN_ROOM_NUMBER) - )); - var action = cursor.getString( - cursor.getColumnIndex( - PREFIX_LESSON - + LessonModel.PREFIX_LESSON_ACTION - + LessonAction.COLUMN_LESSON_TYPE_TITLE - )); - if (action == null) - rv.setViewVisibility(R.id.widget_item_lesson_action, View.GONE); - else - rv.setTextViewText(R.id.widget_item_lesson_action, action); - - rv.setTextColor(R.id.widget_item_lesson_action, theme.textPrimary); - rv.setTextColor(R.id.widget_item_lesson_title, theme.textPrimary); - rv.setTextColor(R.id.widget_item_teacher_or_group, theme.textPrimary); - rv.setTextColor(R.id.widget_item_start, theme.textPrimary); - rv.setTextColor(R.id.widget_item_finish, theme.textPrimary); - rv.setTextColor(R.id.widget_item_room_number, theme.textPrimary); - - rv.setImageViewBitmap( - R.id.widget_item_image, - buildItemBitmap(ctx) - ); - } - - return rv; - } - - @Override - public RemoteViews getLoadingView() { - // We aren't going to return a default loading view in this sample - return null; - } - - @Override - public int getViewTypeCount() { - // Technically, we have two types of views (the dark and light background views) - return 2; - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public boolean hasStableIds() { - return true; - } - - @Override - public void onDataSetChanged() { - // Refresh the cursor - if (cursor != null) { - cursor.close(); - } - log.info("Database cursor refresh... date: " + dateMillis); - cursor = TimetableDatabase.getInstance(ctx).timetable().selectByDate(dateMillis); - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/ru/coolone/ranepatimetable/MainActivity.kt b/android/app/src/main/kotlin/ru/coolone/ranepatimetable/MainActivity.kt new file mode 100644 index 0000000..b7e923d --- /dev/null +++ b/android/app/src/main/kotlin/ru/coolone/ranepatimetable/MainActivity.kt @@ -0,0 +1,6 @@ +package ru.coolone.ranepatimetable + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png deleted file mode 100644 index 0bd8e7e..0000000 Binary files a/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png deleted file mode 100644 index bb7ac31..0000000 Binary files a/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-night/launch_background.xml b/android/app/src/main/res/drawable-night/launch_background.xml deleted file mode 100644 index dc657be..0000000 --- a/android/app/src/main/res/drawable-night/launch_background.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png deleted file mode 100644 index 2f75c04..0000000 Binary files a/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png deleted file mode 100644 index b7b0e8d..0000000 Binary files a/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png deleted file mode 100644 index addba27..0000000 Binary files a/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/android/app/src/main/res/drawable/ic_alarm.xml b/android/app/src/main/res/drawable/ic_alarm.xml deleted file mode 100644 index 934b067..0000000 --- a/android/app/src/main/res/drawable/ic_alarm.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_calendar.xml b/android/app/src/main/res/drawable/ic_calendar.xml deleted file mode 100644 index 22f1bb6..0000000 --- a/android/app/src/main/res/drawable/ic_calendar.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_navigate_before.xml b/android/app/src/main/res/drawable/ic_navigate_before.xml deleted file mode 100644 index e6bb3ca..0000000 --- a/android/app/src/main/res/drawable/ic_navigate_before.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_navigate_next.xml b/android/app/src/main/res/drawable/ic_navigate_next.xml deleted file mode 100644 index 2483512..0000000 --- a/android/app/src/main/res/drawable/ic_navigate_next.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml index c182832..304732f 100644 --- a/android/app/src/main/res/drawable/launch_background.xml +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -1,10 +1,12 @@ + - + - + + diff --git a/android/app/src/main/res/drawable/logo_vector.xml b/android/app/src/main/res/drawable/logo_vector.xml deleted file mode 100644 index 0fbeac8..0000000 --- a/android/app/src/main/res/drawable/logo_vector.xml +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/android/app/src/main/res/drawable/rounded_body_layout_dark.xml b/android/app/src/main/res/drawable/rounded_body_layout_dark.xml deleted file mode 100644 index b4879a6..0000000 --- a/android/app/src/main/res/drawable/rounded_body_layout_dark.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/rounded_body_layout_dark_translucent.xml b/android/app/src/main/res/drawable/rounded_body_layout_dark_translucent.xml deleted file mode 100644 index 5ba8c4e..0000000 --- a/android/app/src/main/res/drawable/rounded_body_layout_dark_translucent.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/rounded_body_layout_light.xml b/android/app/src/main/res/drawable/rounded_body_layout_light.xml deleted file mode 100644 index ad1142c..0000000 --- a/android/app/src/main/res/drawable/rounded_body_layout_light.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/rounded_body_layout_light_translucent.xml b/android/app/src/main/res/drawable/rounded_body_layout_light_translucent.xml deleted file mode 100644 index 061b93a..0000000 --- a/android/app/src/main/res/drawable/rounded_body_layout_light_translucent.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/rounded_head_layout_dark.xml b/android/app/src/main/res/drawable/rounded_head_layout_dark.xml deleted file mode 100644 index 72eaf5a..0000000 --- a/android/app/src/main/res/drawable/rounded_head_layout_dark.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/rounded_head_layout_dark_translucent.xml b/android/app/src/main/res/drawable/rounded_head_layout_dark_translucent.xml deleted file mode 100644 index b5e6167..0000000 --- a/android/app/src/main/res/drawable/rounded_head_layout_dark_translucent.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/rounded_head_layout_light.xml b/android/app/src/main/res/drawable/rounded_head_layout_light.xml deleted file mode 100644 index 4d13065..0000000 --- a/android/app/src/main/res/drawable/rounded_head_layout_light.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/rounded_head_layout_light_translucent.xml b/android/app/src/main/res/drawable/rounded_head_layout_light_translucent.xml deleted file mode 100644 index 07e62ee..0000000 --- a/android/app/src/main/res/drawable/rounded_head_layout_light_translucent.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/rounded_layout_dark.xml b/android/app/src/main/res/drawable/rounded_layout_dark.xml deleted file mode 100644 index 3c3cde8..0000000 --- a/android/app/src/main/res/drawable/rounded_layout_dark.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/rounded_layout_dark_translucent.xml b/android/app/src/main/res/drawable/rounded_layout_dark_translucent.xml deleted file mode 100644 index 81d5a41..0000000 --- a/android/app/src/main/res/drawable/rounded_layout_dark_translucent.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/rounded_layout_light.xml b/android/app/src/main/res/drawable/rounded_layout_light.xml deleted file mode 100644 index 7ba53b3..0000000 --- a/android/app/src/main/res/drawable/rounded_layout_light.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/rounded_layout_light_translucent.xml b/android/app/src/main/res/drawable/rounded_layout_light_translucent.xml deleted file mode 100644 index 45683b1..0000000 --- a/android/app/src/main/res/drawable/rounded_layout_light_translucent.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/widget_preview.png b/android/app/src/main/res/drawable/widget_preview.png deleted file mode 100644 index 9b42d5f..0000000 Binary files a/android/app/src/main/res/drawable/widget_preview.png and /dev/null differ diff --git a/android/app/src/main/res/layout/widget_item.xml b/android/app/src/main/res/layout/widget_item.xml deleted file mode 100644 index c6f7d05..0000000 --- a/android/app/src/main/res/layout/widget_item.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/android/app/src/main/res/layout/widget_layout.xml b/android/app/src/main/res/layout/widget_layout.xml deleted file mode 100644 index da3eca3..0000000 --- a/android/app/src/main/res/layout/widget_layout.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/layout/widget_no_cache_layout.xml b/android/app/src/main/res/layout/widget_no_cache_layout.xml deleted file mode 100644 index 17ef540..0000000 --- a/android/app/src/main/res/layout/widget_no_cache_layout.xml +++ /dev/null @@ -1,6 +0,0 @@ - - \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 5f349f7..0000000 --- a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index 36496eb..db77bb4 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/logo_mipmap.png b/android/app/src/main/res/mipmap-hdpi/logo_mipmap.png deleted file mode 100644 index 407df47..0000000 Binary files a/android/app/src/main/res/mipmap-hdpi/logo_mipmap.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 91937c4..17987b7 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/logo_mipmap.png b/android/app/src/main/res/mipmap-mdpi/logo_mipmap.png deleted file mode 100644 index 0d796a5..0000000 Binary files a/android/app/src/main/res/mipmap-mdpi/logo_mipmap.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 346a523..09d4391 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/logo_mipmap.png b/android/app/src/main/res/mipmap-xhdpi/logo_mipmap.png deleted file mode 100644 index 82a2634..0000000 Binary files a/android/app/src/main/res/mipmap-xhdpi/logo_mipmap.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 2145ad1..d5f1c8d 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/logo_mipmap.png b/android/app/src/main/res/mipmap-xxhdpi/logo_mipmap.png deleted file mode 100644 index 23f05f7..0000000 Binary files a/android/app/src/main/res/mipmap-xxhdpi/logo_mipmap.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 358c39c..4d6372e 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/logo_mipmap.png b/android/app/src/main/res/mipmap-xxxhdpi/logo_mipmap.png deleted file mode 100644 index 0682729..0000000 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/logo_mipmap.png and /dev/null differ diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..06952be --- /dev/null +++ b/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/main/res/values-port/bools.xml b/android/app/src/main/res/values-port/bools.xml deleted file mode 100644 index 67cf5c9..0000000 --- a/android/app/src/main/res/values-port/bools.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - true - \ No newline at end of file diff --git a/android/app/src/main/res/values-ru/values.xml b/android/app/src/main/res/values-ru/values.xml deleted file mode 100644 index e118720..0000000 --- a/android/app/src/main/res/values-ru/values.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - НИУ РАНХиГС (Расписание) - Сегодня - Завтра - Послезавтра - Через %o дня(-ей) - Пар не найдено. - Не задано время до будильника.\nЕго можно задать в настройках приложения. - Не удалось получить доступ к календарю. - Произошла ошибка при добавлении событий в календарь. - События успешно добавлены в календарь. - Свободный день - Расписание не закэшировано.\nТапните на виджет чтобы открыть\nприложение и его закешировать. - \ No newline at end of file diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml deleted file mode 100644 index 8649d74..0000000 --- a/android/app/src/main/res/values/colors.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - #F06B7E - #80000000 - #303030 - \ No newline at end of file diff --git a/android/app/src/main/res/values/dimen.xml b/android/app/src/main/res/values/dimen.xml deleted file mode 100644 index e3ba21d..0000000 --- a/android/app/src/main/res/values/dimen.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - 40dp - 16dp - 10dp - \ No newline at end of file diff --git a/android/app/src/main/res/values/orientation.xml b/android/app/src/main/res/values/orientation.xml deleted file mode 100644 index f47e01b..0000000 --- a/android/app/src/main/res/values/orientation.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - false - \ No newline at end of file diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index 00fa441..cb1ef88 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -1,8 +1,18 @@ - + + diff --git a/android/app/src/main/res/values/values.xml b/android/app/src/main/res/values/values.xml deleted file mode 100644 index 6536af1..0000000 --- a/android/app/src/main/res/values/values.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - NRU RANEPA (Timetable) - Today - Tomorrow - Day after tomorrow - In %o days - No lessons found. - Not set time to alarm.\nIt can be set in the application settings. - Could not access the calendar. - An error occurred while adding events to the calendar. - Events successfully added to calendar. - Free day - The schedule is not cached.\nTap on the widget to open\nthe application and cache it. - \ No newline at end of file diff --git a/android/app/src/main/res/xml-v17/timetable_widget_info.xml b/android/app/src/main/res/xml-v17/timetable_widget_info.xml deleted file mode 100644 index 52f2067..0000000 --- a/android/app/src/main/res/xml-v17/timetable_widget_info.xml +++ /dev/null @@ -1,10 +0,0 @@ - - \ No newline at end of file diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/build.gradle b/android/build.gradle index 77da17e..f7eb7f6 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,19 +1,20 @@ buildscript { + ext.kotlin_version = '1.7.10' repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath 'com.google.gms:google-services:4.3.3' - classpath 'com.android.tools.build:gradle:3.5.3' + classpath 'com.android.tools.build:gradle:7.3.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } allprojects { repositories { google() - jcenter() + mavenCentral() } } @@ -25,6 +26,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/android/gradle.properties b/android/gradle.properties index b6e61b6..94adc3a 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,4 +1,3 @@ -android.enableJetifier=true -android.useAndroidX=true org.gradle.jvmargs=-Xmx1536M -android.enableR8=true +android.useAndroidX=true +android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index c1637d8..3c472b9 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Wed Oct 02 22:35:17 MSK 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/android/key.properties b/android/key.properties deleted file mode 100644 index 034e2ac..0000000 --- a/android/key.properties +++ /dev/null @@ -1,4 +0,0 @@ -storePassword=c6o00ol10on14e3 -keyPassword=c6o00ol10on14e3 -keyAlias=ranepatimetable -storeFile=../../../cool_android_release.keystore \ No newline at end of file diff --git a/android/settings.gradle b/android/settings.gradle index 5a2f14f..44e62bc 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,15 +1,11 @@ include ':app' -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } -} +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":$name" - project(":$name").projectDir = pluginDirectory -} +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..7a7f987 --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/ios/Cartfile b/ios/Cartfile deleted file mode 100644 index 2e50df7..0000000 --- a/ios/Cartfile +++ /dev/null @@ -1 +0,0 @@ -github "stephencelis/SQLite.swift" ~> 0.12.2 \ No newline at end of file diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index 9367d48..9625e10 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 8.0 + 11.0 diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig index e8efba1..ec97fc6 100644 --- a/ios/Flutter/Debug.xcconfig +++ b/ios/Flutter/Debug.xcconfig @@ -1,2 +1,2 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Flutter/Generated.xcconfig b/ios/Flutter/Generated.xcconfig index 4a78848..7761b7e 100644 --- a/ios/Flutter/Generated.xcconfig +++ b/ios/Flutter/Generated.xcconfig @@ -1,11 +1,15 @@ // This is a generated file; do not edit or check into version control. -FLUTTER_ROOT=/Users/coolone/AndroidStudioProjects/flutter -FLUTTER_APPLICATION_PATH=/Users/coolone/AndroidStudioProjects/ranepa_timetable -FLUTTER_TARGET=/Users/coolone/AndroidStudioProjects/ranepa_timetable/lib/main.dart +FLUTTER_ROOT=/Users/vadimruzavin/fvm/versions/3.10.1 +FLUTTER_APPLICATION_PATH=/Users/vadimruzavin/AndroidStudioProjects/ranepa_timetable +COCOAPODS_PARALLEL_CODE_SIGN=true +FLUTTER_TARGET=/Users/vadimruzavin/AndroidStudioProjects/ranepa_timetable/lib/main.dart FLUTTER_BUILD_DIR=build -SYMROOT=${SOURCE_ROOT}/../build/ios -OTHER_LDFLAGS=$(inherited) -framework Flutter -FLUTTER_FRAMEWORK_DIR=/Users/coolone/AndroidStudioProjects/flutter/bin/cache/artifacts/engine/ios -FLUTTER_BUILD_NAME=1.8.0 -FLUTTER_BUILD_NUMBER=19 +FLUTTER_BUILD_NAME=1.0.0 +FLUTTER_BUILD_NUMBER=1 +EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386 +EXCLUDED_ARCHS[sdk=iphoneos*]=armv7 +DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==,RkxVVFRFUl9XRUJfQ0FOVkFTS0lUX1VSTD1odHRwczovL3d3dy5nc3RhdGljLmNvbS9mbHV0dGVyLWNhbnZhc2tpdC9iNGZiMTEyMTRkZDJkZGE2Y2UwMTJkZDk4ZWE0OThlOWU4YjkxMjYyLw== +DART_OBFUSCATION=false TRACK_WIDGET_CREATION=true +TREE_SHAKE_ICONS=false +PACKAGE_CONFIG=/Users/vadimruzavin/AndroidStudioProjects/ranepa_timetable/.dart_tool/package_config.json diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig index 399e934..c4855bf 100644 --- a/ios/Flutter/Release.xcconfig +++ b/ios/Flutter/Release.xcconfig @@ -1,2 +1,2 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..6f0819c --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,44 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '11.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +# target 'RunnerTests' do +# inherit! :search_paths +# end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000..c4c7d4c --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,72 @@ +PODS: + - connectivity (0.0.1): + - Flutter + - Reachability + - device_calendar (0.0.1): + - Flutter + - Flutter (1.0.0) + - flutter_email_sender (0.0.1): + - Flutter + - FMDB (2.7.5): + - FMDB/standard (= 2.7.5) + - FMDB/standard (2.7.5) + - package_info (0.0.1): + - Flutter + - Reachability (3.2) + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS + - sqflite (0.0.3): + - Flutter + - FMDB (>= 2.7.5) + - url_launcher_ios (0.0.1): + - Flutter + +DEPENDENCIES: + - connectivity (from `.symlinks/plugins/connectivity/ios`) + - device_calendar (from `.symlinks/plugins/device_calendar/ios`) + - Flutter (from `Flutter`) + - flutter_email_sender (from `.symlinks/plugins/flutter_email_sender/ios`) + - package_info (from `.symlinks/plugins/package_info/ios`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) + - sqflite (from `.symlinks/plugins/sqflite/ios`) + - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) + +SPEC REPOS: + trunk: + - FMDB + - Reachability + +EXTERNAL SOURCES: + connectivity: + :path: ".symlinks/plugins/connectivity/ios" + device_calendar: + :path: ".symlinks/plugins/device_calendar/ios" + Flutter: + :path: Flutter + flutter_email_sender: + :path: ".symlinks/plugins/flutter_email_sender/ios" + package_info: + :path: ".symlinks/plugins/package_info/ios" + shared_preferences_foundation: + :path: ".symlinks/plugins/shared_preferences_foundation/darwin" + sqflite: + :path: ".symlinks/plugins/sqflite/ios" + url_launcher_ios: + :path: ".symlinks/plugins/url_launcher_ios/ios" + +SPEC CHECKSUMS: + connectivity: c4130b2985d4ef6fd26f9702e886bd5260681467 + device_calendar: 9cb33f88a02e19652ec7b8b122ca778f751b1f7b + Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + flutter_email_sender: 02d7443217d8c41483223627972bfdc09f74276b + FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a + package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62 + Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 + shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c + sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a + url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4 + +PODFILE CHECKSUM: b17e1ecfe97aba85f3997d462fe23d9e4313a8d8 + +COCOAPODS: 1.11.2 diff --git a/ios/Runner-Bridging-Header.h b/ios/Runner-Bridging-Header.h deleted file mode 100644 index 1b2cb5d..0000000 --- a/ios/Runner-Bridging-Header.h +++ /dev/null @@ -1,4 +0,0 @@ -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// - diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 40ffdbf..21b2625 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -3,64 +3,26 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 31D3B112F8A2533B0A7C9C5E /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66A6929F0B3CDA6C1F10FE2B /* Pods_Runner.framework */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 7AFEC5E8ED9E1A07079435E5 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A9BBFDCB1E71FC1AFED79AB /* Pods_Runner.framework */; }; - 858E64B323ED6E8000722D91 /* NotificationCenter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 858E64B223ED6E8000722D91 /* NotificationCenter.framework */; }; - 858E64B623ED6E8000722D91 /* TodayViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 858E64B523ED6E8000722D91 /* TodayViewController.swift */; }; - 858E64B923ED6E8000722D91 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 858E64B723ED6E8000722D91 /* MainInterface.storyboard */; }; - 858E64BE23ED6E8100722D91 /* TodayExtTest.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 858E64B123ED6E8000722D91 /* TodayExtTest.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - 858E64C623ED6EA500722D91 /* CustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 858E64C323ED6EA400722D91 /* CustomCell.swift */; }; - 858E64C723ED6EA500722D91 /* TimelinePainter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 858E64C423ED6EA400722D91 /* TimelinePainter.swift */; }; - 858E64CC23EDD32900722D91 /* FlutterUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 858E64CB23EDD32900722D91 /* FlutterUserDefaults.swift */; }; - 858E64D823EDE53800722D91 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 858E64CD23EDD5F300722D91 /* SQLite.framework */; }; - 858E64D923EDE53800722D91 /* SQLite.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 858E64CD23EDD5F300722D91 /* SQLite.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 858E64DB23EDE83E00722D91 /* LessonsDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 858E64DA23EDE83E00722D91 /* LessonsDatabase.swift */; }; - 858E64DE23EDFB7A00722D91 /* TimetableIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 858E64DD23EDFB7A00722D91 /* TimetableIcons.ttf */; }; - 858E64E423EFFFBE00722D91 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 858E64E623EFFFBE00722D91 /* Localizable.strings */; }; - 858E64EA23F007E000722D91 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 858E64EC23F007E000722D91 /* InfoPlist.strings */; }; - 858E64F023F008FE00722D91 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 858E64F223F008FE00722D91 /* InfoPlist.strings */; }; - 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; - 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; - 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - 858E64BB23ED6E8000722D91 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 97C146E61CF9000F007C117D /* Project object */; - proxyType = 1; - remoteGlobalIDString = 858E64B023ED6E8000722D91; - remoteInfo = TodayExt; - }; -/* End PBXContainerItemProxy section */ - /* Begin PBXCopyFilesBuildPhase section */ - 858E64BD23ED6E8100722D91 /* Embed App Extensions */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 13; - files = ( - 858E64BE23ED6E8100722D91 /* TodayExtTest.appex in Embed App Extensions */, - ); - name = "Embed App Extensions"; - runOnlyForDeploymentPostprocessing = 0; - }; 9705A1C41CF9048500538489 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( - 858E64D923EDE53800722D91 /* SQLite.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -68,104 +30,62 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 0A9BBFDCB1E71FC1AFED79AB /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 0BAC359DFFE2CD3E06588691 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 361DA379224581B40067E0D1 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 3CBE2D7E8A29364C72C76242 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 66A6929F0B3CDA6C1F10FE2B /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 858E64B123ED6E8000722D91 /* TodayExtTest.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = TodayExtTest.appex; sourceTree = BUILT_PRODUCTS_DIR; }; - 858E64B223ED6E8000722D91 /* NotificationCenter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NotificationCenter.framework; path = System/Library/Frameworks/NotificationCenter.framework; sourceTree = SDKROOT; }; - 858E64B523ED6E8000722D91 /* TodayViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewController.swift; sourceTree = ""; }; - 858E64B823ED6E8000722D91 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = ""; }; - 858E64BA23ED6E8000722D91 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 858E64C323ED6EA400722D91 /* CustomCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomCell.swift; sourceTree = ""; }; - 858E64C423ED6EA400722D91 /* TimelinePainter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimelinePainter.swift; sourceTree = ""; }; - 858E64C923ED73AD00722D91 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; - 858E64CA23ED73B500722D91 /* TodayExt.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = TodayExt.entitlements; sourceTree = ""; }; - 858E64CB23EDD32900722D91 /* FlutterUserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlutterUserDefaults.swift; sourceTree = ""; }; - 858E64CD23EDD5F300722D91 /* SQLite.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SQLite.framework; path = Carthage/Build/iOS/SQLite.framework; sourceTree = ""; }; - 858E64DA23EDE83E00722D91 /* LessonsDatabase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LessonsDatabase.swift; sourceTree = ""; }; - 858E64DD23EDFB7A00722D91 /* TimetableIcons.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = TimetableIcons.ttf; path = ../../../assets/fonts/TimetableIcons.ttf; sourceTree = ""; }; - 858E64DF23EFFEBD00722D91 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Main.strings; sourceTree = ""; }; - 858E64E023EFFEBD00722D91 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/LaunchScreen.strings; sourceTree = ""; }; - 858E64E123EFFEBE00722D91 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/MainInterface.strings; sourceTree = ""; }; - 858E64E523EFFFBE00722D91 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; - 858E64E723EFFFC600722D91 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; - 858E64EB23F007E000722D91 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/InfoPlist.strings; sourceTree = ""; }; - 858E64ED23F007E300722D91 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 858E64F123F008FE00722D91 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 858E64F323F0090200722D91 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/InfoPlist.strings; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - BDB2D09F1D667B2F2AB72262 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - FBA08CCD21D8309086188A22 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + A6CC1614CF06CAF2675AB1EA /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + BF4A51DB6377345C580D7A7C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 858E64AE23ED6E8000722D91 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 858E64B323ED6E8000722D91 /* NotificationCenter.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 97C146EB1CF9000F007C117D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 858E64D823EDE53800722D91 /* SQLite.framework in Frameworks */, - 7AFEC5E8ED9E1A07079435E5 /* Pods_Runner.framework in Frameworks */, + 31D3B112F8A2533B0A7C9C5E /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 7C54038238C58F9C2299D867 /* Frameworks */ = { + 331C8082294A63A400263BE5 /* RunnerTests */ = { isa = PBXGroup; children = ( - 858E64CD23EDD5F300722D91 /* SQLite.framework */, - 0A9BBFDCB1E71FC1AFED79AB /* Pods_Runner.framework */, - 858E64B223ED6E8000722D91 /* NotificationCenter.framework */, + 331C807B294A618700263BE5 /* RunnerTests.swift */, ); - name = Frameworks; + path = RunnerTests; sourceTree = ""; }; - 858E64B423ED6E8000722D91 /* TodayExt */ = { + 646D31469DEB8F7FAB56A658 /* Frameworks */ = { isa = PBXGroup; children = ( - 858E64DC23EDFB4400722D91 /* fonts */, - 858E64CA23ED73B500722D91 /* TodayExt.entitlements */, - 858E64C323ED6EA400722D91 /* CustomCell.swift */, - 858E64C423ED6EA400722D91 /* TimelinePainter.swift */, - 858E64B523ED6E8000722D91 /* TodayViewController.swift */, - 858E64B723ED6E8000722D91 /* MainInterface.storyboard */, - 858E64BA23ED6E8000722D91 /* Info.plist */, - 858E64CB23EDD32900722D91 /* FlutterUserDefaults.swift */, - 858E64DA23EDE83E00722D91 /* LessonsDatabase.swift */, - 858E64E623EFFFBE00722D91 /* Localizable.strings */, - 858E64EC23F007E000722D91 /* InfoPlist.strings */, - ); - path = TodayExt; + 66A6929F0B3CDA6C1F10FE2B /* Pods_Runner.framework */, + ); + name = Frameworks; sourceTree = ""; }; - 858E64DC23EDFB4400722D91 /* fonts */ = { + 748099FFE838F230F4FE8EAE /* Pods */ = { isa = PBXGroup; children = ( - 858E64DD23EDFB7A00722D91 /* TimetableIcons.ttf */, + BF4A51DB6377345C580D7A7C /* Pods-Runner.debug.xcconfig */, + 0BAC359DFFE2CD3E06588691 /* Pods-Runner.release.xcconfig */, + A6CC1614CF06CAF2675AB1EA /* Pods-Runner.profile.xcconfig */, ); - path = fonts; + path = Pods; sourceTree = ""; }; 9740EEB11CF90186004384FC /* Flutter */ = { @@ -184,11 +104,10 @@ children = ( 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, - 858E64B423ED6E8000722D91 /* TodayExt */, 97C146EF1CF9000F007C117D /* Products */, - 361DA379224581B40067E0D1 /* Runner-Bridging-Header.h */, - C03C6CD75B87690C002B6016 /* Pods */, - 7C54038238C58F9C2299D867 /* Frameworks */, + 331C8082294A63A400263BE5 /* RunnerTests */, + 748099FFE838F230F4FE8EAE /* Pods */, + 646D31469DEB8F7FAB56A658 /* Frameworks */, ); sourceTree = ""; }; @@ -196,7 +115,6 @@ isa = PBXGroup; children = ( 97C146EE1CF9000F007C117D /* Runner.app */, - 858E64B123ED6E8000722D91 /* TodayExtTest.appex */, ); name = Products; sourceTree = ""; @@ -204,77 +122,37 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( - 858E64C923ED73AD00722D91 /* Runner.entitlements */, - 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, - 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 97C147021CF9000F007C117D /* Info.plist */, - 97C146F11CF9000F007C117D /* Supporting Files */, 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - 858E64F223F008FE00722D91 /* InfoPlist.strings */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, ); path = Runner; sourceTree = ""; }; - 97C146F11CF9000F007C117D /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 97C146F21CF9000F007C117D /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - C03C6CD75B87690C002B6016 /* Pods */ = { - isa = PBXGroup; - children = ( - BDB2D09F1D667B2F2AB72262 /* Pods-Runner.debug.xcconfig */, - 3CBE2D7E8A29364C72C76242 /* Pods-Runner.release.xcconfig */, - FBA08CCD21D8309086188A22 /* Pods-Runner.profile.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 858E64B023ED6E8000722D91 /* TodayExt */ = { - isa = PBXNativeTarget; - buildConfigurationList = 858E64C223ED6E8100722D91 /* Build configuration list for PBXNativeTarget "TodayExt" */; - buildPhases = ( - 858E64AD23ED6E8000722D91 /* Sources */, - 858E64AE23ED6E8000722D91 /* Frameworks */, - 858E64AF23ED6E8000722D91 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = TodayExt; - productName = TodayExt; - productReference = 858E64B123ED6E8000722D91 /* TodayExtTest.appex */; - productType = "com.apple.product-type.app-extension"; - }; 97C146ED1CF9000F007C117D /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - F2ACD30CC13C75F237B13CD1 /* [CP] Check Pods Manifest.lock */, + 7977F567B709FD4F10570591 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - D543A9A3220BCC574F9D4AFC /* [CP] Embed Pods Frameworks */, - 858E64BD23ED6E8100722D91 /* Embed App Extensions */, + B827779E9AC03B6035AFCF10 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( - 858E64BC23ED6E8000722D91 /* PBXTargetDependency */, ); name = Runner; productName = Runner; @@ -287,32 +165,22 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - DefaultBuildSystemTypeForWorkspace = Original; - LastSwiftUpdateCheck = 1130; - LastUpgradeCheck = 0910; - ORGANIZATIONNAME = "The Chromium Authors"; + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; TargetAttributes = { - 858E64B023ED6E8000722D91 = { - CreatedOnToolsVersion = 11.3.1; - DevelopmentTeam = 99C2LB4W93; - ProvisioningStyle = Automatic; - }; 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; - DevelopmentTeam = 99C2LB4W93; - LastSwiftMigration = 1010; + LastSwiftMigration = 1100; }; }; }; buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( - English, en, Base, - ru, ); mainGroup = 97C146E51CF9000F007C117D; productRefGroup = 97C146EF1CF9000F007C117D /* Products */; @@ -320,31 +188,17 @@ projectRoot = ""; targets = ( 97C146ED1CF9000F007C117D /* Runner */, - 858E64B023ED6E8000722D91 /* TodayExt */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 858E64AF23ED6E8000722D91 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 858E64B923ED6E8000722D91 /* MainInterface.storyboard in Resources */, - 858E64EA23F007E000722D91 /* InfoPlist.strings in Resources */, - 858E64E423EFFFBE00722D91 /* Localizable.strings in Resources */, - 858E64DE23EDFB7A00722D91 /* TimetableIcons.ttf in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 97C146EC1CF9000F007C117D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 858E64F023F008FE00722D91 /* InfoPlist.strings in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); @@ -355,146 +209,93 @@ /* Begin PBXShellScriptBuildPhase section */ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; - 9740EEB61CF901F6004384FC /* Run Script */ = { + 7977F567B709FD4F10570591 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "Run Script"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; }; - D543A9A3220BCC574F9D4AFC /* [CP] Embed Pods Frameworks */ = { + 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "[CP] Embed Pods Frameworks"; + name = "Run Script"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; - F2ACD30CC13C75F237B13CD1 /* [CP] Check Pods Manifest.lock */ = { + B827779E9AC03B6035AFCF10 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; + name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 858E64AD23ED6E8000722D91 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 858E64C623ED6EA500722D91 /* CustomCell.swift in Sources */, - 858E64CC23EDD32900722D91 /* FlutterUserDefaults.swift in Sources */, - 858E64DB23EDE83E00722D91 /* LessonsDatabase.swift in Sources */, - 858E64B623ED6E8000722D91 /* TodayViewController.swift in Sources */, - 858E64C723ED6EA500722D91 /* TimelinePainter.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 97C146EA1CF9000F007C117D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, - 97C146F31CF9000F007C117D /* main.m in Sources */, + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 858E64BC23ED6E8000722D91 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 858E64B023ED6E8000722D91 /* TodayExt */; - targetProxy = 858E64BB23ED6E8000722D91 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin PBXVariantGroup section */ - 858E64B723ED6E8000722D91 /* MainInterface.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 858E64B823ED6E8000722D91 /* Base */, - 858E64E123EFFEBE00722D91 /* ru */, - ); - name = MainInterface.storyboard; - sourceTree = ""; - }; - 858E64E623EFFFBE00722D91 /* Localizable.strings */ = { - isa = PBXVariantGroup; - children = ( - 858E64E523EFFFBE00722D91 /* ru */, - 858E64E723EFFFC600722D91 /* en */, - ); - name = Localizable.strings; - sourceTree = ""; - }; - 858E64EC23F007E000722D91 /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 858E64EB23F007E000722D91 /* ru */, - 858E64ED23F007E300722D91 /* en */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; - 858E64F223F008FE00722D91 /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 858E64F123F008FE00722D91 /* en */, - 858E64F323F0090200722D91 /* ru */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; 97C146FA1CF9000F007C117D /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 97C146FB1CF9000F007C117D /* Base */, - 858E64DF23EFFEBD00722D91 /* ru */, ); name = Main.storyboard; sourceTree = ""; @@ -503,7 +304,6 @@ isa = PBXVariantGroup; children = ( 97C147001CF9000F007C117D /* Base */, - 858E64E023EFFEBD00722D91 /* ru */, ); name = LaunchScreen.storyboard; sourceTree = ""; @@ -524,12 +324,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -540,7 +342,6 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_BITCODE = NO; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -551,9 +352,10 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -563,129 +365,26 @@ isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = 99C2LB4W93; + DEVELOPMENT_TEAM = G37GC839TX; ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( + INFOPLIST_KEY_CFBundleDisplayName = RANEPA; + LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/Flutter", + "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = "ru.coolone.ranepa-timetable"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.coolone.ranepa; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner-Bridging-Header.h"; - SWIFT_VERSION = 4.2; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Profile; - }; - 858E64BF23ED6E8100722D91 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_ENTITLEMENTS = TodayExt/TodayExt.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 99C2LB4W93; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu11; - INFOPLIST_FILE = TodayExt/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 13.2; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "ru.coolone.ranepa-timetable.TodayExt"; - PRODUCT_NAME = TodayExtTest; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 858E64C023ED6E8100722D91 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_ENTITLEMENTS = TodayExt/TodayExt.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 99C2LB4W93; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu11; - INFOPLIST_FILE = TodayExt/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 13.2; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "ru.coolone.ranepa-timetable.TodayExt"; - PRODUCT_NAME = TodayExtTest; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - 858E64C123ED6E8100722D91 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_ENTITLEMENTS = TodayExt/TodayExt.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 99C2LB4W93; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu11; - INFOPLIST_FILE = TodayExt/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 13.2; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "ru.coolone.ranepa-timetable.TodayExt"; - PRODUCT_NAME = TodayExtTest; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; }; name = Profile; }; @@ -702,12 +401,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -718,7 +419,6 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -735,7 +435,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -756,12 +456,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -772,7 +474,6 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_BITCODE = NO; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -783,9 +484,12 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -795,31 +499,26 @@ isa = XCBuildConfiguration; baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = 99C2LB4W93; + DEVELOPMENT_TEAM = G37GC839TX; ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( + INFOPLIST_KEY_CFBundleDisplayName = RANEPA; + LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/Flutter", + "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = "ru.coolone.ranepa-timetable"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.coolone.ranepa; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner-Bridging-Header.h"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -828,30 +527,25 @@ isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = 99C2LB4W93; + DEVELOPMENT_TEAM = G37GC839TX; ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( + INFOPLIST_KEY_CFBundleDisplayName = RANEPA; + LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/Flutter", + "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = "ru.coolone.ranepa-timetable"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.coolone.ranepa; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner-Bridging-Header.h"; - SWIFT_VERSION = 4.2; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; @@ -859,16 +553,6 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 858E64C223ED6E8100722D91 /* Build configuration list for PBXNativeTarget "TodayExt" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 858E64BF23ED6E8100722D91 /* Debug */, - 858E64C023ED6E8100722D91 /* Release */, - 858E64C123ED6E8100722D91 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 1d526a1..919434a 100644 --- a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:"> diff --git a/ios/Runner/Runner.entitlements b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 60% rename from ios/Runner/Runner.entitlements rename to ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist index abb4917..18d9810 100644 --- a/ios/Runner/Runner.entitlements +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -2,9 +2,7 @@ - com.apple.security.application-groups - - group.coolone.ranepatimetable.data - + IDEDidComputeMac32BitWarning + diff --git a/ios/TodayExt/TodayExt.entitlements b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings similarity index 60% rename from ios/TodayExt/TodayExt.entitlements rename to ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings index abb4917..f9b0d7c 100644 --- a/ios/TodayExt/TodayExt.entitlements +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -2,9 +2,7 @@ - com.apple.security.application-groups - - group.coolone.ranepatimetable.data - + PreviewsEnabled + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 786d6aa..e42adcb 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ - - - - + + + + + + - - + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner/AppDelegate.h b/ios/Runner/AppDelegate.h deleted file mode 100644 index 36e21bb..0000000 --- a/ios/Runner/AppDelegate.h +++ /dev/null @@ -1,6 +0,0 @@ -#import -#import - -@interface AppDelegate : FlutterAppDelegate - -@end diff --git a/ios/Runner/AppDelegate.m b/ios/Runner/AppDelegate.m deleted file mode 100644 index 59a72e9..0000000 --- a/ios/Runner/AppDelegate.m +++ /dev/null @@ -1,13 +0,0 @@ -#include "AppDelegate.h" -#include "GeneratedPluginRegistrant.h" - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application - didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - [GeneratedPluginRegistrant registerWithRegistry:self]; - // Override point for customization after application launch. - return [super application:application didFinishLaunchingWithOptions:launchOptions]; -} - -@end diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..70693e4 --- /dev/null +++ b/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png index 4837b42..dc9ada4 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png index 123b2f6..7353c41 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png index 106e31b..797d452 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png index cb1c8be..6ed2d93 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png index 88444a7..4cd7b00 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png index 6b3fc2b..fe73094 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png index e7f1aba..321773c 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png index 106e31b..797d452 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png index 5a5860d..502f463 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png index 9d0f709..0ec3034 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png index 9d0f709..0ec3034 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png index 090b97c..e9f5fea 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png index adaf4d3..84ac32a 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png index 0872b4b..8953cba 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png index 892e46b..0467bf1 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/ios/Runner/Assets.xcassets/Contents.json b/ios/Runner/Assets.xcassets/Contents.json deleted file mode 100644 index da4a164..0000000 --- a/ios/Runner/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ios/Runner/Assets.xcassets/SplashIcon.imageset/Contents.json b/ios/Runner/Assets.xcassets/SplashIcon.imageset/Contents.json deleted file mode 100644 index 63391aa..0000000 --- a/ios/Runner/Assets.xcassets/SplashIcon.imageset/Contents.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "ic_launcher.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "logo_mipmap.png", - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "ic_launcher-1.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "logo_mipmap-1.png", - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "ic_launcher-2.png", - "scale" : "3x" - }, - { - "idiom" : "universal", - "filename" : "logo_mipmap-2.png", - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ios/Runner/Assets.xcassets/SplashIcon.imageset/ic_launcher-1.png b/ios/Runner/Assets.xcassets/SplashIcon.imageset/ic_launcher-1.png deleted file mode 100644 index 2145ad1..0000000 Binary files a/ios/Runner/Assets.xcassets/SplashIcon.imageset/ic_launcher-1.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/SplashIcon.imageset/ic_launcher-2.png b/ios/Runner/Assets.xcassets/SplashIcon.imageset/ic_launcher-2.png deleted file mode 100644 index 358c39c..0000000 Binary files a/ios/Runner/Assets.xcassets/SplashIcon.imageset/ic_launcher-2.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/SplashIcon.imageset/ic_launcher.png b/ios/Runner/Assets.xcassets/SplashIcon.imageset/ic_launcher.png deleted file mode 100644 index 346a523..0000000 Binary files a/ios/Runner/Assets.xcassets/SplashIcon.imageset/ic_launcher.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/SplashIcon.imageset/logo_mipmap-1.png b/ios/Runner/Assets.xcassets/SplashIcon.imageset/logo_mipmap-1.png deleted file mode 100644 index 23f05f7..0000000 Binary files a/ios/Runner/Assets.xcassets/SplashIcon.imageset/logo_mipmap-1.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/SplashIcon.imageset/logo_mipmap-2.png b/ios/Runner/Assets.xcassets/SplashIcon.imageset/logo_mipmap-2.png deleted file mode 100644 index 0682729..0000000 Binary files a/ios/Runner/Assets.xcassets/SplashIcon.imageset/logo_mipmap-2.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/SplashIcon.imageset/logo_mipmap.png b/ios/Runner/Assets.xcassets/SplashIcon.imageset/logo_mipmap.png deleted file mode 100644 index 82a2634..0000000 Binary files a/ios/Runner/Assets.xcassets/SplashIcon.imageset/logo_mipmap.png and /dev/null differ diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard index 1d9a853..f2e259c 100644 --- a/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -1,10 +1,8 @@ - - - + + - - + @@ -16,32 +14,24 @@ - - - - - - + - - - + - - + diff --git a/ios/Runner/GeneratedPluginRegistrant.h b/ios/Runner/GeneratedPluginRegistrant.h index ed9a5c6..7a89092 100644 --- a/ios/Runner/GeneratedPluginRegistrant.h +++ b/ios/Runner/GeneratedPluginRegistrant.h @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #ifndef GeneratedPluginRegistrant_h #define GeneratedPluginRegistrant_h diff --git a/ios/Runner/GeneratedPluginRegistrant.m b/ios/Runner/GeneratedPluginRegistrant.m index a95da0d..d0ac594 100644 --- a/ios/Runner/GeneratedPluginRegistrant.m +++ b/ios/Runner/GeneratedPluginRegistrant.m @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #import "GeneratedPluginRegistrant.h" #if __has_include() @@ -22,34 +24,28 @@ @import flutter_email_sender; #endif -#if __has_include() -#import -#else -@import ios_app_group; -#endif - #if __has_include() #import #else @import package_info; #endif -#if __has_include() -#import +#if __has_include() +#import #else -@import sqflite; +@import shared_preferences_foundation; #endif -#if __has_include() -#import +#if __has_include() +#import #else -@import url_launcher; +@import sqflite; #endif -#if __has_include() -#import +#if __has_include() +#import #else -@import shared_preferences; +@import url_launcher_ios; #endif @implementation GeneratedPluginRegistrant @@ -58,11 +54,10 @@ + (void)registerWithRegistry:(NSObject*)registry { [FLTConnectivityPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTConnectivityPlugin"]]; [DeviceCalendarPlugin registerWithRegistrar:[registry registrarForPlugin:@"DeviceCalendarPlugin"]]; [FlutterEmailSenderPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterEmailSenderPlugin"]]; - [IosAppGroupPlugin registerWithRegistrar:[registry registrarForPlugin:@"IosAppGroupPlugin"]]; [FLTPackageInfoPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTPackageInfoPlugin"]]; + [SharedPreferencesPlugin registerWithRegistrar:[registry registrarForPlugin:@"SharedPreferencesPlugin"]]; [SqflitePlugin registerWithRegistrar:[registry registrarForPlugin:@"SqflitePlugin"]]; [FLTURLLauncherPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTURLLauncherPlugin"]]; - [FLTSharedPreferencesPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTSharedPreferencesPlugin"]]; } @end diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index d228eb9..e253225 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -2,8 +2,12 @@ + CADisableMinimumFrameDurationOnPhone + CFBundleDevelopmentRegion - ru + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Ranepatimetable CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -11,7 +15,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleName - ranepa_timetable + ranepatimetable CFBundlePackageType APPL CFBundleShortVersionString @@ -22,10 +26,8 @@ $(FLUTTER_BUILD_NUMBER) LSRequiresIPhoneOS - NSCalendarsUsageDescription - INSERT_REASON_HERE - NSContactsUsageDescription - INSERT_REASON_HERE + UIApplicationSupportsIndirectInputEvents + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/ios/Runner/en.lproj/InfoPlist.strings b/ios/Runner/en.lproj/InfoPlist.strings deleted file mode 100644 index bcf8584..0000000 --- a/ios/Runner/en.lproj/InfoPlist.strings +++ /dev/null @@ -1,10 +0,0 @@ -/* - InfoPlist.strings - Runner - - Created by Nickolay Truhin on 09.02.2020. - Copyright © 2020 The Chromium Authors. All rights reserved. -*/ - -"CFBundleName" = "NRU RANEPA"; -"CFBundleDisplayName" = "NRU RANEPA"; diff --git a/ios/Runner/main.m b/ios/Runner/main.m deleted file mode 100644 index dff6597..0000000 --- a/ios/Runner/main.m +++ /dev/null @@ -1,9 +0,0 @@ -#import -#import -#import "AppDelegate.h" - -int main(int argc, char* argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/ios/Runner/ru.lproj/InfoPlist.strings b/ios/Runner/ru.lproj/InfoPlist.strings deleted file mode 100644 index 072ff4a..0000000 --- a/ios/Runner/ru.lproj/InfoPlist.strings +++ /dev/null @@ -1,10 +0,0 @@ -/* - InfoPlist.strings - Runner - - Created by Nickolay Truhin on 09.02.2020. - Copyright © 2020 The Chromium Authors. All rights reserved. -*/ - -"CFBundleName" = "НИУ РАНХиГС"; -"CFBundleDisplayName" = "НИУ РАНХиГС"; diff --git a/ios/Runner/ru.lproj/LaunchScreen.strings b/ios/Runner/ru.lproj/LaunchScreen.strings deleted file mode 100644 index 8b13789..0000000 --- a/ios/Runner/ru.lproj/LaunchScreen.strings +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ios/Runner/ru.lproj/Main.strings b/ios/Runner/ru.lproj/Main.strings deleted file mode 100644 index 8b13789..0000000 --- a/ios/Runner/ru.lproj/Main.strings +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ios/RunnerTests/RunnerTests.swift b/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..86a7c3b --- /dev/null +++ b/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/ios/TodayExt/Base.lproj/MainInterface.storyboard b/ios/TodayExt/Base.lproj/MainInterface.storyboard deleted file mode 100644 index bcf1418..0000000 --- a/ios/TodayExt/Base.lproj/MainInterface.storyboard +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/TodayExt/CustomCell.swift b/ios/TodayExt/CustomCell.swift deleted file mode 100644 index 61c84fd..0000000 --- a/ios/TodayExt/CustomCell.swift +++ /dev/null @@ -1,263 +0,0 @@ -// -// CustomCell.swift -// TodayExt -// -// Created by Nickolay Truhin on 06.02.2020. -// Copyright © 2020 The Chromium Authors. All rights reserved. -// - -import UIKit - -extension UIColor { - convenience init(red: Int, green: Int, blue: Int) { - assert(red >= 0 && red <= 255, "Invalid red component") - assert(green >= 0 && green <= 255, "Invalid green component") - assert(blue >= 0 && blue <= 255, "Invalid blue component") - - self.init(red: CGFloat(red) / 255.0, green: CGFloat(green) / 255.0, blue: CGFloat(blue) / 255.0, alpha: 1.0) - } - - convenience init(rgb: Int) { - self.init( - red: (rgb >> 16) & 0xFF, - green: (rgb >> 8) & 0xFF, - blue: rgb & 0xFF - ) - } - - convenience init(rgbStr: String) { - self.init( - rgb: Int(rgbStr, radix: 16)! - ) - } -} - -class TitleLabel: UILabel { - override func draw(_ rect: CGRect) { - super.drawText(in: rect.insetBy(dx: 5, dy: 0)) - } -} - -public enum FontIcon: UInt32 { - case studyHostel = 0xe802, - hotel = 0xe801, - academy = 0xe81b, - beer = 0xe838, - confetti = 0xe839, - unknownLesson = 0xe826 - - func toStringIcon() -> String { - return FontIcon.intToStringIcon(self.rawValue) - } - - static func intToStringIcon(_ int: UInt32) -> String { - var rawIcon = int - let xPtr = withUnsafeMutablePointer(to: &rawIcon, { $0 }) - return String(bytesNoCopy: xPtr, length:MemoryLayout.size, encoding: String.Encoding.utf32LittleEndian, freeWhenDone: false)! - } -} - -class CustomCell: UITableViewCell { - var model: TimelineModel? - - var painterView: TimelinePainter = { - var painterView = TimelinePainter() - painterView.translatesAutoresizingMaskIntoConstraints = false - return painterView - }() - - var painterContentView: UIView = { - var contentView = UIView() - contentView.translatesAutoresizingMaskIntoConstraints = false - return contentView - }() - - var startView: UILabel = { - var labelView = UILabel() - labelView.translatesAutoresizingMaskIntoConstraints = false - - let color = Prefs.THEME_TEXT_PRIMARY.fromUserDefaults() as? String ?? "ff0000ff" - debugPrint("theme primary: \(color)") - labelView.textColor = UIColor(rgbStr: color) - labelView.font = labelView.font.withSize(20) - return labelView - }() - - var finishView: UILabel = { - var labelView = UILabel() - labelView.translatesAutoresizingMaskIntoConstraints = false - - let color = Prefs.THEME_TEXT_PRIMARY.fromUserDefaults() as? String ?? "ff0000ff" - labelView.textColor = UIColor(rgbStr: color) - labelView.font = labelView.font.withSize(14) - return labelView - }() - - var locationView: UILabel = { - var labelView = UILabel() - labelView.translatesAutoresizingMaskIntoConstraints = false - - let color = Prefs.THEME_TEXT_PRIMARY.fromUserDefaults() as? String ?? "ff0000ff" - labelView.textColor = UIColor(rgbStr: color) - labelView.font = labelView.font.withSize(14) - return labelView - }() - - var locationIconView: UILabel = { - var labelView = UILabel() - labelView.translatesAutoresizingMaskIntoConstraints = false - - let color = Prefs.THEME_TEXT_PRIMARY.fromUserDefaults() as? String ?? "ff0000ff" - labelView.textColor = UIColor(rgbStr: color) - labelView.font = UIFont.init(name: "TimetableIcons", size: 20) - return labelView - }() - - var iconView: UILabel = { - var labelView = UILabel() - labelView.translatesAutoresizingMaskIntoConstraints = false - - let color = Prefs.THEME_TEXT_ACCENT.fromUserDefaults() as? String ?? "ff0000ff" - labelView.textColor = UIColor(rgbStr: color) - labelView.font = UIFont.init(name: "TimetableIcons", size: 20) - return labelView - }() - - var lessonTypeView: TitleLabel = { - var labelView = TitleLabel() - labelView.translatesAutoresizingMaskIntoConstraints = false - - let color = Prefs.THEME_TEXT_PRIMARY.fromUserDefaults() as? String ?? "ff0000ff" - labelView.textColor = UIColor(rgbStr: color) - labelView.font = labelView.font.withSize(14) - return labelView - }() - - var teacherGroupView: TitleLabel = { - var labelView = TitleLabel() - labelView.translatesAutoresizingMaskIntoConstraints = false - - let color = Prefs.THEME_TEXT_PRIMARY.fromUserDefaults() as? String ?? "ff0000ff" - labelView.textColor = UIColor(rgbStr: color) - labelView.font = labelView.font.withSize(14) - return labelView - }() - - var titleView: TitleLabel = { - var labelView = TitleLabel() - labelView.translatesAutoresizingMaskIntoConstraints = false - - let color = Prefs.THEME_TEXT_PRIMARY.fromUserDefaults() as? String ?? "ff0000ff" - labelView.textColor = UIColor(rgbStr: color) - labelView.lineBreakMode = .byWordWrapping - labelView.numberOfLines = 0 - return labelView - }() - - static let innerPadding = 4.0 - static let leftContentWidth = CGFloat(68 - innerPadding) - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - - self.addSubview(painterView) - painterView.backgroundColor = UIColor(white: 1, alpha: 0) - painterView.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true - painterView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true - painterView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true - painterView.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true - - self.addSubview(painterContentView) - painterContentView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: CGFloat(TimelinePainter.rectMargins * 2)).isActive = true - painterContentView.topAnchor.constraint(equalTo: self.topAnchor, constant: CGFloat(TimelinePainter.rectMargins * 2)).isActive = true - painterContentView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -CGFloat(TimelinePainter.rectMargins)).isActive = true - painterContentView.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -CGFloat(TimelinePainter.rectMargins * 2)).isActive = true - - painterContentView.addSubview(startView) - startView.textAlignment = .center - startView.leftAnchor.constraint(equalTo: painterContentView.leftAnchor).isActive = true - startView.topAnchor.constraint(equalTo: painterContentView.topAnchor).isActive = true - startView.addConstraint(NSLayoutConstraint(item: startView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: CustomCell.leftContentWidth)) - - painterContentView.addSubview(finishView) - finishView.textAlignment = .center - finishView.leftAnchor.constraint(equalTo: startView.leftAnchor).isActive = true - finishView.rightAnchor.constraint(equalTo: startView.rightAnchor).isActive = true - finishView.topAnchor.constraint(equalTo: startView.bottomAnchor).isActive = true - - painterContentView.addSubview(locationView) - locationView.textAlignment = .left - locationView.topAnchor.constraint(equalTo: finishView.bottomAnchor, constant: 5).isActive = true - - switch RoomLocationStyle.fromUserDefaults() { - case .Text: - locationView.textAlignment = .center - - locationView.leftAnchor.constraint(equalTo: startView.leftAnchor).isActive = true - locationView.rightAnchor.constraint(equalTo: startView.rightAnchor).isActive = true - case .Icon: - locationView.textAlignment = .left - painterContentView.addSubview(locationIconView) - - locationIconView.leftAnchor.constraint(equalTo: startView.leftAnchor).isActive = true - locationIconView.topAnchor.constraint(equalTo: finishView.bottomAnchor, constant: 2).isActive = true - locationView.leftAnchor.constraint(equalTo: locationIconView.rightAnchor, constant: 5).isActive = true - } - - painterContentView.addSubview(iconView) - iconView.textAlignment = .center - iconView.addConstraint(NSLayoutConstraint(item: iconView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 54)) - iconView.leftAnchor.constraint(equalTo: startView.rightAnchor).isActive = true - iconView.topAnchor.constraint(equalTo: painterContentView.topAnchor).isActive = true - iconView.bottomAnchor.constraint(equalTo: painterContentView.bottomAnchor).isActive = true - - painterContentView.addSubview(lessonTypeView) - lessonTypeView.leftAnchor.constraint(equalTo: iconView.rightAnchor).isActive = true - lessonTypeView.topAnchor.constraint(equalTo: painterContentView.topAnchor).isActive = true - - painterContentView.addSubview(teacherGroupView) - teacherGroupView.textAlignment = .right - teacherGroupView.leftAnchor.constraint(equalTo: lessonTypeView.rightAnchor).isActive = true - teacherGroupView.topAnchor.constraint(equalTo: painterContentView.topAnchor).isActive = true - teacherGroupView.rightAnchor.constraint(equalTo: painterContentView.rightAnchor).isActive = true - - teacherGroupView.widthAnchor.constraint(equalTo: lessonTypeView.widthAnchor, multiplier: 1.0).isActive = true - - painterContentView.addSubview(titleView) - titleView.leftAnchor.constraint(equalTo: iconView.rightAnchor).isActive = true - titleView.topAnchor.constraint(equalTo: lessonTypeView.bottomAnchor).isActive = true - titleView.bottomAnchor.constraint(equalTo: painterContentView.bottomAnchor).isActive = true - titleView.rightAnchor.constraint(equalTo: painterContentView.rightAnchor).isActive = true - } - - override func layoutSubviews() { - super.layoutSubviews() - if let model = model { - painterView.model = model - startView.text = model.start.format() - finishView.text = model.finish.format() - locationView.text = model.room.formatNumber() - locationIconView.text = model.room.formatLocation() - lessonTypeView.text = model.lesson.actionTitle - switch SearchItemTypeId.fromUserDefaults() { - case .Group: - teacherGroupView.text = model.teacher.format() - case .Teacher: - teacherGroupView.text = model.group - } - - titleView.text = Prefs.OPTIMIZED_LESSON_TITLES.fromUserDefaults() as? Bool ?? true - ? model.lesson.title - : model.lesson.fullTitle - if titleView.text!.count > 30 { - titleView.font = titleView.font.withSize(14) - titleView.textAlignment = .center - } - iconView.text = FontIcon.intToStringIcon(UInt32(model.lesson.iconCodePoint)) - } - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} diff --git a/ios/TodayExt/FlutterUserDefaults.swift b/ios/TodayExt/FlutterUserDefaults.swift deleted file mode 100644 index 03155ff..0000000 --- a/ios/TodayExt/FlutterUserDefaults.swift +++ /dev/null @@ -1,103 +0,0 @@ -// -// FlutterUserDefaults.swift -// TodayExt -// -// Created by Nickolay Truhin on 07.02.2020. -// Copyright © 2020 The Chromium Authors. All rights reserved. -// - -import Foundation - -enum RoomLocationStyle: Int { - case Text = 0, Icon = 1 - - static func fromUserDefaults() -> RoomLocationStyle { - return RoomLocationStyle.init(rawValue: Prefs.ROOM_LOCATION_STYLE.fromUserDefaults() as? Int ?? RoomLocationStyle.Text.rawValue)! - } -} - -enum SearchItemTypeId: Int { - case Group = 0, Teacher = 1 - - static func fromUserDefaults() -> SearchItemTypeId { - return SearchItemTypeId.init(rawValue: Prefs.ITEM_TYPE.fromUserDefaults() as? Int ?? SearchItemTypeId.Group.rawValue)! - } -} - -enum Prefs { - case LAST_UPDATE, - ROOM_LOCATION_STYLE, - WIDGET_TRANSLUCENT, - THEME_PRIMARY, - THEME_ACCENT, - THEME_TEXT_PRIMARY, - THEME_TEXT_ACCENT, - THEME_BACKGROUND, - THEME_BRIGHTNESS, - BEFORE_ALARM_CLOCK, - END_CACHE, - SEARCH_ITEM_PREFIX, - ITEM_TYPE, - ITEM_ID, - ITEM_TITLE, - SITE_API, - OPTIMIZED_LESSON_TITLES, - DAY_STYLE - - func fromUserDefaults() -> Any? { - var str: String - switch self { - case .LAST_UPDATE: - str = "last_update" - case .ROOM_LOCATION_STYLE: - str = "room_location_style" - case .WIDGET_TRANSLUCENT: - str = "widget_translucent" - case .THEME_PRIMARY: - str = "theme_primary" - case .THEME_ACCENT: - str = "theme_accent" - case .THEME_TEXT_PRIMARY: - str = "theme_text_primary" - case .THEME_TEXT_ACCENT: - str = "theme_text_accent" - case .THEME_BACKGROUND: - str = "theme_background" - case .THEME_BRIGHTNESS: - str = "theme_brightness" - case .BEFORE_ALARM_CLOCK: - str = "before_alarm_clock" - case .END_CACHE: - str = "end_cache" - case .SEARCH_ITEM_PREFIX: - str = "primary_search_item_" - case .ITEM_TYPE: - str = "type" - case .ITEM_ID: - str = "id" - case .ITEM_TITLE: - str = "title" - case .SITE_API: - str = "site_api" - case .OPTIMIZED_LESSON_TITLES: - str = "optimized_lesson_titles" - case .DAY_STYLE: - str = "day_style" - } - - return FlutterUserDefaults.userDefaults.object(forKey: "flutter.\(str)") - } -} - -class FlutterUserDefaults { - static private var userDefaultsInstance: UserDefaults? - - static var userDefaults: UserDefaults { - get { - if userDefaultsInstance == nil { - userDefaultsInstance = UserDefaults.init(suiteName: "group.coolone.ranepatimetable.data") - } - return self.userDefaultsInstance! - } - } -} diff --git a/ios/TodayExt/Info.plist b/ios/TodayExt/Info.plist deleted file mode 100644 index 76a1144..0000000 --- a/ios/TodayExt/Info.plist +++ /dev/null @@ -1,37 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - $(PRODUCT_NAME) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - LSHasLocalizedDisplayName - - NSExtension - - NSExtensionMainStoryboard - MainInterface - NSExtensionPointIdentifier - com.apple.widget-extension - - UIAppFonts - - TimetableIcons.ttf - - - diff --git a/ios/TodayExt/LessonsDatabase.swift b/ios/TodayExt/LessonsDatabase.swift deleted file mode 100644 index 866dd2e..0000000 --- a/ios/TodayExt/LessonsDatabase.swift +++ /dev/null @@ -1,181 +0,0 @@ -// -// LessonsDatabase.swift -// TodayExt -// -// Created by Nickolay Truhin on 07.02.2020. -// Copyright © 2020 The Chromium Authors. All rights reserved. -// - -import Foundation -import SQLite - -class LessonsDatabase { - static let db: Connection = try! Connection(URL.storeURL(for: "group.coolone.ranepatimetable.data", databaseName: "timetable").path) - - static let table = Table("lessons") - - static func getAll() throws -> [TimelineModel] { - var lessons = [TimelineModel]() - let midnight = Calendar.current.date(byAdding: .day, value: 1, to: - Calendar(identifier: .gregorian).startOfDay(for: Date()))! - - for data in try self.db.prepare(table - .filter(TimelineModel.TableKeys.date == Int(midnight.timeIntervalSince1970 * 1000)) - ) { - lessons.append(TimelineModel.init(data)) - } - - return lessons - } -} - -struct TimelineModel { - - let date: Date - let lesson: LessonModel - let teacher: TeacherModel - let group: String - let room: RoomModel - let start: TimeModel - let finish: TimeModel - let first, last: Bool - let mergeBottom, mergeTop: Bool - - init(_ data: Row) { - date = Date(timeIntervalSince1970: Double(data[TableKeys.date] / 1000)) - lesson = LessonModel.init(data) - teacher = TeacherModel.init(data) - room = RoomModel.init(data) - start = TimeModel.init(data, prefix: "start") - finish = TimeModel.init(data, prefix: "finish") - group = data[TableKeys.group] - mergeTop = data[TableKeys.mergeTop] - mergeBottom = data[TableKeys.mergeBottom] - first = data[TableKeys.first] - last = data[TableKeys.last] - } - - class TableKeys { - static let - date = Expression("date"), - group = Expression("group"), - first = Expression("first"), - last = Expression("last"), - mergeTop = Expression("mergeTop"), - mergeBottom = Expression("mergeBottom") - } -} - -struct LessonModel { - let title: String - let fullTitle: String - let iconCodePoint: Int - let actionTitle: String - - init(_ data: Row) { - title = data[TableKeys.title] - fullTitle = data[TableKeys.fullTitle] - iconCodePoint = data[TableKeys.iconCodePoint] - actionTitle = data[TableKeys.actionTitle] - } - - class TableKeys { - static let - title = Expression("lesson_title"), - fullTitle = Expression("lesson_fullTitle"), - iconCodePoint = Expression("lesson_iconCodePoint"), - actionTitle = Expression("lesson_action_title") - } -} - -struct TeacherModel { - let name: String - let surname: String - let patronymic: String - - init(_ data: Row) { - name = data[TableKeys.name] - surname = data[TableKeys.surname] - patronymic = data[TableKeys.patronymic] - } - - func format() -> String { - return "\(surname) \(name.prefix(1)). \(patronymic.prefix(1))." - } - - class TableKeys { - static let - name = Expression("teacher_name"), - surname = Expression("teacher_surname"), - patronymic = Expression("teacher_patronymic") - } -} - -struct RoomModel { - let number: String - let location: String - - init(_ data: Row) { - number = data[TableKeys.number] - location = data[TableKeys.location] - } - - func formatNumber() -> String { - switch RoomLocationStyle.fromUserDefaults() { - case .Text: - let prefix: String - - switch location { - case Location.studyHostel: - prefix = "СО-" - case Location.hotel: - prefix = "П8-" - default: - prefix = "" - } - - return prefix + number - case .Icon: - return number - } - } - - func formatLocation() -> String { - var icon: FontIcon - switch location { - case Location.studyHostel: - icon = FontIcon.studyHostel - case Location.hotel: - icon = FontIcon.hotel - default: - icon = FontIcon.academy - } - return icon.toStringIcon() - } - - class Location { - static let - studyHostel = "StudyHostel", - hotel = "Hotel" - } - - class TableKeys { - static let - number = Expression("room_number"), - location = Expression("room_location") - } -} - -struct TimeModel { - let hour: Int - let minute: Int - - init(_ data: Row, prefix: String) { - hour = data[Expression(prefix + "_hour")] - minute = data[Expression(prefix + "_minute")] - } - - func format() -> String { - return "\(String(format: "%02d", hour)):\(String(format: "%02d", minute))" - } -} diff --git a/ios/TodayExt/TimelinePainter.swift b/ios/TodayExt/TimelinePainter.swift deleted file mode 100644 index d079ac3..0000000 --- a/ios/TodayExt/TimelinePainter.swift +++ /dev/null @@ -1,171 +0,0 @@ -// -// LessonPainter.swift -// TodayExt -// -// Created by Nickolay Truhin on 07.02.2020. -// Copyright © 2020 The Chromium Authors. All rights reserved. -// - -import UIKit - -class TimelinePainter: UIView { - var model: TimelineModel? - - func drawPath( - _ ctx: CGContext, - path: CGPath, - fillColor: UIColor - ) { - ctx.saveGState() - - ctx.addPath(path) - ctx.setFillColor(fillColor.cgColor) - - ctx.closePath() - ctx.fillPath() - ctx.restoreGState() - } - - func drawRRect( - _ ctx: CGContext, - rect: CGRect, - cornerRadius: CGFloat, - fillColor: UIColor - ) - { - drawPath(ctx, path: UIBezierPath( - roundedRect: rect, - cornerRadius: cornerRadius - ).cgPath, fillColor: fillColor) - } - - func drawArc( - _ ctx: CGContext, - center: CGPoint, - radius: CGFloat, - startAngle: CGFloat, - endAngle: CGFloat, - fillColor: UIColor, - clockwise: Bool - ) { - drawPath(ctx, path: UIBezierPath( - arcCenter: center, - radius: radius, - startAngle: startAngle.toRadians(), - endAngle: endAngle.toRadians(), - clockwise: clockwise - ).cgPath, fillColor: fillColor) - } - - func drawCircle( - _ ctx: CGContext, - center: CGPoint, - radius: Int, - fillColor: UIColor - ) { - ctx.setFillColor(fillColor.cgColor) - ctx.fillEllipse(in: CGRect( - x: center.x - CGFloat(radius), - y: center.y - CGFloat(radius), - width: CGFloat(radius * 2), - height: CGFloat(radius * 2) - )) - } - - static let rectMargins = 8.0, - iconSize = 15.0, - circleRadius = 23.0, - rectCornersRadius = 10.0, - circleMargin = 5.0, - circleRadiusAdd = 3.0; - - override func draw(_ rect: CGRect) { - guard let ctx = UIGraphicsGetCurrentContext(), let model = model else { - return - } - - let bgColor = UIColor.init(rgbStr: Prefs.THEME_BACKGROUND.fromUserDefaults() as! String) - let accentColor = UIColor.init(rgbStr: Prefs.THEME_ACCENT.fromUserDefaults() as! String) - - if model.mergeTop { - ctx.setFillColor(bgColor.withAlphaComponent(0.5).cgColor) - ctx.fill(CGRect( - x: TimelinePainter.rectCornersRadius * 2, - y: 0, - width: Double(frame.width) - TimelinePainter.rectCornersRadius * 4, - height: TimelinePainter.rectMargins - )) - } - - drawRRect( - ctx, - rect: CGRect( - x: TimelinePainter.rectMargins, y: TimelinePainter.rectMargins, - width: Double(frame.width) - TimelinePainter.rectMargins * 2, - height: 80.0 - ), - cornerRadius: 10, - fillColor: bgColor.withAlphaComponent( - traitCollection.userInterfaceStyle == .light - ? 0.4 - : 0.2 - ) - ) - - let circleOffset = CGPoint( - x: TimelinePainter.rectMargins * 2 + TimelinePainter.circleRadius + 68, - y: (Double(frame.height) + TimelinePainter.rectMargins) / 2 - ) - - ctx.setFillColor(accentColor.cgColor) - if !(model.first && model.last) { - if model.first || !model.last { - ctx.fill(CGRect( - x: circleOffset.x - CGFloat(TimelinePainter.circleRadius), - y: circleOffset.y, - width: CGFloat(TimelinePainter.circleRadius * 2), - height: frame.height - circleOffset.y - )) - } - - if model.last || !model.first { - ctx.fill(CGRect( - x: circleOffset.x - CGFloat(TimelinePainter.circleRadius), - y: 0, - width: CGFloat(TimelinePainter.circleRadius * 2), - height: frame.height - circleOffset.y + CGFloat(TimelinePainter.rectMargins) - )) - } - - if model.first || model.last { - drawArc( - ctx, - center: CGPoint( - x: circleOffset.x, - y: circleOffset.y - ), - radius: CGFloat(TimelinePainter.circleRadius), - startAngle: CGFloat(0), - endAngle: CGFloat(180), - fillColor: accentColor, - clockwise: model.last - ) - } - } else { - drawCircle( - ctx, - center: circleOffset, - radius: Int(TimelinePainter.circleRadius + TimelinePainter.circleRadiusAdd), - fillColor: accentColor - ) - } - - ctx.strokePath() - } -} - -extension CGFloat { - func toRadians() -> CGFloat { - return self * CGFloat(Float.pi) / 180.0 - } -} diff --git a/ios/TodayExt/TodayViewController.swift b/ios/TodayExt/TodayViewController.swift deleted file mode 100644 index cf52dfd..0000000 --- a/ios/TodayExt/TodayViewController.swift +++ /dev/null @@ -1,132 +0,0 @@ -// -// TodayViewController.swift -// TodayExt -// -// Created by Nickolay Truhin on 07.02.2020. -// Copyright © 2020 The Chromium Authors. All rights reserved. -// - -import UIKit -import NotificationCenter -import SQLite - -class TodayViewController: UIViewController, NCWidgetProviding { - @IBOutlet var tableView: UITableView! - - var data = [TimelineModel]() - - var messageView: TitleLabel = { - var labelView = TitleLabel() - labelView.translatesAutoresizingMaskIntoConstraints = false - - let color = Prefs.THEME_TEXT_PRIMARY.fromUserDefaults() as? String ?? "ff0000ff" - labelView.textColor = UIColor(rgbStr: color) - return labelView - }() - - var messageIconView: TitleLabel = { - var labelView = TitleLabel() - labelView.translatesAutoresizingMaskIntoConstraints = false - - let color = Prefs.THEME_PRIMARY.fromUserDefaults() as? String ?? "ff0000ff" - labelView.textColor = UIColor(rgbStr: color) - labelView.font = UIFont.init(name: "TimetableIcons", size: 50) - return labelView - }() - - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view. - - var dbExist = false - - do { - try data = LessonsDatabase.getAll() - - dbExist = true - } catch {} - - if dbExist { - if data.isEmpty { - let icon: FontIcon - switch SearchItemTypeId.fromUserDefaults() { - case .Group: - icon = FontIcon.beer - case .Teacher: - icon = FontIcon.confetti - } - buildMessage(text: NSLocalizedString("freeDay", comment: ""), icon: icon) - } else { - tableView.delegate = self - tableView.dataSource = self - - tableView.register(CustomCell.self, forCellReuseIdentifier: "custom") - - self.extensionContext?.widgetLargestAvailableDisplayMode = .expanded - } - } else { - buildMessage(text: NSLocalizedString("noCache", comment: ""), icon: FontIcon.unknownLesson) - } - } - - func buildMessage(text: String, icon: FontIcon) { - view.addSubview(messageIconView) - messageIconView.text = icon.toStringIcon() - messageIconView.textAlignment = .center - messageIconView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true - messageIconView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true - messageIconView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -20).isActive = true - - view.addSubview(messageView) - messageView.text = text - messageView.textAlignment = .center - messageView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true - messageView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true - messageView.topAnchor.constraint(equalTo: messageIconView.bottomAnchor, constant: 10).isActive = true - } - - func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) { - // Perform any setup necessary in order to update the view. - - // If an error is encountered, use NCUpdateResult.Failed - // If there's no update required, use NCUpdateResult.NoData - // If there's an update, use NCUpdateResult.NewData - - completionHandler(NCUpdateResult.newData) - } - - func widgetActiveDisplayModeDidChange(_ activeDisplayMode: NCWidgetDisplayMode, withMaximumSize maxSize: CGSize) { - - if activeDisplayMode == NCWidgetDisplayMode.compact { - //compact - self.preferredContentSize = maxSize - } else { - //extended - self.preferredContentSize = CGSize(width: maxSize.width, height: CGFloat(data.count * 88 + Int(TimelinePainter.rectMargins))) - } - } -} - -extension TodayViewController: UITableViewDataSource, UITableViewDelegate { - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return data.count - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = self.tableView.dequeueReusableCell(withIdentifier: "custom") as! CustomCell - cell.model = data[indexPath.row] - return cell - } -} - -public extension URL { - - /// Returns a URL for the given app group and database pointing to the sqlite database. - static func storeURL(for appGroup: String, databaseName: String) -> URL { - guard let fileContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroup) else { - fatalError("Shared file container could not be created.") - } - - return fileContainer.appendingPathComponent("\(databaseName).db") - } -} diff --git a/ios/TodayExt/en.lproj/InfoPlist.strings b/ios/TodayExt/en.lproj/InfoPlist.strings deleted file mode 100644 index 205fa34..0000000 --- a/ios/TodayExt/en.lproj/InfoPlist.strings +++ /dev/null @@ -1,10 +0,0 @@ -/* - InfoPlist.strings - Runner - - Created by Nickolay Truhin on 09.02.2020. - Copyright © 2020 The Chromium Authors. All rights reserved. -*/ - -"CFBundleName" = "Class schedule"; -"CFBundleDisplayName" = "Class schedule"; diff --git a/ios/TodayExt/en.lproj/Localizable.strings b/ios/TodayExt/en.lproj/Localizable.strings deleted file mode 100644 index 6d6a96c..0000000 --- a/ios/TodayExt/en.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -/* - Localizable.strings - Runner - - Created by Nickolay Truhin on 09.02.2020. - Copyright © 2020 The Chromium Authors. All rights reserved. -*/ - -"noCache" = "The shedule is not cached"; -"freeDay" = "Free day"; diff --git a/ios/TodayExt/ru.lproj/InfoPlist.strings b/ios/TodayExt/ru.lproj/InfoPlist.strings deleted file mode 100644 index 4b28304..0000000 --- a/ios/TodayExt/ru.lproj/InfoPlist.strings +++ /dev/null @@ -1,10 +0,0 @@ -/* - InfoPlist.strings - Runner - - Created by Nickolay Truhin on 09.02.2020. - Copyright © 2020 The Chromium Authors. All rights reserved. -*/ - -"CFBundleName" = "Расписание занятий"; -"CFBundleDisplayName" = "Расписание занятий"; diff --git a/ios/TodayExt/ru.lproj/Localizable.strings b/ios/TodayExt/ru.lproj/Localizable.strings deleted file mode 100644 index 8dac9a0..0000000 --- a/ios/TodayExt/ru.lproj/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -/* - Localizable.strings - Runner - - Created by Nickolay Truhin on 09.02.2020. - Copyright © 2020 The Chromium Authors. All rights reserved. -*/ - -"noCache" = "Расписание не закешировано"; -"freeDay" = "Свободный день"; diff --git a/ios/TodayExt/ru.lproj/MainInterface.strings b/ios/TodayExt/ru.lproj/MainInterface.strings deleted file mode 100644 index 8b13789..0000000 --- a/ios/TodayExt/ru.lproj/MainInterface.strings +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ios/input.xcfilelist b/ios/input.xcfilelist deleted file mode 100644 index 945be05..0000000 --- a/ios/input.xcfilelist +++ /dev/null @@ -1 +0,0 @@ -$(SRCROOT)/Carthage/Build/iOS/SQLite.framework \ No newline at end of file diff --git a/ios/output.xcfilelist b/ios/output.xcfilelist deleted file mode 100644 index 8d4765e..0000000 --- a/ios/output.xcfilelist +++ /dev/null @@ -1 +0,0 @@ -$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/SQLite.framework \ No newline at end of file diff --git a/lib/about.dart b/lib/about.dart index 2fd937f..2838e71 100644 --- a/lib/about.dart +++ b/lib/about.dart @@ -5,10 +5,10 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:ranepa_timetable/intro.dart'; -import 'package:ranepa_timetable/localizations.dart'; -import 'package:ranepa_timetable/theme.dart'; -import 'package:ranepa_timetable/widget_templates.dart'; +import 'package:ranepatimetable/intro.dart'; +import 'package:ranepatimetable/localizations.dart'; +import 'package:ranepatimetable/theme.dart'; +import 'package:ranepatimetable/widget_templates.dart'; import 'package:url_launcher/url_launcher.dart'; class AboutBackgroundClipper extends CustomClipper { @@ -58,7 +58,7 @@ void main() => runApp(MaterialApp( )); class AboutScreen extends StatelessWidget { - BuildContext ctx; + static late BuildContext ctx; static const ROUTE = "/about"; Widget _buildGuyIconContent( @@ -67,9 +67,9 @@ class AboutScreen extends StatelessWidget { String name, String url, String image, { - String descriptionLeft, - String descriptionRight, - String singleStr, + String? descriptionLeft, + String? descriptionRight, + String? singleStr, }) => Container( height: 220, @@ -83,14 +83,14 @@ class AboutScreen extends StatelessWidget { width: 100.0, height: 100.0, decoration: BoxDecoration( - color: textTheme.title.color, + color: textTheme.titleLarge?.color, image: DecorationImage( image: AssetImage('assets/images/$image.jpg'), fit: BoxFit.cover, ), borderRadius: BorderRadius.all(Radius.circular(50.0)), border: Border.all( - color: textTheme.title.color, + color: textTheme.titleLarge?.color ?? Colors.transparent, width: 4.0, ), ), @@ -100,11 +100,11 @@ class AboutScreen extends StatelessWidget { RichText( text: TextSpan( text: '$name\n', - style: textTheme.title, + style: textTheme.titleLarge, children: [ TextSpan( text: '"$url"', - style: textTheme.body2, + style: textTheme.bodyLarge, ), ], ), @@ -115,7 +115,7 @@ class AboutScreen extends StatelessWidget { child: singleStr != null ? AutoSizeText( singleStr, - style: textTheme.subtitle, + style: textTheme.titleMedium, textAlign: TextAlign.center, ) : Row( @@ -126,21 +126,21 @@ class AboutScreen extends StatelessWidget { children: [ Flexible( child: AutoSizeText( - descriptionLeft, - style: textTheme.subtitle, + descriptionLeft ?? '', + style: textTheme.titleMedium, textAlign: TextAlign.right, minFontSize: 2, - maxLines: descriptionLeft.split('\n').length, + maxLines: descriptionLeft?.split('\n').length, softWrap: false, ), ), Container(width: 4), Flexible( child: AutoSizeText( - descriptionRight, - style: textTheme.subtitle, + descriptionRight ?? '', + style: textTheme.titleMedium, textAlign: TextAlign.left, - maxLines: descriptionRight.split('\n').length, + maxLines: descriptionRight?.split('\n').length, minFontSize: 2, softWrap: false, ), @@ -161,9 +161,9 @@ class AboutScreen extends StatelessWidget { String url, String image, Orientation orientation, { - String descriptionLeft, - String descriptionRight, - String singleStr, + String? descriptionLeft, + String? descriptionRight, + String? singleStr, }) => orientation == Orientation.portrait ? Flexible( @@ -234,7 +234,7 @@ class AboutScreen extends StatelessWidget { ) => IntroScreen.buildWelcomeTextList( AppLocalizations.of(ctx), - Theme.of(ctx).accentTextTheme, + Theme.of(ctx).textTheme, ); List _buildLogoText( @@ -247,7 +247,7 @@ class AboutScreen extends StatelessWidget { padding: const EdgeInsets.all(20), child: WidgetTemplates.buildLogo( Theme.of(ctx), - color: textTheme.title.color, + color: textTheme.titleLarge?.color ?? Colors.transparent, ), ), orientation == Orientation.landscape @@ -264,7 +264,7 @@ class AboutScreen extends StatelessWidget { Widget build(BuildContext ctx) { final currentTheme = Theme.of(ctx); final textTheme = (currentTheme.brightness == Brightness.dark - ? Theme.of(ctx).accentTextTheme + ? Theme.of(ctx).textTheme : Theme.of(ctx).primaryTextTheme); return PlatformScaffold( @@ -342,7 +342,7 @@ class AboutScreen extends StatelessWidget { ), ), appBar: PlatformAppBar( - android: (ctx) => MaterialAppBarData(elevation: 0), + material: (ctx, platform) => MaterialAppBarData(elevation: 0), title: Text( AppLocalizations.of(ctx).about, style: TextStyle(color: Colors.white), @@ -352,7 +352,7 @@ class AboutScreen extends StatelessWidget { padding: EdgeInsets.zero, icon: Icon( PlatformIcons(ctx).back, - color: Platform.isIOS ? getTheme().accentColor : null, + color: Platform.isIOS ? ColorScheme.fromSwatch().secondary : null, ), onPressed: () => Navigator.pop(ctx), ), diff --git a/lib/apis.dart b/lib/apis.dart index 446cc53..fd9de3b 100644 --- a/lib/apis.dart +++ b/lib/apis.dart @@ -1,7 +1,7 @@ import 'dart:convert'; import 'package:flutter/widgets.dart'; -import 'package:ranepa_timetable/localizations.dart'; +import 'package:ranepatimetable/localizations.dart'; import 'package:xml/xml.dart' as xml; const DEFAULT_API_ID = SiteApiIds.SITE; @@ -15,8 +15,9 @@ enum SiteApiIds { class SiteApi { final String title; final Uri url; + final bool isHidden; - const SiteApi(this.title, this.url); + const SiteApi(this.title, this.url, this.isHidden); } enum OldAppApiTimetableIndexes { @@ -35,12 +36,9 @@ enum OldAppApiSearchIndexes { } class SiteApis { - static SiteApis _singleton; + static SiteApis? _singleton; - factory SiteApis(BuildContext ctx) { - if (_singleton == null) _singleton = SiteApis._internal(ctx); - return _singleton; - } + factory SiteApis(BuildContext ctx) => _singleton ?? SiteApis._internal(ctx); final List apis; @@ -53,6 +51,7 @@ class SiteApis { "test.ranhigs-nn.ru", "/api/WebService.asmx", ), + true ), // APP_NEW @@ -62,6 +61,7 @@ class SiteApis { "services.niu.ranepa.ru", "/wp-content/plugins/rasp/rasp_json_data.php", ), + true ), // SITE @@ -71,6 +71,7 @@ class SiteApis { "services.niu.ranepa.ru", "/API/public/", ), + true ), ]; } @@ -81,13 +82,13 @@ parseResp(SiteApiIds api, String resp) { var arr = json.decode(resp); return arr is Iterable ? arr : [arr]; case SiteApiIds.APP_OLD: - return xml + return xml.XmlDocument .parse(resp) .children[1] .firstChild - .firstChild - .firstChild - .children; + ?.firstChild + ?.firstChild + ?.children; case SiteApiIds.SITE: final arr = json.decode(resp).entries.first.value.entries; diff --git a/lib/generated/i18n.dart b/lib/generated/i18n.dart deleted file mode 100644 index a1f1fd4..0000000 --- a/lib/generated/i18n.dart +++ /dev/null @@ -1,77 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -// ignore_for_file: non_constant_identifier_names -// ignore_for_file: camel_case_types -// ignore_for_file: prefer_single_quotes - -//This file is automatically generated. DO NOT EDIT, all your changes would be lost. - -class S implements WidgetsLocalizations { - const S(); - - static const GeneratedLocalizationsDelegate delegate = - const GeneratedLocalizationsDelegate(); - - static S of(BuildContext context) => - Localizations.of(context, WidgetsLocalizations); - - @override - TextDirection get textDirection => TextDirection.ltr; - -} - -class en extends S { - const en(); -} - - -class GeneratedLocalizationsDelegate extends LocalizationsDelegate { - const GeneratedLocalizationsDelegate(); - - List get supportedLocales { - return const [ - - const Locale("en", ""), - - ]; - } - - LocaleResolutionCallback resolution({Locale fallback}) { - return (Locale locale, Iterable supported) { - final Locale languageLocale = new Locale(locale.languageCode, ""); - if (supported.contains(locale)) - return locale; - else if (supported.contains(languageLocale)) - return languageLocale; - else { - final Locale fallbackLocale = fallback ?? supported.first; - return fallbackLocale; - } - }; - } - - @override - Future load(Locale locale) { - final String lang = getLang(locale); - switch (lang) { - - case "en": - return new SynchronousFuture(const en()); - - default: - return new SynchronousFuture(const S()); - } - } - - @override - bool isSupported(Locale locale) => supportedLocales.contains(locale); - - @override - bool shouldReload(GeneratedLocalizationsDelegate old) => false; -} - -String getLang(Locale l) => l.countryCode != null && l.countryCode.isEmpty - ? l.languageCode - : l.toString(); diff --git a/lib/intro.dart b/lib/intro.dart index e8b9e30..1aeae9b 100644 --- a/lib/intro.dart +++ b/lib/intro.dart @@ -5,20 +5,19 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:intro_views_flutter/Models/page_view_model.dart'; import 'package:intro_views_flutter/intro_views_flutter.dart'; -import 'package:ranepa_timetable/about.dart'; -import 'package:ranepa_timetable/localizations.dart'; -import 'package:ranepa_timetable/prefs.dart'; -import 'package:ranepa_timetable/theme.dart'; -import 'package:ranepa_timetable/timeline.dart'; -import 'package:ranepa_timetable/timetable.dart'; -import 'package:ranepa_timetable/widget_templates.dart'; +import 'package:ranepatimetable/about.dart'; +import 'package:ranepatimetable/localizations.dart'; +import 'package:ranepatimetable/prefs.dart'; +import 'package:ranepatimetable/theme.dart'; +import 'package:ranepatimetable/timeline.dart'; +import 'package:ranepatimetable/timetable.dart'; +import 'package:ranepatimetable/widget_templates.dart'; class IntroScreen extends StatelessWidget { - static const ROUTE = "/intro"; + static String ROUTE = "/intro"; - IntroScreen({Key key}) : super(key: key); + IntroScreen({Key? key}) : super(key: key); PageViewModel _buildTimetable(BuildContext ctx) => PageViewModel( bubbleBackgroundColor: contentColor, @@ -41,7 +40,7 @@ class IntroScreen extends StatelessWidget { static Widget buildWelcomeTextList( AppLocalizations localizations, TextTheme textTheme, { - Orientation orientation, + Orientation? orientation, }) => Column( mainAxisSize: MainAxisSize.max, @@ -49,12 +48,12 @@ class IntroScreen extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ orientation == Orientation.landscape - ? Expanded + ? Expanded(child: Container()) : Flexible( child: SingleChildScrollView( child: Text( localizations.introWelcomeDescription, - style: textTheme.body1.merge( + style: textTheme.bodyMedium?.merge( TextStyle(color: Colors.white, fontSize: 20), ), textAlign: TextAlign.center, @@ -66,7 +65,7 @@ class IntroScreen extends StatelessWidget { child: Text( localizations.introWelcomeSupportBy, textAlign: TextAlign.center, - style: textTheme.caption.merge( + style: textTheme.bodySmall?.merge( TextStyle( fontSize: 20, color: Colors.white.withOpacity(0.5), @@ -91,8 +90,8 @@ class IntroScreen extends StatelessWidget { body: buildWelcomeTextList( localizations, TextTheme( - body1: TextStyle(color: Colors.white), - caption: TextStyle(color: Colors.grey), + bodyLarge: TextStyle(color: Colors.white), + bodySmall: TextStyle(color: Colors.grey), ), ), title: _buildTitleText(localizations.introWelcomeTitle), @@ -138,7 +137,7 @@ class IntroScreen extends StatelessWidget { PlatformIcons(ctx).search, onPressed: () async { await onThemeChange(); - return showSearchItemSelect(ctx); + showSearchItemSelect(ctx); }, ), ), @@ -159,7 +158,7 @@ class IntroScreen extends StatelessWidget { RawMaterialButton _buildCircleButton( IconData icon, { double size = 100, - VoidCallback onPressed, + required VoidCallback onPressed, bool enabled = true, }) => RawMaterialButton( @@ -176,10 +175,10 @@ class IntroScreen extends StatelessWidget { padding: EdgeInsets.all(size / 3), ); - ThemeData theme; - Color backgroundColor; - Color contentColor; - AppLocalizations localizations; + static late ThemeData theme; + static late Color backgroundColor; + static late Color contentColor; + static late AppLocalizations localizations; @override Widget build(BuildContext ctx) => buildThemeStream( @@ -192,10 +191,8 @@ class IntroScreen extends StatelessWidget { ? theme.primaryColor : theme.canvasColor; contentColor = (theme.brightness == Brightness.light - ? theme.accentTextTheme - : theme.textTheme) - .body1 - .color; + ? Colors.white + : Colors.black); return IntroViewsFlutter( [ diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index b4f1061..0ae2a08 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2020-02-05T14:06:26.216374", + "@@last_modified": "2023-06-04T16:56:33.684027", "title": "RANEPA (Timetable)", "@title": { "type": "text", @@ -345,12 +345,12 @@ "type": "text", "placeholders": {} }, - "themeTitle": "Theme", + "themeTitle": "Dark mode", "@themeTitle": { "type": "text", "placeholders": {} }, - "themeDescription": "Color scheme of the application and widget", + "themeDescription": "Dark color scheme of the application and widget", "@themeDescription": { "type": "text", "placeholders": {} diff --git a/lib/l10n/messages_all.dart b/lib/l10n/messages_all.dart index 835026b..fc55d77 100644 --- a/lib/l10n/messages_all.dart +++ b/lib/l10n/messages_all.dart @@ -2,66 +2,6 @@ // This is a library that looks up messages for specific locales by // delegating to the appropriate library. -// Ignore issues from commonly used lints in this file. -// ignore_for_file:implementation_imports, file_names, unnecessary_new -// ignore_for_file:unnecessary_brace_in_string_interps, directives_ordering -// ignore_for_file:argument_type_not_assignable, invalid_assignment -// ignore_for_file:prefer_single_quotes, prefer_generic_function_type_aliases -// ignore_for_file:comment_references +export 'messages_all_locales.dart' + show initializeMessages; -import 'dart:async'; - -import 'package:intl/intl.dart'; -import 'package:intl/message_lookup_by_library.dart'; -import 'package:intl/src/intl_helpers.dart'; - -import 'messages_messages.dart' as messages_messages; -import 'messages_ru.dart' as messages_ru; - -typedef Future LibraryLoader(); -Map _deferredLibraries = { - 'messages': () => new Future.value(null), - 'ru': () => new Future.value(null), -}; - -MessageLookupByLibrary _findExact(String localeName) { - switch (localeName) { - case 'messages': - return messages_messages.messages; - case 'ru': - return messages_ru.messages; - default: - return null; - } -} - -/// User programs should call this before using [localeName] for messages. -Future initializeMessages(String localeName) async { - var availableLocale = Intl.verifiedLocale( - localeName, - (locale) => _deferredLibraries[locale] != null, - onFailure: (_) => null); - if (availableLocale == null) { - return new Future.value(false); - } - var lib = _deferredLibraries[availableLocale]; - await (lib == null ? new Future.value(false) : lib()); - initializeInternalMessageLookup(() => new CompositeMessageLookup()); - messageLookup.addLocale(availableLocale, _findGeneratedMessagesFor); - return new Future.value(true); -} - -bool _messagesExistFor(String locale) { - try { - return _findExact(locale) != null; - } catch (e) { - return false; - } -} - -MessageLookupByLibrary _findGeneratedMessagesFor(String locale) { - var actualLocale = Intl.verifiedLocale(locale, _messagesExistFor, - onFailure: (_) => null); - if (actualLocale == null) return null; - return _findExact(actualLocale); -} diff --git a/lib/l10n/messages_all_locales.dart b/lib/l10n/messages_all_locales.dart new file mode 100644 index 0000000..7311918 --- /dev/null +++ b/lib/l10n/messages_all_locales.dart @@ -0,0 +1,65 @@ +// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart +// This is a library that looks up messages for specific locales by +// delegating to the appropriate library. + +// Ignore issues from commonly used lints in this file. +// ignore_for_file:implementation_imports, file_names +// ignore_for_file:unnecessary_brace_in_string_interps, directives_ordering +// ignore_for_file:argument_type_not_assignable, invalid_assignment +// ignore_for_file:prefer_single_quotes, prefer_generic_function_type_aliases +// ignore_for_file:comment_references + +import 'package:intl/intl.dart'; +import 'package:intl/message_lookup_by_library.dart'; +import 'package:intl/src/intl_helpers.dart'; + +import 'messages_messages.dart' as messages_messages; +import 'messages_ru.dart' as messages_ru; + +typedef Future LibraryLoader(); +Map _deferredLibraries = { + 'messages': () => Future.value(null), + 'ru': () => Future.value(null), +}; + +MessageLookupByLibrary? _findExact(String localeName) { + switch (localeName) { + case 'messages': + return messages_messages.messages; + case 'ru': + return messages_ru.messages; + default: + return null; + } +} + +/// User programs should call this before using [localeName] for messages. +Future initializeMessages(String? localeName) async { + var availableLocale = Intl.verifiedLocale( + localeName, + (locale) => _deferredLibraries[locale] != null, + onFailure: (_) => null); + if (availableLocale == null) { + return Future.value(false); + } + var lib = _deferredLibraries[availableLocale]; + await (lib == null ? Future.value(false) : lib()); + initializeInternalMessageLookup(() => CompositeMessageLookup()); + messageLookup.addLocale(availableLocale, _findGeneratedMessagesFor); + return Future.value(true); +} + +bool _messagesExistFor(String locale) { + try { + return _findExact(locale) != null; + } catch (e) { + return false; + } +} + +MessageLookupByLibrary? _findGeneratedMessagesFor(String locale) { + var actualLocale = Intl.verifiedLocale(locale, _messagesExistFor, + onFailure: (_) => null); + if (actualLocale == null) return null; + return _findExact(actualLocale); +} diff --git a/lib/l10n/messages_messages.dart b/lib/l10n/messages_messages.dart index 26a8a30..1844738 100644 --- a/lib/l10n/messages_messages.dart +++ b/lib/l10n/messages_messages.dart @@ -4,7 +4,7 @@ // function name. // Ignore issues from commonly used lints in this file. -// ignore_for_file:unnecessary_brace_in_string_interps, unnecessary_new +// ignore_for_file:unnecessary_brace_in_string_interps // ignore_for_file:prefer_single_quotes,comment_references, directives_ordering // ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases // ignore_for_file:unused_import, file_names @@ -12,124 +12,128 @@ import 'package:intl/intl.dart'; import 'package:intl/message_lookup_by_library.dart'; -final messages = new MessageLookup(); +final messages = MessageLookup(); -typedef String MessageIfAbsent(String messageStr, List args); +typedef String? MessageIfAbsent( + String? messageStr, List? args); class MessageLookup extends MessageLookupByLibrary { + @override String get localeName => 'messages'; - final messages = _notInlinedMessages(_notInlinedMessages); - static _notInlinedMessages(_) => { - "about" : MessageLookupByLibrary.simpleMessage("About"), - "accounting" : MessageLookupByLibrary.simpleMessage("Accounting"), - "accountingAnalysis" : MessageLookupByLibrary.simpleMessage("Accounting analysis"), - "alarmAddSuccess" : MessageLookupByLibrary.simpleMessage("The alarm clock is turned on at "), - "alarmTip" : MessageLookupByLibrary.simpleMessage("Add to alarm clock"), - "beforeAlarmClockDescription" : MessageLookupByLibrary.simpleMessage("How much before the first lesson you need to add an alarm clock"), - "beforeAlarmClockTitle" : MessageLookupByLibrary.simpleMessage("Time before alarm clock"), - "biology" : MessageLookupByLibrary.simpleMessage("Biology"), - "budgetCalculations" : MessageLookupByLibrary.simpleMessage("Budget calculations"), - "businessPlanning" : MessageLookupByLibrary.simpleMessage("Business planning"), - "calendarEventsAddFailed" : MessageLookupByLibrary.simpleMessage("An error occurred while adding events to the calendar"), - "calendarEventsAddSuccess" : MessageLookupByLibrary.simpleMessage("Events successfully added to calendar"), - "calendarGetFailed" : MessageLookupByLibrary.simpleMessage("Аn error occurred while getting the calendars"), - "calendarTip" : MessageLookupByLibrary.simpleMessage("Add to calendar"), - "chemistry" : MessageLookupByLibrary.simpleMessage("Chemistry"), - "close" : MessageLookupByLibrary.simpleMessage("Close"), - "computerArchitecture" : MessageLookupByLibrary.simpleMessage("Сomputer Architecture"), - "computerGraphic" : MessageLookupByLibrary.simpleMessage("Computer Graphic"), - "credit" : MessageLookupByLibrary.simpleMessage("Reception of credit"), - "databases" : MessageLookupByLibrary.simpleMessage("Databases"), - "dayStyleDate" : MessageLookupByLibrary.simpleMessage("Date"), - "dayStyleDescription" : MessageLookupByLibrary.simpleMessage("Date display style"), - "dayStyleTitle" : MessageLookupByLibrary.simpleMessage("Date display format"), - "dayStyleWeekday" : MessageLookupByLibrary.simpleMessage("Day of week"), - "discMath" : MessageLookupByLibrary.simpleMessage("Discrete math"), - "documentManagementSupport" : MessageLookupByLibrary.simpleMessage("Document management support"), - "economics" : MessageLookupByLibrary.simpleMessage("Economic theory"), - "english" : MessageLookupByLibrary.simpleMessage("English"), - "errorMessage" : MessageLookupByLibrary.simpleMessage("Something went wrong"), - "ethics" : MessageLookupByLibrary.simpleMessage("Ethics"), - "exam" : MessageLookupByLibrary.simpleMessage("Exam"), - "examConsultation" : MessageLookupByLibrary.simpleMessage("Exam consultation"), - "freeDay" : MessageLookupByLibrary.simpleMessage("Free day"), - "friday" : MessageLookupByLibrary.simpleMessage("Fr"), - "geography" : MessageLookupByLibrary.simpleMessage("Geography"), - "groupDescription" : MessageLookupByLibrary.simpleMessage("Default timetable for the group/teacher"), - "groupEconomics" : MessageLookupByLibrary.simpleMessage("Economics"), - "groupInformatics" : MessageLookupByLibrary.simpleMessage("Informatics"), - "groupTitle" : MessageLookupByLibrary.simpleMessage("Group/teacher"), - "history" : MessageLookupByLibrary.simpleMessage("History"), - "informatics" : MessageLookupByLibrary.simpleMessage("Informatics"), - "informationTheory" : MessageLookupByLibrary.simpleMessage("Information theory"), - "introGroupDescription" : MessageLookupByLibrary.simpleMessage("For this group or teacher, the schedule will be loaded at startup."), - "introGroupTitle" : MessageLookupByLibrary.simpleMessage("Group or teacher"), - "introThemeDescription" : MessageLookupByLibrary.simpleMessage("The selected theme will be used when drawing the schedule and everything else. The theme can be changed in the settings."), - "introThemeTitle" : MessageLookupByLibrary.simpleMessage("Color scheme"), - "introTimetableDescription" : MessageLookupByLibrary.simpleMessage("So the schedule will look. If necessary, you can go back and change the theme."), - "introTimetableTitle" : MessageLookupByLibrary.simpleMessage("Shedule example"), - "introWelcomeDescription" : MessageLookupByLibrary.simpleMessage("This application is an unofficial client of the site of the Nizhny Novgorod RANEPA and has no relation to its administration."), - "introWelcomeInitialSetup" : MessageLookupByLibrary.simpleMessage("To use the application, you must pass the initial setup."), - "introWelcomeSupportBy" : MessageLookupByLibrary.simpleMessage("with the support of trade Union Nizhny Novgorod RANEPA"), - "introWelcomeTitle" : MessageLookupByLibrary.simpleMessage("Welcome"), - "inventory" : MessageLookupByLibrary.simpleMessage("Inventarization"), - "lecture" : MessageLookupByLibrary.simpleMessage("Lecture"), - "legalSupport" : MessageLookupByLibrary.simpleMessage("Legal support"), - "lifeSafety" : MessageLookupByLibrary.simpleMessage("Basics of life safety"), - "literature" : MessageLookupByLibrary.simpleMessage("Literature"), - "loading" : MessageLookupByLibrary.simpleMessage("Loading"), - "management" : MessageLookupByLibrary.simpleMessage("Management"), - "math" : MessageLookupByLibrary.simpleMessage("Mathematics"), - "monday" : MessageLookupByLibrary.simpleMessage("Mo"), - "noCache" : MessageLookupByLibrary.simpleMessage("Schedule not loaded"), - "noLessonsFound" : MessageLookupByLibrary.simpleMessage("No lessons found"), - "noNetworkConnection" : MessageLookupByLibrary.simpleMessage("No network connection"), - "operatingSystems" : MessageLookupByLibrary.simpleMessage("Operating Systems"), - "optimizedLessonTitlesDescription" : MessageLookupByLibrary.simpleMessage("Shortens the lesson names"), - "optimizedLessonTitlesTitle" : MessageLookupByLibrary.simpleMessage("Replacing lesson names"), - "philosophy" : MessageLookupByLibrary.simpleMessage("Philosophy"), - "physicalCulture" : MessageLookupByLibrary.simpleMessage("Physical Culture"), - "physics" : MessageLookupByLibrary.simpleMessage("Physics"), - "practice" : MessageLookupByLibrary.simpleMessage("Practice"), - "prefs" : MessageLookupByLibrary.simpleMessage("Preferences"), - "projectDevelopment" : MessageLookupByLibrary.simpleMessage("Project Development"), - "receptionExamination" : MessageLookupByLibrary.simpleMessage("Reception examination"), - "refreshTip" : MessageLookupByLibrary.simpleMessage("Refresh shedule"), - "roomLocationAcademy" : MessageLookupByLibrary.simpleMessage("Academy"), - "roomLocationHotel" : MessageLookupByLibrary.simpleMessage("Hotel (St. Pushkin, 8)"), - "roomLocationStudyHostel" : MessageLookupByLibrary.simpleMessage("Study hostel"), - "roomLocationStyleDescriptionIcon" : MessageLookupByLibrary.simpleMessage("Icon showing the location of the room"), - "roomLocationStyleDescriptionText" : MessageLookupByLibrary.simpleMessage("Text showing the location of the room"), - "roomLocationStyleIcon" : MessageLookupByLibrary.simpleMessage("Icon"), - "roomLocationStyleText" : MessageLookupByLibrary.simpleMessage("Text"), - "roomLocationStyleTitle" : MessageLookupByLibrary.simpleMessage("Room location style"), - "saturday" : MessageLookupByLibrary.simpleMessage("Sa"), - "searchResults" : MessageLookupByLibrary.simpleMessage("Web search results"), - "searchTip" : MessageLookupByLibrary.simpleMessage("Search"), - "sendError" : MessageLookupByLibrary.simpleMessage("Send error description\nto developers"), - "siteApiDescription" : MessageLookupByLibrary.simpleMessage("How the app will receive the schedule"), - "siteApiNewApp" : MessageLookupByLibrary.simpleMessage("New app API"), - "siteApiOldApp" : MessageLookupByLibrary.simpleMessage("Old app API"), - "siteApiSite" : MessageLookupByLibrary.simpleMessage("Official site API"), - "siteApiTitle" : MessageLookupByLibrary.simpleMessage("Site API"), - "socialStudies" : MessageLookupByLibrary.simpleMessage("Social Studies"), - "softwareDevelopment" : MessageLookupByLibrary.simpleMessage("Software Development"), - "speechCulture" : MessageLookupByLibrary.simpleMessage("Culture of Speech"), - "statMath" : MessageLookupByLibrary.simpleMessage("Theory of probability and mathematical statistics"), - "taxation" : MessageLookupByLibrary.simpleMessage("Taxation"), - "themeAccentDescription" : MessageLookupByLibrary.simpleMessage("Accent color of theme"), - "themeAccentTitle" : MessageLookupByLibrary.simpleMessage("Theme accent color"), - "themeDark" : MessageLookupByLibrary.simpleMessage("Dark"), - "themeDescription" : MessageLookupByLibrary.simpleMessage("Color scheme of the application and widget"), - "themeLight" : MessageLookupByLibrary.simpleMessage("Light"), - "themeTitle" : MessageLookupByLibrary.simpleMessage("Theme"), - "thursday" : MessageLookupByLibrary.simpleMessage("Th"), - "timetable" : MessageLookupByLibrary.simpleMessage("Timetable"), - "title" : MessageLookupByLibrary.simpleMessage("RANEPA (Timetable)"), - "tuesday" : MessageLookupByLibrary.simpleMessage("Tu"), - "wednesday" : MessageLookupByLibrary.simpleMessage("We"), - "widgetTranslucentDescription" : MessageLookupByLibrary.simpleMessage("Translucency android widget on home screen"), - "widgetTranslucentTitle" : MessageLookupByLibrary.simpleMessage("Widget translucency") + @override + final Map messages = _notInlinedMessages(_notInlinedMessages); + + static Map _notInlinedMessages(_) => { + 'about': MessageLookupByLibrary.simpleMessage('About'), + 'accounting': MessageLookupByLibrary.simpleMessage('Accounting'), + 'accountingAnalysis': MessageLookupByLibrary.simpleMessage('Accounting analysis'), + 'alarmAddSuccess': MessageLookupByLibrary.simpleMessage('The alarm clock is turned on at '), + 'alarmTip': MessageLookupByLibrary.simpleMessage('Add to alarm clock'), + 'beforeAlarmClockDescription': MessageLookupByLibrary.simpleMessage('How much before the first lesson you need to add an alarm clock'), + 'beforeAlarmClockTitle': MessageLookupByLibrary.simpleMessage('Time before alarm clock'), + 'biology': MessageLookupByLibrary.simpleMessage('Biology'), + 'budgetCalculations': MessageLookupByLibrary.simpleMessage('Budget calculations'), + 'businessPlanning': MessageLookupByLibrary.simpleMessage('Business planning'), + 'calendarEventsAddFailed': MessageLookupByLibrary.simpleMessage('An error occurred while adding events to the calendar'), + 'calendarEventsAddSuccess': MessageLookupByLibrary.simpleMessage('Events successfully added to calendar'), + 'calendarGetFailed': MessageLookupByLibrary.simpleMessage('Аn error occurred while getting the calendars'), + 'calendarTip': MessageLookupByLibrary.simpleMessage('Add to calendar'), + 'chemistry': MessageLookupByLibrary.simpleMessage('Chemistry'), + 'close': MessageLookupByLibrary.simpleMessage('Close'), + 'computerArchitecture': MessageLookupByLibrary.simpleMessage('Сomputer Architecture'), + 'computerGraphic': MessageLookupByLibrary.simpleMessage('Computer Graphic'), + 'credit': MessageLookupByLibrary.simpleMessage('Reception of credit'), + 'databases': MessageLookupByLibrary.simpleMessage('Databases'), + 'dayStyleDate': MessageLookupByLibrary.simpleMessage('Date'), + 'dayStyleDescription': MessageLookupByLibrary.simpleMessage('Date display style'), + 'dayStyleTitle': MessageLookupByLibrary.simpleMessage('Date display format'), + 'dayStyleWeekday': MessageLookupByLibrary.simpleMessage('Day of week'), + 'discMath': MessageLookupByLibrary.simpleMessage('Discrete math'), + 'documentManagementSupport': MessageLookupByLibrary.simpleMessage('Document management support'), + 'economics': MessageLookupByLibrary.simpleMessage('Economic theory'), + 'english': MessageLookupByLibrary.simpleMessage('English'), + 'errorMessage': MessageLookupByLibrary.simpleMessage('Something went wrong'), + 'ethics': MessageLookupByLibrary.simpleMessage('Ethics'), + 'exam': MessageLookupByLibrary.simpleMessage('Exam'), + 'examConsultation': MessageLookupByLibrary.simpleMessage('Exam consultation'), + 'freeDay': MessageLookupByLibrary.simpleMessage('Free day'), + 'friday': MessageLookupByLibrary.simpleMessage('Fr'), + 'geography': MessageLookupByLibrary.simpleMessage('Geography'), + 'groupDescription': MessageLookupByLibrary.simpleMessage('Default timetable for the group/teacher'), + 'groupEconomics': MessageLookupByLibrary.simpleMessage('Economics'), + 'groupInformatics': MessageLookupByLibrary.simpleMessage('Informatics'), + 'groupTitle': MessageLookupByLibrary.simpleMessage('Group/teacher'), + 'history': MessageLookupByLibrary.simpleMessage('History'), + 'informatics': MessageLookupByLibrary.simpleMessage('Informatics'), + 'informationTheory': MessageLookupByLibrary.simpleMessage('Information theory'), + 'introGroupDescription': MessageLookupByLibrary.simpleMessage('For this group or teacher, the schedule will be loaded at startup.'), + 'introGroupTitle': MessageLookupByLibrary.simpleMessage('Group or teacher'), + 'introThemeDescription': MessageLookupByLibrary.simpleMessage('The selected theme will be used when drawing the schedule and everything else. The theme can be changed in the settings.'), + 'introThemeTitle': MessageLookupByLibrary.simpleMessage('Color scheme'), + 'introTimetableDescription': MessageLookupByLibrary.simpleMessage('So the schedule will look. If necessary, you can go back and change the theme.'), + 'introTimetableTitle': MessageLookupByLibrary.simpleMessage('Shedule example'), + 'introWelcomeDescription': MessageLookupByLibrary.simpleMessage('This application is an unofficial client of the site of the Nizhny Novgorod RANEPA and has no relation to its administration.'), + 'introWelcomeInitialSetup': MessageLookupByLibrary.simpleMessage('To use the application, you must pass the initial setup.'), + 'introWelcomeSupportBy': MessageLookupByLibrary.simpleMessage('with the support of trade Union Nizhny Novgorod RANEPA'), + 'introWelcomeTitle': MessageLookupByLibrary.simpleMessage('Welcome'), + 'inventory': MessageLookupByLibrary.simpleMessage('Inventarization'), + 'lecture': MessageLookupByLibrary.simpleMessage('Lecture'), + 'legalSupport': MessageLookupByLibrary.simpleMessage('Legal support'), + 'lifeSafety': MessageLookupByLibrary.simpleMessage('Basics of life safety'), + 'literature': MessageLookupByLibrary.simpleMessage('Literature'), + 'loading': MessageLookupByLibrary.simpleMessage('Loading'), + 'management': MessageLookupByLibrary.simpleMessage('Management'), + 'math': MessageLookupByLibrary.simpleMessage('Mathematics'), + 'monday': MessageLookupByLibrary.simpleMessage('Mo'), + 'noCache': MessageLookupByLibrary.simpleMessage('Schedule not loaded'), + 'noLessonsFound': MessageLookupByLibrary.simpleMessage('No lessons found'), + 'noNetworkConnection': MessageLookupByLibrary.simpleMessage('No network connection'), + 'operatingSystems': MessageLookupByLibrary.simpleMessage('Operating Systems'), + 'optimizedLessonTitlesDescription': MessageLookupByLibrary.simpleMessage('Shortens the lesson names'), + 'optimizedLessonTitlesTitle': MessageLookupByLibrary.simpleMessage('Replacing lesson names'), + 'philosophy': MessageLookupByLibrary.simpleMessage('Philosophy'), + 'physicalCulture': MessageLookupByLibrary.simpleMessage('Physical Culture'), + 'physics': MessageLookupByLibrary.simpleMessage('Physics'), + 'practice': MessageLookupByLibrary.simpleMessage('Practice'), + 'prefs': MessageLookupByLibrary.simpleMessage('Preferences'), + 'projectDevelopment': MessageLookupByLibrary.simpleMessage('Project Development'), + 'receptionExamination': MessageLookupByLibrary.simpleMessage('Reception examination'), + 'refreshTip': MessageLookupByLibrary.simpleMessage('Refresh shedule'), + 'roomLocationAcademy': MessageLookupByLibrary.simpleMessage('Academy'), + 'roomLocationHotel': MessageLookupByLibrary.simpleMessage('Hotel (St. Pushkin, 8)'), + 'roomLocationStudyHostel': MessageLookupByLibrary.simpleMessage('Study hostel'), + 'roomLocationStyleDescriptionIcon': MessageLookupByLibrary.simpleMessage('Icon showing the location of the room'), + 'roomLocationStyleDescriptionText': MessageLookupByLibrary.simpleMessage('Text showing the location of the room'), + 'roomLocationStyleIcon': MessageLookupByLibrary.simpleMessage('Icon'), + 'roomLocationStyleText': MessageLookupByLibrary.simpleMessage('Text'), + 'roomLocationStyleTitle': MessageLookupByLibrary.simpleMessage('Room location style'), + 'saturday': MessageLookupByLibrary.simpleMessage('Sa'), + 'searchResults': MessageLookupByLibrary.simpleMessage('Web search results'), + 'searchTip': MessageLookupByLibrary.simpleMessage('Search'), + 'sendError': MessageLookupByLibrary.simpleMessage('Send error description\nto developers'), + 'siteApiDescription': MessageLookupByLibrary.simpleMessage('How the app will receive the schedule'), + 'siteApiNewApp': MessageLookupByLibrary.simpleMessage('New app API'), + 'siteApiOldApp': MessageLookupByLibrary.simpleMessage('Old app API'), + 'siteApiSite': MessageLookupByLibrary.simpleMessage('Official site API'), + 'siteApiTitle': MessageLookupByLibrary.simpleMessage('Site API'), + 'socialStudies': MessageLookupByLibrary.simpleMessage('Social Studies'), + 'softwareDevelopment': MessageLookupByLibrary.simpleMessage('Software Development'), + 'speechCulture': MessageLookupByLibrary.simpleMessage('Culture of Speech'), + 'statMath': MessageLookupByLibrary.simpleMessage('Theory of probability and mathematical statistics'), + 'taxation': MessageLookupByLibrary.simpleMessage('Taxation'), + 'themeAccentDescription': MessageLookupByLibrary.simpleMessage('Accent color of theme'), + 'themeAccentTitle': MessageLookupByLibrary.simpleMessage('Theme accent color'), + 'themeDark': MessageLookupByLibrary.simpleMessage('Dark'), + 'themeDescription': MessageLookupByLibrary.simpleMessage('Dark color scheme of the application and widget'), + 'themeLight': MessageLookupByLibrary.simpleMessage('Light'), + 'themeTitle': MessageLookupByLibrary.simpleMessage('Dark mode'), + 'thursday': MessageLookupByLibrary.simpleMessage('Th'), + 'timetable': MessageLookupByLibrary.simpleMessage('Timetable'), + 'title': MessageLookupByLibrary.simpleMessage('RANEPA (Timetable)'), + 'tuesday': MessageLookupByLibrary.simpleMessage('Tu'), + 'wednesday': MessageLookupByLibrary.simpleMessage('We'), + 'widgetTranslucentDescription': MessageLookupByLibrary.simpleMessage('Translucency android widget on home screen'), + 'widgetTranslucentTitle': MessageLookupByLibrary.simpleMessage('Widget translucency') }; } diff --git a/lib/l10n/messages_ru.dart b/lib/l10n/messages_ru.dart index 1fd8710..15bea9a 100644 --- a/lib/l10n/messages_ru.dart +++ b/lib/l10n/messages_ru.dart @@ -4,7 +4,7 @@ // function name. // Ignore issues from commonly used lints in this file. -// ignore_for_file:unnecessary_brace_in_string_interps, unnecessary_new +// ignore_for_file:unnecessary_brace_in_string_interps // ignore_for_file:prefer_single_quotes,comment_references, directives_ordering // ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases // ignore_for_file:unused_import, file_names @@ -12,124 +12,128 @@ import 'package:intl/intl.dart'; import 'package:intl/message_lookup_by_library.dart'; -final messages = new MessageLookup(); +final messages = MessageLookup(); -typedef String MessageIfAbsent(String messageStr, List args); +typedef String? MessageIfAbsent( + String? messageStr, List? args); class MessageLookup extends MessageLookupByLibrary { + @override String get localeName => 'ru'; - final messages = _notInlinedMessages(_notInlinedMessages); - static _notInlinedMessages(_) => { - "about" : MessageLookupByLibrary.simpleMessage("О приложении"), - "accounting" : MessageLookupByLibrary.simpleMessage("Бухучет"), - "accountingAnalysis" : MessageLookupByLibrary.simpleMessage("Анализ бухгалтерской отчетности"), - "alarmAddSuccess" : MessageLookupByLibrary.simpleMessage("Будильник заведен на "), - "alarmTip" : MessageLookupByLibrary.simpleMessage("Добавить в будильник"), - "beforeAlarmClockDescription" : MessageLookupByLibrary.simpleMessage("Насколько заранее нужно заводить будильник"), - "beforeAlarmClockTitle" : MessageLookupByLibrary.simpleMessage("Время до будильника"), - "biology" : MessageLookupByLibrary.simpleMessage("Биология"), - "budgetCalculations" : MessageLookupByLibrary.simpleMessage("Расчеты с бюджетом"), - "businessPlanning" : MessageLookupByLibrary.simpleMessage("Бизнес-планирование"), - "calendarEventsAddFailed" : MessageLookupByLibrary.simpleMessage("Произошла ошибка при добавлении событий в календарь"), - "calendarEventsAddSuccess" : MessageLookupByLibrary.simpleMessage("События успешно добавлены в календарь"), - "calendarGetFailed" : MessageLookupByLibrary.simpleMessage("Произошла ошибка при получении календарей"), - "calendarTip" : MessageLookupByLibrary.simpleMessage("Добавить в календарь"), - "chemistry" : MessageLookupByLibrary.simpleMessage("Химия"), - "close" : MessageLookupByLibrary.simpleMessage("Выход"), - "computerArchitecture" : MessageLookupByLibrary.simpleMessage("Архитектура ПК"), - "computerGraphic" : MessageLookupByLibrary.simpleMessage("Компьютерная графика"), - "credit" : MessageLookupByLibrary.simpleMessage("Прием зачета"), - "databases" : MessageLookupByLibrary.simpleMessage("Базы данных"), - "dayStyleDate" : MessageLookupByLibrary.simpleMessage("Дата"), - "dayStyleDescription" : MessageLookupByLibrary.simpleMessage("Стиль отображения дней в расписании"), - "dayStyleTitle" : MessageLookupByLibrary.simpleMessage("Формат отображения дат"), - "dayStyleWeekday" : MessageLookupByLibrary.simpleMessage("День недели"), - "discMath" : MessageLookupByLibrary.simpleMessage("Дискретная математика"), - "documentManagementSupport" : MessageLookupByLibrary.simpleMessage("ДОУ (Документационное обеспечение управление)"), - "economics" : MessageLookupByLibrary.simpleMessage("Экономическая теория"), - "english" : MessageLookupByLibrary.simpleMessage("Английский язык"), - "errorMessage" : MessageLookupByLibrary.simpleMessage("Что-то пошло не так"), - "ethics" : MessageLookupByLibrary.simpleMessage("Этика"), - "exam" : MessageLookupByLibrary.simpleMessage("Экзамен"), - "examConsultation" : MessageLookupByLibrary.simpleMessage("Консультация к экзамену"), - "freeDay" : MessageLookupByLibrary.simpleMessage("Свободный день"), - "friday" : MessageLookupByLibrary.simpleMessage("Пт"), - "geography" : MessageLookupByLibrary.simpleMessage("География"), - "groupDescription" : MessageLookupByLibrary.simpleMessage("Группа/преподаватель для которой(-го) при запуске загружается расписание"), - "groupEconomics" : MessageLookupByLibrary.simpleMessage("Экономика"), - "groupInformatics" : MessageLookupByLibrary.simpleMessage("Информатика"), - "groupTitle" : MessageLookupByLibrary.simpleMessage("Изменить группу/преподавателя"), - "history" : MessageLookupByLibrary.simpleMessage("История"), - "informatics" : MessageLookupByLibrary.simpleMessage("Информатика"), - "informationTheory" : MessageLookupByLibrary.simpleMessage("Теория информации"), - "introGroupDescription" : MessageLookupByLibrary.simpleMessage("Для этой группы или преподавателя будет показываться расписание в будущем."), - "introGroupTitle" : MessageLookupByLibrary.simpleMessage("Группа или преподаватель"), - "introThemeDescription" : MessageLookupByLibrary.simpleMessage("Выбранная тема будет использоваться для отрисовки расписания и всего остального. Тему можно поменять в настройках."), - "introThemeTitle" : MessageLookupByLibrary.simpleMessage("Тема"), - "introTimetableDescription" : MessageLookupByLibrary.simpleMessage("Так будет выглядеть расписание. При необходимости можно вернуться назад и сменить цветовую схему."), - "introTimetableTitle" : MessageLookupByLibrary.simpleMessage("Пример расписания"), - "introWelcomeDescription" : MessageLookupByLibrary.simpleMessage("Это приложение является неофициальным клиентом сайта РАНХиГС Нижнего Новгорода и не имеет ничего общего с его админинстрацией."), - "introWelcomeInitialSetup" : MessageLookupByLibrary.simpleMessage("Для использования приложения необходимо пройти начальную настройку."), - "introWelcomeSupportBy" : MessageLookupByLibrary.simpleMessage("при поддержке Профкома НИУ РАНХиГС"), - "introWelcomeTitle" : MessageLookupByLibrary.simpleMessage("Добро пожаловать"), - "inventory" : MessageLookupByLibrary.simpleMessage("Инвентаризация"), - "lecture" : MessageLookupByLibrary.simpleMessage("Лекция"), - "legalSupport" : MessageLookupByLibrary.simpleMessage("Правовое обеспечение"), - "lifeSafety" : MessageLookupByLibrary.simpleMessage("ОБЖ"), - "literature" : MessageLookupByLibrary.simpleMessage("Литература"), - "loading" : MessageLookupByLibrary.simpleMessage("Загрузка"), - "management" : MessageLookupByLibrary.simpleMessage("Менеджмент"), - "math" : MessageLookupByLibrary.simpleMessage("Математика"), - "monday" : MessageLookupByLibrary.simpleMessage("Пн"), - "noCache" : MessageLookupByLibrary.simpleMessage("День не загружен"), - "noLessonsFound" : MessageLookupByLibrary.simpleMessage("Уроков не найдено"), - "noNetworkConnection" : MessageLookupByLibrary.simpleMessage("Отсутствует подключение к сети"), - "operatingSystems" : MessageLookupByLibrary.simpleMessage("Операционные системы"), - "optimizedLessonTitlesDescription" : MessageLookupByLibrary.simpleMessage("Упрощает названия пар"), - "optimizedLessonTitlesTitle" : MessageLookupByLibrary.simpleMessage("Замена названий предметов"), - "philosophy" : MessageLookupByLibrary.simpleMessage("Философия"), - "physicalCulture" : MessageLookupByLibrary.simpleMessage("Физ-ра"), - "physics" : MessageLookupByLibrary.simpleMessage("Физика"), - "practice" : MessageLookupByLibrary.simpleMessage("Практика"), - "prefs" : MessageLookupByLibrary.simpleMessage("Настройки"), - "projectDevelopment" : MessageLookupByLibrary.simpleMessage("Проектная разработка"), - "receptionExamination" : MessageLookupByLibrary.simpleMessage("Прием защиты"), - "refreshTip" : MessageLookupByLibrary.simpleMessage("Обновить расписание"), - "roomLocationAcademy" : MessageLookupByLibrary.simpleMessage("Академия"), - "roomLocationHotel" : MessageLookupByLibrary.simpleMessage("Гостиница (ул. Пушкина, 8)"), - "roomLocationStudyHostel" : MessageLookupByLibrary.simpleMessage("Студенческое общежитие"), - "roomLocationStyleDescriptionIcon" : MessageLookupByLibrary.simpleMessage("Корпус отображает иконка"), - "roomLocationStyleDescriptionText" : MessageLookupByLibrary.simpleMessage("Корпус обозначается текстом"), - "roomLocationStyleIcon" : MessageLookupByLibrary.simpleMessage("Иконка"), - "roomLocationStyleText" : MessageLookupByLibrary.simpleMessage("Текст"), - "roomLocationStyleTitle" : MessageLookupByLibrary.simpleMessage("Отображение аудиторий"), - "saturday" : MessageLookupByLibrary.simpleMessage("Сб"), - "searchResults" : MessageLookupByLibrary.simpleMessage("Результаты веб-поиска"), - "searchTip" : MessageLookupByLibrary.simpleMessage("Поиск"), - "sendError" : MessageLookupByLibrary.simpleMessage("Отправить описание\nошибки разработчикам"), - "siteApiDescription" : MessageLookupByLibrary.simpleMessage("Способ получения расписания"), - "siteApiNewApp" : MessageLookupByLibrary.simpleMessage("API нового приложения"), - "siteApiOldApp" : MessageLookupByLibrary.simpleMessage("API старого приложения"), - "siteApiSite" : MessageLookupByLibrary.simpleMessage("API официального сайта"), - "siteApiTitle" : MessageLookupByLibrary.simpleMessage("Используемое для получения расписания API"), - "socialStudies" : MessageLookupByLibrary.simpleMessage("Обществознание"), - "softwareDevelopment" : MessageLookupByLibrary.simpleMessage("Разработка ПО"), - "speechCulture" : MessageLookupByLibrary.simpleMessage("Культура речи"), - "statMath" : MessageLookupByLibrary.simpleMessage("Теория вероятностей и мат. статистика"), - "taxation" : MessageLookupByLibrary.simpleMessage("Налогообложение"), - "themeAccentDescription" : MessageLookupByLibrary.simpleMessage("Цвет подсветки цветовой схемы"), - "themeAccentTitle" : MessageLookupByLibrary.simpleMessage("Дополнительный цвет"), - "themeDark" : MessageLookupByLibrary.simpleMessage("Темная"), - "themeDescription" : MessageLookupByLibrary.simpleMessage("Темная цветовая схема приложения и виджета"), - "themeLight" : MessageLookupByLibrary.simpleMessage("Светлая"), - "themeTitle" : MessageLookupByLibrary.simpleMessage("Тёмный режим"), - "thursday" : MessageLookupByLibrary.simpleMessage("Чт"), - "timetable" : MessageLookupByLibrary.simpleMessage("Расписание"), - "title" : MessageLookupByLibrary.simpleMessage("РАНХиГС (Расписание)"), - "tuesday" : MessageLookupByLibrary.simpleMessage("Вт"), - "wednesday" : MessageLookupByLibrary.simpleMessage("Ср"), - "widgetTranslucentDescription" : MessageLookupByLibrary.simpleMessage("Полупрозрачность виджета на домашнем экране"), - "widgetTranslucentTitle" : MessageLookupByLibrary.simpleMessage("Полупрозрачность виджета") + @override + final Map messages = _notInlinedMessages(_notInlinedMessages); + + static Map _notInlinedMessages(_) => { + 'about': MessageLookupByLibrary.simpleMessage('О приложении'), + 'accounting': MessageLookupByLibrary.simpleMessage('Бухучет'), + 'accountingAnalysis': MessageLookupByLibrary.simpleMessage('Анализ бухгалтерской отчетности'), + 'alarmAddSuccess': MessageLookupByLibrary.simpleMessage('Будильник заведен на '), + 'alarmTip': MessageLookupByLibrary.simpleMessage('Добавить в будильник'), + 'beforeAlarmClockDescription': MessageLookupByLibrary.simpleMessage('Насколько заранее нужно заводить будильник'), + 'beforeAlarmClockTitle': MessageLookupByLibrary.simpleMessage('Время до будильника'), + 'biology': MessageLookupByLibrary.simpleMessage('Биология'), + 'budgetCalculations': MessageLookupByLibrary.simpleMessage('Расчеты с бюджетом'), + 'businessPlanning': MessageLookupByLibrary.simpleMessage('Бизнес-планирование'), + 'calendarEventsAddFailed': MessageLookupByLibrary.simpleMessage('Произошла ошибка при добавлении событий в календарь'), + 'calendarEventsAddSuccess': MessageLookupByLibrary.simpleMessage('События успешно добавлены в календарь'), + 'calendarGetFailed': MessageLookupByLibrary.simpleMessage('Произошла ошибка при получении календарей'), + 'calendarTip': MessageLookupByLibrary.simpleMessage('Добавить в календарь'), + 'chemistry': MessageLookupByLibrary.simpleMessage('Химия'), + 'close': MessageLookupByLibrary.simpleMessage('Выход'), + 'computerArchitecture': MessageLookupByLibrary.simpleMessage('Архитектура ПК'), + 'computerGraphic': MessageLookupByLibrary.simpleMessage('Компьютерная графика'), + 'credit': MessageLookupByLibrary.simpleMessage('Прием зачета'), + 'databases': MessageLookupByLibrary.simpleMessage('Базы данных'), + 'dayStyleDate': MessageLookupByLibrary.simpleMessage('Дата'), + 'dayStyleDescription': MessageLookupByLibrary.simpleMessage('Стиль отображения дней в расписании'), + 'dayStyleTitle': MessageLookupByLibrary.simpleMessage('Формат отображения дат'), + 'dayStyleWeekday': MessageLookupByLibrary.simpleMessage('День недели'), + 'discMath': MessageLookupByLibrary.simpleMessage('Дискретная математика'), + 'documentManagementSupport': MessageLookupByLibrary.simpleMessage('ДОУ (Документационное обеспечение управление)'), + 'economics': MessageLookupByLibrary.simpleMessage('Экономическая теория'), + 'english': MessageLookupByLibrary.simpleMessage('Английский язык'), + 'errorMessage': MessageLookupByLibrary.simpleMessage('Что-то пошло не так'), + 'ethics': MessageLookupByLibrary.simpleMessage('Этика'), + 'exam': MessageLookupByLibrary.simpleMessage('Экзамен'), + 'examConsultation': MessageLookupByLibrary.simpleMessage('Консультация к экзамену'), + 'freeDay': MessageLookupByLibrary.simpleMessage('Свободный день'), + 'friday': MessageLookupByLibrary.simpleMessage('Пт'), + 'geography': MessageLookupByLibrary.simpleMessage('География'), + 'groupDescription': MessageLookupByLibrary.simpleMessage('Группа/преподаватель для которой(-го) при запуске загружается расписание'), + 'groupEconomics': MessageLookupByLibrary.simpleMessage('Экономика'), + 'groupInformatics': MessageLookupByLibrary.simpleMessage('Информатика'), + 'groupTitle': MessageLookupByLibrary.simpleMessage('Изменить группу/преподавателя'), + 'history': MessageLookupByLibrary.simpleMessage('История'), + 'informatics': MessageLookupByLibrary.simpleMessage('Информатика'), + 'informationTheory': MessageLookupByLibrary.simpleMessage('Теория информации'), + 'introGroupDescription': MessageLookupByLibrary.simpleMessage('Для этой группы или преподавателя будет показываться расписание в будущем.'), + 'introGroupTitle': MessageLookupByLibrary.simpleMessage('Группа или преподаватель'), + 'introThemeDescription': MessageLookupByLibrary.simpleMessage('Выбранная тема будет использоваться для отрисовки расписания и всего остального. Тему можно поменять в настройках.'), + 'introThemeTitle': MessageLookupByLibrary.simpleMessage('Тема'), + 'introTimetableDescription': MessageLookupByLibrary.simpleMessage('Так будет выглядеть расписание. При необходимости можно вернуться назад и сменить цветовую схему.'), + 'introTimetableTitle': MessageLookupByLibrary.simpleMessage('Пример расписания'), + 'introWelcomeDescription': MessageLookupByLibrary.simpleMessage('Это приложение является неофициальным клиентом сайта РАНХиГС Нижнего Новгорода и не имеет ничего общего с его админинстрацией.'), + 'introWelcomeInitialSetup': MessageLookupByLibrary.simpleMessage('Для использования приложения необходимо пройти начальную настройку.'), + 'introWelcomeSupportBy': MessageLookupByLibrary.simpleMessage('при поддержке Профкома НИУ РАНХиГС'), + 'introWelcomeTitle': MessageLookupByLibrary.simpleMessage('Добро пожаловать'), + 'inventory': MessageLookupByLibrary.simpleMessage('Инвентаризация'), + 'lecture': MessageLookupByLibrary.simpleMessage('Лекция'), + 'legalSupport': MessageLookupByLibrary.simpleMessage('Правовое обеспечение'), + 'lifeSafety': MessageLookupByLibrary.simpleMessage('ОБЖ'), + 'literature': MessageLookupByLibrary.simpleMessage('Литература'), + 'loading': MessageLookupByLibrary.simpleMessage('Загрузка'), + 'management': MessageLookupByLibrary.simpleMessage('Менеджмент'), + 'math': MessageLookupByLibrary.simpleMessage('Математика'), + 'monday': MessageLookupByLibrary.simpleMessage('Пн'), + 'noCache': MessageLookupByLibrary.simpleMessage('День не загружен'), + 'noLessonsFound': MessageLookupByLibrary.simpleMessage('Уроков не найдено'), + 'noNetworkConnection': MessageLookupByLibrary.simpleMessage('Отсутствует подключение к сети'), + 'operatingSystems': MessageLookupByLibrary.simpleMessage('Операционные системы'), + 'optimizedLessonTitlesDescription': MessageLookupByLibrary.simpleMessage('Упрощает названия пар'), + 'optimizedLessonTitlesTitle': MessageLookupByLibrary.simpleMessage('Замена названий предметов'), + 'philosophy': MessageLookupByLibrary.simpleMessage('Философия'), + 'physicalCulture': MessageLookupByLibrary.simpleMessage('Физ-ра'), + 'physics': MessageLookupByLibrary.simpleMessage('Физика'), + 'practice': MessageLookupByLibrary.simpleMessage('Практика'), + 'prefs': MessageLookupByLibrary.simpleMessage('Настройки'), + 'projectDevelopment': MessageLookupByLibrary.simpleMessage('Проектная разработка'), + 'receptionExamination': MessageLookupByLibrary.simpleMessage('Прием защиты'), + 'refreshTip': MessageLookupByLibrary.simpleMessage('Обновить расписание'), + 'roomLocationAcademy': MessageLookupByLibrary.simpleMessage('Академия'), + 'roomLocationHotel': MessageLookupByLibrary.simpleMessage('Гостиница (ул. Пушкина, 8)'), + 'roomLocationStudyHostel': MessageLookupByLibrary.simpleMessage('Студенческое общежитие'), + 'roomLocationStyleDescriptionIcon': MessageLookupByLibrary.simpleMessage('Корпус отображает иконка'), + 'roomLocationStyleDescriptionText': MessageLookupByLibrary.simpleMessage('Корпус обозначается текстом'), + 'roomLocationStyleIcon': MessageLookupByLibrary.simpleMessage('Иконка'), + 'roomLocationStyleText': MessageLookupByLibrary.simpleMessage('Текст'), + 'roomLocationStyleTitle': MessageLookupByLibrary.simpleMessage('Отображение аудиторий'), + 'saturday': MessageLookupByLibrary.simpleMessage('Сб'), + 'searchResults': MessageLookupByLibrary.simpleMessage('Результаты веб-поиска'), + 'searchTip': MessageLookupByLibrary.simpleMessage('Поиск'), + 'sendError': MessageLookupByLibrary.simpleMessage('Отправить описание\nошибки разработчикам'), + 'siteApiDescription': MessageLookupByLibrary.simpleMessage('Способ получения расписания'), + 'siteApiNewApp': MessageLookupByLibrary.simpleMessage('API нового приложения'), + 'siteApiOldApp': MessageLookupByLibrary.simpleMessage('API старого приложения'), + 'siteApiSite': MessageLookupByLibrary.simpleMessage('API официального сайта'), + 'siteApiTitle': MessageLookupByLibrary.simpleMessage('Используемое для получения расписания API'), + 'socialStudies': MessageLookupByLibrary.simpleMessage('Обществознание'), + 'softwareDevelopment': MessageLookupByLibrary.simpleMessage('Разработка ПО'), + 'speechCulture': MessageLookupByLibrary.simpleMessage('Культура речи'), + 'statMath': MessageLookupByLibrary.simpleMessage('Теория вероятностей и мат. статистика'), + 'taxation': MessageLookupByLibrary.simpleMessage('Налогообложение'), + 'themeAccentDescription': MessageLookupByLibrary.simpleMessage('Цвет подсветки цветовой схемы'), + 'themeAccentTitle': MessageLookupByLibrary.simpleMessage('Дополнительный цвет'), + 'themeDark': MessageLookupByLibrary.simpleMessage('Темная'), + 'themeDescription': MessageLookupByLibrary.simpleMessage('Темная цветовая схема приложения и виджета'), + 'themeLight': MessageLookupByLibrary.simpleMessage('Светлая'), + 'themeTitle': MessageLookupByLibrary.simpleMessage('Тёмный режим'), + 'thursday': MessageLookupByLibrary.simpleMessage('Чт'), + 'timetable': MessageLookupByLibrary.simpleMessage('Расписание'), + 'title': MessageLookupByLibrary.simpleMessage('РАНХиГС (Расписание)'), + 'tuesday': MessageLookupByLibrary.simpleMessage('Вт'), + 'wednesday': MessageLookupByLibrary.simpleMessage('Ср'), + 'widgetTranslucentDescription': MessageLookupByLibrary.simpleMessage('Полупрозрачность виджета на домашнем экране'), + 'widgetTranslucentTitle': MessageLookupByLibrary.simpleMessage('Полупрозрачность виджета') }; } diff --git a/lib/localizations.dart b/lib/localizations.dart index 90640fe..905847e 100644 --- a/lib/localizations.dart +++ b/lib/localizations.dart @@ -18,7 +18,7 @@ class AppLocalizations { } static AppLocalizations of(BuildContext ctx) { - return Localizations.of(ctx, AppLocalizations); + return Localizations.of(ctx, AppLocalizations)!; } // App title diff --git a/lib/main.dart b/lib/main.dart index 8a1dffe..91dcf2d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -9,24 +9,24 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_email_sender/flutter_email_sender.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; -import 'package:ranepa_timetable/about.dart'; -import 'package:ranepa_timetable/intro.dart'; -import 'package:ranepa_timetable/localizations.dart'; -import 'package:ranepa_timetable/platform_channels.dart'; -import 'package:ranepa_timetable/prefs.dart'; -import 'package:ranepa_timetable/search.dart'; -import 'package:ranepa_timetable/theme.dart'; -import 'package:ranepa_timetable/timetable.dart'; -import 'package:ranepa_timetable/widget_templates.dart'; +import 'package:ranepatimetable/about.dart'; +import 'package:ranepatimetable/intro.dart'; +import 'package:ranepatimetable/localizations.dart'; +import 'package:ranepatimetable/platform_channels.dart'; +import 'package:ranepatimetable/prefs.dart'; +import 'package:ranepatimetable/search.dart'; +import 'package:ranepatimetable/theme.dart'; +import 'package:ranepatimetable/timetable.dart'; +import 'package:ranepatimetable/widget_templates.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:package_info/package_info.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -SharedPreferences prefs; -String version; final random = new Random(); class BaseWidget extends StatelessWidget { + String version = ''; + SharedPreferences? prefs; @override Widget build(BuildContext ctx) => WidgetTemplates.buildFutureBuilder( @@ -34,8 +34,7 @@ class BaseWidget extends StatelessWidget { loading: Container(), future: PackageInfo.fromPlatform(), builder: (ctx, snapshot) { - version = snapshot.data.version; - debugPrint("App version: " + version); + version = snapshot.data?.version ?? ''; return WidgetTemplates.buildFutureBuilder( ctx, @@ -44,13 +43,13 @@ class BaseWidget extends StatelessWidget { builder: (ctx, snapshot) { prefs = snapshot.data; if (Platform.isAndroid && - prefs.getString(PrefsIds.LAST_UPDATE) != version) { + prefs!.getString(PrefsIds.LAST_UPDATE) != version) { return WidgetTemplates.buildFutureBuilder(ctx, loading: Container(), future: Future.wait( - [prefs.clear(), PlatformChannels.deleteDb()]), + [prefs!.clear(), PlatformChannels.deleteDb()]), builder: (ctx, _) { - prefs.setString(PrefsIds.LAST_UPDATE, version); + prefs!.setString(PrefsIds.LAST_UPDATE, version); return _build(ctx); }); } @@ -63,9 +62,9 @@ class BaseWidget extends StatelessWidget { Widget _build(BuildContext ctx) => buildThemeStream( (ctx, snapshot) { - final theme = snapshot.data; + final theme = snapshot.data ?? ThemeData(); - debugPrint("prefskeys: ${prefs.getKeys()}"); + debugPrint("prefskeys: ${prefs!.getKeys()}"); return Theme( data: theme, @@ -77,7 +76,7 @@ class BaseWidget extends StatelessWidget { return MediaQuery( data: MediaQuery.of(ctx).copyWith(alwaysUse24HourFormat: true), - child: child, + child: child!, ); }, localizationsDelegates: [ @@ -99,7 +98,7 @@ class BaseWidget extends StatelessWidget { SearchScreen.ROUTE: (ctx) => SearchScreen(), TimetableScreen.ROUTE: (ctx) => TimetableScreen(), }, - initialRoute: prefs.getInt( + initialRoute: prefs!.getInt( PrefsIds.SEARCH_ITEM_PREFIX + PrefsIds.ITEM_ID) == null ? IntroScreen.ROUTE @@ -160,4 +159,13 @@ Widget Function(FlutterErrorDetails) _buildError(BuildContext ctx) { )); } -Future main() async => runApp(BaseWidget()); +Future main() async { + runZonedGuarded(() async { + WidgetsFlutterBinding.ensureInitialized(); + prefs = await SharedPreferences.getInstance(); + runApp(BaseWidget()); + }, (error, stack) { + print(error); + print(stack); + }); +} diff --git a/lib/platform_channels.dart b/lib/platform_channels.dart index be1d521..a414852 100644 --- a/lib/platform_channels.dart +++ b/lib/platform_channels.dart @@ -3,8 +3,7 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; -import 'package:ios_app_group/ios_app_group.dart'; -import 'package:ranepa_timetable/timeline_models.dart'; +import 'package:ranepatimetable/timeline_models.dart'; import 'package:sqflite/sqflite.dart'; class PlatformChannels { @@ -15,13 +14,11 @@ class PlatformChannels { static const tableFile = 'timetable.db'; static const iosAppGroup = 'group.coolone.ranepatimetable.data'; - static Database _db; + static Database? _db; static get db async { if (_db == null) { - String path = Platform.isIOS - ? "${(await IosAppGroup.getAppGroupDirectory(iosAppGroup)).path}/$tableFile" - : tableFile; + String path = '${await getDatabasesPath()}/$tableFile'; _db = await openDatabase( path, @@ -72,7 +69,7 @@ class PlatformChannels { } else { Map dataMap; if (mValue is Map) { - dataMap = jsonToDb(mValue); + dataMap = jsonToDb(mValue as Map); } else { dataMap = jsonToDb(mValue.toJson()); } @@ -94,7 +91,7 @@ class PlatformChannels { for (var mEntry in changeMap.entries) { data.remove(mEntry.key); - data.addEntries(mEntry.value); + data.addEntries(mEntry.value as dynamic); } return data; @@ -139,7 +136,7 @@ class PlatformChannels { } } - static Future>> getDb() async { + static Future>?> getDb() async { Database database = await db; var res = await database.query(tableName); @@ -175,7 +172,7 @@ class PlatformChannels { static Future refreshWidget() async { if (Platform.isAndroid) { debugPrint("Refreshing widget..."); - methodChannel.invokeMethod("refreshWidget"); + // methodChannel.invokeMethod("refreshWidget"); } } } diff --git a/lib/prefs.dart b/lib/prefs.dart index 278f413..44b2ebc 100644 --- a/lib/prefs.dart +++ b/lib/prefs.dart @@ -3,22 +3,22 @@ import 'dart:io'; import 'package:duration/duration.dart'; import 'package:duration/locale.dart'; +import 'package:duration_picker/duration_picker.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; -import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; -import 'package:flutter_duration_picker/flutter_duration_picker.dart'; import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; -import 'package:ranepa_timetable/apis.dart'; -import 'package:ranepa_timetable/localizations.dart'; -import 'package:ranepa_timetable/main.dart'; -import 'package:ranepa_timetable/platform_channels.dart'; -import 'package:ranepa_timetable/search.dart'; -import 'package:ranepa_timetable/timeline_models.dart'; -import 'package:ranepa_timetable/timetable.dart'; -import 'package:ranepa_timetable/widget_templates.dart'; +import 'package:ranepatimetable/apis.dart'; +import 'package:ranepatimetable/localizations.dart'; +import 'package:ranepatimetable/main.dart'; +import 'package:ranepatimetable/platform_channels.dart'; +import 'package:ranepatimetable/search.dart'; +import 'package:ranepatimetable/timeline_models.dart'; +import 'package:ranepatimetable/timetable.dart'; +import 'package:ranepatimetable/widget_templates.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:tuple/tuple.dart'; -import 'package:ranepa_timetable/theme.dart'; +import 'package:ranepatimetable/theme.dart'; import 'package:flutter_material_color_picker/flutter_material_color_picker.dart'; class PrefsIds { @@ -42,12 +42,13 @@ class PrefsIds { DAY_STYLE = "day_style"; } +late SharedPreferences prefs; + Future showSearchItemSelect( BuildContext ctx, { primary = true, }) async { final searchItem = await SearchScreen.showSearch(ctx); - if (searchItem != null) { if (primary) { TimetableScreen.fromDay = TimetableScreen.todayMidnight; @@ -55,25 +56,22 @@ Future showSearchItemSelect( await PlatformChannels.deleteDb(); } else { if (Platform.isIOS) { - TimetableScreen.fromDay = await DatePicker.showDatePicker(ctx, - minTime: TimetableScreen.todayMidnight, - maxTime: TimetableScreen.todayMidnight.add(Duration(days: 365)), + TimetableScreen.fromDay = (await showDatePicker( + context: ctx, locale: Localizations.localeOf(ctx) == SupportedLocales.ru - ? LocaleType.ru - : LocaleType.en, - theme: DatePickerTheme( - backgroundColor: getTheme().brightness == Brightness.dark - ? Colors.black - : Colors.white, - itemStyle: getTheme().textTheme.body1, - cancelStyle: getTheme().textTheme.caption)); + ? Locale('ru') + : Locale('en'), + initialDate: TimetableScreen.todayMidnight, + firstDate: TimetableScreen.todayMidnight, + lastDate: TimetableScreen.todayMidnight.add(Duration(days: 365)) + ))!; } else { - TimetableScreen.fromDay = await showDatePicker( + TimetableScreen.fromDay = (await showDatePicker( context: ctx, initialDate: TimetableScreen.fromDay ?? TimetableScreen.todayMidnight, firstDate: TimetableScreen.todayMidnight, lastDate: TimetableScreen.todayMidnight.add(Duration(days: 365)), - ); + ))!; } TimetableScreen.fromDay ??= TimetableScreen.todayMidnight; TimetableScreen.selected = searchItem; @@ -84,7 +82,7 @@ Future showSearchItemSelect( return searchItem; } -Future showThemeBrightnessSelect(BuildContext ctx) => +Future showThemeBrightnessSelect(BuildContext ctx) => showDialog( context: ctx, builder: (BuildContext ctx) => SimpleDialog( @@ -107,7 +105,7 @@ Future showThemeBrightnessSelect(BuildContext ctx) => void showMaterialColorPicker(BuildContext ctx) => showPlatformDialog( context: ctx, builder: (ctx) { - var pickedColor = accentColor; + ColorSwatch? pickedColor = accentColor; return PlatformAlertDialog( title: Text(AppLocalizations.of(ctx).themeAccentTitle), content: Container( @@ -120,11 +118,11 @@ void showMaterialColorPicker(BuildContext ctx) => showPlatformDialog( ), ), actions: [ - FlatButton( + TextButton( child: Text(MaterialLocalizations.of(ctx).cancelButtonLabel), onPressed: () => Navigator.of(ctx).pop(), ), - FlatButton( + TextButton( child: Text(MaterialLocalizations.of(ctx).okButtonLabel), onPressed: () { Navigator.of(ctx).pop(); @@ -145,39 +143,26 @@ final widgetTranslucentBloc = StreamController.broadcast(), class PrefsScreen extends StatelessWidget { static const ROUTE = "/prefs"; - static Widget _buildThemePreference(BuildContext ctx) => - WidgetTemplates.buildListTile( - ctx, - title: Text(AppLocalizations.of(ctx).themeTitle), - subtitle: Text(AppLocalizations.of(ctx).themeDescription), - trailing: buildThemeStream( - (ctx, snapshot) => PlatformSwitch( - value: brightness == Brightness.dark, - onChanged: (value) { - brightness = value ? Brightness.dark : Brightness.light; - }, - ), - ), - ); static Widget _buildThemeAccentPreference(BuildContext ctx) => WidgetTemplates.buildListTile( ctx, title: Text(AppLocalizations.of(ctx).themeAccentTitle), - subtitle: Text(AppLocalizations.of(ctx).themeAccentDescription), + subtitle: Text(AppLocalizations.of(ctx).themeAccentDescription, style: TextStyle( + color: MediaQueryData.fromWindow(WidgetsBinding.instance.window).platformBrightness == Brightness.dark ? Colors.white : Colors.black + )), onTap: () => showMaterialColorPicker(ctx), trailing: buildThemeStream( (ctx, snapshot) => Container( width: 30, height: 30, decoration: BoxDecoration( - color: snapshot.data.accentColor, + color: snapshot.data?.colorScheme.secondary, shape: BoxShape.circle, ), ), ), ); - static Widget _buildWidgetTranslucentPreference(BuildContext ctx) => StreamBuilder( initialData: prefs.getBool(PrefsIds.WIDGET_TRANSLUCENT) ?? true, @@ -187,7 +172,7 @@ class PrefsScreen extends StatelessWidget { title: Text(AppLocalizations.of(ctx).widgetTranslucentTitle), subtitle: Text(AppLocalizations.of(ctx).widgetTranslucentDescription), trailing: PlatformSwitch( - value: snapshot.data, + value: snapshot.data!, onChanged: (value) { widgetTranslucentBloc.add(value); prefs.setBool(PrefsIds.WIDGET_TRANSLUCENT, value).then( @@ -207,11 +192,11 @@ class PrefsScreen extends StatelessWidget { ).then((duration) { prefs.setInt( PrefsIds.BEFORE_ALARM_CLOCK, - duration.inMinutes, + duration?.inMinutes ?? 0, ); - beforeAlarmBloc.add(duration); + beforeAlarmBloc.add(duration ?? Duration()); - return duration; + return duration ?? Duration(); }); static Widget _buildBeforeAlarmClockPreference(BuildContext ctx) => @@ -224,10 +209,10 @@ class PrefsScreen extends StatelessWidget { stream: beforeAlarmBloc.stream, initialData: Duration(minutes: prefs.getInt(PrefsIds.BEFORE_ALARM_CLOCK) ?? 0), - builder: (ctx, snapshot) => snapshot.data.inMicroseconds != 0 + builder: (ctx, snapshot) => snapshot.data?.inMicroseconds != 0 ? Text( printDuration( - snapshot.data, + snapshot.data ?? Duration(), delimiter: "\n", locale: Localizations.localeOf(ctx) == SupportedLocales.ru ? russianLocale @@ -242,15 +227,17 @@ class PrefsScreen extends StatelessWidget { WidgetTemplates.buildListTile( ctx, title: Text(AppLocalizations.of(ctx).groupTitle), - subtitle: Text(AppLocalizations.of(ctx).groupDescription), + subtitle: Text(AppLocalizations.of(ctx).groupDescription, style: TextStyle( + color: MediaQueryData.fromWindow(WidgetsBinding.instance.window).platformBrightness == Brightness.dark ? Colors.white : Colors.black + )), onTap: () => showSearchItemSelect(ctx), trailing: StreamBuilder>( stream: timetableIdBloc.stream, - initialData: Tuple2(null, SearchItem.fromPrefs()), + initialData: Tuple2(true, SearchItem.fromPrefs()), builder: (ctx, snapshot) => Text( - snapshot.data.item2.typeId == SearchItemTypeId.Group - ? snapshot.data.item2.title - : snapshot.data.item2.title.replaceAll(' ', '\n'), + snapshot.data?.item2.typeId == SearchItemTypeId.Group + ? snapshot.data?.item2.title ?? '' + : snapshot.data?.item2.title.replaceAll(' ', '\n') ?? '', ), ), ); @@ -284,7 +271,10 @@ class PrefsScreen extends StatelessWidget { title: Text(AppLocalizations.of(ctx).roomLocationStyleText), subtitle: Text(snapshot.data == RoomLocationStyle.Icon ? AppLocalizations.of(ctx).roomLocationStyleDescriptionIcon - : AppLocalizations.of(ctx).roomLocationStyleDescriptionText), + : AppLocalizations.of(ctx).roomLocationStyleDescriptionText, + style: TextStyle( + color: MediaQueryData.fromWindow(WidgetsBinding.instance.window).platformBrightness == Brightness.dark ? Colors.white : Colors.black + )), trailing: Row( children: [ Icon(Icons.text_format), @@ -318,7 +308,7 @@ class PrefsScreen extends StatelessWidget { subtitle: Text(AppLocalizations.of(ctx).optimizedLessonTitlesDescription), trailing: PlatformSwitch( - value: snapshot.data, + value: snapshot.data ?? false, onChanged: (value) async { optimizedLessonTitlesBloc.add(value); await prefs.setBool(PrefsIds.OPTIMIZED_LESSON_TITLES, value); @@ -329,28 +319,16 @@ class PrefsScreen extends StatelessWidget { ), ); - static Widget _buildSiteApiPreference(BuildContext ctx) => - WidgetTemplates.buildListTile( - ctx, - title: Text(AppLocalizations.of(ctx).siteApiTitle), - subtitle: Text(AppLocalizations.of(ctx).siteApiDescription), - onTap: () => showSiteApiSelect(ctx), - trailing: StreamBuilder( - builder: (BuildContext ctx, AsyncSnapshot snapshot) => - Text(snapshot.data.title), - stream: siteApiBloc.stream, - initialData: SiteApis(ctx) - .apis[prefs.getInt(PrefsIds.SITE_API) ?? DEFAULT_API_ID.index], - ), - ); - static Future showSiteApiSelect(BuildContext ctx) => + static Future showSiteApiSelect(BuildContext ctx) => showDialog( context: ctx, builder: (BuildContext ctx) => SimpleDialog( title: Text(AppLocalizations.of(ctx).siteApiTitle), children: SiteApis(ctx) .apis + .where((api) => !api.isHidden) + .toList() .asMap() .map( (index, mApi) => MapEntry( @@ -414,10 +392,6 @@ class PrefsScreen extends StatelessWidget { List buildPrefsEntries(BuildContext ctx) { List entries = []; - if (!Platform.isIOS) { - entries.add(_buildThemePreference(ctx)); - } - entries.addAll([ _buildThemeAccentPreference(ctx), _buildSearchItemPreference(ctx), @@ -432,7 +406,6 @@ class PrefsScreen extends StatelessWidget { entries.addAll([ _buildRoomLocationStylePreference(ctx), - _buildSiteApiPreference(ctx), _buildOptimizedLessonTitlesPreference(ctx), ]); @@ -454,7 +427,7 @@ class PrefsScreen extends StatelessWidget { padding: EdgeInsets.zero, icon: Icon( ctx.platformIcons.back, - color: Platform.isIOS ? getTheme().accentColor : null, + color: Platform.isIOS ? getTheme().colorScheme.secondary : null, ), onPressed: () => Navigator.pop(ctx), ), diff --git a/lib/search.dart b/lib/search.dart index 14ca337..e0a46e0 100644 --- a/lib/search.dart +++ b/lib/search.dart @@ -4,13 +4,11 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; import 'package:http/http.dart' as http; -import 'package:ranepa_timetable/apis.dart'; -import 'package:ranepa_timetable/localizations.dart'; -import 'package:ranepa_timetable/main.dart'; -import 'package:ranepa_timetable/prefs.dart'; -import 'package:ranepa_timetable/theme.dart'; -import 'package:ranepa_timetable/widget_templates.dart'; -import 'package:shared_preferences/shared_preferences.dart'; +import 'package:ranepatimetable/apis.dart'; +import 'package:ranepatimetable/localizations.dart'; +import 'package:ranepatimetable/prefs.dart'; +import 'package:ranepatimetable/theme.dart'; +import 'package:ranepatimetable/widget_templates.dart'; class SearchItemType { final IconData icon; @@ -36,7 +34,6 @@ final searchItemTypes = List.generate( case SearchItemTypeId.Group: return SearchItemType(Icons.group, "Group", "group"); } - return null; }, ); @@ -74,8 +71,8 @@ class SearchItem extends SearchItemBase { SearchItem( SearchItemTypeId.values[prefs.getInt(prefix + PrefsIds.ITEM_TYPE) ?? DEFAULT_ITEM_TYPE_ID.index], - prefs.getInt(prefix + PrefsIds.ITEM_ID), - prefs.getString(prefix + PrefsIds.ITEM_TITLE), + prefs.getInt(prefix + PrefsIds.ITEM_ID) ?? 0, + prefs.getString(prefix + PrefsIds.ITEM_TITLE) ?? '', ); } @@ -132,17 +129,17 @@ class _SearchScreenState extends State { get query => searchController.text; - static http.Response _newApiCachedResults; + static http.Response? _newApiCachedResults; Future _buildHttpRequest(SiteApiIds api) { switch (api) { case SiteApiIds.APP_NEW: return _newApiCachedResults == null - ? http.get('http://services.niu.ranepa.ru/' - 'API/public/teacher/teachersAndGroupsList') + ? http.get(Uri.parse('http://services.niu.ranepa.ru/' + 'API/public/teacher/teachersAndGroupsList')) : Future.value(_newApiCachedResults); case SiteApiIds.APP_OLD: - return http.post('http://test.ranhigs-nn.ru/api/WebService.asmx', + return http.post(Uri.parse('http://test.ranhigs-nn.ru/api/WebService.asmx'), headers: {'Content-Type': 'text/xml; charset=utf-8'}, body: ''' @@ -154,14 +151,13 @@ class _SearchScreenState extends State { '''); case SiteApiIds.SITE: - return http.get('http://services.niu.ranepa.ru/' - 'wp-content/plugins/rasp/rasp_json_data.php?name=$query'); + return http.get(Uri.parse('http://services.niu.ranepa.ru/' + 'wp-content/plugins/rasp/rasp_json_data.php?name=$query')); default: throw Exception("api is fucked up"); } } - @override Widget buildSuggestions(BuildContext ctx) { debugPrint("Suggestions build start"); webSuggestions.clear(); @@ -175,8 +171,8 @@ class _SearchScreenState extends State { future: _buildHttpRequest(api).then((response) => response), builder: (ctx, snapshot) { if (_newApiCachedResults == null) - _newApiCachedResults = snapshot.data; - final body = snapshot.data.body; + _newApiCachedResults = snapshot.data as http.Response; + final body = (snapshot.data as http.Response).body; debugPrint("Search snapshot data body: " + body); @@ -211,7 +207,7 @@ class _SearchScreenState extends State { break; } - SearchItemTypeId mItemTypeId; + SearchItemTypeId? mItemTypeId; switch (api) { case SiteApiIds.APP_NEW: @@ -232,7 +228,7 @@ class _SearchScreenState extends State { } webSuggestions.add(SearchItem( - mItemTypeId, + mItemTypeId!, mItemId, mItemTitle, )); @@ -270,10 +266,8 @@ class _SearchScreenState extends State { final SearchItem mSearchItem = mSearchItemBase; return mSearchItem.title .startsWith(RegExp("^" + query, caseSensitive: false)); - break; case SearchDivider: return true; - break; } return false; @@ -309,8 +303,8 @@ class _SearchScreenState extends State { if (mItem is SearchItem) { final queryIndex = mItem.title.indexOf(RegExp(query, caseSensitive: false)), - selectColor = theme.textSelectionColor, - normalColor = theme.textTheme.title.color; + selectColor = Colors.blue, + normalColor = theme.textTheme.titleLarge?.color; return WidgetTemplates.buildListTile( ctx, @@ -319,7 +313,7 @@ class _SearchScreenState extends State { }, leading: Icon( searchItemTypes[mItem.typeId.index].icon, - color: Platform.isIOS ? theme.accentColor : null, + color: Platform.isIOS ? theme.primaryColor : null, ), title: RichText( // Recent suggestion @@ -383,7 +377,7 @@ class _SearchScreenState extends State { } return null; }, - itemCount: suggestions?.length ?? 0), + itemCount: suggestions.length ?? 0), ); } @@ -391,7 +385,7 @@ class _SearchScreenState extends State { Widget build(BuildContext ctx) { return PlatformScaffold( appBar: PlatformAppBar( - ios: (ctx) => CupertinoNavigationBarData( + cupertino: (ctx, _) => CupertinoNavigationBarData( padding: const EdgeInsetsDirectional.only(end: 15), ), leading: !Platform.isIOS @@ -412,7 +406,7 @@ class _SearchScreenState extends State { child: Text( SearchScreen._capitalizeString( MaterialLocalizations.of(ctx).cancelButtonLabel), - style: getTheme().textTheme.body1, + style: getTheme().textTheme.bodyLarge, ), onPressed: () => _cancelPressed(ctx), ), @@ -432,19 +426,19 @@ class _SearchScreenState extends State { onChanged: (_) { setState(() {}); }, - ios: (ctx) => CupertinoTextFieldData( + cupertino: (ctx, _) => CupertinoTextFieldData( prefix: Padding( padding: const EdgeInsets.only(left: 5), child: Icon( CupertinoIcons.search, size: 20, - color: getTheme().accentColor, + color: getTheme().primaryColor, ), ), placeholder: _searchPlaceholder(ctx), clearButtonMode: OverlayVisibilityMode.editing, - cursorColor: getTheme().accentColor), - android: (ctx) => MaterialTextFieldData( + cursorColor: getTheme().primaryColor), + material: (ctx, _) => MaterialTextFieldData( decoration: InputDecoration( border: InputBorder.none, hintText: _searchPlaceholder(ctx), @@ -452,7 +446,7 @@ class _SearchScreenState extends State { ? IconButton( icon: Icon( Icons.clear, - color: getTheme().accentTextTheme.body1.color, + color: getTheme().textTheme.bodyLarge?.color, ), onPressed: () { searchController.clear(); diff --git a/lib/theme.dart b/lib/theme.dart index 61158bd..b6d828b 100644 --- a/lib/theme.dart +++ b/lib/theme.dart @@ -2,16 +2,16 @@ import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; -import 'package:ranepa_timetable/localizations.dart'; -import 'package:ranepa_timetable/main.dart'; -import 'package:ranepa_timetable/platform_channels.dart'; -import 'package:ranepa_timetable/prefs.dart'; +import 'package:ranepatimetable/localizations.dart'; +import 'package:ranepatimetable/main.dart'; +import 'package:ranepatimetable/platform_channels.dart'; +import 'package:ranepatimetable/prefs.dart'; -ThemeData _theme; +ThemeData? _theme = ThemeData(); ThemeData getTheme() { - if (_theme == null) _theme = buildTheme(brightness, accentColor); - return _theme; + if (_theme == null) _theme = buildTheme(brightness, accentColor!); + return ThemeData(); } ThemeData buildTheme( @@ -25,7 +25,7 @@ ThemeData buildTheme( primaryColorLight: accentColor.shade100, primaryColorDark: accentColor.shade700, toggleableActiveColor: accentColor.shade600, - accentColor: accentColor.shade500, + hintColor: accentColor.shade500, ); Future onThemeChange() async { @@ -39,16 +39,16 @@ Future onThemeChange() async { await prefs.setString( PrefsIds.THEME_PRIMARY, _colorToHex(theme.primaryColor)); - await prefs.setString(PrefsIds.THEME_ACCENT, _colorToHex(theme.accentColor)); + await prefs.setString(PrefsIds.THEME_ACCENT, _colorToHex(theme.colorScheme.secondary)); await prefs.setString( PrefsIds.THEME_BACKGROUND, _colorToHex(theme.backgroundColor)); await prefs.setString( - PrefsIds.THEME_TEXT_PRIMARY, _colorToHex(theme.textTheme.body1.color)); + PrefsIds.THEME_TEXT_PRIMARY, _colorToHex(theme.textTheme.bodyLarge?.color ?? Colors.white)); await prefs.setString(PrefsIds.THEME_TEXT_ACCENT, - _colorToHex(theme.accentTextTheme.body1.color)); + _colorToHex(theme.textTheme.bodyLarge?.color ?? Colors.white)); await prefs.setInt(PrefsIds.THEME_BRIGHTNESS, theme.brightness.index); @@ -74,7 +74,7 @@ StreamBuilder buildThemeStream( // Brightness -Brightness _brightness; +Brightness? _brightness; get brightness { if (Platform.isIOS) @@ -105,16 +105,16 @@ MaterialColor _toMaterialColor(Color color) { throw Exception('Material color ${color.toString()} not found!!!'); } -MaterialColor _accentColor; +MaterialColor? _accentColor; -MaterialColor get accentColor { +MaterialColor? get accentColor { final prefColor = prefs.getString(PrefsIds.THEME_PRIMARY); return _accentColor != null ? _accentColor : prefColor != null ? _toMaterialColor(_hexToColor(prefColor)) - : ThemeData.light().primaryColor; + : _toMaterialColor(ThemeData.light().primaryColor); } set accentColor(value) { @@ -125,11 +125,10 @@ set accentColor(value) { // Theme brightness titles class ThemeBrightnessTitles { - static ThemeBrightnessTitles _singleton; + static ThemeBrightnessTitles? _singleton; factory ThemeBrightnessTitles(BuildContext ctx) { - if (_singleton == null) _singleton = ThemeBrightnessTitles._internal(ctx); - return _singleton; + return _singleton ?? ThemeBrightnessTitles._internal(ctx); } final List titles; diff --git a/lib/timeline.dart b/lib/timeline.dart index 27cce4f..5518674 100644 --- a/lib/timeline.dart +++ b/lib/timeline.dart @@ -18,8 +18,8 @@ import 'dart:io'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:ranepa_timetable/timeline_element.dart'; -import 'package:ranepa_timetable/timeline_models.dart'; +import 'package:ranepatimetable/timeline_element.dart'; +import 'package:ranepatimetable/timeline_models.dart'; class TimelineComponent extends StatelessWidget { final List timelineList; @@ -29,11 +29,11 @@ class TimelineComponent extends StatelessWidget { const TimelineComponent( this.timelineList, { this.optimizeLessonTitles = true, - Key key, + Key? key, this.onRefresh, }) : super(key: key); - final Future Function() onRefresh; + final Future Function()? onRefresh; Widget itemBuild(ctx, index) => TimelineElement( timelineList[index], @@ -72,7 +72,7 @@ class TimelineComponent extends StatelessWidget { ),] ) : RefreshIndicator( - onRefresh: onRefresh, + onRefresh: onRefresh ?? () async {}, child: defaultListView(), ) : defaultListView(), diff --git a/lib/timeline_element.dart b/lib/timeline_element.dart index 5a5c356..403f984 100644 --- a/lib/timeline_element.dart +++ b/lib/timeline_element.dart @@ -16,18 +16,18 @@ import 'dart:io'; import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; -import 'package:ranepa_timetable/main.dart'; -import 'package:ranepa_timetable/prefs.dart'; -import 'package:ranepa_timetable/search.dart'; -import 'package:ranepa_timetable/timeline_models.dart'; -import 'package:ranepa_timetable/timeline_painter.dart'; -import 'package:ranepa_timetable/timetable.dart'; +import 'package:ranepatimetable/main.dart'; +import 'package:ranepatimetable/prefs.dart'; +import 'package:ranepatimetable/search.dart'; +import 'package:ranepatimetable/timeline_models.dart'; +import 'package:ranepatimetable/timeline_painter.dart'; +import 'package:ranepatimetable/timetable.dart'; class TimelineElement extends StatelessWidget { final TimelineModel model; final bool optimizeLessonTitles; - TimelineElement(this.model, {@required this.optimizeLessonTitles}); + TimelineElement(this.model, {required this.optimizeLessonTitles}); Widget _buildLine(BuildContext ctx) => SizedBox.expand( child: Container( @@ -45,7 +45,7 @@ class TimelineElement extends StatelessWidget { child: Text( user == User.Student ? model.teacher.initials() : model.group, overflow: TextOverflow.ellipsis, - style: Theme.of(ctx).textTheme.body2, + style: Theme.of(ctx).textTheme.bodyMedium, ), ); } @@ -53,7 +53,7 @@ class TimelineElement extends StatelessWidget { Widget _buildStart(BuildContext ctx) => AutoSizeText( model.start.format(ctx), textAlign: TextAlign.center, - style: Theme.of(ctx).textTheme.title, + style: Theme.of(ctx).textTheme.titleLarge, maxFontSize: 20, maxLines: 1, ); @@ -61,7 +61,7 @@ class TimelineElement extends StatelessWidget { Widget _buildFinish(BuildContext ctx) => AutoSizeText( model.finish.format(ctx), textAlign: TextAlign.center, - style: Theme.of(ctx).textTheme.body2, + style: Theme.of(ctx).textTheme.bodyMedium, maxFontSize: 14, maxLines: 1, ); @@ -69,24 +69,24 @@ class TimelineElement extends StatelessWidget { Widget _buildLessonType(BuildContext ctx) => Tooltip( message: model.lesson.action?.title ?? model.lesson.fullTitle, child: AutoSizeText( - model.lesson.action.title, + model.lesson.action?.title ?? '', overflow: TextOverflow.ellipsis, - style: Theme.of(ctx).textTheme.body2, + style: Theme.of(ctx).textTheme.bodyMedium, maxLines: 1, ), ); - Widget _buildLessonTitle(BuildContext ctx, {@required bool optimizeTitles}) => + Widget _buildLessonTitle(BuildContext ctx, {required bool optimizeTitles}) => Tooltip( message: model.lesson.fullTitle ?? model.lesson.title, child: Container( height: 40, child: AutoSizeText( - optimizeTitles ? model.lesson.title : model.lesson.fullTitle, + optimizeTitles ? model.lesson.title ?? '' : model.lesson.fullTitle ?? '', overflow: TextOverflow.ellipsis, softWrap: true, maxLines: 2, textAlign: TextAlign.center, - style: Theme.of(ctx).textTheme.title, + style: Theme.of(ctx).textTheme.titleLarge, maxFontSize: 20, ), ), @@ -109,7 +109,7 @@ class TimelineElement extends StatelessWidget { return AutoSizeText( prefix + model.room.number, - style: Theme.of(ctx).textTheme.subtitle, + style: Theme.of(ctx).textTheme.titleMedium, maxLines: 1, textAlign: RoomLocationStyle .values[prefs.getInt(PrefsIds.ROOM_LOCATION_STYLE) ?? 0] == @@ -149,7 +149,7 @@ class TimelineElement extends StatelessWidget { Widget _buildRightContent( BuildContext ctx, { - @required bool optimizeTitles, + required bool optimizeTitles, }) => Expanded( child: Column( diff --git a/lib/timeline_models.dart b/lib/timeline_models.dart index 6a34479..2d95222 100644 --- a/lib/timeline_models.dart +++ b/lib/timeline_models.dart @@ -15,10 +15,10 @@ limitations under the License. */ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:json_annotation/json_annotation.dart'; -import 'package:ranepa_timetable/apis.dart'; -import 'package:ranepa_timetable/localizations.dart'; -import 'package:ranepa_timetable/main.dart'; -import 'package:ranepa_timetable/timetable_icons.dart'; +import 'package:ranepatimetable/apis.dart'; +import 'package:ranepatimetable/localizations.dart'; +import 'package:ranepatimetable/main.dart'; +import 'package:ranepatimetable/timetable_icons.dart'; import 'package:tuple/tuple.dart'; part 'timeline_models.g.dart'; @@ -29,7 +29,7 @@ abstract class FindableModel { mixin ToAlias {} -class FindTree = Tuple2, dynamic>> +class FindTree = Tuple2, dynamic>> with ToAlias; enum User { @@ -37,7 +37,7 @@ enum User { Teacher, } -@JsonSerializable(nullable: false) +@JsonSerializable() class TimelineModel { @JsonKey(fromJson: _numToDate, toJson: _dateToNum) final DateTime date; @@ -73,13 +73,13 @@ class TimelineModel { static DateTime _numToDate(int n) => DateTime.fromMillisecondsSinceEpoch(n); TimelineModel({ - @required this.date, - @required this.start, - @required this.finish, - @required this.room, - @required this.group, - @required this.lesson, - @required this.teacher, + required this.date, + required this.start, + required this.finish, + required this.room, + required this.group, + required this.lesson, + required this.teacher, this.first = false, this.last = false, this.mergeBottom = false, @@ -99,12 +99,10 @@ enum DayStyle { Weekday, Date } enum RoomLocation { Academy, Hotel, StudyHostel } class RoomLocationsTitles { - static RoomLocationsTitles _singleton; + static RoomLocationsTitles? _singleton; factory RoomLocationsTitles(BuildContext ctx) { - if (_singleton == null) _singleton = RoomLocationsTitles._(ctx); - - return _singleton; + return _singleton ?? RoomLocationsTitles._(ctx); } RoomLocationsTitles._(this.ctx) @@ -140,7 +138,7 @@ class RoomModel extends FindableModel { Map toJson() => _$RoomModelToJson(this); factory RoomModel.fromString(String str) => RoomModel( - RegExp(r"(\d{3}[А-я]?)").stringMatch(str), + RegExp(r"(\d{3}[А-я]?)").stringMatch(str ?? '') ?? '', str.startsWith("СО") ? RoomLocation.StudyHostel : str.startsWith("П8") ? RoomLocation.Hotel : RoomLocation.Academy); @@ -161,12 +159,10 @@ class LessonAction extends FindableModel { } class LessonActions { - static LessonActions _singleton; + static LessonActions? _singleton; factory LessonActions(BuildContext ctx, SiteApiIds api) { - if (_singleton == null) _singleton = LessonActions._(ctx, api); - - return _singleton; + return _singleton ?? LessonActions._(ctx, api); } final SiteApiIds api; @@ -213,10 +209,10 @@ class LessonActions { @JsonSerializable(nullable: false) class LessonModel extends FindableModel { - String fullTitle; + String? fullTitle; final String title; final int iconCodePoint; - LessonAction action; + LessonAction? action; LessonModel( this.title, @@ -260,12 +256,10 @@ class LessonModel extends FindableModel { } class Lessons { - static Lessons _singleton; + static Lessons? _singleton; factory Lessons(BuildContext ctx) { - if (_singleton == null) _singleton = Lessons._(ctx); - - return _singleton; + return _singleton ?? Lessons._(ctx); } Lessons._(this.ctx) diff --git a/lib/timeline_models.g.dart b/lib/timeline_models.g.dart index d40efe2..8d2217d 100644 --- a/lib/timeline_models.g.dart +++ b/lib/timeline_models.g.dart @@ -6,23 +6,30 @@ part of 'timeline_models.dart'; // JsonSerializableGenerator // ************************************************************************** -TimelineModel _$TimelineModelFromJson(Map json) { - return TimelineModel( - date: TimelineModel._numToDate(json['date'] as int), - start: TimelineModel._timeOfDayFromIntList( - json['start'] as Map), - finish: TimelineModel._timeOfDayFromIntList( - json['finish'] as Map), - room: RoomModel.fromJson(json['room'] as Map), - group: json['group'] as String, - lesson: LessonModel.fromJson(json['lesson'] as Map), - teacher: TeacherModel.fromJson(json['teacher'] as Map), - first: TimelineModel._intToBool(json['first'] as int), - last: TimelineModel._intToBool(json['last'] as int), - mergeBottom: TimelineModel._intToBool(json['mergeBottom'] as int), - mergeTop: TimelineModel._intToBool(json['mergeTop'] as int), - ); -} +TimelineModel _$TimelineModelFromJson(Map json) => + TimelineModel( + date: TimelineModel._numToDate(json['date'] as int), + start: TimelineModel._timeOfDayFromIntList( + json['start'] as Map), + finish: TimelineModel._timeOfDayFromIntList( + json['finish'] as Map), + room: RoomModel.fromJson(json['room'] as Map), + group: json['group'] as String, + lesson: LessonModel.fromJson(json['lesson'] as Map), + teacher: TeacherModel.fromJson(json['teacher'] as Map), + first: json['first'] == null + ? false + : TimelineModel._intToBool(json['first'] as int), + last: json['last'] == null + ? false + : TimelineModel._intToBool(json['last'] as int), + mergeBottom: json['mergeBottom'] == null + ? false + : TimelineModel._intToBool(json['mergeBottom'] as int), + mergeTop: json['mergeTop'] == null + ? false + : TimelineModel._intToBool(json['mergeTop'] as int), + ); Map _$TimelineModelToJson(TimelineModel instance) => { @@ -39,64 +46,39 @@ Map _$TimelineModelToJson(TimelineModel instance) => 'finish': TimelineModel._timeOfDayToIntList(instance.finish), }; -RoomModel _$RoomModelFromJson(Map json) { - return RoomModel( - json['number'] as String, - _$enumDecode(_$RoomLocationEnumMap, json['location']), - ); -} +RoomModel _$RoomModelFromJson(Map json) => RoomModel( + json['number'] as String, + $enumDecode(_$RoomLocationEnumMap, json['location']), + ); Map _$RoomModelToJson(RoomModel instance) => { 'number': instance.number, - 'location': _$RoomLocationEnumMap[instance.location], + 'location': _$RoomLocationEnumMap[instance.location]!, }; -T _$enumDecode( - Map enumValues, - dynamic source, { - T unknownValue, -}) { - if (source == null) { - throw ArgumentError('A value must be provided. Supported values: ' - '${enumValues.values.join(', ')}'); - } - - final value = enumValues.entries - .singleWhere((e) => e.value == source, orElse: () => null) - ?.key; - - if (value == null && unknownValue == null) { - throw ArgumentError('`$source` is not one of the supported values: ' - '${enumValues.values.join(', ')}'); - } - return value ?? unknownValue; -} - const _$RoomLocationEnumMap = { RoomLocation.Academy: 'Academy', RoomLocation.Hotel: 'Hotel', RoomLocation.StudyHostel: 'StudyHostel', }; -LessonAction _$LessonActionFromJson(Map json) { - return LessonAction( - json['title'] as String, - ); -} +LessonAction _$LessonActionFromJson(Map json) => LessonAction( + json['title'] as String, + ); Map _$LessonActionToJson(LessonAction instance) => { 'title': instance.title, }; -LessonModel _$LessonModelFromJson(Map json) { - return LessonModel( - json['title'] as String, - json['iconCodePoint'] as int, - json['fullTitle'] as String, - LessonAction.fromJson(json['action'] as Map), - ); -} +LessonModel _$LessonModelFromJson(Map json) => LessonModel( + json['title'] as String, + json['iconCodePoint'] as int, + json['fullTitle'] as String?, + json['action'] == null + ? null + : LessonAction.fromJson(json['action'] as Map), + ); Map _$LessonModelToJson(LessonModel instance) => { @@ -106,13 +88,11 @@ Map _$LessonModelToJson(LessonModel instance) => 'action': instance.action, }; -TeacherModel _$TeacherModelFromJson(Map json) { - return TeacherModel( - json['name'] as String, - json['surname'] as String, - json['patronymic'] as String, - ); -} +TeacherModel _$TeacherModelFromJson(Map json) => TeacherModel( + json['name'] as String, + json['surname'] as String, + json['patronymic'] as String, + ); Map _$TeacherModelToJson(TeacherModel instance) => { diff --git a/lib/timeline_painter.dart b/lib/timeline_painter.dart index acd0470..12b0329 100644 --- a/lib/timeline_painter.dart +++ b/lib/timeline_painter.dart @@ -18,10 +18,10 @@ import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:ranepa_timetable/main.dart'; -import 'package:ranepa_timetable/prefs.dart'; -import 'package:ranepa_timetable/timeline_models.dart'; -import 'package:ranepa_timetable/timetable_icons.dart'; +import 'package:ranepatimetable/main.dart'; +import 'package:ranepatimetable/prefs.dart'; +import 'package:ranepatimetable/timeline_models.dart'; +import 'package:ranepatimetable/timetable_icons.dart'; import 'package:shared_preferences/shared_preferences.dart'; class TimelinePainter extends CustomPainter { @@ -85,7 +85,7 @@ class TimelinePainter extends CustomPainter { if (!(model.first && model.last)) { // Timeline rect final rectPaint = Paint() - ..color = theme.accentColor + ..color = theme.primaryColor ..strokeCap = StrokeCap.round; if (model.first || !model.last) { @@ -107,7 +107,7 @@ class TimelinePainter extends CustomPainter { // Timeline border arc final arcPaint = Paint() - ..color = theme.accentColor + ..color = theme.primaryColor ..style = PaintingStyle.fill; if (model.first) @@ -132,7 +132,7 @@ class TimelinePainter extends CustomPainter { circleOffset, circleRadius + circleRadiusAdd, Paint() - ..color = theme.accentColor + ..color = theme.primaryColor ..style = PaintingStyle.fill); // Icons @@ -143,7 +143,7 @@ class TimelinePainter extends CustomPainter { text: TextSpan( style: TextStyle( fontFamily: fontFamily, - color: theme.accentTextTheme.body1.color, + color: theme.textTheme.bodyLarge?.color, fontSize: iconSize * 2, ), text: String.fromCharCode(model.lesson.iconCodePoint), @@ -166,7 +166,7 @@ class TimelinePainter extends CustomPainter { text: TextSpan( style: TextStyle( fontFamily: fontFamily, - color: theme.textTheme.body1.color, + color: theme.textTheme.bodyLarge?.color, fontSize: 20, ), text: String.fromCharCode( diff --git a/lib/timetable.dart b/lib/timetable.dart index 57614ae..89ece1f 100644 --- a/lib/timetable.dart +++ b/lib/timetable.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:collection'; +import 'dart:developer'; import 'dart:io'; import 'dart:ui'; @@ -12,40 +13,40 @@ import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; import 'package:http/http.dart' as http; -import 'package:ranepa_timetable/about.dart'; -import 'package:ranepa_timetable/apis.dart'; -import 'package:ranepa_timetable/localizations.dart'; -import 'package:ranepa_timetable/main.dart'; -import 'package:ranepa_timetable/platform_channels.dart'; -import 'package:ranepa_timetable/prefs.dart'; -import 'package:ranepa_timetable/search.dart'; -import 'package:ranepa_timetable/theme.dart'; -import 'package:ranepa_timetable/timeline.dart'; -import 'package:ranepa_timetable/timeline_models.dart'; -import 'package:ranepa_timetable/timetable_icons.dart'; -import 'package:ranepa_timetable/widget_templates.dart'; +import 'package:ranepatimetable/about.dart'; +import 'package:ranepatimetable/apis.dart'; +import 'package:ranepatimetable/localizations.dart'; +import 'package:ranepatimetable/main.dart'; +import 'package:ranepatimetable/platform_channels.dart'; +import 'package:ranepatimetable/prefs.dart'; +import 'package:ranepatimetable/search.dart'; +import 'package:ranepatimetable/theme.dart'; +import 'package:ranepatimetable/timeline.dart'; +import 'package:ranepatimetable/timeline_models.dart'; +import 'package:ranepatimetable/timetable_icons.dart'; +import 'package:ranepatimetable/widget_templates.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:tuple/tuple.dart'; class TimetableScreen extends StatefulWidget { static const ROUTE = "/timetable"; - static SearchItem selected; + static SearchItem? selected; static final LinkedHashMap> timetable = LinkedHashMap>(); TimetableScreen({ - Key key, + Key? key, }) : _deviceCalendarPlugin = DeviceCalendarPlugin(), super(key: key); - static DateTime _toDateTime(TimeOfDay tod, [DateTime dt]) { + static DateTime _toDateTime(TimeOfDay tod, [DateTime? dt]) { dt ??= DateTime.now(); return DateTime(dt.year, dt.month, dt.day, tod.hour, tod.minute); } - static TimeOfDay _toTimeOfDay([DateTime dt]) { + static TimeOfDay _toTimeOfDay([DateTime? dt]) { dt ??= DateTime.now(); return TimeOfDay(hour: dt.hour, minute: dt.minute); } @@ -129,7 +130,7 @@ class TimetableScreen extends StatefulWidget { timetable.clear(); timetable.addAll(dbTimetable); - final endCache = DateTime.parse(prefs.getString(PrefsIds.END_CACHE)); + final endCache = DateTime.parse(prefs.getString(PrefsIds.END_CACHE) ?? ''); if (endCache.compareTo(endCacheMidnight) != 0) { debugPrint("Starting additional cache.."); await loadTimetable( @@ -152,24 +153,25 @@ class TimetableScreen extends StatefulWidget { SearchItem searchItem, [ bool updateDb = true, ]) async { - if (!await WidgetTemplates.checkInternetConnection()) return; + try { + if (!await WidgetTemplates.checkInternetConnection()) return; - final api = SiteApiIds - .values[prefs.getInt(PrefsIds.SITE_API) ?? DEFAULT_API_ID.index]; + final api = SiteApiIds + .values[prefs.getInt(PrefsIds.SITE_API) ?? DEFAULT_API_ID.index]; - debugPrint("Starting load timetable ${updateDb ? "to cache" : "locallly"} via API №${api.index}"); + debugPrint("Starting load timetable ${updateDb ? "to cache" : "locallly"} via API №${api.index}"); - var resp; + var resp; - switch (api) { - case SiteApiIds.APP_NEW: - resp = await http.get('http://services.niu.ranepa.ru/API/public/' - '${searchItemTypes[searchItem.typeId.index].newApiStr}/${searchItem.id}' - '/schedule/${formatDateTime(from)}/${formatDateTime(to.add(Duration(days: 1)))}'); - break; - case SiteApiIds.APP_OLD: - resp = await http.post('http://test.ranhigs-nn.ru/api/WebService.asmx', - headers: {'Content-Type': 'text/xml; charset=utf-8'}, body: ''' + switch (api) { + case SiteApiIds.APP_NEW: + resp = await http.get(Uri.parse('http://services.niu.ranepa.ru/API/public/' + '${searchItemTypes[searchItem.typeId.index].newApiStr}/${searchItem.id}' + '/schedule/${formatDateTime(from)}/${formatDateTime(to.add(Duration(days: 1)))}')); + break; + case SiteApiIds.APP_OLD: + resp = await http.post(Uri.parse('http://test.ranhigs-nn.ru/api/WebService.asmx'), + headers: {'Content-Type': 'text/xml; charset=utf-8'}, body: ''' @@ -181,175 +183,177 @@ class TimetableScreen extends StatefulWidget { '''); - break; - case SiteApiIds.SITE: - resp = await http.get('http://services.niu.ranepa.ru/' - 'wp-content/plugins/rasp/rasp_json_data.php' - '?user=${searchItem.title}' - '&dstart=${formatDateTime(from)}' - '&dfinish=${formatDateTime(to)}'); - break; - } - - debugPrint("http load end. starting parse request.."); - - var itemArr = parseResp(api, resp.body); - - var mDate = from.subtract(Duration(days: 1)); - final _startDayId = timetable.keys.length; - for (var mItem in itemArr) { - DateTime mItemDate; - var mItemTimeStart; - var mItemTimeFinish; - String mItemTeacher; - String mItemName; - String mItemRoomStr; - String mItemGroup; - - switch (api) { - case SiteApiIds.APP_NEW: - mItemDate = DateTime.parse(mItem["xdt"]); - mItemTimeStart = mItem["nf"]; - mItemTimeFinish = mItem["kf"]; - mItemTeacher = searchItem.typeId == SearchItemTypeId.Group - ? mItem["teacher"] - : searchItem.title; - mItemRoomStr = mItem["number"]; - mItemGroup = searchItem.typeId == SearchItemTypeId.Teacher - ? mItem["group"] - : searchItem.title; - break; - case SiteApiIds.APP_OLD: - mItemDate = DateTime.parse( - mItem.children[OldAppApiTimetableIndexes.Date.index].text); - mItemTimeStart = - mItem.children[OldAppApiTimetableIndexes.TimeStart.index].text; - mItemTimeFinish = - mItem.children[OldAppApiTimetableIndexes.TimeFinish.index].text; - mItemName = mItem.children[OldAppApiTimetableIndexes.Name.index].text; - mItemRoomStr = - mItem.children[OldAppApiTimetableIndexes.Room.index].text; - mItemGroup = - mItem.children[OldAppApiTimetableIndexes.Group.index].text; - break; case SiteApiIds.SITE: - String mItemDateStr = mItem["date"]; - mItemDate = DateTime( - int.parse(mItemDateStr.substring(6)), - int.parse(mItemDateStr.substring(3, 5)), - int.parse(mItemDateStr.substring(0, 2)), - ); - mItemTimeStart = mItem["timestart"]; - mItemTimeFinish = mItem["timefinish"]; - mItemName = mItem["name"]; - mItemRoomStr = mItem["aydit"]; - mItemGroup = mItem["namegroup"]; + resp = await http.get(Uri.parse('http://services.niu.ranepa.ru/' + 'wp-content/plugins/rasp/rasp_json_data.php' + '?user=${searchItem.title}' + '&dstart=${formatDateTime(from)}' + '&dfinish=${formatDateTime(to)}')); break; } - String mItemSubject; - String mItemType; + debugPrint("http load end. starting parse request.."); + + var itemArr = parseResp(api, resp.body); + + var mDate = from.subtract(Duration(days: 1)); + final _startDayId = timetable.keys.length; + for (var mItem in itemArr) { + DateTime mItemDate; + var mItemTimeStart; + var mItemTimeFinish; + String? mItemTeacher; + String? mItemName; + String mItemRoomStr; + String mItemGroup; + + switch (api) { + case SiteApiIds.APP_NEW: + mItemDate = DateTime.parse(mItem["xdt"]); + mItemTimeStart = mItem["nf"]; + mItemTimeFinish = mItem["kf"]; + mItemTeacher = searchItem.typeId == SearchItemTypeId.Group + ? mItem["teacher"] + : searchItem.title; + mItemRoomStr = mItem["number"]; + mItemGroup = searchItem.typeId == SearchItemTypeId.Teacher + ? mItem["group"] + : searchItem.title; + break; + case SiteApiIds.APP_OLD: + mItemDate = DateTime.parse( + mItem.children[OldAppApiTimetableIndexes.Date.index].text); + mItemTimeStart = + mItem.children[OldAppApiTimetableIndexes.TimeStart.index].text; + mItemTimeFinish = + mItem.children[OldAppApiTimetableIndexes.TimeFinish.index].text; + mItemName = mItem.children[OldAppApiTimetableIndexes.Name.index].text; + mItemRoomStr = + mItem.children[OldAppApiTimetableIndexes.Room.index].text; + mItemGroup = + mItem.children[OldAppApiTimetableIndexes.Group.index].text; + + break; + case SiteApiIds.SITE: + String mItemDateStr = mItem?["date"] ?? ''; + mItemDate = DateTime( + int.parse(mItemDateStr.substring(6)), + int.parse(mItemDateStr.substring(3, 5)), + int.parse(mItemDateStr.substring(0, 2)), + ); + mItemTimeStart = mItem?["timestart"] ?? ''; + mItemTimeFinish = mItem?["timefinish"] ?? ''; + mItemName = mItem?["name"] ?? ''; + mItemRoomStr = mItem?["aydit"] ?? ''; + mItemGroup = mItem?["namegroup"] ?? ''; + break; + } - switch (api) { - case SiteApiIds.APP_NEW: - mItemSubject = mItem["subject"]; - mItemType = mItem["type"]; - break; - case SiteApiIds.SITE: - case SiteApiIds.APP_OLD: - mItemSubject = mItemName.substring(0, mItemName.indexOf('(')); - mItemType = RegExp(r"\(([^)]*)\)[^(]*$").stringMatch(mItemName); - mItemType = mItemType.substring(1, mItemType.lastIndexOf(')')); - mItemTeacher = mItemName.substring(mItemName.indexOf('>') + 1); - break; - } + String? mItemSubject; + String? mItemType; + + switch (api) { + case SiteApiIds.APP_NEW: + mItemSubject = mItem["subject"]; + mItemType = mItem["type"]; + break; + case SiteApiIds.SITE: + case SiteApiIds.APP_OLD: + mItemSubject = mItemName?.substring(0, mItemName.indexOf('(')); + mItemType = RegExp(r"\(([^)]*)\)[^(]*$").stringMatch(mItemName ?? ''); + mItemType = mItemType?.substring(1, mItemType.lastIndexOf(')')); + mItemTeacher = mItemName?.substring(mItemName.indexOf('>') + 1) ?? ''; + break; + } - while (mDate != mItemDate) { - mDate = mDate.add(Duration(days: 1)); - // skip sunday - if (mDate.weekday != DateTime.sunday) { - timetable[mDate] = List(); + while (mDate != mItemDate) { + mDate = mDate.add(Duration(days: 1)); + // skip sunday + if (mDate.weekday != DateTime.sunday) { + timetable[mDate] = []; + } } - } - final mLesson = TimelineModel( - date: mItemDate, - start: TimeOfDay( - hour: int.parse( - mItemTimeStart.substring(0, mItemTimeStart.length - 3)), - minute: int.parse(mItemTimeStart.substring( - mItemTimeStart.length - 2, mItemTimeStart.length))), - finish: TimeOfDay( - hour: int.parse( - mItemTimeFinish.substring(0, mItemTimeFinish.length - 3)), - minute: int.parse(mItemTimeFinish.substring( - mItemTimeFinish.length - 2, mItemTimeFinish.length))), - room: RoomModel.fromString(mItemRoomStr), - group: mItemGroup, - lesson: LessonModel.build( - ctx, - mItemSubject, - mItemType, - api, - ), - teacher: TeacherModel.fromString( - searchItem.typeId == SearchItemTypeId.Group - ? mItemTeacher - : searchItem.title), - ); + final mLesson = TimelineModel( + date: mItemDate, + start: TimeOfDay( + hour: int.parse( + mItemTimeStart.substring(0, mItemTimeStart.length - 3)), + minute: int.parse(mItemTimeStart.substring( + mItemTimeStart.length - 2, mItemTimeStart.length))), + finish: TimeOfDay( + hour: int.parse( + mItemTimeFinish.substring(0, mItemTimeFinish.length - 3)), + minute: int.parse(mItemTimeFinish.substring( + mItemTimeFinish.length - 2, mItemTimeFinish.length))), + room: RoomModel.fromString(mItemRoomStr), + group: mItemGroup, + lesson: LessonModel.build( + ctx, + mItemSubject ?? '', + mItemType ?? '', + api, + ), + teacher: TeacherModel.fromString( + (searchItem.typeId == SearchItemTypeId.Group + ? mItemTeacher + : searchItem.title) ?? ''), + ); - timetable[mItemDate].add(mLesson); - } + timetable[mItemDate]?.add(mLesson); + } - for (var mDay in timetable.values) { - if (mDay.isEmpty) continue; + for (var mDay in timetable.values) { + if (mDay.isEmpty) continue; - mDay.first.first = true; - mDay.last.last = true; + mDay.first.first = true; + mDay.last.last = true; - for (var mItemId = 0; mItemId < mDay.length - 1; mItemId++) { - final mItem = mDay[mItemId], mNextItem = mDay[mItemId + 1]; + for (var mItemId = 0; mItemId < mDay.length - 1; mItemId++) { + final mItem = mDay[mItemId], mNextItem = mDay[mItemId + 1]; - if (mItem.start == mNextItem.start) { - mItem.mergeBottom = true; - mNextItem.mergeTop = true; - } else { - final diff = _toDateTime(mNextItem.start) - .difference(_toDateTime(mItem.finish)); + if (mItem.start == mNextItem.start) { + mItem.mergeBottom = true; + mNextItem.mergeTop = true; + } else { + final diff = _toDateTime(mNextItem.start) + .difference(_toDateTime(mItem.finish)); - debugPrint("mDiff: $diff"); - if (diff.inMinutes > 10) { - mItem.last = true; - mNextItem.first = true; + debugPrint("mDiff: $diff"); + if (diff.inMinutes > 10) { + mItem.last = true; + mNextItem.first = true; + } } } } - } - debugPrint("parsing http requests end.."); - - // Update db - if (updateDb) - await PlatformChannels.updateDb( - timetable.values - .toList() - .sublist( - _startDayId, - ) - .expand( - (f) => f, - ), - ); + debugPrint("parsing http requests end.."); + // Update db + if (updateDb) + await PlatformChannels.updateDb( + timetable.values + .toList() + .sublist( + _startDayId, + ) + .expand( + (f) => f, + ), + ); - // Save cache end - prefs.setString(PrefsIds.END_CACHE, to.toIso8601String()); + // Save cache end + prefs.setString(PrefsIds.END_CACHE, to.toIso8601String()); - // Refresh widget - PlatformChannels.refreshWidget(); + // Refresh widget + PlatformChannels.refreshWidget(); + } catch (e, s) { + print(s); + } } - static DateTime _todayMidnight; + static DateTime? _todayMidnight; static DateTime get todayMidnight { if (_todayMidnight == null) { @@ -362,11 +366,11 @@ class TimetableScreen extends StatefulWidget { ? now.day + 1 : now.day); // skip sunday } - return _todayMidnight; + return _todayMidnight ?? DateTime.now(); } - static DateTime get nextDayDate { - final todayLastLesson = timetable[todayMidnight]?.last?.finish; + static DateTime? get nextDayDate { + final todayLastLesson = timetable[todayMidnight]?.last.finish; if (todayLastLesson == null) return null; return _toDateTime(todayLastLesson).isBefore(DateTime.now()) @@ -392,9 +396,9 @@ class TimetableScreen extends StatefulWidget { final alarmDay = timetable[alarmLessonDate]; if (alarmDay?.isNotEmpty ?? false) { - final alarmLesson = alarmDay.first; + final alarmLesson = alarmDay?.first; final alarmClock = - _toDateTime(alarmLesson.start).subtract(beforeAlarmClock); + _toDateTime(alarmLesson!.start).subtract(beforeAlarmClock); await AndroidIntent( action: 'android.intent.action.SET_ALARM', @@ -434,27 +438,27 @@ class TimetableScreen extends StatefulWidget { var permissionsGranted = permissionsGrantedResult.data ?? false; if (permissionsGrantedResult.isSuccess && !permissionsGranted) { permissionsGrantedResult = await calPlugin.requestPermissions(); - if (permissionsGrantedResult.isSuccess && permissionsGrantedResult.data) + if (permissionsGrantedResult.isSuccess && permissionsGrantedResult.data!) permissionsGranted = true; } if (permissionsGranted) { // Add calendar event - final calendarArr = (await calPlugin.retrieveCalendars())?.data; + final calendarArr = (await calPlugin.retrieveCalendars()).data; if (calendarArr?.isNotEmpty ?? false) { - final calendar = calendarArr.lastWhere((mCal) => !mCal.isReadOnly); + final calendar = calendarArr!.lastWhere((mCal) => !mCal.isReadOnly!); final eventsDay = timetable[nextDayDate]; if (eventsDay?.isNotEmpty ?? false) { - for (var mLesson in eventsDay) { + for (var mLesson in eventsDay!) { calPlugin.createOrUpdateEvent( Event( calendar.id, title: mLesson.lesson.title, description: mLesson.lesson.fullTitle, - start: _toDateTime(mLesson.start, mLesson.date), - end: _toDateTime(mLesson.finish, mLesson.date), + start: TZDateTime.from(_toDateTime(mLesson.start, mLesson.date), local), + end: TZDateTime.from(_toDateTime(mLesson.finish, mLesson.date), local), ), ); } @@ -486,7 +490,7 @@ class TimetableScreen extends StatefulWidget { class CupertinoCustomNavigationBar extends StatelessWidget implements ObstructingPreferredSizeWidget { CupertinoCustomNavigationBar({ - Key key, + Key? key, this.backgroundColor, this.bottom, this.title, @@ -494,12 +498,12 @@ class CupertinoCustomNavigationBar extends StatelessWidget this.trailing, }); - final Color backgroundColor; + final Color? backgroundColor; - final Widget bottom; - final Widget title; - final Widget leading; - final Widget trailing; + final Widget? bottom; + final Widget? title; + final Widget? leading; + final Widget? trailing; @override Size get preferredSize => Size.fromHeight(44.0 + 80.0); @@ -550,19 +554,19 @@ class CupertinoCustomNavigationBar extends StatelessWidget @override bool shouldFullyObstruct(BuildContext context) { final Color backgroundColor = - CupertinoDynamicColor.resolve(this.backgroundColor, context) ?? + CupertinoDynamicColor.resolve(this.backgroundColor ?? Colors.white, context) ?? CupertinoTheme.of(context).barBackgroundColor; return backgroundColor.alpha == 0xFF; } } class CupertinoTabBar extends StatefulWidget { - final TabController controller; + final TabController? controller; - final List titles; + final List? titles; const CupertinoTabBar({ - Key key, + Key? key, this.controller, this.titles, }) : super(key: key); @@ -574,18 +578,18 @@ class CupertinoTabBar extends StatefulWidget { class _CupertinoTabBarState extends State with TickerProviderStateMixin { // this will control the animation when a button changes from an off state to an on state - AnimationController _animationControllerOn; + AnimationController? _animationControllerOn; // this will control the animation when a button changes from an on state to an off state - AnimationController _animationControllerOff; + AnimationController? _animationControllerOff; // this will give the background color values of a button when it changes to an on state - Animation _colorTweenBackgroundOn; - Animation _colorTweenBackgroundOff; + Animation? _colorTweenBackgroundOn; + Animation? _colorTweenBackgroundOff; // this will give the foreground color values of a button when it changes to an on state - Animation _colorTweenForegroundOn; - Animation _colorTweenForegroundOff; + Animation? _colorTweenForegroundOn; + Animation? _colorTweenForegroundOff; // when swiping, the _controller.index value only changes after the animation, therefore, we need this to trigger the animations and save the current index int _currentIndex = 0; @@ -599,16 +603,16 @@ class _CupertinoTabBarState extends State // saves the previous value of the tab animation. It's used to figure the direction of the animation double _prevAniValue = 0.0; - get _foregroundOn => getTheme().accentIconTheme.color; + get _foregroundOn => getTheme().colorScheme.secondary; Color get _foregroundOff { return getTheme().brightness == Brightness.dark - ? Colors.white - : Colors.black; + ? Colors.black + : Colors.white; } // active button's background color - get _backgroundOn => getTheme().accentColor; + get _backgroundOn => getTheme().colorScheme.secondary; Color _backgroundOff = Colors.transparent; List _keys = []; @@ -620,37 +624,37 @@ class _CupertinoTabBarState extends State void initState() { super.initState(); - for (int index = 0; index < widget.titles.length; index++) { + for (int index = 0; index < (widget.titles ?? []).length; index++) { // create a GlobalKey for each Tab _keys.add(GlobalKey()); } // this will execute the function every time there's a swipe animation - widget.controller.animation.addListener(_handleTabAnimation); + widget.controller!.animation!.addListener(_handleTabAnimation); // this will execute the function every time the _controller.index value changes - widget.controller.addListener(_handleTabChange); + widget.controller!.addListener(_handleTabChange); _animationControllerOff = AnimationController(vsync: this, duration: Duration(milliseconds: 75)); // so the inactive buttons start in their "final" state (color) - _animationControllerOff.value = 1.0; + _animationControllerOff!.value = 1.0; _colorTweenBackgroundOff = ColorTween(begin: _backgroundOn, end: _backgroundOff) - .animate(_animationControllerOff); + .animate(_animationControllerOff!); _colorTweenForegroundOff = ColorTween(begin: _foregroundOn, end: _foregroundOff) - .animate(_animationControllerOff); + .animate(_animationControllerOff!); _animationControllerOn = AnimationController(vsync: this, duration: Duration(milliseconds: 150)); // so the inactive buttons start in their "final" state (color) - _animationControllerOn.value = 1.0; + _animationControllerOn!.value = 1.0; _colorTweenBackgroundOn = ColorTween(begin: _backgroundOff, end: _backgroundOn) - .animate(_animationControllerOn); + .animate(_animationControllerOn!); _colorTweenForegroundOn = ColorTween(begin: _foregroundOff, end: _foregroundOn) - .animate(_animationControllerOn); + .animate(_animationControllerOn!); } @override @@ -659,7 +663,7 @@ class _CupertinoTabBarState extends State // this generates our tabs buttons child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: widget.titles + children: (widget.titles ?? []) .asMap() .map((index, mTitle) { return MapEntry( @@ -684,7 +688,7 @@ class _CupertinoTabBarState extends State height: 35, child: ButtonTheme( child: AnimatedBuilder( - animation: _colorTweenBackgroundOn, + animation: _colorTweenBackgroundOn!, builder: (ctx, child) => RawMaterialButton( highlightElevation: 0, enableFeedback: false, @@ -698,7 +702,7 @@ class _CupertinoTabBarState extends State setState(() { _buttonTap = true; // trigger the controller to change between Tab Views - widget.controller.animateTo(index); + widget.controller?.animateTo(index); // set the current index _setCurrentIndex(index); // scroll to the tapped button @@ -724,7 +728,7 @@ class _CupertinoTabBarState extends State _handleTabAnimation() { // gets the value of the animation. For example, if one is between the 1st and the 2nd tab, this value will be 0.5 - _aniValue = widget.controller.animation.value; + _aniValue = widget.controller!.animation!.value; // if the button wasn't pressed, which means the user is swiping, and the amount swipped is less than 1 (this means that we're swiping through neighbor Tab Views) if (!_buttonTap && ((_aniValue - _prevAniValue).abs() < 1)) { @@ -739,14 +743,14 @@ class _CupertinoTabBarState extends State // runs when the displayed tab changes _handleTabChange() { // if a button was tapped, change the current index - if (_buttonTap) _setCurrentIndex(widget.controller.index); + if (_buttonTap) _setCurrentIndex(widget.controller!.index); // this resets the button tap - if ((widget.controller.index == _prevControllerIndex) || - (widget.controller.index == _aniValue.round())) _buttonTap = false; + if ((widget.controller!.index == _prevControllerIndex) || + (widget.controller!.index == _aniValue.round())) _buttonTap = false; // save the previous controller index - _prevControllerIndex = widget.controller.index; + _prevControllerIndex = widget.controller!.index; } _setCurrentIndex(int index) { @@ -766,12 +770,12 @@ class _CupertinoTabBarState extends State _triggerAnimation() { // reset the animations so they're ready to go - _animationControllerOn.reset(); - _animationControllerOff.reset(); + _animationControllerOn!.reset(); + _animationControllerOff!.reset(); // run the animations! - _animationControllerOn.forward(); - _animationControllerOff.forward(); + _animationControllerOn!.forward(); + _animationControllerOff!.forward(); } _scrollTo(int index) { @@ -802,7 +806,7 @@ class _CupertinoTabBarState extends State // get the last button renderBox = - _keys[widget.titles.length - 1].currentContext.findRenderObject(); + _keys[widget.titles!.length - 1].currentContext.findRenderObject(); // get its position position = renderBox.localToGlobal(Offset.zero).dx; // and size @@ -821,10 +825,10 @@ class _CupertinoTabBarState extends State _getBackgroundColor(int index) { if (index == _currentIndex) { // if it's active button - return _colorTweenBackgroundOn.value; + return _colorTweenBackgroundOn!.value; } else if (index == _prevControllerIndex) { // if it's the previous active button - return _colorTweenBackgroundOff.value; + return _colorTweenBackgroundOff!.value; } else { // if the button is inactive return _backgroundOff; @@ -834,9 +838,9 @@ class _CupertinoTabBarState extends State _getForegroundColor(int index) { // the same as the above if (index == _currentIndex) { - return _colorTweenForegroundOn.value; + return Colors.white; } else if (index == _prevControllerIndex) { - return _colorTweenForegroundOff.value; + return _colorTweenForegroundOff!.value; } else { return _foregroundOff; } @@ -845,7 +849,7 @@ class _CupertinoTabBarState extends State class _TimetableScreenState extends State with SingleTickerProviderStateMixin { - TabController _tabController; + late TabController _tabController; @override void initState() { @@ -870,12 +874,12 @@ class _TimetableScreenState extends State List buildTrailingActions(BuildContext ctx) => [ PlatformIconButton( padding: EdgeInsets.zero, - android: (ctx) => MaterialIconButtonData( + material: (ctx, _) => MaterialIconButtonData( tooltip: AppLocalizations.of(ctx).searchTip, ), icon: Icon( ctx.platformIcons.search, - color: Platform.isIOS ? getTheme().accentColor : null, + color: Platform.isIOS ? getTheme().colorScheme.secondary : null, ), onPressed: () => showSearchItemSelect( ctx, @@ -887,14 +891,14 @@ class _TimetableScreenState extends State List buildIntegratingActions(BuildContext ctx) => [ PlatformIconButton( padding: EdgeInsets.zero, - android: (ctx) => MaterialIconButtonData( + material: (ctx, _) => MaterialIconButtonData( tooltip: AppLocalizations.of(ctx).calendarTip), icon: PlatformWidget( - ios: (ctx) => Icon( + cupertino: (ctx, _) => Icon( TimetableIcons.calendar, - color: getTheme().accentColor, + color: getTheme().colorScheme.secondary, ), - android: (ctx) => Icon(Icons.calendar_today), + material: (ctx, _) => Icon(Icons.calendar_today), ), onPressed: () => TimetableScreen._createCalendarEvents( ctx, widget._deviceCalendarPlugin), @@ -903,7 +907,7 @@ class _TimetableScreenState extends State ? [ PlatformIconButton( padding: EdgeInsets.zero, - android: (ctx) => MaterialIconButtonData( + material: (ctx, _) => MaterialIconButtonData( tooltip: AppLocalizations.of(ctx).alarmTip), icon: const Icon(Icons.alarm), onPressed: () => TimetableScreen._createAlarm(ctx, prefs), @@ -920,7 +924,7 @@ class _TimetableScreenState extends State ctx, (ctx, ssDayStyle) { // Create tabs - final tabs = List(); + final tabs = []; var mDay = TimetableScreen.fromDay.subtract(Duration(days: 1)); for (int mTabId = 0; mTabId < TimetableScreen.dayCount; mTabId++) { mDay = mDay.add(Duration(days: 1)); @@ -933,14 +937,14 @@ class _TimetableScreenState extends State tabs.add(Platform.isIOS ? mDay : Tab( - text: ssDayStyle.data.index == DayStyle.Weekday.index + text: ssDayStyle.data?.index == DayStyle.Weekday.index ? getWeekdayTitle(ctx, mDay) : mDay.day.toString(), )); } return PlatformScaffold( - android: (ctx) => MaterialScaffoldData( + material: (ctx, _) => MaterialScaffoldData( drawer: Drawer( child: ListView( padding: EdgeInsets.zero, @@ -995,7 +999,7 @@ class _TimetableScreenState extends State controller: _tabController, ), )), - ios: (ctx) => CupertinoPageScaffoldData( + cupertino: (ctx, _) => CupertinoPageScaffoldData( navigationBar: CupertinoCustomNavigationBar( bottom: buildThemeStream((ctx, _) => CupertinoTabBar( controller: _tabController, @@ -1009,7 +1013,7 @@ class _TimetableScreenState extends State padding: EdgeInsets.zero, icon: Icon( ctx.platformIcons.info, - color: getTheme().accentColor, + color: getTheme().colorScheme.secondary, ), onPressed: () => Navigator.pushNamed(ctx, AboutScreen.ROUTE), @@ -1024,7 +1028,7 @@ class _TimetableScreenState extends State padding: EdgeInsets.zero, icon: Icon( ctx.platformIcons.settings, - color: getTheme().accentColor, + color: getTheme().colorScheme.secondary, ), onPressed: () => Navigator.pushNamed(ctx, PrefsScreen.ROUTE), @@ -1038,19 +1042,19 @@ class _TimetableScreenState extends State builder: (ctx, _) => WidgetTemplates.buildFutureBuilder(ctx, future: WidgetTemplates.checkInternetConnection(), builder: (ctx, internetConn) { - if (!internetConn.data) + if (!(internetConn.data as bool)) return WidgetTemplates.buildNetworkErrorNotification(ctx); return WidgetTemplates.buildFutureBuilder( ctx, - future: ssSearchItem.data.item1 + future: ssSearchItem.data?.item1 ?? false ? TimetableScreen._getTimetable( ctx, - ssSearchItem.data.item2, + ssSearchItem.data!.item2, prefs, ) : TimetableScreen._loadAllTimetable( ctx, - ssSearchItem.data.item2, + ssSearchItem.data!.item2, updateDb: false, ), builder: (ctx, _) { @@ -1064,12 +1068,12 @@ class _TimetableScreenState extends State TimetableScreen.fromDay.add( Duration(days: dayIndex), ), - List(), + [], ), ), ); - final tabViews = List(), + final tabViews = [], endCacheStr = prefs.getString(PrefsIds.END_CACHE), endCache = endCacheStr != null ? DateTime.parse(endCacheStr) @@ -1091,19 +1095,19 @@ class _TimetableScreenState extends State ? WidgetTemplates .buildFreeDayNotification( ctx, - ssSearchItem.data.item2, + ssSearchItem.data!.item2, ) : TimelineComponent( timetableIter.current.value, optimizeLessonTitles: optimizeLessonTitles, onRefresh: () async { - if (ssSearchItem.data.item1) { + if (ssSearchItem.data!.item1) { await PlatformChannels.deleteDb(); await TimetableScreen ._loadAllTimetable( ctx, - ssSearchItem.data.item2, + ssSearchItem.data!.item2, updateDb: true, ); } @@ -1114,7 +1118,7 @@ class _TimetableScreenState extends State ) : WidgetTemplates.buildFreeDayNotification( ctx, - ssSearchItem.data.item2, + ssSearchItem.data!.item2, ), ); diff --git a/lib/widget_templates.dart b/lib/widget_templates.dart index 3b2c8a0..9a57e76 100644 --- a/lib/widget_templates.dart +++ b/lib/widget_templates.dart @@ -1,38 +1,39 @@ import 'dart:io'; import 'package:connectivity/connectivity.dart'; -import 'package:flushbar/flushbar.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; -import 'package:ranepa_timetable/localizations.dart'; -import 'package:ranepa_timetable/search.dart'; -import 'package:ranepa_timetable/theme.dart'; -import 'package:ranepa_timetable/timetable.dart'; -import 'package:ranepa_timetable/timetable_icons.dart'; +import 'package:ranepatimetable/localizations.dart'; +import 'package:ranepatimetable/search.dart'; +import 'package:ranepatimetable/theme.dart'; +import 'package:ranepatimetable/timetable.dart'; +import 'package:ranepatimetable/timetable_icons.dart'; class WidgetTemplates { static Widget buildDivider() => Divider( height: Platform.isIOS ? 0 : 1, color: Platform.isIOS ? Color(0x4D000000) - : getTheme().textTheme.caption.color, + : getTheme().textTheme.bodySmall!.color, ); static Widget buildListTile( BuildContext ctx, { - @required Widget title, - Widget subtitle, - VoidCallback onTap, - Widget leading, - Widget trailing, - Widget bottom, - EdgeInsets padding, + required Widget title, + Widget? subtitle, + VoidCallback? onTap, + Widget? leading, + Widget? trailing, + Widget? bottom, + EdgeInsets? padding, }) { var expandedChildren = [ DefaultTextStyle( - style: Theme.of(ctx).textTheme.subtitle, + style: Theme.of(ctx).textTheme.titleMedium!.copyWith( + color: MediaQueryData.fromWindow(WidgetsBinding.instance.window).platformBrightness == Brightness.dark ? Colors.white : Colors.black + ), child: title, ) ]; @@ -43,7 +44,7 @@ class WidgetTemplates { height: 2, ), DefaultTextStyle( - style: Theme.of(ctx).textTheme.caption, + style: Theme.of(ctx).textTheme.bodySmall!, child: subtitle, ), ]); @@ -74,9 +75,10 @@ class WidgetTemplates { ), ); - return FlatButton( - color: Platform.isIOS ? CupertinoTheme.of(ctx).barBackgroundColor : null, - splashColor: Platform.isIOS ? Colors.transparent : null, + return TextButton( + style: TextButton.styleFrom( + backgroundColor: Platform.isIOS ? CupertinoTheme.of(ctx).barBackgroundColor : null, + ), child: Padding( padding: padding ?? EdgeInsets.symmetric( @@ -101,7 +103,7 @@ class WidgetTemplates { Container(height: 20), Text( text, - style: Theme.of(ctx).textTheme.title, + style: Theme.of(ctx).textTheme.titleLarge!, ) ], ), @@ -110,7 +112,7 @@ class WidgetTemplates { static Widget _buildIconNotification( BuildContext ctx, String text, [ - IconData icon, + IconData? icon, ]) => _buildNotification( ctx, @@ -120,7 +122,7 @@ class WidgetTemplates { child: Icon( icon, size: 140, - color: Platform.isIOS ? getTheme().accentColor : null, + color: Platform.isIOS ? getTheme().colorScheme.secondary : null, ), ), ); @@ -167,7 +169,7 @@ class WidgetTemplates { static Image buildLogo( ThemeData theme, { - Color color, + Color? color, }) => Image( image: AssetImage( @@ -192,40 +194,45 @@ class WidgetTemplates { return _buildIconNotification(ctx, AppLocalizations.of(ctx).freeDay, icon); } - static Flushbar buildFlushbar( + static buildFlushbar( BuildContext ctx, String msg, { - String title, - IconData iconData, - }) => - Flushbar( - title: title, - messageText: Text( - msg, - style: (Platform.isIOS - ? getTheme().textTheme - : getTheme().accentTextTheme) - .body1, - ), - icon: Icon(iconData, - color: Platform.isIOS - ? getTheme().primaryColor - : getTheme().accentIconTheme.color), - duration: Duration(seconds: 3), - flushbarStyle: FlushbarStyle.GROUNDED, - backgroundColor: Platform.isIOS - ? CupertinoTheme.of(ctx).barBackgroundColor - : getTheme().accentColor, - ); + String? title, + IconData? iconData, + }) => ScaffoldMessenger.of(ctx).showSnackBar( + SnackBar( + content: Text(msg) + ) + ); + // __DEPRECATED + // Flushbar( + // title: title, + // messageText: Text( + // msg, + // style: (Platform.isIOS + // ? getTheme().textTheme + // : getTheme().accentTextTheme) + // .body1, + // ), + // icon: Icon(iconData, + // color: Platform.isIOS + // ? getTheme().primaryColor + // : getTheme().accentIconTheme.color), + // duration: Duration(seconds: 3), + // flushbarStyle: FlushbarStyle.GROUNDED, + // backgroundColor: Platform.isIOS + // ? CupertinoTheme.of(ctx).barBackgroundColor + // : getTheme().accentColor, + // ); static Widget buildFutureBuilder( BuildContext ctx, { - @required Future future, - @required AsyncWidgetBuilder builder, - Widget loading, - Widget error, + required Future future, + required AsyncWidgetBuilder builder, + Widget? loading, + Widget? error, }) => - FutureBuilder( + FutureBuilder( future: future, builder: (BuildContext ctx, AsyncSnapshot snapshot) { switch (snapshot.connectionState) { @@ -241,7 +248,6 @@ class WidgetTemplates { ctx, "${snapshot.error}" ?? "Unknown"); return builder(ctx, snapshot); } - return null; }, ); diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..ef38cf7 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,1008 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a + url: "https://pub.dev" + source: hosted + version: "61.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 + url: "https://pub.dev" + source: hosted + version: "5.13.0" + android_intent: + dependency: "direct main" + description: + name: android_intent + sha256: "498b451c6be831de2fe032290a8699d2a185c9c6de3bbe6d90db1623a9f62321" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + archive: + dependency: transitive + description: + name: archive + sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a" + url: "https://pub.dev" + source: hosted + version: "3.3.7" + args: + dependency: transitive + description: + name: args + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + url: "https://pub.dev" + source: hosted + version: "2.4.2" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + auto_size_text: + dependency: "direct main" + description: + name: auto_size_text + sha256: "3f5261cd3fb5f2a9ab4e2fc3fba84fd9fcaac8821f20a1d4e71f557521b22599" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "43865b79fbb78532e4bff7c33087aa43b1d488c4fdef014eaef568af6d8016dc" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: db49b8609ef8c81cca2b310618c3017c00f03a92af44c04d310b907b2d692d95 + url: "https://pub.dev" + source: hosted + version: "2.2.0" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "5e1929ad37d48bd382b124266cb8e521de5548d406a45a5ae6656c13dab73e37" + url: "https://pub.dev" + source: hosted + version: "2.4.5" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41" + url: "https://pub.dev" + source: hosted + version: "7.2.10" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: "598a2a682e2a7a90f08ba39c0aaa9374c5112340f0a2e275f61b59389543d166" + url: "https://pub.dev" + source: hosted + version: "8.6.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: b8db3080e59b2503ca9e7922c3df2072cf13992354d5e944074ffa836fba43b7 + url: "https://pub.dev" + source: hosted + version: "0.4.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "4ad01d6e56db961d29661561effde45e519939fdaeb46c351275b182eac70189" + url: "https://pub.dev" + source: hosted + version: "4.5.0" + collection: + dependency: transitive + description: + name: collection + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + url: "https://pub.dev" + source: hosted + version: "1.17.1" + connectivity: + dependency: "direct main" + description: + name: connectivity + sha256: a8e91263cf3e25fb5cc95e19dfde4999e32a648ac3b9e8a558a28165731678f8 + url: "https://pub.dev" + source: hosted + version: "3.0.6" + connectivity_for_web: + dependency: transitive + description: + name: connectivity_for_web + sha256: "01a390c1d5adc2ed1fa1f52d120c07fe9fd01166a93f965a832fd6cfc0ea6482" + url: "https://pub.dev" + source: hosted + version: "0.4.0+1" + connectivity_macos: + dependency: transitive + description: + name: connectivity_macos + sha256: "51ae08d5162eca9669b9d8951ed83ce19c5355a81149f94e4dee2740beb93628" + url: "https://pub.dev" + source: hosted + version: "0.2.1+2" + connectivity_platform_interface: + dependency: transitive + description: + name: connectivity_platform_interface + sha256: "2d82e942df9d49f29a24bb07fb5ce085d4a53e47818c62364d2b6deb9e0d7a8e" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" + source: hosted + version: "1.0.5" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: f4f1f73ab3fd2afcbcca165ee601fe980d966af6a21b5970c6c9376955c528ad + url: "https://pub.dev" + source: hosted + version: "2.3.1" + device_calendar: + dependency: "direct main" + description: + path: "." + ref: "4.3.1" + resolved-ref: c7300b0e729889311243cea51adfdf04761157ef + url: "https://github.com/builttoroam/device_calendar.git" + source: git + version: "4.2.1" + duration: + dependency: "direct main" + description: + name: duration + sha256: d0b29d0a345429e3986ac56d60e4aef65b37d11e653022b2b9a4b361332b777f + url: "https://pub.dev" + source: hosted + version: "3.0.12" + duration_picker: + dependency: "direct main" + description: + name: duration_picker + sha256: "052b34dac04c29f3849bb3817a26c5aebe9e5f0697c3a374be87db2b84d75753" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 + url: "https://pub.dev" + source: hosted + version: "2.0.2" + file: + dependency: transitive + description: + name: file + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" + source: hosted + version: "6.1.4" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_email_sender: + dependency: "direct main" + description: + name: flutter_email_sender + sha256: "39398c3e6cf4fbe99798d3ac6ae7d229290d57f1504a4a9a0d35f3737dc28930" + url: "https://pub.dev" + source: hosted + version: "6.0.0" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" + url: "https://pub.dev" + source: hosted + version: "0.13.1" + flutter_localizations: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_material_color_picker: + dependency: "direct main" + description: + name: flutter_material_color_picker + sha256: "64432c3b13bbcc6f428bae9d2e75b1b3da1e6f3219979e08a3bd9f176781d9f2" + url: "https://pub.dev" + source: hosted + version: "1.1.0+2" + flutter_platform_widgets: + dependency: "direct main" + description: + name: flutter_platform_widgets + sha256: "107d5bc9a167b4e268cba44075ee399b6b2c63d44ede28f7e8c983d7fa4b59be" + url: "https://pub.dev" + source: hosted + version: "3.3.5" + flutter_screenutil: + dependency: "direct main" + description: + name: flutter_screenutil + sha256: "1b61f8c4cbf965104b6ca7160880ff1af6755aad7fec70b58444245132453745" + url: "https://pub.dev" + source: hosted + version: "5.8.4" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "8c5d68a82add3ca76d792f058b186a0599414f279f00ece4830b9b231b570338" + url: "https://pub.dev" + source: hosted + version: "2.0.7" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + graphs: + dependency: transitive + description: + name: graphs + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + url: "https://pub.dev" + source: hosted + version: "2.3.1" + http: + dependency: "direct main" + description: + name: http + sha256: "4c3f04bfb64d3efd508d06b41b825542f08122d30bda4933fb95c069d22a4fa3" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + image: + dependency: transitive + description: + name: image + sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf + url: "https://pub.dev" + source: hosted + version: "4.0.17" + intl: + dependency: transitive + description: + name: intl + sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 + url: "https://pub.dev" + source: hosted + version: "0.18.0" + intl_translation: + dependency: "direct dev" + description: + name: intl_translation + sha256: c8dce69cd7ce7ffea26126c32d284c829a94f08c13e4322ec0d98753dde6baff + url: "https://pub.dev" + source: hosted + version: "0.18.2" + intro_views_flutter: + dependency: "direct main" + description: + name: intro_views_flutter + sha256: "08dfee202ad72efc2d32377ccd3cab1c42d4c68863e877a311491af628ac24dd" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + url: "https://pub.dev" + source: hosted + version: "4.8.1" + json_serializable: + dependency: "direct main" + description: + name: json_serializable + sha256: "61a60716544392a82726dd0fa1dd6f5f1fd32aec66422b6e229e7b90d52325c4" + url: "https://pub.dev" + source: hosted + version: "6.7.0" + logging: + dependency: transitive + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + url: "https://pub.dev" + source: hosted + version: "0.12.15" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + meta: + dependency: transitive + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + mime: + dependency: transitive + description: + name: mime + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" + source: hosted + version: "1.0.4" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + package_info: + dependency: "direct main" + description: + name: package_info + sha256: "6c07d9d82c69e16afeeeeb6866fe43985a20b3b50df243091bfc4a4ad2b03b75" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: ffbb8cc9ed2c9ec0e4b7a541e56fd79b138e8f47d2fb86815f15358a349b3b57 + url: "https://pub.dev" + source: hosted + version: "2.1.11" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" + url: "https://pub.dev" + source: hosted + version: "2.0.6" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: "1cb68ba4cd3a795033de62ba1b7b4564dace301f952de6bfb3cd91b202b6ee96" + url: "https://pub.dev" + source: hosted + version: "2.1.7" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + url: "https://pub.dev" + source: hosted + version: "5.4.0" + platform: + dependency: transitive + description: + name: platform + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + url: "https://pub.dev" + source: hosted + version: "3.7.3" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + process: + dependency: transitive + description: + name: process + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" + source: hosted + version: "4.2.4" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 + url: "https://pub.dev" + source: hosted + version: "1.2.3" + rrule: + dependency: transitive + description: + name: rrule + sha256: e441fc40006dfc0087e5bff07216dfa738cfab7c7b2e8255f8f62a49a07f625d + url: "https://pub.dev" + source: hosted + version: "0.2.13" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "396f85b8afc6865182610c0a2fc470853d56499f75f7499e2a73a9f0539d23d0" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "6478c6bbbecfe9aced34c483171e90d7c078f5883558b30ec3163cf18402c749" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: e014107bb79d6d3297196f4f2d0db54b5d1f85b8ea8ff63b8e8b391a02700feb + url: "https://pub.dev" + source: hosted + version: "2.2.2" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d + url: "https://pub.dev" + source: hosted + version: "2.2.0" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "373f96cf5a8744bc9816c1ff41cf5391bbdbe3d7a96fe98c622b6738a8a7bd33" + url: "https://pub.dev" + source: hosted + version: "1.3.2" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f" + url: "https://pub.dev" + source: hosted + version: "1.3.3" + source_span: + dependency: transitive + description: + name: source_span + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" + source: hosted + version: "1.9.1" + sqflite: + dependency: "direct main" + description: + name: sqflite + sha256: b4d6710e1200e96845747e37338ea8a819a12b51689a3bcf31eff0003b37a0b9 + url: "https://pub.dev" + source: hosted + version: "2.2.8+4" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "8f7603f3f8f126740bc55c4ca2d1027aab4b74a1267a3e31ce51fe40e3b65b8f" + url: "https://pub.dev" + source: hosted + version: "2.4.5+1" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + url: "https://pub.dev" + source: hosted + version: "0.5.1" + time: + dependency: transitive + description: + name: time + sha256: "83427e11d9072e038364a5e4da559e85869b227cf699a541be0da74f14140124" + url: "https://pub.dev" + source: hosted + version: "2.1.3" + timezone: + dependency: transitive + description: + name: timezone + sha256: "1cfd8ddc2d1cfd836bc93e67b9be88c3adaeca6f40a00ca999104c30693cdca0" + url: "https://pub.dev" + source: hosted + version: "0.9.2" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + tuple: + dependency: "direct main" + description: + name: tuple + sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 + url: "https://pub.dev" + source: hosted + version: "2.0.2" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: eb1e00ab44303d50dd487aab67ebc575456c146c6af44422f9c13889984c00f3 + url: "https://pub.dev" + source: hosted + version: "6.1.11" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: eed4e6a1164aa9794409325c3b707ff424d4d1c2a785e7db67f8bbda00e36e51 + url: "https://pub.dev" + source: hosted + version: "6.0.35" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2" + url: "https://pub.dev" + source: hosted + version: "6.1.4" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "91ee3e75ea9dadf38036200c5d3743518f4a5eb77a8d13fda1ee5764373f185e" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: bfdfa402f1f3298637d71ca8ecfe840b4696698213d5346e9d12d4ab647ee2ea + url: "https://pub.dev" + source: hosted + version: "2.1.3" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "6bb1e5d7fe53daf02a8fee85352432a40b1f868a81880e99ec7440113d5cfcab" + url: "https://pub.dev" + source: hosted + version: "2.0.17" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "254708f17f7c20a9c8c471f67d86d76d4a3f9c1591aad1e15292008aceb82771" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "670f6e07aca990b4a2bcdc08a784193c4ccdd1932620244c3a86bb72a0eac67f" + url: "https://pub.dev" + source: hosted + version: "1.1.7" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "7451721781d967db9933b63f5733b1c4533022c0ba373a01bdd79d1a5457f69f" + url: "https://pub.dev" + source: hosted + version: "1.1.7" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "80a13c613c8bde758b1464a1755a7b3a8f2b6cec61fbf0f5a53c94c30f03ba2e" + url: "https://pub.dev" + source: hosted + version: "1.1.7" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + url: "https://pub.dev" + source: hosted + version: "2.4.0" + win32: + dependency: transitive + description: + name: win32 + sha256: "7dacfda1edcca378031db9905ad7d7bd56b29fd1a90b0908b71a52a12c41e36b" + url: "https://pub.dev" + source: hosted + version: "5.0.3" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 + url: "https://pub.dev" + source: hosted + version: "1.0.0" + xml: + dependency: "direct main" + description: + name: xml + sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + url: "https://pub.dev" + source: hosted + version: "6.3.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.0.1 <4.0.0" + flutter: ">=3.10.0" diff --git a/pubspec.yaml b/pubspec.yaml index ec1caf4..194d7ae 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,55 +1,63 @@ -name: ranepa_timetable +name: ranepatimetable description: Custom RANEPA android client on Flutter. +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 1.8.0+19 +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +# In Windows, build-name is used as the major, minor, and patch parts +# of the product and file versions while build-number is used as the build suffix. +version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: '>=3.0.1 <4.0.0' dependencies: flutter: sdk: flutter flutter_localizations: sdk: flutter - flutter_cupertino_localizations: ^1.0.1 - sqflite: ^1.3.0 - cupertino_icons: ^0.1.3 - http: ^0.12.1 - xml: ^3.3.1 - shared_preferences: - path: shared_preferences_suite_name - json_serializable: ^3.3.0 - intro_views_flutter: ^2.8.1 - android_intent: ^0.3.7+1 - tuple: ^1.0.3 - device_calendar: ^3.1.0 - ios_app_group: ^1.0.2 - flushbar: + sqflite: ^2.2.8+4 + cupertino_icons: ^1.0.5 + http: ^1.0.0 + xml: ^6.3.0 + shared_preferences: ^2.1.1 + json_serializable: ^6.7.0 + intro_views_flutter: ^3.2.0 + android_intent: ^2.0.2 + tuple: ^2.0.1 + device_calendar: git: - url: git://github.com/valterh4ck3r/flushbar - ref: master - url_launcher: ^5.4.5 - connectivity: ^0.4.8+2 - flutter_svg: ^0.17.4 - duration: ^2.0.11 - flutter_duration_picker: - git: - url: git://github.com/aman-malhotra-1999/flutter_duration_picker.git - auto_size_text: ^2.1.0 - flutter_email_sender: ^3.0.1 + url: https://github.com/builttoroam/device_calendar.git + ref: 4.3.1 + url_launcher: ^6.1.11 + connectivity: ^3.0.6 + flutter_svg: ^2.0.6 + duration: ^3.0.12 + auto_size_text: ^3.0.0 + flutter_email_sender: ^6.0.0 flutter_material_color_picker: ^1.0.5 - package_info: ^0.4.0+17 - flutter_screenutil: ^1.1.0 - flutter_platform_widgets: ^0.32.5 - flutter_datetime_picker: ^1.3.8 + package_info: ^2.0.2 + flutter_screenutil: ^5.8.4 + flutter_platform_widgets: ^3.3.5 + duration_picker: ^1.1.1 dev_dependencies: flutter_test: sdk: flutter - flutter_launcher_icons: ^0.7.5 - intl_translation: ^0.17.10 - build_runner: ^1.9.0 + flutter_launcher_icons: ^0.13.1 + intl_translation: ^0.18.2 + build_runner: ^2.4.4 flutter_icons: image_path_android: "assets/images/icon.png" @@ -64,12 +72,12 @@ flutter: uses-material-design: true assets: - - assets/images/ + - assets/images/ fonts: - - family: TimetableIcons - fonts: - - asset: assets/fonts/TimetableIcons.ttf + - family: TimetableIcons + fonts: + - asset: assets/fonts/TimetableIcons.ttf # To add assets to your application, add an assets section, like this: # assets: diff --git a/ranepa_sessions.saz b/ranepa_sessions.saz deleted file mode 100644 index 34693ba..0000000 Binary files a/ranepa_sessions.saz and /dev/null differ diff --git a/shared_preferences_suite_name b/shared_preferences_suite_name deleted file mode 160000 index bfc2bff..0000000 --- a/shared_preferences_suite_name +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bfc2bff204d8d01efc2be311d6a06fa4cc1201fc diff --git a/test/timeline_models_test.dart b/test/timeline_models_test.dart deleted file mode 100644 index 1993e8c..0000000 --- a/test/timeline_models_test.dart +++ /dev/null @@ -1,8 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:ranepa_timetable/timeline_models.dart'; - -void main() { - test('Parse lessons check', () { -// expect() - }); -} \ No newline at end of file diff --git a/test/widget_test.dart b/test/widget_test.dart new file mode 100644 index 0000000..2b1ae82 --- /dev/null +++ b/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:ranepatimetable/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +}