├── .gitignore ├── .gitlab-ci.yml ├── .gradle ├── 6.1.1 │ ├── fileChanges │ │ └── last-build.bin │ ├── fileContent │ │ └── fileContent.lock │ └── gc.properties ├── buildOutputCleanup │ ├── cache.properties │ └── outputFiles.bin ├── checksums │ ├── md5-checksums.bin │ └── sha1-checksums.bin └── vcs-1 │ └── gc.properties ├── .idea ├── .gitignore ├── assetWizardSettings.xml ├── caches │ └── build_file_checksums.ser ├── codeStyles │ └── Project.xml ├── compiler.xml ├── gradle.xml ├── jarRepositories.xml ├── markdown-doclet.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── Gemfile ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules-debug.pro ├── proguard-rules.pro ├── release │ ├── app-release.apk │ └── output-metadata.json └── src │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-playstore.png │ ├── java │ │ └── com │ │ │ └── ulan │ │ │ └── timetable │ │ │ ├── activities │ │ │ ├── ExamsActivity.java │ │ │ ├── HomeworkActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── NoteInfoActivity.java │ │ │ ├── NotesActivity.java │ │ │ ├── ProfileActivity.java │ │ │ ├── SettingsActivity.java │ │ │ ├── SummaryActivity.java │ │ │ ├── TeachersActivity.java │ │ │ └── TimeSettingsActivity.java │ │ │ ├── adapters │ │ │ ├── ExamsAdapter.java │ │ │ ├── FragmentsTabAdapter.java │ │ │ ├── HomeworkAdapter.java │ │ │ ├── NotesAdapter.java │ │ │ ├── TeachersAdapter.java │ │ │ └── WeekAdapter.java │ │ │ ├── appwidget │ │ │ ├── AppWidgetConfigureActivity.java │ │ │ ├── AppWidgetConstants.java │ │ │ ├── Dao │ │ │ │ ├── AppWidgetDao.java │ │ │ │ ├── BaseDao.java │ │ │ │ ├── DBManager.java │ │ │ │ └── DataBaseHelper.java │ │ │ ├── DayAppWidgetProvider.java │ │ │ └── DayAppWidgetService.java │ │ │ ├── fragments │ │ │ ├── NotificationSettingsFragment.java │ │ │ ├── ProfileActivityFragment.java │ │ │ ├── SettingsFragment.java │ │ │ ├── TimeSettingsFragment.java │ │ │ └── WeekdayFragment.java │ │ │ ├── model │ │ │ ├── Exam.java │ │ │ ├── Homework.java │ │ │ ├── Note.java │ │ │ ├── Teacher.java │ │ │ └── Week.java │ │ │ ├── profiles │ │ │ ├── Profile.java │ │ │ └── ProfileManagement.java │ │ │ ├── receivers │ │ │ ├── DailyReceiver.java │ │ │ ├── DoNotDisturbReceivers.kt │ │ │ ├── MidnightReceiver.kt │ │ │ ├── NotificationDismissButtonReceiver.java │ │ │ └── SubjectReminderReceiver.kt │ │ │ └── utils │ │ │ ├── AlertDialogsHelper.java │ │ │ ├── ColorPalette.java │ │ │ ├── DbHelper.java │ │ │ ├── FragmentHelper.java │ │ │ ├── LinedEditText.java │ │ │ ├── NotificationUtil.java │ │ │ ├── PreferenceUtil.java │ │ │ ├── ShortcutUtils.kt │ │ │ └── WeekUtils.java │ └── res │ │ ├── drawable │ │ ├── card_background_selector.xml │ │ ├── card_state_pressed.xml │ │ ├── home_widget.webp │ │ ├── ic_access_time_black_24dp.xml │ │ ├── ic_add_black_24dp.xml │ │ ├── ic_assignment_black_24dp.xml │ │ ├── ic_assignment_next_black_24dp.xml │ │ ├── ic_baseline_accessibility_new_24.xml │ │ ├── ic_baseline_coffee_24.xml │ │ ├── ic_baseline_notifications_active_24.xml │ │ ├── ic_baseline_person_add_24.xml │ │ ├── ic_baseline_save_24.xml │ │ ├── ic_baseline_settings_backup_restore_24.xml │ │ ├── ic_baseline_view_carousel_24.xml │ │ ├── ic_baseline_view_list_24.xml │ │ ├── ic_book_black_24dp.xml │ │ ├── ic_clear_black_24dp.xml │ │ ├── ic_close_black_24dp.xml │ │ ├── ic_delete_black_24dp.xml │ │ ├── ic_delete_forever_black_24dp.xml │ │ ├── ic_do_not_disturb_on_black_24dp.xml │ │ ├── ic_done_white_24dp.xml │ │ ├── ic_edit_black_24dp.xml │ │ ├── ic_email_black_24dp.xml │ │ ├── ic_event_note_black_24dp.xml │ │ ├── ic_expand_more_black_24dp.xml │ │ ├── ic_go.xml │ │ ├── ic_open_in_browser_white_24dp.xml │ │ ├── ic_palette_black_24dp.xml │ │ ├── ic_people_black_24dp.xml │ │ ├── ic_person_black_24dp.xml │ │ ├── ic_phone_black_24dp.xml │ │ ├── ic_restore.xml │ │ ├── ic_room_black_24dp.xml │ │ ├── ic_school_black_24dp.xml │ │ ├── ic_settings_black_24dp.xml │ │ ├── ic_star_black_24dp.xml │ │ ├── ic_star_border_black_24dp.xml │ │ ├── ic_view_week_black_24dp.xml │ │ ├── launch_screen.xml │ │ ├── shortcuts_background.xml │ │ └── side_nav_bar.xml │ │ ├── layout │ │ ├── activity_appwidget_configure.xml │ │ ├── activity_exams.xml │ │ ├── activity_homeworks.xml │ │ ├── activity_main.xml │ │ ├── activity_note_info.xml │ │ ├── activity_notes.xml │ │ ├── activity_profile.xml │ │ ├── activity_settings.xml │ │ ├── activity_settings_time.xml │ │ ├── activity_summary.xml │ │ ├── activity_teachers.xml │ │ ├── app_bar_main.xml │ │ ├── content_main.xml │ │ ├── day_appwidget.xml │ │ ├── dialog_add_exam.xml │ │ ├── dialog_add_homework.xml │ │ ├── dialog_add_note.xml │ │ ├── dialog_add_subject.xml │ │ ├── dialog_add_teacher.xml │ │ ├── fragment_profile.xml │ │ ├── fragment_weekday.xml │ │ ├── item_day_appwidget.xml │ │ ├── list_profiles_entry.xml │ │ ├── listview_exams_adapter.xml │ │ ├── listview_homeworks_adapter.xml │ │ ├── listview_notes_adapter.xml │ │ ├── listview_teachers_adapter.xml │ │ ├── listview_week_adapter.xml │ │ └── nav_header_main.xml │ │ ├── menu │ │ ├── activity_main_drawer.xml │ │ ├── main.xml │ │ ├── popup_menu.xml │ │ ├── summary.xml │ │ └── toolbar_action_mode.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── values-de │ │ └── strings.xml │ │ ├── values-es │ │ └── strings.xml │ │ ├── values-fr │ │ └── strings.xml │ │ ├── values-it │ │ └── strings.xml │ │ ├── values-ru │ │ └── strings.xml │ │ ├── values-v29 │ │ └── styles.xml │ │ ├── values │ │ ├── arrays.xml │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── ic_launcher_background.xml │ │ ├── integer.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ ├── day_appwidget_info.xml │ │ ├── settings.xml │ │ ├── settings_notification.xml │ │ └── settings_time.xml │ └── test │ └── java │ └── com │ └── ulan │ └── timetable │ └── ExampleUnitTest.java ├── build.gradle ├── fastlane ├── Appfile ├── Fastfile └── metadata │ └── android │ ├── de-DE │ ├── full_description.txt │ ├── short_description.txt │ └── title.txt │ ├── en-US │ ├── full_description.txt │ ├── images │ │ ├── featureGraphic.png │ │ └── phoneScreenshots │ │ │ ├── timetable_screenshot_1.png │ │ │ ├── timetable_screenshot_2.png │ │ │ ├── timetable_screenshot_3.jpg │ │ │ ├── timetable_screenshot_4.jpg │ │ │ └── timetable_screenshot_5.jpg │ ├── short_description.txt │ └── title.txt │ └── es-ES │ ├── full_description.txt │ ├── short_description.txt │ └── title.txt ├── get-updated-badge-info.sh ├── gradle.properties ├── gradle └── wrapper │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── logo-files ├── horizontal.png ├── logomark.png └── vertical.png ├── screenshots ├── timetable_screenshot_1.jpg ├── timetable_screenshot_2.jpg └── timetable_screenshot_3.jpg └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Files for the ART/Dalvik VM 2 | *.dex 3 | 4 | # Java class files 5 | *.class 6 | 7 | # Generated files 8 | bin/ 9 | gen/ 10 | out/ 11 | # Uncomment the following line in case you need and you don't have the release build type files in your app 12 | # release/ 13 | 14 | # Gradle files 15 | .gradle/ 16 | build/ 17 | 18 | # Local configuration file (sdk path, etc) 19 | local.properties 20 | 21 | # Proguard folder generated by Eclipse 22 | proguard/ 23 | 24 | # Log Files 25 | *.log 26 | 27 | # Android Studio Navigation editor temp files 28 | .navigation/ 29 | 30 | # Android Studio captures folder 31 | captures/ 32 | 33 | # IntelliJ 34 | *.iml 35 | .idea/workspace.xml 36 | .idea/tasks.xml 37 | .idea/gradle.xml 38 | .idea/assetWizardSettings.xml 39 | .idea/dictionaries 40 | .idea/libraries 41 | # Android Studio 3 in .gitignore file. 42 | .idea/caches 43 | .idea/modules.xml 44 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 45 | .idea/navEditor.xml 46 | 47 | # Keystore files 48 | # Uncomment the following lines if you do not want to check your keystore files in. 49 | #*.jks 50 | #*.keystore 51 | 52 | # External native build folder generated in Android Studio 2.2 and later 53 | .externalNativeBuild 54 | .cxx/ 55 | 56 | # Google Services (e.g. APIs or Firebase) 57 | # google-services.json 58 | 59 | # Freeline 60 | freeline.py 61 | freeline/ 62 | freeline_project_description.json 63 | 64 | # fastlane 65 | fastlane/report.xml 66 | fastlane/Preview.html 67 | fastlane/screenshots 68 | fastlane/test_output 69 | fastlane/readme.md 70 | 71 | # Version control 72 | vcs.xml 73 | 74 | # lint 75 | lint/intermediates/ 76 | lint/generated/ 77 | lint/outputs/ 78 | lint/tmp/ 79 | # lint/reports/ 80 | 81 | # Android Profiling 82 | *.hprof 83 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | variables: 2 | GIT_DEPTH: 0 3 | ANDROID_COMPILE_SDK: "30" 4 | ANDROID_BUILD_TOOLS: "33.0.1" 5 | 6 | # It's what version of the command line tools we're going to download from the official site. 7 | # Official Site-> https://developer.android.com/studio/index.html 8 | # There, look down below at the cli tools only, sdk tools package is of format: 9 | # commandlinetools-os_type-ANDROID_SDK_TOOLS_latest.zip 10 | # when the script was last modified for latest compileSdkVersion, it was which is written down below 11 | ANDROID_SDK_TOOLS: "9123335" 12 | 13 | stages: 14 | - build 15 | 16 | build_badges: 17 | stage: build 18 | image: python:3.6.6 19 | before_script: 20 | - apt-get update -qy 21 | - pip install anybadge 22 | - chmod +x get-updated-badge-info.sh 23 | script: 24 | - echo "Some script to build your code" 25 | after_script: 26 | - ./get-updated-badge-info.sh 27 | artifacts: 28 | paths: 29 | - badges.json 30 | - badges 31 | when: always 32 | 33 | 34 | assembleDebug: 35 | interruptible: true 36 | stage: build 37 | image: gradle 38 | before_script: 39 | - apt-get --quiet update --yes 40 | - apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1 41 | 42 | - export ANDROID_HOME="${PWD}/android-home" 43 | - install -d $ANDROID_HOME 44 | - wget --output-document=$ANDROID_HOME/cmdline-tools.zip https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_SDK_TOOLS}_latest.zip 45 | # move to the archive at ANDROID_HOME 46 | - pushd $ANDROID_HOME 47 | - unzip -d cmdline-tools cmdline-tools.zip 48 | - mv cmdline-tools/cmdline-tools/ cmdline-tools/latest/ 49 | - popd 50 | - export PATH=$PATH:${ANDROID_HOME}/cmdline-tools/latest/bin/ 51 | 52 | # Nothing fancy here, just checking sdkManager version 53 | - sdkmanager --version 54 | 55 | # use yes to accept all licenses 56 | - yes | sdkmanager --sdk_root=${ANDROID_HOME} --licenses || true 57 | - sdkmanager --sdk_root=${ANDROID_HOME} "platforms;android-${ANDROID_COMPILE_SDK}" 58 | - sdkmanager --sdk_root=${ANDROID_HOME} "platform-tools" 59 | - sdkmanager --sdk_root=${ANDROID_HOME} "build-tools;${ANDROID_BUILD_TOOLS}" 60 | 61 | # Not necessary, but just for surity 62 | - chmod +x ./gradlew 63 | script: 64 | - gradle --version 65 | - gradle wrapper 66 | - ./gradlew assembleDebug 67 | - mv app/build/outputs/apk/debug/app-debug.apk app-debug.apk 68 | artifacts: 69 | paths: 70 | - app-debug.apk -------------------------------------------------------------------------------- /.gradle/6.1.1/fileChanges/last-build.bin: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gradle/6.1.1/fileContent/fileContent.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flxholle/TimeTable/1ab7cd6d7f5f37fd149e7e36b8b37c01ce66f886/.gradle/6.1.1/fileContent/fileContent.lock -------------------------------------------------------------------------------- /.gradle/6.1.1/gc.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flxholle/TimeTable/1ab7cd6d7f5f37fd149e7e36b8b37c01ce66f886/.gradle/6.1.1/gc.properties -------------------------------------------------------------------------------- /.gradle/buildOutputCleanup/cache.properties: -------------------------------------------------------------------------------- 1 | #Sun Nov 27 00:23:14 CET 2022 2 | gradle.version=7.4 3 | -------------------------------------------------------------------------------- /.gradle/buildOutputCleanup/outputFiles.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flxholle/TimeTable/1ab7cd6d7f5f37fd149e7e36b8b37c01ce66f886/.gradle/buildOutputCleanup/outputFiles.bin -------------------------------------------------------------------------------- /.gradle/checksums/md5-checksums.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flxholle/TimeTable/1ab7cd6d7f5f37fd149e7e36b8b37c01ce66f886/.gradle/checksums/md5-checksums.bin -------------------------------------------------------------------------------- /.gradle/checksums/sha1-checksums.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flxholle/TimeTable/1ab7cd6d7f5f37fd149e7e36b8b37c01ce66f886/.gradle/checksums/sha1-checksums.bin -------------------------------------------------------------------------------- /.gradle/vcs-1/gc.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flxholle/TimeTable/1ab7cd6d7f5f37fd149e7e36b8b37c01ce66f886/.gradle/vcs-1/gc.properties -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flxholle/TimeTable/1ab7cd6d7f5f37fd149e7e36b8b37c01ce66f886/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 20 | 21 | 22 | 23 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | xmlns:android 32 | 33 | ^$ 34 | 35 | 36 | 37 |
38 |
39 | 40 | 41 | 42 | xmlns:.* 43 | 44 | ^$ 45 | 46 | 47 | BY_NAME 48 | 49 |
50 |
51 | 52 | 53 | 54 | .*:id 55 | 56 | http://schemas.android.com/apk/res/android 57 | 58 | 59 | 60 |
61 |
62 | 63 | 64 | 65 | .*:name 66 | 67 | http://schemas.android.com/apk/res/android 68 | 69 | 70 | 71 |
72 |
73 | 74 | 75 | 76 | name 77 | 78 | ^$ 79 | 80 | 81 | 82 |
83 |
84 | 85 | 86 | 87 | style 88 | 89 | ^$ 90 | 91 | 92 | 93 |
94 |
95 | 96 | 97 | 98 | .* 99 | 100 | ^$ 101 | 102 | 103 | BY_NAME 104 | 105 |
106 |
107 | 108 | 109 | 110 | .* 111 | 112 | http://schemas.android.com/apk/res/android 113 | 114 | 115 | ANDROID_ATTRIBUTE_ORDER 116 | 117 |
118 |
119 | 120 | 121 | 122 | .* 123 | 124 | .* 125 | 126 | 127 | BY_NAME 128 | 129 |
130 |
131 |
132 |
133 |
134 |
-------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /.idea/markdown-doclet.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "fastlane" 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | Important: We moved to GitLab! The repository on Github will remain as a mirror. Please do not submit pull requests or issues on GitHub. 5 | 6 | # TimeTable 7 | 8 | [![Fdroid](https://img.shields.io/f-droid/v/com.asdoi.timetable.svg)]() 9 | [![Release](https://img.shields.io/badge/dynamic/json.svg?label=Release&url=https://gitlab.com/asdoi/TimeTable/-/jobs/artifacts/master/raw/badges.json?job=build_badges&query=release_tag&colorB=brightgreen&logo=gitlab)]() 10 | [![License](https://img.shields.io/badge/dynamic/json.svg?label=License&url=https://gitlab.com/api/v4/projects/19059184?license=true&query=license.key&colorB=yellow)]() 11 | [![Commits since last release](https://gitlab.com/asdoi/TimeTable/-/jobs/artifacts/master/raw/badges/commits_since_last_release.svg?job=build_badges)]() 12 | [![Commit activity](https://gitlab.com/asdoi/TimeTable/-/jobs/artifacts/master/raw/badges/commit_activity.svg?job=build_badges)]() 13 | [![Day the Repository has been created](https://gitlab.com/asdoi/TimeTable/-/jobs/artifacts/master/raw/badges/repository_creation_day.svg?job=build_badges)]() 14 | 15 | 16 | [Direct apk download](https://gitlab.com/asdoi/TimeTable/-/raw/master/app/release/app-release.apk)* 19 | 20 | 21 | Timetable is an Android Application, which allows you to save timetable, homeworks and notes.
22 | This is an improved version of the app from ulan17 .
23 | With this app you can manage your timetable, your homework, exams, teachers or notes.
24 | The app also automatically switches your phone to do-not-disturb mode during classes and back again afterwards.
25 | In addition, it always shows you a notification with your next subject.
26 | 27 | Some other features I added: 28 | 29 | 30 | ### Contribute 31 | 32 | You are welcome to contribute with issues, pull requests and ideas. And to contribute to this project, please fork the project and submit a pull request. 33 | 34 | ### Todo: 35 | - Add a print option 36 | - Backup all profiles 37 | - Rewrite Database to RoomDB 38 | - Rewrite class 'AlertDialogsHelper' 39 | 40 | ### Screenshots 41 | 1 screenshot      1 screenshot 42 |
43 | 1 screenshot     1 screenshot     1 screenshot 44 | 45 | *Made by smichel17 from LibreShift/red-moon 46 | 47 | ### License 48 | 49 | The source code is licensed under the [GNU v3 Public License](https://github.com/ulan17/TimeTable/blob/master/LICENSE). 50 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'com.mikepenz.aboutlibraries.plugin' 3 | apply plugin: 'kotlin-android' 4 | 5 | android { 6 | compileSdkVersion 29 7 | defaultConfig { 8 | applicationId "com.asdoi.timetable" 9 | minSdkVersion 21 10 | targetSdkVersion 29 11 | versionCode 17 12 | versionName "1.7" 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | vectorDrawables.useSupportLibrary = true 15 | } 16 | buildTypes { 17 | release { 18 | minifyEnabled true 19 | shrinkResources true 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | compileOptions { 24 | sourceCompatibility = JavaVersion.VERSION_1_8 25 | targetCompatibility = JavaVersion.VERSION_1_8 26 | } 27 | namespace 'com.ulan.timetable' 28 | buildToolsVersion '33.0.1' 29 | } 30 | 31 | dependencies { 32 | implementation 'androidx.appcompat:appcompat:1.3.0' 33 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 34 | implementation 'com.google.android.material:material:1.3.0' 35 | implementation 'androidx.constraintlayout:constraintlayout:2.1.2' 36 | implementation 'androidx.browser:browser:1.3.0' 37 | implementation 'androidx.preference:preference-ktx:1.1.1' 38 | implementation 'androidx.cardview:cardview:1.0.0' 39 | implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0" 40 | testImplementation 'junit:junit:4.13' 41 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 42 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 43 | 44 | implementation 'me.jfenn.ColorPickerDialog:base:0.2.2' 45 | implementation 'com.github.quwepiro:SQLite2XL:88883cf56d' 46 | implementation 'saschpe.android:customtabs:3.0.2' 47 | implementation "com.mikepenz:aboutlibraries:8.9.4" 48 | implementation 'com.github.stephenvinouze:shapetextdrawable:1.0.0' 49 | implementation 'com.github.Pradyuman7:ChocoBar:V1.7' 50 | implementation 'com.github.IamIsPra:Sheriff:1.0.2' 51 | implementation 'com.github.quwepiro:TimetableUI:master-SNAPSHOT' 52 | implementation 'com.github.quwepiro:TimetableView:master-SNAPSHOT' 53 | //noinspection NewerVersionAvailable,GradleDependency 54 | implementation 'org.apache.poi:poi:3.16' 55 | //noinspection GradleDependency 56 | implementation 'com.afollestad.material-dialogs:core:0.9.6' 57 | implementation 'com.afollestad.material-dialogs:commons:0.9.6.0' 58 | } -------------------------------------------------------------------------------- /app/proguard-rules-debug.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | -keep class .R 24 | -keep class **.R$* { 25 | ; 26 | } 27 | -keep public class org.apache.poi.hssf.** {*;} 28 | -keep public class org.apache.poi.ss.** {*;} 29 | -keep public class me.jfenn.colorpickerdialog.** {*;} 30 | -keep public class com.ulan.** {*;} -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | -keep class *.R 24 | -keep class **.R$* { 25 | ; 26 | } 27 | -keep public class org.apache.poi.hssf.** {*;} 28 | -keep public class org.apache.poi.ss.** {*;} 29 | -keep public class me.jfenn.colorpickerdialog.** {*;} 30 | -keep public class com.ulan.timetable.fragments.NotificationSettingsFragment 31 | -keep public class com.ulan.timetable.appwidget.** {*;} -------------------------------------------------------------------------------- /app/release/app-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flxholle/TimeTable/1ab7cd6d7f5f37fd149e7e36b8b37c01ce66f886/app/release/app-release.apk -------------------------------------------------------------------------------- /app/release/output-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "artifactType": { 4 | "type": "APK", 5 | "kind": "Directory" 6 | }, 7 | "applicationId": "com.asdoi.timetable", 8 | "variantName": "release", 9 | "elements": [ 10 | { 11 | "type": "SINGLE", 12 | "filters": [], 13 | "attributes": [], 14 | "versionCode": 17, 15 | "versionName": "1.7", 16 | "outputFile": "app-release.apk" 17 | } 18 | ], 19 | "elementType": "File" 20 | } -------------------------------------------------------------------------------- /app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flxholle/TimeTable/1ab7cd6d7f5f37fd149e7e36b8b37c01ce66f886/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/activities/ExamsActivity.java: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.activities; 2 | 3 | import android.os.Bundle; 4 | import android.util.SparseBooleanArray; 5 | import android.view.ActionMode; 6 | import android.view.Menu; 7 | import android.view.MenuInflater; 8 | import android.view.MenuItem; 9 | import android.view.View; 10 | import android.widget.AbsListView; 11 | import android.widget.ListView; 12 | 13 | import androidx.annotation.NonNull; 14 | import androidx.appcompat.app.AppCompatActivity; 15 | 16 | import com.ulan.timetable.R; 17 | import com.ulan.timetable.adapters.ExamsAdapter; 18 | import com.ulan.timetable.model.Exam; 19 | import com.ulan.timetable.utils.AlertDialogsHelper; 20 | import com.ulan.timetable.utils.DbHelper; 21 | import com.ulan.timetable.utils.PreferenceUtil; 22 | 23 | import java.util.ArrayList; 24 | import java.util.Objects; 25 | 26 | public class ExamsActivity extends AppCompatActivity { 27 | 28 | @NonNull 29 | private final AppCompatActivity context = this; 30 | private ListView listView; 31 | private ExamsAdapter adapter; 32 | private DbHelper db; 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | setTheme(PreferenceUtil.getGeneralTheme(this)); 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.activity_exams); 39 | initAll(); 40 | } 41 | 42 | private void initAll() { 43 | setupAdapter(); 44 | setupListViewMultiSelect(); 45 | setupCustomDialog(); 46 | } 47 | 48 | private void setupAdapter() { 49 | db = new DbHelper(context); 50 | listView = findViewById(R.id.examslist); 51 | adapter = new ExamsAdapter(db, ExamsActivity.this, listView, R.layout.listview_exams_adapter, db.getExam()); 52 | listView.setAdapter(adapter); 53 | } 54 | 55 | private void setupListViewMultiSelect() { 56 | listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); 57 | listView.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() { 58 | @Override 59 | public void onItemCheckedStateChanged(@NonNull ActionMode mode, int position, long id, boolean checked) { 60 | final int checkedCount = listView.getCheckedItemCount(); 61 | mode.setTitle(checkedCount + " " + getResources().getString(R.string.selected)); 62 | if (checkedCount == 0) mode.finish(); 63 | } 64 | 65 | @Override 66 | public boolean onCreateActionMode(@NonNull ActionMode mode, Menu menu) { 67 | MenuInflater menuInflater = mode.getMenuInflater(); 68 | menuInflater.inflate(R.menu.toolbar_action_mode, menu); 69 | return true; 70 | } 71 | 72 | @Override 73 | public boolean onPrepareActionMode(ActionMode mode, Menu menu) { 74 | return false; 75 | } 76 | 77 | @Override 78 | public boolean onActionItemClicked(@NonNull final ActionMode mode, @NonNull MenuItem item) { 79 | if (item.getItemId() == R.id.action_delete) { 80 | ArrayList removelist = new ArrayList<>(); 81 | SparseBooleanArray checkedItems = listView.getCheckedItemPositions(); 82 | for (int i = 0; i < checkedItems.size(); i++) { 83 | int key = checkedItems.keyAt(i); 84 | if (checkedItems.get(key)) { 85 | db.deleteExamById(Objects.requireNonNull(adapter.getItem(key))); 86 | removelist.add(adapter.getExamList().get(key)); 87 | } 88 | } 89 | adapter.getExamList().removeAll(removelist); 90 | db.updateExam(adapter.getExam()); 91 | adapter.notifyDataSetChanged(); 92 | mode.finish(); 93 | return true; 94 | } 95 | return false; 96 | } 97 | 98 | @Override 99 | public void onDestroyActionMode(ActionMode mode) { 100 | } 101 | }); 102 | } 103 | 104 | private void setupCustomDialog() { 105 | final View alertLayout = getLayoutInflater().inflate(R.layout.dialog_add_exam, null); 106 | AlertDialogsHelper.getAddExamDialog(db, ExamsActivity.this, alertLayout, adapter); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/activities/NoteInfoActivity.java: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.activities; 2 | 3 | import android.os.Bundle; 4 | import android.view.MenuItem; 5 | import android.widget.EditText; 6 | import android.widget.Toast; 7 | 8 | import androidx.annotation.NonNull; 9 | import androidx.annotation.Nullable; 10 | import androidx.appcompat.app.AppCompatActivity; 11 | 12 | import com.ulan.timetable.R; 13 | import com.ulan.timetable.model.Note; 14 | import com.ulan.timetable.utils.DbHelper; 15 | import com.ulan.timetable.utils.PreferenceUtil; 16 | 17 | import java.util.Objects; 18 | 19 | public class NoteInfoActivity extends AppCompatActivity { 20 | 21 | private DbHelper db; 22 | @Nullable 23 | private Note note; 24 | private EditText text; 25 | 26 | @Override 27 | protected void onCreate(Bundle savedInstanceState) { 28 | setTheme(PreferenceUtil.getGeneralTheme(this)); 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_note_info); 31 | setupIntent(); 32 | } 33 | 34 | private void setupIntent() { 35 | db = new DbHelper(NoteInfoActivity.this); 36 | note = (Note) getIntent().getSerializableExtra(NotesActivity.KEY_NOTE); 37 | text = findViewById(R.id.edittextNote); 38 | if (Objects.requireNonNull(note).getText() != null) { 39 | text.setText(note.getText()); 40 | } 41 | } 42 | 43 | @Override 44 | public void onBackPressed() { 45 | Objects.requireNonNull(note).setText(text.getText().toString()); 46 | db.updateNote(note); 47 | Toast.makeText(NoteInfoActivity.this, getResources().getString(R.string.saved), Toast.LENGTH_SHORT).show(); 48 | super.onBackPressed(); 49 | } 50 | 51 | @Override 52 | public boolean onOptionsItemSelected(@NonNull MenuItem item) { 53 | switch (item.getItemId()) { 54 | case android.R.id.home: 55 | Objects.requireNonNull(note).setText(text.getText().toString()); 56 | db.updateNote(note); 57 | Toast.makeText(NoteInfoActivity.this, getResources().getString(R.string.saved), Toast.LENGTH_SHORT).show(); 58 | super.onBackPressed(); 59 | return true; 60 | default: 61 | return super.onOptionsItemSelected(item); 62 | } 63 | 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/activities/ProfileActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Felix Hollederer 3 | * This file is part of GymWenApp. 4 | * 5 | * GymWenApp is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * GymWenApp is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with GymWenApp. If not, see . 17 | */ 18 | 19 | package com.ulan.timetable.activities; 20 | 21 | import android.content.Intent; 22 | import android.os.Bundle; 23 | 24 | import androidx.appcompat.app.AppCompatActivity; 25 | import androidx.fragment.app.FragmentManager; 26 | 27 | import com.ulan.timetable.R; 28 | import com.ulan.timetable.fragments.ProfileActivityFragment; 29 | import com.ulan.timetable.profiles.ProfileManagement; 30 | import com.ulan.timetable.utils.PreferenceUtil; 31 | 32 | public class ProfileActivity extends AppCompatActivity { 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | setTheme(PreferenceUtil.getGeneralTheme(this)); 37 | super.onCreate(savedInstanceState); 38 | 39 | setContentView(R.layout.activity_profile); 40 | 41 | FragmentManager fragmentManager = getSupportFragmentManager(); 42 | fragmentManager.beginTransaction().replace(R.id.fragment, new ProfileActivityFragment()).commit(); 43 | 44 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 45 | } 46 | 47 | @Override 48 | public void onBackPressed() { 49 | ProfileManagement.resetSelectedProfile(); 50 | ProfileManagement.checkPreferredProfile(); 51 | ProfileManagement.save(this, true); 52 | Intent i = new Intent(this, MainActivity.class); 53 | startActivity(i); 54 | finish(); 55 | } 56 | 57 | @Override 58 | public boolean onSupportNavigateUp() { 59 | onBackPressed(); 60 | return super.onSupportNavigateUp(); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/activities/SettingsActivity.java: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.activities; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | 6 | import androidx.appcompat.app.AppCompatActivity; 7 | import androidx.fragment.app.Fragment; 8 | import androidx.preference.Preference; 9 | import androidx.preference.PreferenceFragmentCompat; 10 | 11 | import com.ulan.timetable.R; 12 | import com.ulan.timetable.fragments.SettingsFragment; 13 | import com.ulan.timetable.utils.PreferenceUtil; 14 | 15 | import java.util.Objects; 16 | 17 | public class SettingsActivity extends AppCompatActivity implements PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { 18 | public static final String KEY_SEVEN_DAYS_SETTING = "sevendays"; 19 | public static final String KEY_SCHOOL_WEBSITE_SETTING = "schoolwebsite"; 20 | public static final String KEY_START_WEEK_ON_SUNDAY = "start_sunday"; 21 | 22 | public int loadedFragments = 0; 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | setTheme(PreferenceUtil.getGeneralTheme(this)); 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_settings); 29 | 30 | getSupportFragmentManager().beginTransaction() 31 | .replace(R.id.settings, new SettingsFragment()) 32 | .commit(); 33 | } 34 | 35 | @Override 36 | public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref) { 37 | // Instantiate the new Fragment 38 | final Bundle args = pref.getExtras(); 39 | final Fragment fragment = getSupportFragmentManager().getFragmentFactory().instantiate( 40 | getClassLoader(), 41 | pref.getFragment()); 42 | fragment.setArguments(args); 43 | fragment.setTargetFragment(caller, 0); 44 | // Replace the existing Fragment with the new Fragment 45 | getSupportFragmentManager().beginTransaction() 46 | .replace(R.id.settings, fragment) 47 | .addToBackStack(null) 48 | .commit(); 49 | 50 | try { 51 | Objects.requireNonNull(getSupportActionBar()).setTitle(pref.getTitle()); 52 | } catch (Exception ignore) { 53 | } 54 | return true; 55 | } 56 | 57 | @Override 58 | public void onBackPressed() { 59 | super.onBackPressed(); 60 | if (loadedFragments == 0) { 61 | startActivity(new Intent(this, MainActivity.class)); 62 | finish(); 63 | } else { 64 | loadedFragments--; 65 | try { 66 | Objects.requireNonNull(getSupportActionBar()).setTitle(R.string.settings); 67 | } catch (Exception ignore) { 68 | } 69 | } 70 | } 71 | 72 | @Override 73 | public boolean onSupportNavigateUp() { 74 | onBackPressed(); 75 | return true; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/activities/TimeSettingsActivity.java: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.activities; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidx.appcompat.app.AppCompatActivity; 6 | 7 | import com.ulan.timetable.R; 8 | import com.ulan.timetable.fragments.TimeSettingsFragment; 9 | import com.ulan.timetable.utils.PreferenceUtil; 10 | 11 | public class TimeSettingsActivity extends AppCompatActivity { 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | setTheme(PreferenceUtil.getGeneralTheme(this)); 16 | super.onCreate(savedInstanceState); 17 | setContentView(R.layout.activity_settings_time); 18 | 19 | getSupportFragmentManager().beginTransaction() 20 | .replace(R.id.settings, new TimeSettingsFragment()) 21 | .commit(); 22 | } 23 | 24 | @Override 25 | public void onBackPressed() { 26 | // startActivity(new Intent(this, SummaryActivity.class)); 27 | PreferenceUtil.setStartActivityShown(this, true); 28 | super.onBackPressed(); 29 | } 30 | 31 | @Override 32 | public boolean onSupportNavigateUp() { 33 | onBackPressed(); 34 | return super.onSupportNavigateUp(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/adapters/FragmentsTabAdapter.java: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.adapters; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.annotation.Nullable; 5 | import androidx.fragment.app.Fragment; 6 | import androidx.fragment.app.FragmentManager; 7 | import androidx.fragment.app.FragmentStatePagerAdapter; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * Created by Ulan on 05.09.2018. 14 | */ 15 | public class FragmentsTabAdapter extends FragmentStatePagerAdapter { 16 | 17 | private final List mFragmentList = new ArrayList<>(); 18 | private final List mFragmentTitleList = new ArrayList<>(); 19 | 20 | public FragmentsTabAdapter(@NonNull FragmentManager fm) { 21 | super(fm, FragmentsTabAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); 22 | } 23 | 24 | @NonNull 25 | @Override 26 | public Fragment getItem(int position) { 27 | return mFragmentList.get(position); 28 | } 29 | 30 | public void addFragment(Fragment fragment, String title) { 31 | mFragmentList.add(fragment); 32 | mFragmentTitleList.add(title); 33 | } 34 | 35 | @Nullable 36 | @Override 37 | public CharSequence getPageTitle(int position) { 38 | return mFragmentTitleList.get(position); 39 | } 40 | 41 | @Override 42 | public int getCount() { 43 | return mFragmentList.size(); 44 | } 45 | 46 | @Override 47 | public int getItemPosition(@NonNull Object object) { 48 | return POSITION_NONE; 49 | } 50 | 51 | @NonNull 52 | public List getFragmentList() { 53 | return mFragmentList; 54 | } 55 | 56 | public void removeFragment(Fragment fragment, int position) { 57 | mFragmentList.remove(position); 58 | mFragmentTitleList.remove(position); 59 | } 60 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/appwidget/AppWidgetConstants.java: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.appwidget; 2 | 3 | /** 4 | * From https://github.com/SubhamTyagi/TimeTable 5 | */ 6 | final class AppWidgetConstants { 7 | 8 | static final int TIME_STYLE_FIRST = 0; 9 | static final int TIME_STYLE_SECOND = 1; 10 | static final int TIME_STYLE_THIRD = 2; 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/appwidget/Dao/BaseDao.java: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.appwidget.Dao; 2 | 3 | import android.content.ContentValues; 4 | import android.database.Cursor; 5 | import android.database.sqlite.SQLiteDatabase; 6 | 7 | import androidx.annotation.NonNull; 8 | 9 | /** 10 | * From https://github.com/SubhamTyagi/TimeTable 11 | */ 12 | class BaseDao { 13 | 14 | /** 15 | * 插入 16 | * 17 | * @param db 数据库 18 | * @param tableName 要操作的表名 19 | * @param contentValues 表中个字段的键值对(键的名字要和表中字段名一致,区分大小写) 20 | */ 21 | static void insert(@NonNull SQLiteDatabase db, String tableName, ContentValues contentValues) { 22 | db.insert(tableName, null, contentValues); 23 | } 24 | 25 | /** 26 | * 插入或替换 27 | * 约束值不存在,进行插入 28 | * 约束值存在,新数据替换掉旧数据 29 | * 约束值:建表时UNIQUE规定的字段 30 | * 31 | * @param db 数据库 32 | * @param tableName 要操作的表名 33 | * @param contentValues 表中个字段的键值对(键的名字要和表中字段名一致,区分大小写) 34 | */ 35 | static void insertOrReplace(@NonNull SQLiteDatabase db, String tableName, ContentValues contentValues) { 36 | db.insertWithOnConflict(tableName, null, contentValues, SQLiteDatabase.CONFLICT_REPLACE); 37 | } 38 | 39 | /** 40 | * 插入或替换 41 | * 约束值不存在,进行插入 42 | * 约束值存在,则忽略 43 | * 约束值:建表时UNIQUE规定的字段 44 | * 45 | * @param db 数据库 46 | * @param tableName 要操作的表名 47 | * @param contentValues 表中个字段的键值对(键的名字要和表中字段名一致,区分大小写) 48 | */ 49 | static void insertOrIgnore(@NonNull SQLiteDatabase db, String tableName, ContentValues contentValues) { 50 | db.insertWithOnConflict(tableName, null, contentValues, SQLiteDatabase.CONFLICT_IGNORE); 51 | } 52 | 53 | /** 54 | * 删除 55 | * 56 | * @param db 数据库 57 | * @param tableName 要操作的表名 58 | * @param whereClause where条件 59 | * @param whereArgs where条件语句中的字段值 60 | */ 61 | static void delete(@NonNull SQLiteDatabase db, String tableName, String whereClause, String[] whereArgs) { 62 | db.delete(tableName, whereClause, whereArgs); 63 | } 64 | 65 | static int update(@NonNull SQLiteDatabase db, String tableName, ContentValues values, String whereClause, String[] whereArgs) { 66 | return db.update(tableName, values, whereClause, whereArgs); 67 | } 68 | 69 | /** 70 | * 查询 71 | * 72 | * @param db 数据库 73 | * @param tableName 要操作的表名 74 | * @param selection 条件语句,where部分 75 | * @param selectionArgs where语句中的字段值 76 | */ 77 | static Cursor query(@NonNull SQLiteDatabase db, String tableName, String selection, String[] selectionArgs) { 78 | return queryComplex(db, tableName, null, selection, selectionArgs, null, null, null, null); 79 | } 80 | 81 | /** 82 | * 复杂查询 83 | * 84 | * @param db 数据库 85 | * @param tableName 要操作的表名 86 | * @param columns 要获取的字段数组 87 | * @param selection 条件语句,where部分 88 | * @param selectionArgs where语句中的字段值 89 | * @param groupBy 与SQL中的group by语句一样 90 | * @param having group bu中的having语句 91 | * @param orderBy SQL中的排序语句 92 | * @param limit 限制返回的数据与偏移量 93 | */ 94 | static Cursor queryComplex(@NonNull SQLiteDatabase db, String tableName, String[] columns, String selection, String[] selectionArgs, String 95 | groupBy, String having, String orderBy, String limit) { 96 | return db.query(tableName, columns, selection, selectionArgs, groupBy, having, orderBy, limit); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/appwidget/Dao/DBManager.java: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.appwidget.Dao; 2 | 3 | import android.content.Context; 4 | import android.database.sqlite.SQLiteDatabase; 5 | 6 | import androidx.annotation.Nullable; 7 | 8 | import java.util.concurrent.atomic.AtomicInteger; 9 | 10 | /** 11 | * From https://github.com/SubhamTyagi/TimeTable 12 | */ 13 | class DBManager { 14 | 15 | private static final AtomicInteger sOpenCounter = new AtomicInteger(); 16 | 17 | static synchronized SQLiteDatabase getDb(Context context) { 18 | sOpenCounter.incrementAndGet(); 19 | return new DataBaseHelper(context).getWritableDatabase(); 20 | } 21 | 22 | 23 | static synchronized void close(@Nullable SQLiteDatabase database) { 24 | if (sOpenCounter.decrementAndGet() == 0) { 25 | if (database != null) { 26 | database.close(); 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/appwidget/Dao/DataBaseHelper.java: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.appwidget.Dao; 2 | 3 | import android.content.Context; 4 | import android.database.sqlite.SQLiteDatabase; 5 | import android.database.sqlite.SQLiteOpenHelper; 6 | 7 | import androidx.annotation.NonNull; 8 | 9 | /** 10 | * From https://github.com/SubhamTyagi/TimeTable 11 | */ 12 | class DataBaseHelper extends SQLiteOpenHelper { 13 | 14 | private static final String DB_NAME = "class_table.db"; 15 | private static final int DB_VERSION = 4; 16 | 17 | public DataBaseHelper(Context context) { 18 | super(context, DB_NAME, null, DB_VERSION); 19 | } 20 | 21 | @Override 22 | public void onCreate(@NonNull SQLiteDatabase db) { 23 | createTables(db); 24 | } 25 | 26 | @Override 27 | public void onUpgrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) { 28 | for (int version = oldVersion + 1; version <= newVersion; version++) { 29 | upgradeTo(db, version); 30 | } 31 | } 32 | 33 | private void upgradeTo(@NonNull SQLiteDatabase db, int version) { 34 | switch (version) { 35 | case 1: 36 | createTables(db); 37 | break; 38 | case 2: 39 | upgradeFrom1To2(db); 40 | break; 41 | case 3: 42 | upgradeFrom2To3(db); 43 | break; 44 | case 4: 45 | upgradeFrom3To4(db); 46 | break; 47 | default: 48 | throw new IllegalStateException("Don't know how to upgrade to " + version); 49 | } 50 | } 51 | 52 | private void upgradeFrom3To4(@NonNull SQLiteDatabase db) { 53 | db.execSQL("ALTER TABLE app_widget ADD profilePosition INTEGER DEFAULT 0;"); 54 | } 55 | 56 | private void upgradeFrom2To3(@NonNull SQLiteDatabase db) { 57 | db.execSQL("CREATE TABLE app_widget(_id INTEGER PRIMARY KEY AUTOINCREMENT , appWidgetId INTEGER , currentTime INTEGER , backgroundColor INTEGER DEFAULT -1 , timeStyle INTEGER DEFAULT -1 , weekStyle INTEGER DEFAULT -1 , UNIQUE(appWidgetId))"); 58 | } 59 | 60 | private void upgradeFrom1To2(@NonNull SQLiteDatabase db) { 61 | // table_1 表主键添加自增长 62 | db.execSQL("CREATE TEMPORARY TABLE table_1_backup(week INTEGER , section INTEGER , time INTEGER , startWeek INTEGER , endWeek INTEGER , doubleWeek INTEGER , course CHAR , classroom CHAR)"); 63 | db.execSQL("INSERT INTO table_1_backup SELECT week , section , time , startWeek , endWeek , doubleWeek , course , classroom FROM table_1"); 64 | db.execSQL("DROP TABLE table_1"); 65 | db.execSQL("CREATE TABLE table_1(_id INTEGER PRIMARY KEY AUTOINCREMENT , week INTEGER , section INTEGER , time INTEGER , startWeek INTEGER , endWeek INTEGER ,doubleWeek INTEGER , course CHAR , classroom CHAR)"); 66 | db.execSQL("INSERT INTO table_1 (week , section , time , startWeek , endWeek , doubleWeek , course , classroom) SELECT week , section , time , startWeek , endWeek , doubleWeek , course , classroom FROM table_1_backup"); 67 | db.execSQL("DROP TABLE table_1_backup"); 68 | 69 | // 创建 course_classroom 表 70 | db.execSQL("CREATE TABLE course_classroom(_id INTEGER PRIMARY KEY AUTOINCREMENT , course CHAR , classroom CHAR)"); 71 | // 初始化 course_classroom 表数据 72 | db.execSQL("INSERT OR IGNORE INTO course_classroom (course , classroom) SELECT course , classroom FROM table_1"); 73 | 74 | // 删除 table_2 表 75 | db.execSQL("DROP TABLE IF EXISTS table_2"); 76 | } 77 | 78 | private void createTables(@NonNull SQLiteDatabase db) { 79 | db.execSQL("CREATE TABLE app_widget(_id INTEGER PRIMARY KEY AUTOINCREMENT , appWidgetId INTEGER , currentTime INTEGER , backgroundColor INTEGER DEFAULT -1 , timeStyle INTEGER DEFAULT -1 , weekStyle INTEGER DEFAULT -1 , profilePosition INTEGER DEFAULT 0 , UNIQUE(appWidgetId))"); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/fragments/NotificationSettingsFragment.java: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.fragments; 2 | 3 | import android.app.AlarmManager; 4 | import android.app.TimePickerDialog; 5 | import android.os.Bundle; 6 | import android.widget.NumberPicker; 7 | 8 | import androidx.preference.Preference; 9 | import androidx.preference.PreferenceFragmentCompat; 10 | import androidx.preference.PreferenceManager; 11 | import androidx.preference.SwitchPreferenceCompat; 12 | 13 | import com.afollestad.materialdialogs.MaterialDialog; 14 | import com.ulan.timetable.R; 15 | import com.ulan.timetable.activities.SettingsActivity; 16 | import com.ulan.timetable.profiles.ProfileManagement; 17 | import com.ulan.timetable.receivers.DailyReceiver; 18 | import com.ulan.timetable.utils.PreferenceUtil; 19 | 20 | import java.util.Objects; 21 | 22 | 23 | public class NotificationSettingsFragment extends PreferenceFragmentCompat { 24 | 25 | @Override 26 | public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { 27 | setPreferencesFromResource(R.xml.settings_notification, rootKey); 28 | 29 | ((SettingsActivity) requireActivity()).loadedFragments++; 30 | 31 | setNotif(); 32 | Preference myPref = findPreference("timetableNotif"); 33 | Objects.requireNonNull(myPref).setOnPreferenceClickListener((Preference preference) -> { 34 | setNotif(); 35 | return true; 36 | }); 37 | 38 | SwitchPreferenceCompat reminderSwitch = findPreference("reminder"); 39 | Objects.requireNonNull(reminderSwitch).setSummary(getString(R.string.notification_reminder_settings_desc, "" + PreferenceUtil.getReminderTime(requireContext()))); 40 | Objects.requireNonNull(reminderSwitch).setOnPreferenceClickListener((Preference p) -> { 41 | if (reminderSwitch.isChecked()) { 42 | NumberPicker numberPicker = new NumberPicker(getContext()); 43 | int max = PreferenceUtil.getPeriodLength(requireContext()) - 2; 44 | numberPicker.setMaxValue(max <= 0 ? 2 : max); 45 | numberPicker.setMinValue(1); 46 | numberPicker.setValue(PreferenceUtil.getReminderTime(requireContext())); 47 | new MaterialDialog.Builder(requireContext()) 48 | .customView(numberPicker, false) 49 | .positiveText(R.string.select) 50 | .onPositive((d, w) -> { 51 | int value = numberPicker.getValue(); 52 | PreferenceUtil.setReminderTime(requireContext(), value); 53 | reminderSwitch.setSummary(getString(R.string.notification_reminder_settings_desc, "" + value)); 54 | }) 55 | .show(); 56 | } 57 | return true; 58 | }); 59 | 60 | 61 | myPref = findPreference("alarm"); 62 | Objects.requireNonNull(myPref).setOnPreferenceClickListener((Preference p) -> { 63 | int[] oldTimes = PreferenceUtil.getAlarmTime(getContext()); 64 | TimePickerDialog timePickerDialog = new TimePickerDialog(getActivity(), 65 | (view, hourOfDay, minute) -> { 66 | PreferenceUtil.setAlarmTime(requireContext(), hourOfDay, minute, 0); 67 | PreferenceUtil.setRepeatingAlarm(requireContext(), DailyReceiver.class, hourOfDay, minute, 0, DailyReceiver.DailyReceiverID, AlarmManager.INTERVAL_DAY); 68 | p.setSummary(hourOfDay + ":" + minute); 69 | }, oldTimes[0], oldTimes[1], true); 70 | timePickerDialog.setTitle(R.string.choose_time); 71 | timePickerDialog.show(); 72 | return true; 73 | }); 74 | int[] oldTimes = PreferenceUtil.getAlarmTime(getContext()); 75 | myPref.setSummary(oldTimes[0] + ":" + oldTimes[1]); 76 | 77 | } 78 | 79 | private void setNotif() { 80 | boolean show = PreferenceManager.getDefaultSharedPreferences(requireContext()).getBoolean("timetableNotif", true); 81 | findPreference("alwaysNotification").setVisible(show); 82 | findPreference("alarm").setVisible(show); 83 | findPreference("reminder").setVisible(show && ProfileManagement.isPreferredProfile()); 84 | findPreference("notification_end").setVisible(show && ProfileManagement.isPreferredProfile()); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/fragments/TimeSettingsFragment.java: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.fragments; 2 | 3 | import android.app.DatePickerDialog; 4 | import android.app.TimePickerDialog; 5 | import android.os.Bundle; 6 | import android.widget.NumberPicker; 7 | 8 | import androidx.preference.Preference; 9 | import androidx.preference.PreferenceFragmentCompat; 10 | 11 | import com.afollestad.materialdialogs.MaterialDialog; 12 | import com.ulan.timetable.R; 13 | import com.ulan.timetable.utils.PreferenceUtil; 14 | import com.ulan.timetable.utils.WeekUtils; 15 | 16 | import java.util.Calendar; 17 | import java.util.Date; 18 | import java.util.Objects; 19 | 20 | 21 | public class TimeSettingsFragment extends PreferenceFragmentCompat { 22 | 23 | @Override 24 | public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { 25 | setPreferencesFromResource(R.xml.settings_time, rootKey); 26 | 27 | Preference myPref = findPreference("start_time"); 28 | Objects.requireNonNull(myPref).setOnPreferenceClickListener((Preference p) -> { 29 | int[] oldTimes = PreferenceUtil.getStartTime(getContext()); 30 | TimePickerDialog timePickerDialog = new TimePickerDialog(getActivity(), 31 | (view, hourOfDay, minute) -> { 32 | PreferenceUtil.setStartTime(getContext(), hourOfDay, minute, 0); 33 | p.setSummary(hourOfDay + ":" + minute); 34 | }, oldTimes[0], oldTimes[1], true); 35 | timePickerDialog.setTitle(R.string.start_of_school); 36 | timePickerDialog.show(); 37 | return true; 38 | }); 39 | int[] oldTimes = PreferenceUtil.getStartTime(getContext()); 40 | myPref.setSummary(oldTimes[0] + ":" + oldTimes[1]); 41 | 42 | 43 | myPref = findPreference("set_period_length"); 44 | Objects.requireNonNull(myPref).setOnPreferenceClickListener((Preference p) -> { 45 | NumberPicker numberPicker = new NumberPicker(getContext()); 46 | numberPicker.setMaxValue(180); 47 | numberPicker.setMinValue(1); 48 | numberPicker.setValue(PreferenceUtil.getPeriodLength(getContext())); 49 | new MaterialDialog.Builder(requireContext()) 50 | .customView(numberPicker, false) 51 | .positiveText(R.string.select) 52 | .onPositive((d, w) -> { 53 | int value = numberPicker.getValue(); 54 | PreferenceUtil.setPeriodLength(getContext(), value); 55 | p.setSummary(value + " " + getString(R.string.minutes)); 56 | }) 57 | .show(); 58 | return true; 59 | }); 60 | myPref.setSummary(PreferenceUtil.getPeriodLength(getContext()) + " " + getString(R.string.minutes)); 61 | 62 | myPref = findPreference("two_weeks"); 63 | Objects.requireNonNull(myPref).setOnPreferenceClickListener((p) -> { 64 | setTermStartVisibility(); 65 | return true; 66 | }); 67 | 68 | setTermStartVisibility(); 69 | myPref = findPreference("term_start"); 70 | 71 | Calendar calendar = PreferenceUtil.getTermStart(requireContext()); 72 | 73 | Objects.requireNonNull(myPref).setTitle(getString(R.string.start_of_term) + " (" + WeekUtils.localizeDate(requireContext(), new Date(calendar.getTimeInMillis())) + ")"); 74 | myPref.setOnPreferenceClickListener((p) -> { 75 | Calendar calendar2 = PreferenceUtil.getTermStart(requireContext()); 76 | int mYear2 = calendar2.get(Calendar.YEAR); 77 | int mMonth2 = calendar2.get(Calendar.MONTH); 78 | int mDayofMonth2 = calendar2.get(Calendar.DAY_OF_MONTH); 79 | 80 | DatePickerDialog datePickerDialog = new DatePickerDialog(requireActivity(), (view, year, month, dayOfMonth) -> { 81 | PreferenceUtil.setTermStart(requireContext(), year, month, dayOfMonth); 82 | Calendar cal = Calendar.getInstance(); 83 | cal.set(Calendar.YEAR, year); 84 | cal.set(Calendar.MONTH, month); 85 | cal.set(Calendar.DAY_OF_MONTH, dayOfMonth); 86 | 87 | p.setTitle(getString(R.string.start_of_term) + " (" + WeekUtils.localizeDate(requireContext(), new Date(cal.getTimeInMillis())) + ")"); 88 | }, mYear2, mMonth2, mDayofMonth2); 89 | 90 | datePickerDialog.setTitle(R.string.choose_date); 91 | datePickerDialog.show(); 92 | return true; 93 | }); 94 | } 95 | 96 | private void setTermStartVisibility() { 97 | findPreference("term_start").setVisible(PreferenceUtil.isTwoWeeksEnabled(requireContext())); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/fragments/WeekdayFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Felix Hollederer 3 | * This file is part of GymWenApp. 4 | * 5 | * GymWenApp is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * GymWenApp is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with GymWenApp. If not, see . 17 | */ 18 | 19 | package com.ulan.timetable.fragments; 20 | 21 | import android.os.Bundle; 22 | import android.view.LayoutInflater; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | import android.widget.ListView; 26 | 27 | import androidx.annotation.NonNull; 28 | import androidx.annotation.Nullable; 29 | import androidx.appcompat.app.AppCompatActivity; 30 | import androidx.fragment.app.Fragment; 31 | 32 | import com.ulan.timetable.R; 33 | import com.ulan.timetable.adapters.WeekAdapter; 34 | import com.ulan.timetable.model.Week; 35 | import com.ulan.timetable.utils.DbHelper; 36 | import com.ulan.timetable.utils.FragmentHelper; 37 | 38 | import java.util.ArrayList; 39 | 40 | public class WeekdayFragment extends Fragment { 41 | public static final String KEY_MONDAY_FRAGMENT = "Monday"; 42 | public static final String KEY_TUESDAY_FRAGMENT = "Tuesday"; 43 | public static final String KEY_WEDNESDAY_FRAGMENT = "Wednesday"; 44 | public static final String KEY_THURSDAY_FRAGMENT = "Thursday"; 45 | public static final String KEY_FRIDAY_FRAGMENT = "Friday"; 46 | public static final String KEY_SATURDAY_FRAGMENT = "Saturday"; 47 | public static final String KEY_SUNDAY_FRAGMENT = "Sunday"; 48 | 49 | @Nullable 50 | private DbHelper db; 51 | private ListView listView; 52 | @Nullable 53 | private WeekAdapter adapter; 54 | private View view; 55 | 56 | private final String key; 57 | 58 | public WeekdayFragment(String key) { 59 | super(); 60 | this.key = key; 61 | } 62 | 63 | public WeekdayFragment() { 64 | super(); 65 | this.key = KEY_MONDAY_FRAGMENT; 66 | } 67 | 68 | @Override 69 | public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, 70 | Bundle savedInstanceState) { 71 | view = inflater.inflate(R.layout.fragment_weekday, container, false); 72 | return view; 73 | } 74 | 75 | @Override 76 | public void onStart() { 77 | super.onStart(); 78 | setupAdapter(view); 79 | setupListViewMultiSelect(); 80 | } 81 | 82 | private void setupAdapter(@NonNull View view) { 83 | db = new DbHelper(getActivity()); 84 | listView = view.findViewById(R.id.daylist); 85 | ArrayList weeks = db.getWeek(key); 86 | adapter = new WeekAdapter(db, (AppCompatActivity) requireActivity(), listView, 0, weeks); 87 | listView.setAdapter(adapter); 88 | } 89 | 90 | private void setupListViewMultiSelect() { 91 | listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); 92 | listView.setMultiChoiceModeListener(FragmentHelper.setupListViewMultiSelect((AppCompatActivity) getActivity(), listView, adapter, db)); 93 | } 94 | 95 | public String getKey() { 96 | return key; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/model/Exam.java: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.model; 2 | 3 | /** 4 | * Created by Ulan on 07.12.2018. 5 | */ 6 | public class Exam { 7 | private String subject, teacher, time, date, room; 8 | private int id, color; 9 | 10 | public Exam() {} 11 | 12 | public Exam(String subject, String teacher, String time, String date, String room, int color) { 13 | this.subject = subject; 14 | this.teacher = teacher; 15 | this.time = time; 16 | this.date = date; 17 | this.room = room; 18 | this.color = color; 19 | } 20 | 21 | public String getSubject() { 22 | return subject; 23 | } 24 | 25 | public void setSubject(String subject) { 26 | this.subject = subject; 27 | } 28 | 29 | public String getTeacher() { 30 | return teacher; 31 | } 32 | 33 | public void setTeacher(String teacher) { 34 | this.teacher = teacher; 35 | } 36 | 37 | public String getTime() { 38 | return time; 39 | } 40 | 41 | public void setTime(String time) { 42 | this.time = time; 43 | } 44 | 45 | public String getDate() { 46 | return date; 47 | } 48 | 49 | public void setDate(String date) { 50 | this.date = date; 51 | } 52 | 53 | public String getRoom() { 54 | return room; 55 | } 56 | 57 | public void setRoom(String room) { 58 | this.room = room; 59 | } 60 | 61 | public int getId() { 62 | return id; 63 | } 64 | 65 | public void setId(int id) { 66 | this.id = id; 67 | } 68 | 69 | public int getColor() { 70 | return color; 71 | } 72 | 73 | public void setColor(int color) { 74 | this.color = color; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/model/Homework.java: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.model; 2 | 3 | /** 4 | * Created by Ulan on 21.09.2018. 5 | */ 6 | public class Homework { 7 | private String subject, description, date; 8 | private int id, color; 9 | 10 | public Homework() {} 11 | 12 | public Homework(String subject, String description, String date, int color) { 13 | this.subject = subject; 14 | this.description = description; 15 | this.date = date; 16 | this.color = color; 17 | } 18 | public String getSubject() { 19 | return subject; 20 | } 21 | 22 | public void setSubject(String subject) { 23 | this.subject = subject; 24 | } 25 | 26 | public String getDescription() { 27 | return description; 28 | } 29 | 30 | public void setDescription(String description) { 31 | this.description = description; 32 | } 33 | 34 | public String getDate() { 35 | return date; 36 | } 37 | 38 | public void setDate(String date) { 39 | this.date = date; 40 | } 41 | 42 | public int getId() { 43 | return id; 44 | } 45 | 46 | public void setId(int id) { 47 | this.id = id; 48 | } 49 | 50 | public int getColor() { 51 | return color; 52 | } 53 | 54 | public void setColor(int color) { 55 | this.color = color; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/model/Note.java: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.model; 2 | 3 | 4 | import java.io.Serializable; 5 | 6 | /** 7 | * Created by Ulan on 28.09.2018. 8 | */ 9 | public class Note implements Serializable { 10 | private String title, text = ""; 11 | private int id, color; 12 | 13 | public Note() {} 14 | 15 | public Note(String title, String text, int color) { 16 | this.title = title; 17 | this.text = text; 18 | this.color = color; 19 | } 20 | 21 | public String getTitle() { 22 | return title; 23 | } 24 | 25 | public void setTitle(String title) { 26 | this.title = title; 27 | } 28 | 29 | public String getText() { 30 | return text; 31 | } 32 | 33 | public void setText(String text) { 34 | this.text = text; 35 | } 36 | 37 | public int getId() { 38 | return id; 39 | } 40 | 41 | public void setId(int id) { 42 | this.id = id; 43 | } 44 | 45 | public int getColor() { 46 | return color; 47 | } 48 | 49 | public void setColor(int color) { 50 | this.color = color; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/model/Teacher.java: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.model; 2 | 3 | /** 4 | * Created by Ulan on 07.10.2018. 5 | */ 6 | public class Teacher { 7 | private String name, post, phonenumber, email; 8 | private int id, color; 9 | 10 | public Teacher() { 11 | } 12 | public Teacher(String name, String post, String phonenumber, String email, int color) { 13 | this.name = name; 14 | this.post = post; 15 | this.phonenumber = phonenumber; 16 | this.email = email; 17 | this.color = color; 18 | } 19 | 20 | public String getName() { 21 | return name; 22 | } 23 | 24 | public void setName(String name) { 25 | this.name = name; 26 | } 27 | 28 | public String getPost() { 29 | return post; 30 | } 31 | 32 | public void setPost(String post) { 33 | this.post = post; 34 | } 35 | 36 | public String getPhonenumber() { 37 | return phonenumber; 38 | } 39 | 40 | public void setPhonenumber(String phonenumber) { 41 | this.phonenumber = phonenumber; 42 | } 43 | 44 | public String getEmail() { 45 | return email; 46 | } 47 | 48 | public void setEmail(String email) { 49 | this.email = email; 50 | } 51 | 52 | public int getId() { 53 | return id; 54 | } 55 | 56 | public void setId(int id) { 57 | this.id = id; 58 | } 59 | 60 | public int getColor() { 61 | return color; 62 | } 63 | 64 | public void setColor(int color) { 65 | this.color = color; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/model/Week.java: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.model; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | /** 6 | * Created by Ulan on 07.09.2018. 7 | */ 8 | public class Week { 9 | 10 | private String subject, fragment, teacher, room, fromtime, totime, time; 11 | private int id, color; 12 | 13 | public Week() {} 14 | 15 | public Week(String subject, String teacher, String room, String fromtime, String totime, int color) { 16 | this.subject = subject; 17 | this.teacher = teacher; 18 | this.room = room; 19 | this.fromtime = fromtime; 20 | this.totime = totime; 21 | this.color = color; 22 | } 23 | 24 | public int getId() { 25 | return id; 26 | } 27 | 28 | public void setId(int id) { 29 | this.id = id; 30 | } 31 | 32 | public String getFragment() { 33 | return fragment; 34 | } 35 | 36 | public void setFragment(String fragment) { 37 | this.fragment = fragment; 38 | } 39 | 40 | public String getFromTime() { 41 | return fromtime; 42 | } 43 | 44 | public void setFromTime(String fromtime) { 45 | this.fromtime = fromtime; 46 | } 47 | 48 | public String getToTime() { 49 | return totime; 50 | } 51 | 52 | public void setToTime(String totime) { 53 | this.totime = totime; 54 | } 55 | 56 | public String getRoom() { 57 | return room; 58 | } 59 | 60 | public void setRoom(String room) { 61 | this.room = room; 62 | } 63 | 64 | public String getSubject() { 65 | return subject; 66 | } 67 | 68 | public void setSubject(String subject) { 69 | this.subject = subject; 70 | } 71 | 72 | public String getTeacher() { 73 | return teacher; 74 | } 75 | 76 | public void setTeacher(String teacher) { 77 | this.teacher = teacher; 78 | } 79 | 80 | @NotNull 81 | public String toString() { 82 | return subject; 83 | } 84 | 85 | public String getTime() { 86 | return time; 87 | } 88 | 89 | public void setTime(String time) { 90 | this.time = time; 91 | } 92 | 93 | public int getColor() { 94 | return color; 95 | } 96 | 97 | public void setColor(int color) { 98 | this.color = color; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/profiles/Profile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Felix Hollederer 3 | * This file is part of GymWenApp. 4 | * 5 | * GymWenApp is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * GymWenApp is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with GymWenApp. If not, see . 17 | */ 18 | 19 | package com.ulan.timetable.profiles; 20 | 21 | 22 | import org.jetbrains.annotations.NotNull; 23 | 24 | public class Profile { 25 | private String name; 26 | 27 | public Profile(String name) { 28 | this.name = name; 29 | } 30 | 31 | public String getName() { 32 | return name; 33 | } 34 | 35 | private void setName(String name) { 36 | this.name = name; 37 | } 38 | 39 | @NotNull 40 | @Override 41 | public String toString() { 42 | return name; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/receivers/DailyReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Felix Hollederer 3 | * This file is part of GymWenApp. 4 | * 5 | * GymWenApp is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * GymWenApp is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with GymWenApp. If not, see . 17 | */ 18 | 19 | package com.ulan.timetable.receivers; 20 | 21 | import android.app.AlarmManager; 22 | import android.content.BroadcastReceiver; 23 | import android.content.Context; 24 | import android.content.Intent; 25 | 26 | import androidx.annotation.NonNull; 27 | 28 | import com.ulan.timetable.utils.NotificationUtil; 29 | import com.ulan.timetable.utils.PreferenceUtil; 30 | 31 | /** 32 | * Created by Ulan on 28.01.2019. 33 | */ 34 | public class DailyReceiver extends BroadcastReceiver { 35 | 36 | public static final int DailyReceiverID = 10000; 37 | 38 | @Override 39 | public void onReceive(@NonNull Context context, @NonNull Intent intent) { 40 | if (intent.getAction() != null) { 41 | if (intent.getAction().equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED)) { 42 | // Set the alarm here. 43 | if (PreferenceUtil.isAlarmOn(context)) { 44 | int[] times = PreferenceUtil.getAlarmTime(context); 45 | PreferenceUtil.setRepeatingAlarm(context, DailyReceiver.class, times[0], times[1], times[2], DailyReceiverID, AlarmManager.INTERVAL_DAY); 46 | } else 47 | PreferenceUtil.cancelAlarm(context, DailyReceiver.class, DailyReceiverID); 48 | NotificationUtil.sendNotificationSummary(context, false); 49 | return; 50 | } 51 | } 52 | 53 | if (!PreferenceUtil.isAlarmOn(context)) { 54 | PreferenceUtil.cancelAlarm(context, DailyReceiver.class, DailyReceiverID); 55 | } else { 56 | NotificationUtil.sendNotificationSummary(context, true); 57 | } 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/receivers/MidnightReceiver.kt: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.receivers 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import com.ulan.timetable.utils.PreferenceUtil 7 | 8 | class MidnightReceiver : BroadcastReceiver() { 9 | override fun onReceive(context: Context, intent: Intent) { 10 | if (intent.action != null) { 11 | if (intent.action.equals(Intent.ACTION_BOOT_COMPLETED, ignoreCase = true)) { 12 | PreferenceUtil.setOneTimeAlarm(context, MidnightReceiver::class.java, hour, minutes, 0, MidnightRecieverID) 13 | return 14 | } 15 | } 16 | 17 | val bootIntent = Intent() 18 | bootIntent.setAction(Intent.ACTION_BOOT_COMPLETED) 19 | val dailyReceiver = DailyReceiver() 20 | dailyReceiver.onReceive(context, bootIntent) 21 | val turnOnReceiver = TurnOnReceiver() 22 | turnOnReceiver.onReceive(context, bootIntent) 23 | PreferenceUtil.setOneTimeAlarm(context, MidnightReceiver::class.java, hour, minutes, 0, MidnightRecieverID) 24 | } 25 | 26 | companion object { 27 | val hour = 0 28 | val minutes = 15 29 | val MidnightRecieverID = 123155 30 | } 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/receivers/NotificationDismissButtonReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Felix Hollederer 3 | * This file is part of GymWenApp. 4 | * 5 | * GymWenApp is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * GymWenApp is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with GymWenApp. If not, see . 17 | */ 18 | 19 | package com.ulan.timetable.receivers; 20 | 21 | import android.app.NotificationManager; 22 | import android.content.BroadcastReceiver; 23 | import android.content.Context; 24 | import android.content.Intent; 25 | 26 | import androidx.annotation.NonNull; 27 | 28 | import java.util.Objects; 29 | 30 | public class NotificationDismissButtonReceiver extends BroadcastReceiver { 31 | public static final String EXTRA_NOTIFICATION_ID = "EXTRA_NOTIFICATION_ID"; 32 | 33 | @Override 34 | public void onReceive(@NonNull Context context, @NonNull Intent intent) { 35 | // if you want cancel notification 36 | int notificationId = intent.getIntExtra(EXTRA_NOTIFICATION_ID, 0); 37 | 38 | // if you want cancel notification 39 | NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 40 | Objects.requireNonNull(manager).cancel(notificationId); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/receivers/SubjectReminderReceiver.kt: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.receivers 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import com.ulan.timetable.profiles.ProfileManagement 7 | import com.ulan.timetable.utils.DbHelper 8 | import com.ulan.timetable.utils.NotificationUtil 9 | import com.ulan.timetable.utils.PreferenceUtil 10 | import java.util.* 11 | 12 | class SubjectReminderReceiver : BroadcastReceiver() { 13 | override fun onReceive(context: Context, intent: Intent) { 14 | setSubjectReminder(context) 15 | if (PreferenceUtil.isReminder(context)) 16 | NotificationUtil.sendNotificationCurrentLesson(context, true) 17 | } 18 | 19 | companion object { 20 | const val SubjectReminderID = 97000 21 | } 22 | } 23 | 24 | 25 | fun setSubjectReminder(context: Context) { 26 | ProfileManagement.initProfiles(context) 27 | if (!ProfileManagement.isPreferredProfile()) 28 | return 29 | Thread(Runnable { 30 | val dbHelper = DbHelper(context, ProfileManagement.getPreferredProfilePosition()) 31 | val calendar = Calendar.getInstance() 32 | val currentDay = NotificationUtil.getCurrentDay(calendar.get(Calendar.DAY_OF_WEEK)) 33 | val weeks = dbHelper.getWeek(currentDay) 34 | 35 | var lastCalendar = Calendar.getInstance() 36 | lastCalendar.set(Calendar.HOUR_OF_DAY, 23) 37 | lastCalendar.set(Calendar.MINUTE, 59) 38 | 39 | for (week in weeks) { 40 | val weekCalendarStart = Calendar.getInstance() 41 | val startHour = Integer.parseInt(week.fromTime.substring(0, week.fromTime.indexOf(":"))) 42 | weekCalendarStart.set(Calendar.HOUR_OF_DAY, startHour) 43 | val startMinute = Integer.parseInt(week.fromTime.substring(week.fromTime.indexOf(":") + 1)) 44 | weekCalendarStart.set(Calendar.MINUTE, startMinute) 45 | 46 | if (((startHour == calendar.get(Calendar.HOUR_OF_DAY) && startMinute > calendar.get(Calendar.MINUTE)) || startHour > calendar.get(Calendar.HOUR_OF_DAY)) && ((startHour == lastCalendar.get(Calendar.HOUR_OF_DAY) && startMinute < lastCalendar.get(Calendar.MINUTE)) || startHour < lastCalendar.get(Calendar.HOUR_OF_DAY))) { 47 | lastCalendar = weekCalendarStart 48 | } 49 | } 50 | 51 | if (lastCalendar.get(Calendar.HOUR_OF_DAY) == 23 && lastCalendar.get(Calendar.MINUTE) == 59) 52 | return@Runnable 53 | 54 | lastCalendar.add(Calendar.MINUTE, -PreferenceUtil.getReminderTime(context)) 55 | PreferenceUtil.setOneTimeAlarm(context, SubjectReminderReceiver::class.java, lastCalendar.get(Calendar.HOUR_OF_DAY), lastCalendar.get(Calendar.MINUTE), 0, SubjectReminderReceiver.SubjectReminderID) 56 | }).start() 57 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/utils/ColorPalette.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Felix Hollederer 3 | * This file is part of GymWenApp. 4 | * 5 | * GymWenApp is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * GymWenApp is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with GymWenApp. If not, see . 17 | */ 18 | 19 | package com.ulan.timetable.utils; 20 | 21 | import android.graphics.Color; 22 | 23 | /** 24 | * @author Aidan Follestad (afollestad) 25 | */ 26 | public class ColorPalette { 27 | 28 | public static final int[] PRIMARY_COLORS = 29 | new int[]{ 30 | Color.parseColor("#F44336"), 31 | Color.parseColor("#E91E63"), 32 | Color.parseColor("#9C27B0"), 33 | Color.parseColor("#673AB7"), 34 | Color.parseColor("#3F51B5"), 35 | Color.parseColor("#2196F3"), 36 | Color.parseColor("#03A9F4"), 37 | Color.parseColor("#00BCD4"), 38 | Color.parseColor("#009688"), 39 | Color.parseColor("#4CAF50"), 40 | Color.parseColor("#8BC34A"), 41 | Color.parseColor("#CDDC39"), 42 | Color.parseColor("#FFEB3B"), 43 | Color.parseColor("#FFC107"), 44 | Color.parseColor("#FF9800"), 45 | Color.parseColor("#FF5722"), 46 | Color.parseColor("#795548"), 47 | Color.parseColor("#9E9E9E"), 48 | Color.parseColor("#607D8B"), 49 | Color.parseColor("#000000"), 50 | Color.parseColor("#FFFFFF"), 51 | Color.parseColor("#FF0000"), 52 | Color.parseColor("#0000FF"), 53 | Color.parseColor("#00FF00"), 54 | Color.parseColor("#FF00FF"), 55 | Color.parseColor("#00FFFF"), 56 | Color.parseColor("#FFFF00") 57 | }; 58 | 59 | public static int pickTextColorBasedOnBgColorSimple(int bgColor, int lightColor, int darkColor) { 60 | String color = String.format("#%06X", (0xFFFFFF & bgColor)); 61 | color = color.substring(1, 7); 62 | int r = Integer.parseInt(color.substring(0, 2), 16); // hexToR 63 | int g = Integer.parseInt(color.substring(2, 4), 16); // hexToG 64 | int b = Integer.parseInt(color.substring(4, 6), 16); // hexToB 65 | return (((r * 0.299) + (g * 0.587) + (b * 0.114)) > 186) ? 66 | darkColor : lightColor; 67 | } 68 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/utils/FragmentHelper.java: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.utils; 2 | 3 | import android.util.SparseBooleanArray; 4 | import android.view.ActionMode; 5 | import android.view.Menu; 6 | import android.view.MenuInflater; 7 | import android.view.MenuItem; 8 | import android.widget.AbsListView; 9 | import android.widget.ListView; 10 | 11 | import androidx.annotation.NonNull; 12 | import androidx.appcompat.app.AppCompatActivity; 13 | 14 | import com.ulan.timetable.R; 15 | import com.ulan.timetable.adapters.WeekAdapter; 16 | import com.ulan.timetable.model.Week; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Objects; 20 | 21 | /** 22 | * Created by Ulan on 03.12.2018. 23 | */ 24 | public class FragmentHelper { 25 | 26 | @NonNull 27 | public static AbsListView.MultiChoiceModeListener setupListViewMultiSelect(@NonNull final AppCompatActivity activity, @NonNull final ListView listView, @NonNull final WeekAdapter adapter, @NonNull final DbHelper db) { 28 | return new AbsListView.MultiChoiceModeListener() { 29 | @Override 30 | public void onItemCheckedStateChanged(@NonNull ActionMode mode, int position, long id, boolean checked) { 31 | final int checkedCount = listView.getCheckedItemCount(); 32 | mode.setTitle(checkedCount + " " + activity.getResources().getString(R.string.selected)); 33 | if(checkedCount == 0) mode.finish(); 34 | } 35 | 36 | @Override 37 | public boolean onActionItemClicked(@NonNull final ActionMode mode, @NonNull MenuItem item) { 38 | switch (item.getItemId()) { 39 | case R.id.action_delete: 40 | ArrayList removelist = new ArrayList<>(); 41 | SparseBooleanArray checkedItems = listView.getCheckedItemPositions(); 42 | for (int i = 0; i < checkedItems.size(); i++) { 43 | int key = checkedItems.keyAt(i); 44 | if (checkedItems.get(key)) { 45 | db.deleteWeekById(Objects.requireNonNull(adapter.getItem(key))); 46 | removelist.add(adapter.getWeekList().get(key)); 47 | } 48 | } 49 | adapter.getWeekList().removeAll(removelist); 50 | db.updateWeek(adapter.getWeek()); 51 | adapter.notifyDataSetChanged(); 52 | mode.finish(); 53 | return true; 54 | 55 | default: 56 | return false; 57 | } 58 | } 59 | 60 | @Override 61 | public boolean onCreateActionMode(@NonNull ActionMode mode, Menu menu) { 62 | MenuInflater menuInflater = mode.getMenuInflater(); 63 | menuInflater.inflate(R.menu.toolbar_action_mode, menu); 64 | return true; 65 | } 66 | 67 | @Override 68 | public void onDestroyActionMode(ActionMode mode) { 69 | } 70 | 71 | @Override 72 | public boolean onPrepareActionMode(ActionMode mode, Menu menu) { 73 | return false; 74 | } 75 | }; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/utils/LinedEditText.java: -------------------------------------------------------------------------------- 1 | package com.ulan.timetable.utils; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.graphics.Rect; 8 | import android.util.AttributeSet; 9 | import android.widget.EditText; 10 | 11 | import androidx.annotation.NonNull; 12 | 13 | /** 14 | * Created by Ulan on 28.09.2018. 15 | */ 16 | @SuppressLint("AppCompatCustomView") 17 | public class LinedEditText extends EditText { 18 | @NonNull 19 | private final Rect mRect; 20 | @NonNull 21 | private final Paint mPaint; 22 | 23 | @SuppressLint("ResourceAsColor") 24 | public LinedEditText(Context context, AttributeSet attrs) { 25 | super(context, attrs); 26 | 27 | mRect = new Rect(); 28 | mPaint = new Paint(); 29 | mPaint.setStyle(Paint.Style.FILL_AND_STROKE); 30 | mPaint.setColor(PreferenceUtil.getTextColorSecondary(context)); 31 | } 32 | 33 | @Override 34 | protected void onDraw(@NonNull Canvas canvas) { 35 | 36 | int height = getHeight(); 37 | int line_height = getLineHeight(); 38 | 39 | int count = height / line_height; 40 | 41 | if (getLineCount() > count) 42 | count = getLineCount(); 43 | 44 | Rect r = mRect; 45 | Paint paint = mPaint; 46 | int baseline = getLineBounds(0, r); 47 | 48 | for (int i = 0; i < count; i++) { 49 | 50 | canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1, paint); 51 | baseline += getLineHeight(); 52 | } 53 | 54 | super.onDraw(canvas); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/ulan/timetable/utils/ShortcutUtils.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Felix Hollederer 3 | * This file is part of GymWenApp. 4 | * 5 | * GymWenApp is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * GymWenApp is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with GymWenApp. If not, see . 17 | */ 18 | 19 | package com.ulan.timetable.utils 20 | 21 | import android.content.Context 22 | import android.content.Intent 23 | import android.content.pm.ShortcutInfo 24 | import android.content.pm.ShortcutManager 25 | import android.graphics.Color 26 | import android.graphics.drawable.Icon 27 | import android.graphics.drawable.LayerDrawable 28 | import android.os.Build 29 | import androidx.annotation.RequiresApi 30 | import androidx.core.content.ContextCompat 31 | import androidx.core.graphics.drawable.toBitmap 32 | import com.ulan.timetable.R 33 | import com.ulan.timetable.activities.HomeworkActivity 34 | import com.ulan.timetable.activities.NotesActivity 35 | import com.ulan.timetable.activities.SummaryActivity 36 | 37 | 38 | @RequiresApi(25) 39 | class ShortcutUtils { 40 | 41 | companion object { 42 | fun createShortcuts(context: Context) { 43 | 44 | val shortcutManager = context.getSystemService(ShortcutManager::class.java) 45 | val shortcutList = mutableListOf() 46 | shortcutList.add(createAddHomeworkShortcut(context)) 47 | shortcutList.add(createNotesShortcut(context)) 48 | shortcutList.add(createSummaryShortcut(context)) 49 | 50 | shortcutManager!!.dynamicShortcuts = shortcutList 51 | } 52 | 53 | 54 | private const val size = 256 55 | private const val padding = 65 56 | private fun createShortcut(context: Context, id: String, shortLabel: String, iconId: Int, intent: Intent): ShortcutInfo { 57 | val icon = ContextCompat.getDrawable(context, iconId) 58 | icon?.setTint(Color.WHITE) 59 | 60 | val background = ContextCompat.getDrawable(context, R.drawable.shortcuts_background) 61 | val combined = LayerDrawable(arrayOf(background, icon)) 62 | combined.setLayerInset(1, padding, padding, padding, padding) 63 | 64 | val combinedIcon = if (Build.VERSION.SDK_INT > 25) Icon.createWithAdaptiveBitmap(combined.toBitmap(size, size)) else Icon.createWithBitmap(combined.toBitmap(size, size)) 65 | 66 | return ShortcutInfo.Builder(context, id) 67 | .setShortLabel(shortLabel) 68 | .setIcon(combinedIcon) 69 | .setIntent(intent) 70 | .build() 71 | } 72 | 73 | private fun createAddHomeworkShortcut(context: Context): ShortcutInfo { 74 | return createShortcut(context, "add_homework", context.getString(R.string.add_homework), R.drawable.ic_book_black_24dp, Intent(context, HomeworkActivity::class.java).setAction(HomeworkActivity.ACTION_ADD_HOMEWORK)) 75 | } 76 | 77 | private fun createNotesShortcut(context: Context): ShortcutInfo { 78 | return createShortcut(context, "open_notes", context.getString(R.string.notes_activity_title), R.drawable.ic_event_note_black_24dp, Intent(context, NotesActivity::class.java).setAction(NotesActivity.ACTION_SHOW)) 79 | } 80 | 81 | private fun createSummaryShortcut(context: Context): ShortcutInfo { 82 | return createShortcut(context, "summary", context.getString(R.string.summary_activity_title), R.drawable.ic_assignment_black_24dp, Intent(context, SummaryActivity::class.java).setAction(SummaryActivity.ACTION_SHOW)) 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/card_background_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/card_state_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/home_widget.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flxholle/TimeTable/1ab7cd6d7f5f37fd149e7e36b8b37c01ce66f886/app/src/main/res/drawable/home_widget.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_access_time_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_assignment_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_assignment_next_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_accessibility_new_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_coffee_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_notifications_active_24.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_person_add_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_save_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_settings_backup_restore_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_view_carousel_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_view_list_24.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_book_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_clear_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_close_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_delete_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_delete_forever_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_do_not_disturb_on_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_done_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 25 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_edit_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_email_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_event_note_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_expand_more_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_go.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_open_in_browser_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_palette_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_people_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_person_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_phone_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_restore.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_room_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_school_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_settings_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_star_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_star_border_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_view_week_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/launch_screen.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shortcuts_background.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 24 | 25 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/side_nav_bar.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 21 | 27 | 28 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_exams.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 16 | 17 | 24 | 25 | 26 | 27 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_homeworks.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 17 | 18 | 19 | 26 | 27 | 28 | 29 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 16 | 17 | 21 | 22 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_note_info.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_notes.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 19 | 20 | 27 | 28 | 29 | 30 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_profile.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 23 | 24 | 28 | 29 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_settings.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 23 | 24 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_settings_time.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_summary.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_teachers.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 24 | 25 | 26 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/app_bar_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 22 | 23 | 32 | 33 | 40 | 41 | 59 | 60 | 61 | 62 | 63 | 66 | 67 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/day_appwidget.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 21 | 22 | 27 | 28 | 34 | 35 | 43 | 44 | 45 | 51 | 52 | 61 | 62 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog_add_note.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 22 | 23 | 31 | 32 | 33 | 38 | 39 |