[
  {
    "path": ".gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/*\n/.idea/caches\n/.idea/libraries\n/.idea/modules.xml\n/.idea/tasks.xml\n/.idea/workspace.xml\n/.idea/navEditor.xml\n/.idea/assetWizardSettings.xml\n/app/build/\n/app/release/\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n.cxx\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright 2023, Isaiah Collins Abetong\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Fokus - To Do app tailored specifically for students\r\n[![License](https://img.shields.io/github/license/icabetong/fokus-android)](https://www.gnu.org/licenses/gpl-3.0.en.html)\r\n![Issues](https://img.shields.io/github/issues/icabetong/fokus-android)\r\n![PRs](https://img.shields.io/github/issues-pr/icabetong/fokus-android)\r\n\r\nFokus is an open source application that combines a todo list and a calendar that can help you manage your school related work and events in one place. It's fast and beautiful yet simple design that can help you focus on what matters most.\r\n\r\n### Not maintained anymore. \r\nI cannot maintain this project anymore due to my full time work. If you want to continue it's development, you can fork this repository and continue maintaining the application. Thank you for using my simple application.\r\n\r\n## Features\r\n\r\n* Get reminded when a task is nearing its due\r\n* Get reminded about incoming events\r\n* Add attachments to your tasks\r\n* Persistent notifications for important tasks or events\r\n* No ads or any tracking\r\n* Open Source Code\r\n* On-Device Database\r\n\r\n## Screenshots\r\n\r\n<img src=\"art/preview-1.jpeg\" width=\"200\"><img src=\"art/preview-2.jpeg\" width=\"200\"><img src=\"art/preview-3.jpeg\" width=\"200\"><img src=\"art/preview-4.jpeg\" width=\"200\">\r\n\r\n*Our preview mockups were created using 'Previewed' at https://previewed.app*\r\n\r\n## Translations\r\n\r\n* 🇮🇶 Arabic (Thanks! Mustafa K. Mirza)\r\n* 🇺🇸 English\r\n* 🇩🇪 German (Thanks! [mschmidm](https://github.com/mschmidm))\r\n* 🇫🇷 French (Thanks! David Simon)\r\n* 🇪🇸 Spanish (Thanks! Emmanuel Kunst)\r\n* 🇷🇺 Russian\r\n* 🇮🇩 Indonesian (Thanks! [Ilham Syahid S](https://github.com/ilhamsyahids))\r\n* 🇹🇷 Turkish (Thanks! [Ahmet YÜREKLİ](https://github.com/vedfi))\r\n\r\n## Built with\r\n\r\n* Kotlin\r\n* Room\r\n* AndroidX\r\n* Other cool open-source libraries (see Acknowledgements)\r\n\r\n## Versioning\r\n\r\nWe use [SemVer](http://www.semver.org) for versioning. For the versions available, see the [tags on this repository](https://github.com/asayah-san/fokus-android/tags)\r\n\r\n## Licenses\r\n\r\nThis project is licensed under the GPL-3.0 - see the license file for more details\r\n\r\n## Contributing\r\n\r\nThis is an open-source personal project and I am very happy to accept community contributions. Open a PR to get started.\r\n\r\n## Acknowledgements\r\n\r\n### Libraries used\r\n\r\n* [Material Dialogs](https://github.com/afollestad/material-dialogs)\r\n* [Konfetti](https://github.com/DanielMartinus/Konfetti)\r\n* [ExpandableBottomBar](https://github.com/st235/ExpandableBottomBar)\r\n* [CommonsIO](https://commons.apache.org/proper/commons-io/)\r\n* [Moshi](https://github.com/square/moshi)\r\n* [Okio](https://github.com/square/okio)\r\n* [CalendarView](https://github.com/kizitonwose/CalendarView)\r\n* [AboutLibraries](https://github.com/mikepenz/AboutLibraries)\r\n* [Cascade](https://github.com/saket/cascade)\r\n\r\n### Other materials used\r\n\r\n* [HeroIcons](https://www.heroicons.dev) - Tailwind Labs\r\n* [Launcher Icon](https://www.flaticon.com/authors/freepik) - Freepik via Flaticon\r\n* [Notification Sound](https://www.zapsplat.com/music/ui-alert-prompt-warm-wooden-mallet-style-notification-tone-generic-11/) - Zapsplat\r\n"
  },
  {
    "path": "app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "app/build.gradle",
    "content": "plugins {\r\n    id 'com.android.application'\r\n    id 'kotlin-android'\r\n    id 'kotlin-kapt'\r\n    id 'kotlin-parcelize'\r\n    id 'com.mikepenz.aboutlibraries.plugin'\r\n    id 'dagger.hilt.android.plugin'\r\n}\r\n\r\nandroid {\r\n    compileSdkVersion 33\r\n    buildToolsVersion \"33.0.0\"\r\n\r\n    defaultConfig {\r\n        applicationId \"com.isaiahvonrundstedt.fokus\"\r\n        minSdkVersion 21\r\n        targetSdkVersion 33\r\n        versionCode 19\r\n        versionName \"2.5.0\"\r\n        testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"\r\n    }\r\n    buildTypes {\r\n        release {\r\n            minifyEnabled true\r\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\r\n        }\r\n    }\r\n    buildFeatures {\r\n        viewBinding true\r\n    }\r\n    composeOptions {\r\n        kotlinCompilerExtensionVersion = \"1.1.0-beta02\"\r\n    }\r\n    compileOptions {\r\n        coreLibraryDesugaringEnabled true\r\n        sourceCompatibility JavaVersion.VERSION_1_8\r\n        targetCompatibility JavaVersion.VERSION_1_8\r\n    }\r\n    kotlinOptions {\r\n        jvmTarget = JavaVersion.VERSION_1_8\r\n    }\r\n    kapt {\r\n        correctErrorTypes true\r\n    }\r\n}\r\n\r\ndependencies {\r\n    implementation fileTree(dir: 'libs', include: ['*.jar'])\r\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version\"\r\n\r\n    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.6'\r\n\r\n    implementation 'com.google.android.material:material:1.6.1'\r\n    implementation 'com.afollestad.material-dialogs:core:3.3.0'\r\n    implementation 'com.afollestad.material-dialogs:color:3.3.0'\r\n    implementation 'com.afollestad.material-dialogs:datetime:3.3.0'\r\n    implementation 'com.afollestad.material-dialogs:lifecycle:3.3.0'\r\n    implementation 'com.github.kizitonwose:CalendarView:1.0.3'\r\n    implementation 'nl.dionsegijn:konfetti-xml:2.0.2'\r\n    implementation 'commons-io:commons-io:2.7'\r\n    implementation 'com.mikepenz:aboutlibraries-core:8.9.4'\r\n    implementation 'me.saket.cascade:cascade:1.3.0'\r\n    implementation 'io.coil-kt:coil:1.2.2'\r\n    implementation 'com.squareup.okio:okio:2.10.0'\r\n    implementation 'com.github.chrisbanes:PhotoView:2.3.0'\r\n    implementation 'com.google.accompanist:accompanist-insets:0.20.2'\r\n\r\n    implementation 'androidx.appcompat:appcompat:1.4.2'\r\n    implementation 'androidx.browser:browser:1.4.0'\r\n    implementation 'androidx.fragment:fragment-ktx:1.5.0'\r\n    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'\r\n    implementation 'androidx.core:core-ktx:1.8.0'\r\n    implementation 'androidx.legacy:legacy-support-v4:1.0.0'\r\n    implementation 'androidx.navigation:navigation-fragment-ktx:2.5.0'\r\n    implementation 'androidx.navigation:navigation-ui-ktx:2.5.0'\r\n    implementation \"androidx.navigation:navigation-compose:2.5.0\"\r\n    implementation 'androidx.preference:preference-ktx:1.2.0'\r\n    implementation 'androidx.recyclerview:recyclerview:1.2.1'\r\n    implementation 'androidx.transition:transition:1.4.1'\r\n    implementation 'androidx.work:work-runtime-ktx:2.7.1'\r\n\r\n    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'\r\n    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.0'\r\n    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.0'\r\n    kapt 'androidx.lifecycle:lifecycle-common-java8:2.5.0'\r\n\r\n    implementation 'androidx.room:room-runtime:2.4.2'\r\n    implementation 'androidx.room:room-ktx:2.4.2'\r\n    kapt 'androidx.room:room-compiler:2.4.2'\r\n\r\n    implementation 'androidx.hilt:hilt-navigation-compose:1.0.0'\r\n    implementation 'androidx.hilt:hilt-work:1.0.0'\r\n    kapt 'androidx.hilt:hilt-compiler:1.0.0'\r\n\r\n    implementation 'com.google.dagger:hilt-android:2.42'\r\n    kapt 'com.google.dagger:hilt-android-compiler:2.42'\r\n\r\n    implementation 'com.squareup.moshi:moshi:1.13.0'\r\n    implementation 'com.squareup.moshi:moshi-kotlin:1.13.0'\r\n    kapt 'com.squareup.moshi:moshi-kotlin-codegen:1.13.0'\r\n\r\n    testImplementation 'junit:junit:4.13.2'\r\n    androidTestImplementation 'androidx.test.ext:junit:1.1.3'\r\n    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'\r\n}"
  },
  {
    "path": "app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\r\n# You can control the set of applied configuration files using the\r\n# proguardFiles setting in build.gradle.\r\n#\r\n# For more details, see\r\n#   http://developer.android.com/guide/developing/tools/proguard.html\r\n\r\n# If your project uses WebView with JS, uncomment the following\r\n# and specify the fully qualified class name to the JavaScript interface\r\n# class:\r\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\r\n#   public *;\r\n#}\r\n\r\n# Uncomment this to preserve the line number information for\r\n# debugging stack traces.\r\n#-keepattributes SourceFile,LineNumberTable\r\n\r\n# If you keep the line number information, uncomment this to\r\n# hide the original source file name.\r\n#-renamesourcefileattribute SourceFile\r\n-keep class *.R\r\n-keep class **.R$* {\r\n    <fields>;\r\n}"
  },
  {
    "path": "app/schemas/com.isaiahvonrundstedt.fokus.database.AppDatabase/8.json",
    "content": "{\n  \"formatVersion\": 1,\n  \"database\": {\n    \"version\": 8,\n    \"identityHash\": \"a5a325b51a216bf9c8987bdd216bf28b\",\n    \"entities\": [\n      {\n        \"tableName\": \"subjects\",\n        \"createSql\": \"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`subjectID` TEXT NOT NULL, `code` TEXT, `description` TEXT, `instructor` TEXT, `tag` INTEGER NOT NULL, `isSubjectArchived` INTEGER NOT NULL, PRIMARY KEY(`subjectID`))\",\n        \"fields\": [\n          {\n            \"fieldPath\": \"subjectID\",\n            \"columnName\": \"subjectID\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"code\",\n            \"columnName\": \"code\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"description\",\n            \"columnName\": \"description\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"instructor\",\n            \"columnName\": \"instructor\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"tag\",\n            \"columnName\": \"tag\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"isSubjectArchived\",\n            \"columnName\": \"isSubjectArchived\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          }\n        ],\n        \"primaryKey\": {\n          \"columnNames\": [\n            \"subjectID\"\n          ],\n          \"autoGenerate\": false\n        },\n        \"indices\": [\n          {\n            \"name\": \"index_subjects_subjectID\",\n            \"unique\": false,\n            \"columnNames\": [\n              \"subjectID\"\n            ],\n            \"orders\": [],\n            \"createSql\": \"CREATE INDEX IF NOT EXISTS `index_subjects_subjectID` ON `${TABLE_NAME}` (`subjectID`)\"\n          }\n        ],\n        \"foreignKeys\": []\n      },\n      {\n        \"tableName\": \"tasks\",\n        \"createSql\": \"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`taskID` TEXT NOT NULL, `name` TEXT, `notes` TEXT, `subject` TEXT, `isImportant` INTEGER NOT NULL, `dueDate` TEXT, `isFinished` INTEGER NOT NULL, `isTaskArchived` INTEGER NOT NULL, `dateAdded` TEXT, PRIMARY KEY(`taskID`), FOREIGN KEY(`subject`) REFERENCES `subjects`(`subjectID`) ON UPDATE NO ACTION ON DELETE SET NULL )\",\n        \"fields\": [\n          {\n            \"fieldPath\": \"taskID\",\n            \"columnName\": \"taskID\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"name\",\n            \"columnName\": \"name\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"notes\",\n            \"columnName\": \"notes\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"subject\",\n            \"columnName\": \"subject\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"isImportant\",\n            \"columnName\": \"isImportant\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"dueDate\",\n            \"columnName\": \"dueDate\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"isFinished\",\n            \"columnName\": \"isFinished\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"isTaskArchived\",\n            \"columnName\": \"isTaskArchived\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"dateAdded\",\n            \"columnName\": \"dateAdded\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          }\n        ],\n        \"primaryKey\": {\n          \"columnNames\": [\n            \"taskID\"\n          ],\n          \"autoGenerate\": false\n        },\n        \"indices\": [\n          {\n            \"name\": \"index_tasks_taskID\",\n            \"unique\": false,\n            \"columnNames\": [\n              \"taskID\"\n            ],\n            \"orders\": [],\n            \"createSql\": \"CREATE INDEX IF NOT EXISTS `index_tasks_taskID` ON `${TABLE_NAME}` (`taskID`)\"\n          }\n        ],\n        \"foreignKeys\": [\n          {\n            \"table\": \"subjects\",\n            \"onDelete\": \"SET NULL\",\n            \"onUpdate\": \"NO ACTION\",\n            \"columns\": [\n              \"subject\"\n            ],\n            \"referencedColumns\": [\n              \"subjectID\"\n            ]\n          }\n        ]\n      },\n      {\n        \"tableName\": \"attachments\",\n        \"createSql\": \"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`attachmentID` TEXT NOT NULL, `name` TEXT, `target` TEXT, `task` TEXT NOT NULL, `type` INTEGER NOT NULL, `dateAttached` TEXT, PRIMARY KEY(`attachmentID`), FOREIGN KEY(`task`) REFERENCES `tasks`(`taskID`) ON UPDATE NO ACTION ON DELETE CASCADE )\",\n        \"fields\": [\n          {\n            \"fieldPath\": \"attachmentID\",\n            \"columnName\": \"attachmentID\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"name\",\n            \"columnName\": \"name\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"target\",\n            \"columnName\": \"target\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"task\",\n            \"columnName\": \"task\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"type\",\n            \"columnName\": \"type\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"dateAttached\",\n            \"columnName\": \"dateAttached\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          }\n        ],\n        \"primaryKey\": {\n          \"columnNames\": [\n            \"attachmentID\"\n          ],\n          \"autoGenerate\": false\n        },\n        \"indices\": [],\n        \"foreignKeys\": [\n          {\n            \"table\": \"tasks\",\n            \"onDelete\": \"CASCADE\",\n            \"onUpdate\": \"NO ACTION\",\n            \"columns\": [\n              \"task\"\n            ],\n            \"referencedColumns\": [\n              \"taskID\"\n            ]\n          }\n        ]\n      },\n      {\n        \"tableName\": \"logs\",\n        \"createSql\": \"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`logID` TEXT NOT NULL, `title` TEXT, `content` TEXT, `data` TEXT, `type` INTEGER NOT NULL, `isImportant` INTEGER NOT NULL, `dateTimeTriggered` TEXT, PRIMARY KEY(`logID`))\",\n        \"fields\": [\n          {\n            \"fieldPath\": \"logID\",\n            \"columnName\": \"logID\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"title\",\n            \"columnName\": \"title\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"content\",\n            \"columnName\": \"content\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"data\",\n            \"columnName\": \"data\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"type\",\n            \"columnName\": \"type\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"isImportant\",\n            \"columnName\": \"isImportant\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"dateTimeTriggered\",\n            \"columnName\": \"dateTimeTriggered\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          }\n        ],\n        \"primaryKey\": {\n          \"columnNames\": [\n            \"logID\"\n          ],\n          \"autoGenerate\": false\n        },\n        \"indices\": [],\n        \"foreignKeys\": []\n      },\n      {\n        \"tableName\": \"events\",\n        \"createSql\": \"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`eventID` TEXT NOT NULL, `name` TEXT, `notes` TEXT, `location` TEXT, `subject` TEXT, `isImportant` INTEGER NOT NULL, `isEventArchived` INTEGER NOT NULL, `schedule` TEXT, `dateAdded` TEXT, PRIMARY KEY(`eventID`), FOREIGN KEY(`subject`) REFERENCES `subjects`(`subjectID`) ON UPDATE NO ACTION ON DELETE SET NULL )\",\n        \"fields\": [\n          {\n            \"fieldPath\": \"eventID\",\n            \"columnName\": \"eventID\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"name\",\n            \"columnName\": \"name\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"notes\",\n            \"columnName\": \"notes\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"location\",\n            \"columnName\": \"location\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"subject\",\n            \"columnName\": \"subject\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"isImportant\",\n            \"columnName\": \"isImportant\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"isEventArchived\",\n            \"columnName\": \"isEventArchived\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"schedule\",\n            \"columnName\": \"schedule\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"dateAdded\",\n            \"columnName\": \"dateAdded\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          }\n        ],\n        \"primaryKey\": {\n          \"columnNames\": [\n            \"eventID\"\n          ],\n          \"autoGenerate\": false\n        },\n        \"indices\": [],\n        \"foreignKeys\": [\n          {\n            \"table\": \"subjects\",\n            \"onDelete\": \"SET NULL\",\n            \"onUpdate\": \"NO ACTION\",\n            \"columns\": [\n              \"subject\"\n            ],\n            \"referencedColumns\": [\n              \"subjectID\"\n            ]\n          }\n        ]\n      },\n      {\n        \"tableName\": \"schedules\",\n        \"createSql\": \"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`scheduleID` TEXT NOT NULL, `classroom` TEXT, `daysOfWeek` INTEGER NOT NULL, `weeksOfMonth` INTEGER NOT NULL, `startTime` TEXT, `endTime` TEXT, `subject` TEXT, PRIMARY KEY(`scheduleID`), FOREIGN KEY(`subject`) REFERENCES `subjects`(`subjectID`) ON UPDATE NO ACTION ON DELETE CASCADE )\",\n        \"fields\": [\n          {\n            \"fieldPath\": \"scheduleID\",\n            \"columnName\": \"scheduleID\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"classroom\",\n            \"columnName\": \"classroom\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"daysOfWeek\",\n            \"columnName\": \"daysOfWeek\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"weeksOfMonth\",\n            \"columnName\": \"weeksOfMonth\",\n            \"affinity\": \"INTEGER\",\n            \"notNull\": true\n          },\n          {\n            \"fieldPath\": \"startTime\",\n            \"columnName\": \"startTime\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"endTime\",\n            \"columnName\": \"endTime\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          },\n          {\n            \"fieldPath\": \"subject\",\n            \"columnName\": \"subject\",\n            \"affinity\": \"TEXT\",\n            \"notNull\": false\n          }\n        ],\n        \"primaryKey\": {\n          \"columnNames\": [\n            \"scheduleID\"\n          ],\n          \"autoGenerate\": false\n        },\n        \"indices\": [],\n        \"foreignKeys\": [\n          {\n            \"table\": \"subjects\",\n            \"onDelete\": \"CASCADE\",\n            \"onUpdate\": \"NO ACTION\",\n            \"columns\": [\n              \"subject\"\n            ],\n            \"referencedColumns\": [\n              \"subjectID\"\n            ]\n          }\n        ]\n      }\n    ],\n    \"views\": [],\n    \"setupQueries\": [\n      \"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)\",\n      \"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'a5a325b51a216bf9c8987bdd216bf28b')\"\n    ]\n  }\n}"
  },
  {
    "path": "app/src/androidTest/java/com/isaiahvonrundstedt/fokus/ExampleInstrumentedTest.kt",
    "content": "package com.isaiahvonrundstedt.fokus\r\n\r\nimport androidx.test.platform.app.InstrumentationRegistry\r\nimport androidx.test.ext.junit.runners.AndroidJUnit4\r\n\r\nimport org.junit.Test\r\nimport org.junit.runner.RunWith\r\n\r\nimport org.junit.Assert.*\r\n\r\n/**\r\n * Instrumented test, which will execute on an Android device.\r\n *\r\n * See [testing documentation](http://d.android.com/tools/testing).\r\n */\r\n@RunWith(AndroidJUnit4::class)\r\nclass ExampleInstrumentedTest {\r\n    @Test\r\n    fun useAppContext() {\r\n        // Context of the app under test.\r\n        val appContext = InstrumentationRegistry.getInstrumentation().targetContext\r\n        assertEquals(\"com.isaiahvonrundstedt.digitaloasis\", appContext.packageName)\r\n    }\r\n}\r\n"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:tools=\"http://schemas.android.com/tools\"\r\n    package=\"com.isaiahvonrundstedt.fokus\">\r\n\r\n    <uses-permission android:name=\"android.permission.WAKE_LOCK\"/>\r\n    <uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" />\r\n    <uses-permission android:name=\"android.permission.FOREGROUND_SERVICE\"/>\r\n    <uses-permission android:name=\"android.permission.POST_NOTIFICATIONS\"/>\r\n\r\n    <queries>\r\n        <intent>\r\n            <action android:name=\"android.intent.action.VIEW\"/>\r\n            <category android:name=\"android.intent.category.BROWSABLE\" />\r\n            <data android:scheme=\"content\"/>\r\n        </intent>\r\n\r\n        <intent>\r\n            <action android:name=\"android.intent.action.VIEW\"/>\r\n            <category android:name=\"android.intent.category.BROWSABLE\"/>\r\n            <data android:scheme=\"http\"/>\r\n        </intent>\r\n\r\n        <intent>\r\n            <action android:name=\"android.intent.action.VIEW\"/>\r\n            <category android:name=\"android.intent.category.BROWSABLE\"/>\r\n            <data android:scheme=\"https\"/>\r\n        </intent>\r\n    </queries>\r\n\r\n    <application\r\n        android:name=\".Fokus\"\r\n        android:allowBackup=\"false\"\r\n        android:icon=\"@mipmap/ic_launcher\"\r\n        android:label=\"@string/app_name\"\r\n        android:supportsRtl=\"true\"\r\n        android:theme=\"@style/Fokus.Theme.Core\">\r\n\r\n        <provider\r\n            android:name=\"androidx.startup.InitializationProvider\"\r\n            android:authorities=\"${applicationId}.androidx-startup\"\r\n            android:exported=\"false\"\r\n            tools:node=\"merge\">\r\n            <!-- If you are using androidx.startup to initialize other components -->\r\n            <meta-data\r\n                android:name=\"androidx.work.WorkManagerInitializer\"\r\n                android:value=\"androidx.startup\"\r\n                tools:node=\"remove\" />\r\n        </provider>\r\n\r\n        <provider\r\n            android:name=\"androidx.core.content.FileProvider\"\r\n            android:authorities=\"com.isaiahvonrundstedt.fokus.provider\"\r\n            android:exported=\"false\"\r\n            android:grantUriPermissions=\"true\">\r\n            <meta-data\r\n                android:name=\"android.support.FILE_PROVIDER_PATHS\"\r\n                android:resource=\"@xml/xml_provider_paths\"/>\r\n        </provider>\r\n\r\n        <activity android:name=\".features.core.activities.MainActivity\"\r\n            android:exported=\"true\"\r\n            android:theme=\"@style/Fokus.Theme.Core.Navigation\" >\r\n            <intent-filter>\r\n                <action android:name=\"android.intent.action.MAIN\" />\r\n                <category android:name=\"android.intent.category.LAUNCHER\" />\r\n            </intent-filter>\r\n\r\n            <meta-data android:name=\"android.app.shortcuts\"\r\n                android:resource=\"@xml/xml_launcher_shortcuts\"/>\r\n        </activity>\r\n        <activity android:name=\".features.attachments.attach.AttachToTaskActivity\"\r\n            android:exported=\"true\">\r\n            <intent-filter android:label=\"@string/sharing_attach_to_task\">\r\n                <action android:name=\"android.intent.action.SEND\"/>\r\n                <category android:name=\"android.intent.category.DEFAULT\"/>\r\n                <data android:mimeType=\"text/plain\"/>\r\n            </intent-filter>\r\n        </activity>\r\n        <activity android:name=\".features.subject.editor.SubjectEditorContainer\" />\r\n        <activity android:name=\".features.task.editor.TaskEditorContainer\"/>\r\n        <activity android:name=\".features.event.editor.EventEditorContainer\"/>\r\n\r\n        <service android:name=\".components.service.NotificationActionService\"\r\n            android:exported=\"false\"/>\r\n        <service android:name=\".components.service.BackupRestoreService\"\r\n            android:exported=\"false\"/>\r\n        <service android:name=\".components.service.FileImporterService\"\r\n            android:exported=\"false\"/>\r\n        <service android:name=\".components.service.DataExporterService\"\r\n            android:exported=\"false\"/>\r\n        <service android:name=\".components.service.DataImporterService\"\r\n            android:exported=\"false\"/>\r\n        <service android:name=\".features.task.widget.TaskWidgetService\"\r\n            android:exported=\"false\"\r\n            android:permission=\"android.permission.BIND_REMOTEVIEWS\"/>\r\n        <service android:name=\"com.isaiahvonrundstedt.fokus.features.event.widget.EventWidgetService\"\r\n            android:exported=\"false\"\r\n            android:permission=\"android.permission.BIND_REMOTEVIEWS\"/>\r\n        <service android:name=\"com.isaiahvonrundstedt.fokus.features.subject.widget.SubjectWidgetService\"\r\n            android:exported=\"false\"\r\n            android:permission=\"android.permission.BIND_REMOTEVIEWS\"/>\r\n\r\n        <receiver android:name=\".components.receiver.LocalizationReceiver\"\r\n            android:enabled=\"true\"\r\n            android:exported=\"true\">\r\n            <intent-filter>\r\n                <action android:name=\"android.intent.action.LOCALE_CHANGED\"/>\r\n            </intent-filter>\r\n        </receiver>\r\n        <receiver\r\n            android:name=\"com.isaiahvonrundstedt.fokus.features.task.widget.TaskWidgetProvider\"\r\n            android:label=\"@string/widget_task_name\"\r\n            android:exported=\"false\">\r\n            <intent-filter>\r\n                <action android:name=\"android.appwidget.action.APPWIDGET_UPDATE\"/>\r\n            </intent-filter>\r\n            <meta-data\r\n                android:name=\"android.appwidget.provider\"\r\n                android:resource=\"@xml/xml_widget_tasks\"/>\r\n        </receiver>\r\n        <receiver\r\n            android:name=\"com.isaiahvonrundstedt.fokus.features.event.widget.EventWidgetProvider\"\r\n            android:label=\"@string/widget_event_name\"\r\n            android:exported=\"false\">\r\n            <intent-filter>\r\n                <action android:name=\"android.appwidget.action.APPWIDGET_UPDATE\"/>\r\n            </intent-filter>\r\n            <meta-data\r\n                android:name=\"android.appwidget.provider\"\r\n                android:resource=\"@xml/xml_widget_events\"/>\r\n        </receiver>\r\n        <receiver\r\n            android:name=\"com.isaiahvonrundstedt.fokus.features.subject.widget.SubjectWidgetProvider\"\r\n            android:label=\"@string/widget_class_name\"\r\n            android:exported=\"false\">\r\n            <intent-filter>\r\n                <action android:name=\"android.appwidget.action.APPWIDGET_UPDATE\"/>\r\n            </intent-filter>\r\n            <meta-data\r\n                android:name=\"android.appwidget.provider\"\r\n                android:resource=\"@xml/xml_widget_subjects\"/>\r\n        </receiver>\r\n\r\n    </application>\r\n</manifest>"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/Fokus.kt",
    "content": "package com.isaiahvonrundstedt.fokus\n\nimport android.app.Application\nimport android.content.Context\nimport android.net.Uri\nimport androidx.core.content.FileProvider\nimport androidx.hilt.work.HiltWorkerFactory\nimport androidx.work.Configuration\nimport com.google.android.material.color.DynamicColors\nimport dagger.hilt.android.HiltAndroidApp\nimport java.io.File\nimport javax.inject.Inject\n\n@HiltAndroidApp\nclass Fokus : Application(), Configuration.Provider {\n\n    @Inject\n    lateinit var workerFactory: HiltWorkerFactory\n\n    override fun onCreate() {\n        super.onCreate()\n        DynamicColors.applyToActivitiesIfAvailable(this)\n    }\n\n    override fun getWorkManagerConfiguration(): Configuration {\n        return Configuration.Builder()\n            .setWorkerFactory(workerFactory)\n            .build()\n    }\n\n    companion object {\n        fun obtainUriForFile(context: Context, source: File): Uri {\n            return FileProvider.getUriForFile(\n                context,\n                \"${BuildConfig.APPLICATION_ID}.provider\", source\n            )\n        }\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/custom/ItemDecoration.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.custom\n\nimport android.content.Context\nimport androidx.recyclerview.widget.DividerItemDecoration\n\nclass ItemDecoration(context: Context) : DividerItemDecoration(context, VERTICAL)"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/custom/ItemSwipeCallback.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.custom\r\n\r\nimport android.content.Context\r\nimport android.content.res.Configuration\r\nimport android.graphics.Canvas\r\nimport android.graphics.Color\r\nimport android.graphics.drawable.ColorDrawable\r\nimport android.graphics.drawable.Drawable\r\nimport android.view.View\r\nimport androidx.core.content.ContextCompat\r\nimport androidx.recyclerview.widget.ItemTouchHelper\r\nimport androidx.recyclerview.widget.RecyclerView\r\nimport com.isaiahvonrundstedt.fokus.R\r\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Swipeable\r\n\r\nclass ItemSwipeCallback<T : Swipeable>(context: Context, private var adapter: T) :\r\n    ItemTouchHelper.Callback() {\r\n\r\n    private var isThemeDark: Boolean = false\r\n    private var iconDelete = ContextCompat.getDrawable(context, R.drawable.ic_outline_delete_24)\r\n    private var iconArchive = ContextCompat.getDrawable(context, R.drawable.ic_outline_archive_24)\r\n    private var backgroundDelete: Drawable\r\n    private var backgroundArchive: Drawable\r\n\r\n    init {\r\n        isThemeDark = (context.resources.configuration.uiMode and\r\n                Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES\r\n\r\n        val colorDelete = if (isThemeDark)\r\n            Color.parseColor(COLOR_BACKGROUND_DARK_DELETE)\r\n        else Color.parseColor(COLOR_BACKGROUND_LIGHT_DELETE)\r\n\r\n        val colorArchive = if (isThemeDark)\r\n            Color.parseColor(COLOR_BACKGROUND_DARK_ARCHIVE)\r\n        else Color.parseColor(COLOR_BACKGROUND_LIGHT_ARCHIVE)\r\n\r\n        backgroundDelete = ColorDrawable(colorDelete)\r\n        backgroundArchive = ColorDrawable(colorArchive)\r\n    }\r\n\r\n    override fun getMovementFlags(\r\n        recyclerView: RecyclerView,\r\n        viewHolder: RecyclerView.ViewHolder\r\n    ): Int {\r\n        return makeMovementFlags(0, ItemTouchHelper.START or ItemTouchHelper.END)\r\n    }\r\n\r\n    override fun onMove(\r\n        recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder,\r\n        target: RecyclerView.ViewHolder\r\n    ): Boolean = false\r\n\r\n    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {\r\n        adapter.onSwipe(viewHolder.bindingAdapterPosition, direction)\r\n    }\r\n\r\n    override fun getSwipeEscapeVelocity(defaultValue: Float): Float {\r\n        return defaultValue * 10\r\n    }\r\n\r\n    override fun onChildDraw(\r\n        c: Canvas, recyclerView: RecyclerView,\r\n        viewHolder: RecyclerView.ViewHolder,\r\n        dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean\r\n    ) {\r\n        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)\r\n\r\n        val itemView: View = viewHolder.itemView\r\n        val backgroundCornerOffset = 40\r\n\r\n        if (dX > 0) {\r\n            with(backgroundArchive) {\r\n                setBounds(\r\n                    itemView.left, itemView.top,\r\n                    itemView.left + dX.toInt() + backgroundCornerOffset, itemView.bottom\r\n                )\r\n                draw(c)\r\n            }\r\n\r\n            iconArchive?.let {\r\n                val tintColor = if (isThemeDark)\r\n                    Color.parseColor(COLOR_ICON_DARK_ARCHIVE)\r\n                else Color.parseColor(COLOR_ICON_LIGHT_ARCHIVE)\r\n\r\n                it.mutate()\r\n                it.setTint(tintColor)\r\n\r\n                val iconMargin: Int = (itemView.height - it.intrinsicHeight) / 2\r\n\r\n                val iconTop: Int = itemView.top + (itemView.height - it.intrinsicHeight) / 2\r\n                val iconBottom: Int = iconTop + it.intrinsicHeight\r\n                val iconLeft: Int = itemView.left + iconMargin\r\n                val iconRight: Int = iconLeft + it.intrinsicWidth\r\n\r\n                it.setBounds(iconLeft, iconTop, iconRight, iconBottom)\r\n                it.draw(c)\r\n            }\r\n        } else if (dX < 0) {\r\n            with(backgroundDelete) {\r\n                setBounds(\r\n                    itemView.right + dX.toInt() - backgroundCornerOffset, itemView.top,\r\n                    itemView.right, itemView.bottom\r\n                )\r\n                draw(c)\r\n            }\r\n\r\n            iconDelete?.let {\r\n                val tintColor = if (isThemeDark)\r\n                    Color.parseColor(COLOR_ICON_DARK_DELETE)\r\n                else Color.parseColor(COLOR_ICON_LIGHT_DELETE)\r\n\r\n                it.mutate()\r\n                it.setTint(tintColor)\r\n\r\n                val iconMargin: Int = (itemView.height - it.intrinsicHeight) / 2\r\n\r\n                val iconTop: Int = itemView.top + (itemView.height - it.intrinsicHeight) / 2\r\n                val iconBottom: Int = iconTop + it.intrinsicHeight\r\n                val iconLeft: Int = itemView.right - iconMargin - it.intrinsicWidth\r\n                val iconRight: Int = itemView.right - iconMargin\r\n\r\n                it.setBounds(iconLeft, iconTop, iconRight, iconBottom)\r\n                it.draw(c)\r\n            }\r\n        }\r\n    }\r\n\r\n    companion object {\r\n        const val COLOR_ICON_LIGHT_DELETE = \"#ea4335\"\r\n        const val COLOR_ICON_DARK_DELETE = \"#000000\"\r\n        const val COLOR_ICON_LIGHT_ARCHIVE = \"#00c853\"\r\n        const val COLOR_ICON_DARK_ARCHIVE = \"#000000\"\r\n\r\n        const val COLOR_BACKGROUND_LIGHT_DELETE = \"#66ea4335\"\r\n        const val COLOR_BACKGROUND_DARK_DELETE = \"#ea4335\"\r\n        const val COLOR_BACKGROUND_LIGHT_ARCHIVE = \"#6600c853\"\r\n        const val COLOR_BACKGROUND_DARK_ARCHIVE = \"#00c853\"\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/enums/SortDirection.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.enums\n\nenum class SortDirection {\n    ASCENDING, DESCENDING;\n\n    companion object {\n        fun parse(s: String?): SortDirection {\n            return when (s) {\n                ASCENDING.toString() -> ASCENDING\n                DESCENDING.toString() -> DESCENDING\n                else -> throw IllegalStateException(\"Sort Direction must be ascending or descending\")\n            }\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/extensions/android/AppCompatExtensions.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.extensions.android\n\nimport android.content.Context\nimport android.content.Intent\nimport android.content.res.Configuration\nimport android.os.Build\nimport android.view.View\nimport android.widget.Toast\nimport androidx.annotation.DimenRes\nimport androidx.annotation.StringRes\nimport androidx.appcompat.app.AppCompatActivity\nimport androidx.appcompat.app.AppCompatDelegate\nimport androidx.fragment.app.Fragment\nimport com.google.android.material.snackbar.Snackbar\n\nfun Context.isDark(): Boolean {\n    return resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES\n}\n\nfun Context.getDimension(@DimenRes res: Int): Int {\n    return (resources.getDimension(res) / resources.displayMetrics.density).toInt()\n}\n\nfun Context.startForegroundServiceCompat(service: Intent) {\n    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)\n        startForegroundService(service)\n    else startService(service)\n}\n\nfun AppCompatActivity.createSnackbar(\n    @StringRes textRes: Int,\n    view: View = window.decorView.rootView,\n    duration: Int = Snackbar.LENGTH_SHORT\n): Snackbar {\n    return Snackbar.make(view, getString(textRes), duration).apply { show() }\n}\n\nfun AppCompatActivity.createToast(\n    @StringRes textRes: Int,\n    duration: Int = Toast.LENGTH_SHORT\n): Toast {\n    return Toast.makeText(this, getString(textRes), duration).apply { show() }\n}\n\nfun Fragment.createSnackbar(\n    @StringRes textRes: Int,\n    view: View = this.requireView(),\n    duration: Int = Snackbar.LENGTH_SHORT\n): Snackbar {\n    return Snackbar.make(view, getString(textRes), duration).apply { show() }\n}\n\nfun Fragment.createToast(\n    @StringRes textRes: Int,\n    duration: Int = Toast.LENGTH_SHORT\n): Toast {\n    return Toast.makeText(requireContext(), getString(textRes), duration).apply { show() }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/extensions/android/IntentExtensions.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.extensions.android\r\n\r\nimport android.content.Intent\r\nimport android.os.Parcelable\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.toArrayList\r\n\r\nfun <T : Parcelable> Intent.putExtra(key: String, items: List<T>) {\r\n    putParcelableArrayListExtra(key, items.toArrayList())\r\n}\r\n\r\nfun <T : Parcelable> Intent.getParcelableListExtra(key: String): List<T>? {\r\n    return getParcelableArrayListExtra<T>(key)?.toList()\r\n}\r\n"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/extensions/android/TextViewExtensions.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.extensions.android\r\n\r\nimport android.graphics.Paint\r\nimport android.graphics.drawable.Drawable\r\nimport android.widget.TextView\r\nimport androidx.annotation.ColorRes\r\nimport androidx.core.content.ContextCompat\r\n\r\n/**\r\n *   Extension function used to change the text color\r\n *   of a AppCompatTextView\r\n *   @param id a color id from the Android resource\r\n */\r\nfun TextView.setTextColorFromResource(@ColorRes id: Int) {\r\n    this.setTextColor(ContextCompat.getColor(this.context, id))\r\n}\r\n\r\n/**\r\n *  Extension function used to set an strike through effect on the\r\n *  painted text on the view\r\n *  @param status determines whether to add or remove the effect on the text\r\n */\r\nfun TextView.setStrikeThroughEffect(status: Boolean) {\r\n    if (status) this.paintFlags = this.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG\r\n    else this.paintFlags = this.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()\r\n}\r\n\r\n/**\r\n *  Extension function used to add a compound drawable in the\r\n *  TextView at a specific position\r\n */\r\nfun TextView.setCompoundDrawableAtStart(drawable: Drawable?) {\r\n    this.setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, null, null)\r\n}\r\n\r\n/**\r\n *  Extension function used to get the compound drawable in the\r\n *  TextView at the specific position\r\n */\r\nfun TextView.getCompoundDrawableAtStart(): Drawable? {\r\n    // Start, Top, End, Bottom\r\n    return this.compoundDrawablesRelative[0]\r\n}\r\n\r\n/**\r\n *  Extension function to remove the compound drawable\r\n *  in the TextView at the specific position\r\n */\r\nfun TextView.removeCompoundDrawableAtStart() {\r\n    this.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, null, null)\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/extensions/android/UriExtensions.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.extensions.android\r\n\r\nimport android.content.Context\r\nimport android.database.Cursor\r\nimport android.net.Uri\r\nimport android.provider.OpenableColumns\r\n\r\n/**\r\n *  Extension function used to get the file name\r\n *  of an uri object\r\n *  @param context used to get access for a contentResolver object\r\n */\r\nfun Uri.getFileName(context: Context): String {\r\n    var result = \"\"\r\n    if (this.scheme == \"content\") {\r\n        val cursor: Cursor? = context.contentResolver?.query(this, null, null, null, null)\r\n        try {\r\n            if (cursor != null && cursor.moveToFirst())\r\n                result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))\r\n        } catch (ex: Exception) {\r\n        } finally {\r\n            cursor?.close()\r\n        }\r\n    } else {\r\n        result = this.path.toString()\r\n        val index = result.lastIndexOf('/')\r\n        if (index != 1)\r\n            result = result.substring(index + 1)\r\n    }\r\n    return result\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/extensions/jdk/CalendarExtensions.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.extensions.jdk\n\nimport java.time.LocalTime\nimport java.time.ZoneId\nimport java.time.ZonedDateTime\nimport java.util.*\n\n/**\n *   An extension function used to convert\n *   the legacy Calendar instance to the\n *   modern java.time.LocalTime instance\n *\n *   @return the converted LocalTime instance\n */\nfun Calendar.toLocalTime(): LocalTime {\n    return LocalTime.of(\n        this.get(Calendar.HOUR_OF_DAY), this.get(Calendar.MINUTE),\n        this.get(Calendar.SECOND)\n    )\n}\n\n/**\n *   An extension function used to convert\n *   the legacy Calendar instance to the\n *   modern java.time.ZonedDateTime instance\n *\n *   @return the converted ZonedDateTime instance\n */\nfun Calendar.toZonedDateTime(): ZonedDateTime? {\n    return ZonedDateTime.ofInstant(this.toInstant(), ZoneId.systemDefault())\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/extensions/jdk/ListExtensions.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.extensions.jdk\n\nimport com.isaiahvonrundstedt.fokus.features.attachments.Attachment\nimport com.isaiahvonrundstedt.fokus.features.event.Event\nimport com.isaiahvonrundstedt.fokus.features.log.Log\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\nimport com.isaiahvonrundstedt.fokus.features.task.Task\n\nfun <T> List<T>.getIndexByID(id: String): Int {\n    this.forEachIndexed { index, it ->\n        if (it is Task)\n            if (it.taskID == id) return index\n\n        if (it is Event)\n            if (it.eventID == id) return index\n\n        if (it is Subject)\n            if (it.subjectID == id) return index\n\n        if (it is Attachment)\n            if (it.attachmentID == id) return index\n\n        if (it is Log)\n            if (it.logID == id) return index\n\n        if (it is Schedule)\n            if (it.scheduleID == id) return index\n    }\n    return -1\n}\n\n/**\n *  Extension function to create an ArrayList\n *  from the current List object\n */\nfun <T> List<T>.toArrayList(): ArrayList<T> {\n    return ArrayList(this)\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/extensions/jdk/TimeExtensions.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.extensions.jdk\n\nimport java.time.LocalDate\nimport java.time.LocalTime\nimport java.time.ZoneId\nimport java.time.ZonedDateTime\nimport java.util.*\n\n/**\n *   An extension function to convert the\n *   LocalTime instance to a ZonedDateTime instance\n *   with the current date\n *\n *   @return the ZonedDateTime instance with the values of the\n *          LocalTime instance\n */\nfun LocalTime.toZonedDateTimeToday(): ZonedDateTime? {\n    return LocalDate.now().atStartOfDay(ZoneId.systemDefault())\n        .with(this)\n}\n\n/**\n *   An extension function used to\n *   determine if the ZonedDateTime object\n *   is same as the date today\n *\n *   @return true if the date matches from the current date\n */\nfun ZonedDateTime.isToday(): Boolean {\n    return LocalDate.now().isEqual(this.toLocalDate())\n}\n\n/**\n *   An extension function used to\n *   determine if the ZonedDateTime object\n *   is the same as the next day\n *   @return true if the ZonedDateTime object is the\n *           same as the next day\n */\nfun ZonedDateTime.isTomorrow(): Boolean {\n    return LocalDate.now().plusDays(1).compareTo(this.toLocalDate()) == 0\n}\n\n/**\n *   An extension function used to\n *   determine if the ZonedDateTime object\n *   is the same as the previous day\n *   @return true if the ZonedDateTime object is the\n *           same as the previous day\n */\nfun ZonedDateTime.isYesterday(): Boolean {\n    return LocalDate.now().minusDays(1).compareTo(this.toLocalDate()) == 0\n}\n\n/**\n *   An extension function used to determine\n *   if the ZonedDateTime object is before\n *   the current datetime\n *   @return true if the current ZonedDateTime object\n *              is before the current date-time\n */\nfun ZonedDateTime.isBeforeNow(): Boolean {\n    return this.isBefore(ZonedDateTime.now())\n}\n\n/**\n *   An extension function used to determine\n *   if the ZonedDateTime object is after\n *   the current datetime\n *   @return true if the current ZonedDateTime object\n *           is after the current date-time\n */\nfun ZonedDateTime.isAfterNow(): Boolean {\n    return this.isAfter(ZonedDateTime.now())\n}\n\n/**\n *  An extension function used to convert the\n *  current instance of ZonedDateTime to\n *  a legacy Calendar instance\n *  @return calendar instance with the same values as\n *          this instance\n */\nfun ZonedDateTime.toCalendar(): Calendar {\n    return GregorianCalendar.from(this)\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/interfaces/Streamable.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.interfaces\n\nimport java.io.File\nimport java.io.InputStream\n\ninterface Streamable {\n\n    fun toJsonString(): String?\n\n    fun toJsonFile(destination: File, name: String): File\n\n    fun fromInputStream(inputStream: InputStream)\n\n    companion object {\n        const val ARCHIVE_NAME_GENERIC = \"exported\"\n        const val FILE_NAME_TASK = \"task.json\"\n        const val FILE_NAME_ATTACHMENT = \"attachment.json\"\n        const val FILE_NAME_SUBJECT = \"subject.json\"\n        const val FILE_NAME_SCHEDULE = \"schedule.json\"\n        const val FILE_NAME_EVENT = \"event.json\"\n        const val FILE_NAME_LOG = \"log.json\"\n\n        const val DIRECTORY_GENERIC = \"others\"\n        const val DIRECTORY_ATTACHMENTS = \"attachments\"\n\n        const val MIME_TYPE_ZIP = \"application/zip\"\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/interfaces/Swipeable.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.interfaces\n\ninterface Swipeable {\n\n    fun onSwipe(position: Int, direction: Int)\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/json/JsonDataStreamer.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.json\n\nimport android.net.Uri\nimport com.isaiahvonrundstedt.fokus.database.converter.DateTimeConverter\nimport com.squareup.moshi.*\nimport com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory\nimport okio.buffer\nimport okio.source\nimport java.io.InputStream\nimport java.time.LocalTime\nimport java.time.ZonedDateTime\n\nclass JsonDataStreamer private constructor() {\n\n    class DateTimeAdapter {\n\n        @FromJson\n        fun toDateTime(string: String): ZonedDateTime? = DateTimeConverter.toZonedDateTime(string)\n\n        @ToJson\n        fun fromDateTime(dateTime: ZonedDateTime): String? =\n            DateTimeConverter.fromZonedDateTime(dateTime)\n    }\n\n    class LocalTimeAdapter {\n\n        @FromJson\n        fun toLocalTime(string: String): LocalTime? = DateTimeConverter.toLocalTime(string)\n\n        @ToJson\n        fun fromLocalTime(time: LocalTime): String? = DateTimeConverter.fromLocalTime(time)\n    }\n\n    class UriAdapter {\n\n        @FromJson\n        fun toUri(data: String): Uri = Uri.parse(data)\n\n        @ToJson\n        fun fromUri(uri: Uri): String = uri.toString()\n    }\n\n    companion object {\n        val moshi: Moshi\n            get() = Moshi.Builder()\n                .add(KotlinJsonAdapterFactory())\n                .add(DateTimeAdapter())\n                .add(LocalTimeAdapter())\n                .add(UriAdapter())\n                .build()\n\n        fun <T> encodeToJson(data: T?, dataType: Class<T>): String? {\n            if (data == null) return null\n\n            val adapter: JsonAdapter<T> = moshi.adapter(dataType)\n            return adapter.toJson(data)\n        }\n\n        fun <T> encodeToJson(dataItems: List<T>?, dataType: Class<T>): String? {\n            if (dataItems == null || dataItems.isEmpty()) return null\n\n            val type = Types.newParameterizedType(List::class.java, dataType)\n            val adapter: JsonAdapter<List<T>> = moshi.adapter(type)\n            return adapter.toJson(dataItems)\n        }\n\n        fun <T> decodeOnceFromJson(stream: InputStream, dataType: Class<T>): T? {\n            if (stream.isEmpty()) return null\n\n            val adapter: JsonAdapter<T> = moshi.adapter(dataType)\n            return adapter.fromJson(stream.source().buffer())\n        }\n\n        fun <T> decodeFromJson(stream: InputStream, dataType: Class<T>): List<T>? {\n            if (stream.isEmpty()) return emptyList()\n\n            val type = Types.newParameterizedType(List::class.java, dataType)\n            val adapter: JsonAdapter<List<T>> = moshi.adapter(type)\n            return adapter.fromJson(stream.source().buffer())\n        }\n\n        private fun InputStream.isEmpty(): Boolean {\n            return this.available() < 1\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/json/Metadata.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.json\n\nimport com.isaiahvonrundstedt.fokus.BuildConfig\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Streamable\nimport com.isaiahvonrundstedt.fokus.database.AppDatabase\nimport com.squareup.moshi.JsonClass\nimport okio.buffer\nimport okio.sink\nimport java.io.File\nimport java.io.InputStream\n\n/**\n *   Metadata class handles exported json\n *   data the is packaged through zip.\n *   It reads what data are inside the package,\n *   and if the corresponding data is compatible\n *   with the application.\n */\n@JsonClass(generateAdapter = true)\ndata class Metadata @JvmOverloads constructor(\n    var appVersion: Int = BuildConfig.VERSION_CODE,\n    var appBuildName: String? = BuildConfig.VERSION_NAME,\n    var databaseVersion: Int = AppDatabase.DATABASE_VERSION,\n    var data: String? = null\n) : Streamable {\n\n    fun verify(dataString: String): Boolean {\n        return databaseVersion == AppDatabase.DATABASE_VERSION &&\n                data == dataString\n    }\n\n    override fun toJsonString(): String? {\n        return JsonDataStreamer.encodeToJson(this, Metadata::class.java)\n    }\n\n    override fun toJsonFile(destination: File, name: String): File {\n        return File(destination, name).apply {\n            this.sink().buffer().use {\n                toJsonString()?.also { json -> it.write(json.toByteArray()) }\n            }\n        }\n    }\n\n    override fun fromInputStream(inputStream: InputStream) {\n        JsonDataStreamer.decodeOnceFromJson(inputStream, Metadata::class.java)?.also {\n            appVersion = it.appVersion\n            appBuildName = it.appBuildName\n            databaseVersion = it.databaseVersion\n            data = it.data\n        }\n    }\n\n    companion object {\n        const val DATA_BUNDLE = \"data:bundle\"\n        const val DATA_TASK = \"data:task\"\n        const val DATA_SUBJECT = \"data:subject\"\n        const val DATA_EVENT = \"data:event\"\n        const val DATA_LOG = \"data:log\"\n\n        const val FILE_NAME = \"metadata.json\"\n\n        fun fromInputStream(inputStream: InputStream): Metadata {\n            return Metadata().apply {\n                this.fromInputStream(inputStream)\n            }\n        }\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/modules/DatabaseModule.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.modules\n\nimport android.app.NotificationManager\nimport android.content.Context\nimport androidx.work.WorkManager\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\nimport com.isaiahvonrundstedt.fokus.database.AppDatabase\nimport com.isaiahvonrundstedt.fokus.database.dao.*\nimport com.isaiahvonrundstedt.fokus.database.repository.EventRepository\nimport com.isaiahvonrundstedt.fokus.database.repository.LogRepository\nimport com.isaiahvonrundstedt.fokus.database.repository.SubjectRepository\nimport com.isaiahvonrundstedt.fokus.database.repository.TaskRepository\nimport dagger.Module\nimport dagger.Provides\nimport dagger.hilt.InstallIn\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport dagger.hilt.components.SingletonComponent\nimport javax.inject.Singleton\n\n@Module\n@InstallIn(SingletonComponent::class)\nclass DatabaseModule {\n\n    @Singleton\n    @Provides\n    fun provideDatabase(@ApplicationContext context: Context): AppDatabase {\n        return AppDatabase.getInstance(context)\n    }\n\n    @Provides\n    fun provideTaskDao(database: AppDatabase): TaskDAO = database.tasks()\n\n    @Provides\n    fun provideAttachmentDao(database: AppDatabase): AttachmentDAO = database.attachments()\n\n    @Provides\n    fun provideSubjectDao(database: AppDatabase): SubjectDAO = database.subjects()\n\n    @Provides\n    fun provideScheduleDao(database: AppDatabase): ScheduleDAO = database.schedules()\n\n    @Provides\n    fun provideEventDao(database: AppDatabase): EventDAO = database.events()\n\n    @Provides\n    fun provideLogDao(database: AppDatabase): LogDAO = database.logs()\n\n    @Provides\n    fun provideTaskRepository(\n        @ApplicationContext\n        context: Context,\n        taskDao: TaskDAO,\n        attachmentDao: AttachmentDAO,\n        preferenceManager: PreferenceManager,\n        workManager: WorkManager,\n        notificationManager: NotificationManager\n    ): TaskRepository {\n        return TaskRepository(\n            context,\n            taskDao,\n            attachmentDao,\n            preferenceManager,\n            workManager,\n            notificationManager\n        )\n    }\n\n    @Provides\n    fun provideSubjectRepository(\n        @ApplicationContext\n        context: Context,\n        subjectDAO: SubjectDAO,\n        scheduleDAO: ScheduleDAO,\n        preferenceManager: PreferenceManager,\n        workManager: WorkManager\n    ): SubjectRepository {\n        return SubjectRepository(context, subjectDAO, scheduleDAO, preferenceManager, workManager)\n    }\n\n    @Provides\n    fun provideEventRepository(\n        @ApplicationContext\n        context: Context,\n        eventDAO: EventDAO,\n        preferenceManager: PreferenceManager,\n        workManager: WorkManager,\n        notificationManager: NotificationManager\n    ): EventRepository {\n        return EventRepository(\n            context,\n            eventDAO,\n            preferenceManager,\n            workManager,\n            notificationManager\n        )\n    }\n\n    @Provides\n    fun provideLogRepository(dao: LogDAO): LogRepository = LogRepository(dao)\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/modules/ExternalModule.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.modules\n\nimport android.app.NotificationManager\nimport android.content.ClipboardManager\nimport android.content.Context\nimport androidx.work.WorkManager\nimport dagger.Module\nimport dagger.Provides\nimport dagger.hilt.InstallIn\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport dagger.hilt.components.SingletonComponent\nimport javax.inject.Singleton\n\n@Module\n@InstallIn(SingletonComponent::class)\nclass ExternalModule {\n\n    @Singleton\n    @Provides\n    fun provideWorkManager(@ApplicationContext context: Context): WorkManager {\n        return WorkManager.getInstance(context)\n    }\n\n    @Provides\n    fun provideNotificationManager(@ApplicationContext context: Context): NotificationManager {\n        return context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager\n    }\n\n    @Provides\n    fun provideClipboardManager(@ApplicationContext context: Context): ClipboardManager {\n        return context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/modules/InternalModule.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.modules\n\nimport android.content.Context\nimport com.isaiahvonrundstedt.fokus.components.utils.PermissionManager\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\nimport dagger.Module\nimport dagger.Provides\nimport dagger.hilt.InstallIn\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport dagger.hilt.components.SingletonComponent\nimport javax.inject.Singleton\n\n@Module\n@InstallIn(SingletonComponent::class)\nclass InternalModule {\n\n    @Singleton\n    @Provides\n    fun providePreferenceManager(@ApplicationContext context: Context): PreferenceManager {\n        return PreferenceManager(context)\n    }\n\n    @Singleton\n    @Provides\n    fun providePermissionManager(@ApplicationContext context: Context): PermissionManager {\n        return PermissionManager(context)\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/preference/InformationHolder.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.preference\r\n\r\nimport android.annotation.SuppressLint\r\nimport android.content.Context\r\nimport android.util.AttributeSet\r\nimport androidx.core.content.res.TypedArrayUtils\r\nimport androidx.preference.Preference\r\nimport com.isaiahvonrundstedt.fokus.R\r\n\r\n@SuppressLint(\"RestrictedApi\")\r\nclass InformationHolder(\r\n    context: Context,\r\n    attr: AttributeSet?,\r\n    defStyleAttr: Int,\r\n    defStyleRes: Int\r\n) : Preference(context, attr, defStyleAttr, defStyleRes) {\r\n\r\n    constructor(context: Context, attr: AttributeSet?, defStyleAttr: Int)\r\n            : this(context, attr, defStyleAttr, 0)\r\n\r\n    constructor(context: Context, attr: AttributeSet?)\r\n            : this(\r\n        context, attr, TypedArrayUtils.getAttr(\r\n            context,\r\n            androidx.preference.R.attr.preferenceStyle, android.R.attr.preferenceStyle\r\n        )\r\n    )\r\n\r\n    constructor(context: Context) : this(context, null)\r\n\r\n    init {\r\n        layoutResource = R.layout.layout_preference_info\r\n    }\r\n\r\n    override fun onClick() {}\r\n    override fun performClick() {}\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/receiver/LocalizationReceiver.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.receiver\r\n\r\nimport android.app.NotificationManager\r\nimport android.content.BroadcastReceiver\r\nimport android.content.Context\r\nimport android.content.Intent\r\nimport android.os.Build\r\nimport com.isaiahvonrundstedt.fokus.components.utils.NotificationChannelManager\r\n\r\nclass LocalizationReceiver : BroadcastReceiver() {\r\n\r\n    override fun onReceive(context: Context?, intent: Intent?) {\r\n        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)\r\n            return\r\n\r\n        if (intent?.action == Intent.ACTION_LOCALE_CHANGED) {\r\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\r\n                with(NotificationChannelManager(context!!)) {\r\n                    register(\r\n                        NotificationChannelManager.CHANNEL_ID_GENERIC,\r\n                        NotificationManager.IMPORTANCE_DEFAULT\r\n                    )\r\n                    register(\r\n                        NotificationChannelManager.CHANNEL_ID_TASK,\r\n                        groupID = NotificationChannelManager.CHANNEL_GROUP_ID_REMINDERS\r\n                    )\r\n                    register(\r\n                        NotificationChannelManager.CHANNEL_ID_EVENT,\r\n                        groupID = NotificationChannelManager.CHANNEL_GROUP_ID_REMINDERS\r\n                    )\r\n                    register(\r\n                        NotificationChannelManager.CHANNEL_ID_CLASS,\r\n                        groupID = NotificationChannelManager.CHANNEL_GROUP_ID_REMINDERS\r\n                    )\r\n                }\r\n            }\r\n        }\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/service/BackupRestoreService.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.service\n\nimport android.content.Intent\nimport android.net.Uri\nimport android.os.Environment\nimport android.os.IBinder\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Streamable\nimport com.isaiahvonrundstedt.fokus.components.json.JsonDataStreamer\nimport com.isaiahvonrundstedt.fokus.components.json.Metadata\nimport com.isaiahvonrundstedt.fokus.components.utils.DataArchiver\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\nimport com.isaiahvonrundstedt.fokus.database.AppDatabase\nimport com.isaiahvonrundstedt.fokus.features.attachments.Attachment\nimport com.isaiahvonrundstedt.fokus.features.event.Event\nimport com.isaiahvonrundstedt.fokus.features.log.Log\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseService\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\nimport com.isaiahvonrundstedt.fokus.features.task.Task\nimport kotlinx.coroutines.Job\nimport kotlinx.coroutines.async\nimport kotlinx.coroutines.runBlocking\nimport okio.buffer\nimport okio.sink\nimport org.apache.commons.io.FileUtils\nimport java.io.EOFException\nimport java.io.File\nimport java.io.InputStream\nimport java.time.ZonedDateTime\nimport java.util.zip.ZipEntry\nimport java.util.zip.ZipFile\n\nclass BackupRestoreService : BaseService() {\n\n    private lateinit var database: AppDatabase\n\n    override fun onCreate() {\n        super.onCreate()\n        database = AppDatabase.getInstance(this)\n    }\n\n    override fun onBind(intent: Intent?): IBinder? {\n        return null\n    }\n\n    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {\n        intent?.data?.also {\n            when (intent.action) {\n                ACTION_BACKUP ->\n                    startBackup(it)\n                ACTION_RESTORE ->\n                    startRestore(it)\n            }\n        }\n        return START_NOT_STICKY\n    }\n\n    private fun startRestore(uri: Uri) {\n        startForegroundCompat(\n            NOTIFICATION_RESTORE_ONGOING,\n            createNotification(\n                true, R.string.notification_restore_ongoing,\n                iconRes = R.drawable.ic_outline_file_download_24\n            )\n        )\n\n        try {\n            val archiveStream: InputStream? = contentResolver.openInputStream(uri)\n            val archive = DataArchiver.parseInputStream(this, archiveStream)\n\n            archive.getInputStream(archive.getEntry(Metadata.FILE_NAME))?.use {\n                val metadata = Metadata.fromInputStream(it)\n\n                if (!metadata.verify(Metadata.DATA_BUNDLE)) {\n                    stopForegroundCompat(NOTIFICATION_RESTORE_ONGOING)\n                    manager?.notify(\n                        NOTIFICATION_RESTORE_FAILED,\n                        createNotification(titleRes = R.string.notification_restore_error)\n                    )\n                    terminateService()\n                    archive.close()\n                }\n            }\n\n            for (entry: ZipEntry in archive.entries()) {\n                archive.getInputStream(entry)?.use {\n                    tryParse(archive, entry, it)\n                }\n            }\n\n            stopForegroundCompat(NOTIFICATION_RESTORE_ONGOING)\n            manager?.notify(\n                NOTIFICATION_RESTORE_SUCCESS,\n                createNotification(titleRes = R.string.notification_restore_success)\n            )\n            terminateService()\n\n            archive.close()\n        } catch (e: EOFException) {\n            e.printStackTrace()\n\n            stopForegroundCompat(NOTIFICATION_RESTORE_ONGOING)\n            manager?.notify(\n                NOTIFICATION_RESTORE_FAILED,\n                createNotification(\n                    titleRes = R.string.notification_restore_error,\n                    contentRes = R.string.feedback_restore_corrupted\n                )\n            )\n            terminateService()\n        } catch (e: Exception) {\n            e.printStackTrace()\n\n            stopForegroundCompat(NOTIFICATION_RESTORE_ONGOING)\n            manager?.notify(\n                NOTIFICATION_RESTORE_FAILED,\n                createNotification(\n                    titleRes = R.string.notification_restore_error,\n                    contentRes = R.string.feedback_restore_invalid\n                )\n            )\n            terminateService()\n        }\n    }\n\n    private fun tryParse(archive: ZipFile, entry: ZipEntry, stream: InputStream) {\n        if (entry.name == Streamable.FILE_NAME_SUBJECT) {\n            JsonDataStreamer.decodeFromJson(stream, Subject::class.java)?.run {\n                runBlocking { forEach { database.subjects().insert(it) } }\n            }\n        } else if (entry.name == Streamable.FILE_NAME_SCHEDULE) {\n            JsonDataStreamer.decodeFromJson(stream, Schedule::class.java)?.run {\n                runBlocking { forEach { database.schedules().insert(it) } }\n            }\n        } else if (entry.name == Streamable.FILE_NAME_TASK) {\n            JsonDataStreamer.decodeFromJson(stream, Task::class.java)?.run {\n                runBlocking { forEach { database.tasks().insert(it) } }\n            }\n        } else if (entry.name == Streamable.FILE_NAME_ATTACHMENT) {\n            JsonDataStreamer.decodeFromJson(stream, Attachment::class.java)?.run {\n                runBlocking { forEach { database.attachments().insert(it) } }\n            }\n        } else if (entry.name == Streamable.FILE_NAME_EVENT) {\n            JsonDataStreamer.decodeFromJson(stream, Event::class.java)?.run {\n                runBlocking { forEach { database.events().insert(it) } }\n            }\n        } else if (entry.name == Streamable.FILE_NAME_LOG) {\n            JsonDataStreamer.decodeFromJson(stream, Log::class.java)?.run {\n                runBlocking { forEach { database.logs().insert(it) } }\n            }\n        } else if (entry.name.contains(Streamable.DIRECTORY_ATTACHMENTS)\n            && !entry.isDirectory\n        ) {\n\n            val targetDirectory = File(\n                getExternalFilesDir(null),\n                Streamable.DIRECTORY_ATTACHMENTS\n            )\n\n            val destination = File(targetDirectory, File(entry.name).name)\n\n            archive.getInputStream(entry)?.use { inputStream ->\n                FileUtils.copyToFile(inputStream, destination)\n            }\n        }\n    }\n\n    private fun startBackup(destination: Uri) {\n        if (Environment.getExternalStorageState() != Environment.MEDIA_MOUNTED)\n            return\n\n        startForegroundCompat(\n            NOTIFICATION_BACKUP_ONGOING,\n            createNotification(\n                ongoing = true, titleRes = R.string.notification_backup_ongoing,\n                iconRes = R.drawable.ic_outline_file_upload_24\n            )\n        )\n\n        try {\n            runBlocking {\n                val items = mutableListOf<File>()\n                var fetchJob: Job\n\n                fetchJob = async { database.subjects().fetch() }\n                JsonDataStreamer.encodeToJson(fetchJob.await(), Subject::class.java)?.let {\n                    items.add(createCache(Streamable.FILE_NAME_SUBJECT, it))\n                }\n\n                fetchJob = async { database.schedules().fetch() }\n                JsonDataStreamer.encodeToJson(fetchJob.await(), Schedule::class.java)?.let {\n                    items.add(createCache(Streamable.FILE_NAME_SCHEDULE, it))\n                }\n\n                fetchJob = async { database.tasks().fetch() }\n                JsonDataStreamer.encodeToJson(fetchJob.await(), Task::class.java)?.let {\n                    items.add(createCache(Streamable.FILE_NAME_TASK, it))\n                }\n\n                fetchJob = async { database.attachments().fetch() }\n                val attachments: List<Attachment>? = fetchJob.await()\n                JsonDataStreamer.encodeToJson(attachments, Attachment::class.java)?.let {\n                    items.add(createCache(Streamable.FILE_NAME_ATTACHMENT, it))\n                }\n                val attachmentFolder = File(\n                    cacheDir,\n                    Streamable.DIRECTORY_ATTACHMENTS\n                )\n                if (!attachmentFolder.exists()) attachmentFolder.mkdir()\n                attachments?.forEach {\n                    if (it.type == Attachment.TYPE_IMPORTED_FILE && it.target != null)\n                        FileUtils.copyFileToDirectory(\n                            File(it.target!!),\n                            attachmentFolder\n                        )\n                }\n                items.add(attachmentFolder)\n\n                fetchJob = async { database.events().fetch() }\n                JsonDataStreamer.encodeToJson(fetchJob.await(), Event::class.java)?.let {\n                    items.add(createCache(Streamable.FILE_NAME_EVENT, it))\n                }\n\n                fetchJob = async { database.logs().fetchCore() }\n                JsonDataStreamer.encodeToJson(fetchJob.await(), Log::class.java)?.let {\n                    items.add(createCache(Streamable.FILE_NAME_LOG, it))\n                }\n\n                items.add(\n                    Metadata(data = Metadata.DATA_BUNDLE)\n                        .toJsonFile(cacheDir, Metadata.FILE_NAME)\n                )\n\n                if (items.isEmpty()) {\n                    stopForegroundCompat(NOTIFICATION_BACKUP_ONGOING)\n                    terminateService(BROADCAST_BACKUP_EMPTY)\n                }\n\n                DataArchiver.Create(this@BackupRestoreService)\n                    .addSource(items)\n                    .toDestination(destination)\n                    .start()\n\n                PreferenceManager(this@BackupRestoreService)\n                    .previousBackupDate = ZonedDateTime.now()\n\n                stopForegroundCompat(NOTIFICATION_BACKUP_ONGOING)\n                manager?.notify(\n                    NOTIFICATION_BACKUP_SUCCESS,\n                    createNotification(titleRes = R.string.notification_backup_success)\n                )\n                terminateService(BROADCAST_BACKUP_SUCCESS)\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n\n            stopForegroundCompat(NOTIFICATION_BACKUP_ONGOING)\n            manager?.notify(\n                NOTIFICATION_BACKUP_FAILED,\n                createNotification(titleRes = R.string.notification_backup_error)\n            )\n            terminateService(BROADCAST_BACKUP_FAILED)\n        }\n    }\n\n    private fun createCache(name: String, json: String): File {\n        return File(cacheDir, name).apply {\n            this.sink().buffer().use {\n                it.write(json.toByteArray())\n                it.flush()\n            }\n        }\n    }\n\n    companion object {\n        const val FILE_BACKUP_NAME = \"backup\"\n\n        const val ACTION_BACKUP = \"action:backup\"\n        const val ACTION_RESTORE = \"action:restore\"\n\n        const val NOTIFICATION_BACKUP_ONGOING = 1\n        const val NOTIFICATION_BACKUP_SUCCESS = 2\n        const val NOTIFICATION_BACKUP_FAILED = 3\n        const val NOTIFICATION_RESTORE_ONGOING = 4\n        const val NOTIFICATION_RESTORE_SUCCESS = 5\n        const val NOTIFICATION_RESTORE_FAILED = 6\n\n        const val BROADCAST_BACKUP_SUCCESS = \"broadcast:backup:success\"\n        const val BROADCAST_BACKUP_FAILED = \"broadcast:backup:failed\"\n        const val BROADCAST_BACKUP_EMPTY = \"broadcast:backup:empty\"\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/service/DataExporterService.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.service\n\nimport android.content.Intent\nimport android.net.Uri\nimport android.os.IBinder\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.getParcelableListExtra\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Streamable\nimport com.isaiahvonrundstedt.fokus.components.json.Metadata\nimport com.isaiahvonrundstedt.fokus.components.utils.DataArchiver\nimport com.isaiahvonrundstedt.fokus.features.attachments.Attachment\nimport com.isaiahvonrundstedt.fokus.features.event.Event\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseService\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\nimport com.isaiahvonrundstedt.fokus.features.task.Task\nimport java.io.File\n\nclass DataExporterService : BaseService() {\n\n    override fun onBind(intent: Intent?): IBinder? {\n        return null\n    }\n\n    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {\n        onExport(intent)\n        sendLocalBroadcast(BROADCAST_EXPORT_ONGOING)\n\n        return START_REDELIVER_INTENT\n    }\n\n    private fun onExport(intent: Intent?) {\n        if (intent?.hasExtra(EXTRA_EXPORT_SOURCE) == false)\n            terminateService(BROADCAST_EXPORT_FAILED)\n\n        val destination: Uri? = intent?.data\n        val items = mutableListOf<File>()\n\n        var fileName: String = Streamable.ARCHIVE_NAME_GENERIC\n\n        try {\n            when (intent?.action) {\n                ACTION_EXPORT_SUBJECT -> {\n                    items.add(\n                        Metadata(data = Metadata.DATA_SUBJECT)\n                            .toJsonFile(cacheDir, Metadata.FILE_NAME)\n                    )\n\n                    val subject: Subject? = intent.getParcelableExtra(EXTRA_EXPORT_SOURCE)\n                    val schedules: List<Schedule>? =\n                        intent.getParcelableListExtra(EXTRA_EXPORT_DEPENDENTS)\n\n                    if (subject != null) {\n                        fileName = subject.code ?: Streamable.ARCHIVE_NAME_GENERIC\n                        items.add(subject.toJsonFile(cacheDir, Streamable.FILE_NAME_SUBJECT))\n                    }\n                    items.add(Schedule.toJsonFile(schedules ?: emptyList(), cacheDir))\n\n                }\n                ACTION_EXPORT_TASK -> {\n                    items.add(\n                        Metadata(data = Metadata.DATA_TASK)\n                            .toJsonFile(cacheDir, Metadata.FILE_NAME)\n                    )\n\n                    val task: Task? = intent.getParcelableExtra(EXTRA_EXPORT_SOURCE)\n                    if (task != null) {\n                        fileName = task.name ?: Streamable.ARCHIVE_NAME_GENERIC\n                        items.add(task.toJsonFile(cacheDir, Streamable.FILE_NAME_TASK))\n                    }\n\n                    var attachments: List<Attachment> =\n                        intent.getParcelableListExtra(EXTRA_EXPORT_DEPENDENTS) ?: emptyList()\n                    attachments = attachments.filter { it.type == Attachment.TYPE_WEBSITE_LINK }\n                    items.add(Attachment.toJsonFile(attachments, cacheDir))\n                }\n                ACTION_EXPORT_EVENT -> {\n\n                    items.add(\n                        Metadata(data = Metadata.DATA_EVENT)\n                            .toJsonFile(cacheDir, Metadata.FILE_NAME)\n                    )\n\n                    val event: Event? = intent.getParcelableExtra(EXTRA_EXPORT_SOURCE)\n\n                    if (event != null) {\n                        fileName = event.name ?: Streamable.ARCHIVE_NAME_GENERIC\n                        items.add(event.toJsonFile(cacheDir, Streamable.FILE_NAME_EVENT))\n                    }\n                }\n            }\n\n            if (destination == null) {\n                val cache = File(externalCacheDir, fileName)\n\n                DataArchiver.Create(this)\n                    .addSource(items)\n                    .toDestination(cache)\n                    .start()\n\n                terminateService(BROADCAST_EXPORT_COMPLETED, cache.path)\n            } else {\n                DataArchiver.Create(this)\n                    .addSource(items)\n                    .toDestination(destination)\n                    .start()\n\n                terminateService(BROADCAST_EXPORT_COMPLETED)\n            }\n        } catch (e: Exception) {\n            terminateService(BROADCAST_EXPORT_FAILED)\n        }\n    }\n\n    companion object {\n        const val EXTRA_EXPORT_SOURCE = \"extra:export:source\"\n        const val EXTRA_EXPORT_DEPENDENTS = \"extra:export:dependents\"\n\n        const val ACTION_EXPORT_SUBJECT = \"action:export:subject\"\n        const val ACTION_EXPORT_TASK = \"action:export:task\"\n        const val ACTION_EXPORT_EVENT = \"action:export:event\"\n\n        const val BROADCAST_EXPORT_ONGOING = \"broadcast:export:ongoing\"\n        const val BROADCAST_EXPORT_COMPLETED = \"broadcast:export:completed\"\n        const val BROADCAST_EXPORT_FAILED = \"broadcast:export:failed\"\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/service/DataImporterService.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.service\n\nimport android.content.Intent\nimport android.os.IBinder\nimport android.os.Parcelable\nimport androidx.localbroadcastmanager.content.LocalBroadcastManager\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Streamable\nimport com.isaiahvonrundstedt.fokus.components.json.JsonDataStreamer\nimport com.isaiahvonrundstedt.fokus.components.json.Metadata\nimport com.isaiahvonrundstedt.fokus.components.utils.DataArchiver\nimport com.isaiahvonrundstedt.fokus.features.attachments.Attachment\nimport com.isaiahvonrundstedt.fokus.features.event.Event\nimport com.isaiahvonrundstedt.fokus.features.event.EventPackage\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseService\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\nimport com.isaiahvonrundstedt.fokus.features.subject.SubjectPackage\nimport com.isaiahvonrundstedt.fokus.features.task.Task\nimport com.isaiahvonrundstedt.fokus.features.task.TaskPackage\nimport java.util.zip.ZipEntry\n\nclass DataImporterService : BaseService() {\n\n    override fun onBind(intent: Intent?): IBinder? {\n        return null\n    }\n\n    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {\n        onImport(intent)\n        return START_REDELIVER_INTENT\n    }\n\n    private fun onImport(intent: Intent?) {\n        if (intent?.data == null)\n            terminateService(BROADCAST_IMPORT_FAILED)\n\n        contentResolver.openInputStream(intent?.data!!)?.use { inputStream ->\n            val archive = DataArchiver.parseInputStream(this, inputStream)\n\n            try {\n                archive.getInputStream(archive.getEntry(Metadata.FILE_NAME)).use { it ->\n                    val metadata = Metadata.fromInputStream(it)\n                    if (metadata.verify(Metadata.DATA_SUBJECT) &&\n                        intent.action == ACTION_IMPORT_SUBJECT\n                    ) {\n\n                        val subjectPackage = SubjectPackage(Subject())\n                        for (entry: ZipEntry in archive.entries()) {\n\n                            if (entry.name == Streamable.FILE_NAME_SUBJECT) {\n                                archive.getInputStream(entry)?.use { inputStream ->\n                                    subjectPackage.subject = Subject.fromInputStream(inputStream)\n                                }\n                            } else if (entry.name == Streamable.FILE_NAME_SCHEDULE) {\n                                archive.getInputStream(entry)?.use { inputStream ->\n                                    JsonDataStreamer.decodeFromJson(\n                                        inputStream,\n                                        Schedule::class.java\n                                    )\n                                        ?.also { items ->\n                                            subjectPackage.schedules = items\n                                        }\n                                }\n                            }\n                        }\n\n                        sendResult(subjectPackage)\n                    } else if (metadata.verify(Metadata.DATA_TASK) &&\n                        intent.action == ACTION_IMPORT_TASK\n                    ) {\n\n                        val taskPackage = TaskPackage(Task())\n                        for (entry: ZipEntry in archive.entries()) {\n\n                            if (entry.name == Streamable.FILE_NAME_TASK) {\n                                archive.getInputStream(entry)?.use { inputStream ->\n                                    taskPackage.task = Task.fromInputStream(inputStream)\n                                }\n                            } else if (entry.name == Streamable.FILE_NAME_ATTACHMENT) {\n                                archive.getInputStream(entry)?.use { inputStream ->\n                                    JsonDataStreamer.decodeFromJson(\n                                        inputStream,\n                                        Attachment::class.java\n                                    )\n                                        ?.also { items ->\n                                            taskPackage.attachments = items\n                                        }\n                                }\n                            }\n                        }\n\n                        sendResult(taskPackage)\n                    } else if (metadata.verify(Metadata.DATA_EVENT) &&\n                        intent.action == ACTION_IMPORT_EVENT\n                    ) {\n\n                        val eventPackage = EventPackage(Event())\n                        for (entry: ZipEntry in archive.entries()) {\n                            if (entry.name == Streamable.FILE_NAME_EVENT) {\n                                archive.getInputStream(entry)?.use { inputStream ->\n                                    eventPackage.event = Event.fromInputStream(inputStream)\n                                }\n                            }\n                        }\n                        sendResult(eventPackage)\n                    } else terminateService(BROADCAST_IMPORT_FAILED)\n                }\n            } catch (e: Exception) {\n\n                e.printStackTrace()\n                terminateService(BROADCAST_IMPORT_FAILED)\n            }\n        }\n    }\n\n    private fun <T : Parcelable> sendResult(t: T) {\n        LocalBroadcastManager.getInstance(this)\n            .sendBroadcast(Intent(ACTION_SERVICE_BROADCAST).apply {\n                putExtra(EXTRA_BROADCAST_STATUS, BROADCAST_IMPORT_COMPLETED)\n                putExtra(EXTRA_BROADCAST_DATA, t)\n            })\n        terminateService()\n    }\n\n    companion object {\n        const val ACTION_IMPORT_TASK = \"action:import:task\"\n        const val ACTION_IMPORT_SUBJECT = \"action:import:subject\"\n        const val ACTION_IMPORT_EVENT = \"action:import:event\"\n\n        const val BROADCAST_IMPORT_ONGOING = \"broadcast:import:ongoing\"\n        const val BROADCAST_IMPORT_COMPLETED = \"broadcast:import:completed\"\n        const val BROADCAST_IMPORT_FAILED = \"broadcast:import:failed\"\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/service/FileImporterService.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.service\n\nimport android.content.Intent\nimport android.net.Uri\nimport android.os.Environment\nimport android.os.IBinder\nimport androidx.localbroadcastmanager.content.LocalBroadcastManager\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.getFileName\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Streamable\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseService\nimport org.apache.commons.io.FileUtils\nimport java.io.File\n\nclass FileImporterService : BaseService() {\n\n    private lateinit var targetDirectory: File\n\n    override fun onBind(intent: Intent?): IBinder? {\n        return null\n    }\n\n    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {\n        when (intent?.action) {\n            ACTION_START -> {\n                targetDirectory = File(\n                    getExternalFilesDir(null),\n                    Streamable.DIRECTORY_ATTACHMENTS\n                )\n\n                intent.data?.let { onStartCopy(it, intent.getStringExtra(EXTRA_OBJECT_ID)!!) }\n            }\n            ACTION_CANCEL -> terminateService()\n        }\n        return START_REDELIVER_INTENT\n    }\n\n    private fun onStartCopy(uri: Uri, id: String) {\n        // Check if we have access to the storage\n        if (Environment.getExternalStorageState() != Environment.MEDIA_MOUNTED) {\n            terminateService(BROADCAST_IMPORT_FAILED)\n            return\n        }\n        sendLocalBroadcast(BROADCAST_IMPORT_ONGOING)\n\n        try {\n            contentResolver.openInputStream(uri)?.use {\n                // Use the attachment id to link the raw file\n                // to the database\n                // note: need to remove the target column in the database as it becomes redundant.\n                val fileName = uri.getFileName(this)\n                val extension = File(fileName).extension\n\n                val targetFile = File(targetDirectory, \"${id}.${extension}\")\n                FileUtils.copyToFile(it, targetFile)\n\n                broadcastResultThenTerminate(id, fileName)\n            }\n        } catch (e: Exception) {\n\n            e.printStackTrace()\n            terminateService(BROADCAST_IMPORT_FAILED)\n        }\n    }\n\n    /**\n     *  Sends the required data back to the activity then\n     *  terminates itself.\n     *  @param id the attachment id that the file will be linked in\n     *  @param name the original file name of the file\n     */\n    private fun broadcastResultThenTerminate(id: String, name: String) {\n        LocalBroadcastManager.getInstance(this)\n            .sendBroadcast(Intent(ACTION_SERVICE_BROADCAST).apply {\n\n                // This function is only called when the import is\n                // completed and therefore we should just\n                // put a completed status in the broadcast\n                putExtra(EXTRA_BROADCAST_STATUS, BROADCAST_IMPORT_COMPLETED)\n\n                // Send the attachment id back to the calling activity\n                putExtra(EXTRA_BROADCAST_DATA, id)\n\n                // Send the file name back to the calling activity\n                putExtra(EXTRA_BROADCAST_EXTRA, name)\n            })\n        stopSelf()\n    }\n\n    companion object {\n        const val ACTION_START = \"action:start\"\n        const val ACTION_CANCEL = \"action:cancel\"\n\n        const val EXTRA_OBJECT_ID = \"extra:id\"\n        const val EXTRA_BROADCAST_EXTRA = \"extra:broadcast:extra\"\n\n        const val BROADCAST_IMPORT_ONGOING = \"broadcast:attachment:ongoing\"\n        const val BROADCAST_IMPORT_COMPLETED = \"broadcast:attachment:completed\"\n        const val BROADCAST_IMPORT_FAILED = \"broadcast:attachment:failed\"\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/service/NotificationActionService.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.service\r\n\r\nimport android.app.IntentService\r\nimport android.app.NotificationManager\r\nimport android.content.Context\r\nimport android.content.Intent\r\nimport androidx.work.Data\r\nimport androidx.work.OneTimeWorkRequest\r\nimport androidx.work.WorkManager\r\nimport com.isaiahvonrundstedt.fokus.features.core.worker.ActionWorker\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseWorker\r\n\r\n// This service function is to trigger the worker\r\n// that will perform the appropriate action\r\n// based on what the user tapped on the fokus\r\n// Since PendingIntents can trigger Workers, this service\r\n// acts like a middle man\r\nclass NotificationActionService : IntentService(SERVICE_NAME) {\r\n\r\n\r\n    private val manager by lazy {\r\n        getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager\r\n    }\r\n\r\n    @Deprecated(\"Deprecated in Java\")\r\n    override fun onHandleIntent(intent: Intent?) {\r\n        val taskID = intent?.getStringExtra(EXTRA_TASK_ID)\r\n        val isPersistent = intent?.getBooleanExtra(EXTRA_IS_PERSISTENT, false) ?: false\r\n\r\n        if (isPersistent)\r\n            manager?.cancel(taskID, BaseWorker.NOTIFICATION_ID_TASK)\r\n        else manager?.cancel(BaseWorker.NOTIFICATION_TAG_TASK, BaseWorker.NOTIFICATION_ID_TASK)\r\n\r\n        val data = Data.Builder()\r\n        data.putString(EXTRA_TASK_ID, taskID)\r\n        if (intent?.action == ACTION_FINISHED)\r\n            data.putString(EXTRA_ACTION, ACTION_FINISHED)\r\n\r\n        val workRequest = OneTimeWorkRequest.Builder(ActionWorker::class.java)\r\n            .setInputData(data.build())\r\n            .addTag(ActionWorker::class.java.simpleName)\r\n            .build()\r\n        WorkManager.getInstance(this).enqueue(workRequest)\r\n    }\r\n\r\n    companion object {\r\n        const val SERVICE_NAME = \"service:notification:actions\"\r\n        const val EXTRA_TASK_ID = \"extra:taskID\"\r\n        const val EXTRA_IS_PERSISTENT = \"extra:isPersistent\"\r\n        const val EXTRA_ACTION = \"extra:action\"\r\n\r\n        const val ACTION_FINISHED = \"action:finished\"\r\n\r\n        const val NOTIFICATION_ID_FINISH = 28\r\n    }\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/utils/DataArchiver.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.utils\n\nimport android.content.Context\nimport android.net.Uri\nimport org.apache.commons.io.FileUtils\nimport java.io.*\nimport java.util.zip.ZipEntry\nimport java.util.zip.ZipFile\nimport java.util.zip.ZipOutputStream\n\nclass DataArchiver private constructor(private var context: Context) {\n\n    private var uri: Uri? = null\n    private var destination: File? = null\n    private var items = mutableListOf<File>()\n\n    fun archive() {\n        if (destination != null) {\n            FileOutputStream(destination).use {\n                ZipOutputStream(BufferedOutputStream(it)).use { outputStream ->\n                    setEntries(outputStream)\n                }\n            }\n        } else if (uri != null) {\n            context.contentResolver.openOutputStream(uri!!)?.use {\n                ZipOutputStream(BufferedOutputStream(it)).use { outputStream ->\n                    setEntries(outputStream)\n                }\n            }\n        }\n    }\n\n    private fun setEntries(zip: ZipOutputStream) {\n        items.forEach {\n            if (it.isDirectory) {\n                zip.putNextEntry(ZipEntry(\"${it.name}/\"))\n                for (source: File in it.listFiles()!!) {\n                    onCopyToOutputStream(zip, \"${it.name}/${source.name}\", source)\n                }\n            } else onCopyToOutputStream(zip, it.name, it)\n        }\n    }\n\n    private fun onCopyToOutputStream(zip: ZipOutputStream, entryName: String, source: File) {\n        BufferedInputStream(FileInputStream(source), BUFFER).use { stream ->\n            zip.putNextEntry(ZipEntry(entryName))\n            stream.copyTo(zip, BUFFER)\n        }\n    }\n\n\n    class Create(context: Context) {\n        private var zip = DataArchiver(context)\n\n        fun addSource(items: List<File>): Create {\n            zip.items.addAll(items)\n            return this\n        }\n\n        fun addSource(file: File): Create {\n            zip.items.add(file)\n            return this\n        }\n\n        fun toDestination(uri: Uri): Create {\n            zip.uri = uri\n            return this\n        }\n\n        fun toDestination(file: File): Create {\n            zip.destination = file\n            return this\n        }\n\n        fun start() = zip.archive()\n    }\n\n    companion object {\n        private const val BUFFER = 4096\n        private const val FILE_TEMP_WORKING_FILE = \"temp.fts\"\n\n        fun parseInputStream(context: Context, stream: InputStream?): ZipFile {\n            val temp = File(context.cacheDir, FILE_TEMP_WORKING_FILE)\n            FileUtils.copyToFile(stream, temp)\n            return ZipFile(temp)\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/utils/NotificationChannelManager.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.utils\n\nimport android.app.NotificationChannel\nimport android.app.NotificationChannelGroup\nimport android.app.NotificationManager\nimport android.content.Context\nimport android.media.AudioAttributes\nimport android.net.Uri\nimport androidx.annotation.RequiresApi\nimport androidx.annotation.StringRes\nimport androidx.core.app.NotificationManagerCompat\nimport com.isaiahvonrundstedt.fokus.R\n\nclass NotificationChannelManager(private var context: Context) {\n\n    private val manager = NotificationManagerCompat.from(context)\n\n    @RequiresApi(26)\n    fun register(\n        id: String,\n        importance: Int = NotificationManager.IMPORTANCE_HIGH,\n        groupID: String? = null\n    ) {\n\n        if (groupID != null && manager.getNotificationChannelGroup(groupID) == null) {\n            manager.createNotificationChannelGroup(createGroup(groupID))\n        }\n\n        manager.createNotificationChannel(createChannel(id, importance, groupID))\n    }\n\n    @RequiresApi(26)\n    private fun createChannel(\n        id: String,\n        importance: Int = NotificationManager.IMPORTANCE_HIGH,\n        groupID: String?\n    ): NotificationChannel {\n        return NotificationChannel(id, context.getString(getChannelNameRes(id)), importance).apply {\n            setSound(notificationSoundUri, attributes)\n            group = groupID\n        }\n    }\n\n    @RequiresApi(26)\n    private fun createGroup(id: String): NotificationChannelGroup {\n        return NotificationChannelGroup(id, context.getString(getGroupNameRes(id)))\n    }\n\n    @StringRes\n    private fun getChannelNameRes(id: String): Int {\n        return when (id) {\n            CHANNEL_ID_TASK -> R.string.notification_channel_task_reminders\n            CHANNEL_ID_EVENT -> R.string.notification_channel_event_reminders\n            CHANNEL_ID_CLASS -> R.string.notification_channel_class_reminders\n            CHANNEL_ID_GENERIC -> R.string.notification_channel_general\n            else -> 0\n        }\n    }\n\n    @StringRes\n    private fun getGroupNameRes(id: String): Int {\n        return when (id) {\n            CHANNEL_GROUP_ID_REMINDERS -> R.string.notification_channel_group_reminders\n            else -> 0\n        }\n    }\n\n    private val attributes: AudioAttributes\n        get() = AudioAttributes.Builder()\n            .setUsage(AudioAttributes.USAGE_NOTIFICATION)\n            .build()\n\n    private val notificationSoundUri: Uri\n        get() = Uri.parse(PreferenceManager.DEFAULT_SOUND)\n\n    companion object {\n        const val CHANNEL_ID_TASK = \"channel:task\"\n        const val CHANNEL_ID_EVENT = \"channel:event\"\n        const val CHANNEL_ID_CLASS = \"channel:class\"\n        const val CHANNEL_ID_GENERIC = \"channel:generic\"\n\n        const val CHANNEL_GROUP_ID_REMINDERS = \"group:reminders\"\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/utils/PermissionManager.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.utils\n\nimport android.Manifest\nimport android.content.Context\nimport android.content.pm.PackageManager\nimport android.os.Build\n\nclass PermissionManager(var context: Context) {\n\n    val readStorageGranted: Boolean\n        get() {\n            return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)\n                context.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED\n            else true\n        }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/utils/PreferenceManager.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.utils\n\nimport android.content.ContentResolver\nimport android.content.Context\nimport androidx.preference.PreferenceManager\nimport com.isaiahvonrundstedt.fokus.BuildConfig\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.enums.SortDirection\nimport com.isaiahvonrundstedt.fokus.database.converter.DateTimeConverter\nimport com.isaiahvonrundstedt.fokus.features.subject.SubjectViewModel\nimport com.isaiahvonrundstedt.fokus.features.task.TaskViewModel\nimport java.time.LocalTime\nimport java.time.ZonedDateTime\n\nclass PreferenceManager(private val context: Context) {\n\n    enum class Theme {\n        SYSTEM, DARK, LIGHT;\n\n        companion object {\n            fun parse(s: String?): Theme {\n                return when (s) {\n                    DARK.toString() -> DARK\n                    LIGHT.toString() -> LIGHT\n                    else -> SYSTEM\n                }\n            }\n        }\n    }\n\n    var theme: Theme\n        get() = Theme.parse(\n            sharedPreference.getString(\n                PREFERENCE_THEME,\n                Theme.SYSTEM.toString()\n            )\n        )\n        set(value) {\n            sharedPreference.edit().run {\n                putString(PREFERENCE_THEME, value.toString())\n                apply()\n            }\n        }\n\n    var previousBackupDate: ZonedDateTime?\n        get() = DateTimeConverter.toZonedDateTime(\n            sharedPreference.getString(PREFERENCE_BACKUP, null)\n        )\n        set(value) {\n            sharedPreference.edit().run {\n                putString(\n                    PREFERENCE_BACKUP,\n                    DateTimeConverter.fromZonedDateTime(value)\n                )\n                apply()\n            }\n        }\n\n    var reminderTime: LocalTime?\n        get() = DateTimeConverter.toLocalTime(\n            sharedPreference.getString(PREFERENCE_REMINDER_TIME, \"08:30\")\n        )\n        set(value) {\n            sharedPreference.edit().run {\n                putString(PREFERENCE_REMINDER_TIME, DateTimeConverter.fromLocalTime(value))\n                apply()\n            }\n        }\n\n    var taskConstraint: TaskViewModel.Constraint\n        get() = TaskViewModel.Constraint.parse(\n            sharedPreference.getString(\n                PREFERENCE_TASK_FILTER_OPTION,\n                TaskViewModel.Constraint.ALL.toString()\n            ) ?: TaskViewModel.Constraint.ALL.toString()\n        )\n        set(value) {\n            sharedPreference.edit().run {\n                putString(PREFERENCE_TASK_FILTER_OPTION, value.toString())\n                apply()\n            }\n        }\n\n    var tasksSort: TaskViewModel.Sort\n        get() = TaskViewModel.Sort.parse(\n            sharedPreference.getString(\n                PREFERENCE_TASK_SORT_OPTION,\n                TaskViewModel.Sort.NAME.toString()\n            ) ?: TaskViewModel.Sort.NAME.toString()\n        )\n        set(value) {\n            sharedPreference.edit().run {\n                putString(PREFERENCE_TASK_SORT_OPTION, value.toString())\n                apply()\n            }\n        }\n\n    var tasksSortDirection: SortDirection\n        get() = SortDirection.parse(\n            sharedPreference.getString(\n                PREFERENCE_TASK_SORT_DIRECTION,\n                SortDirection.ASCENDING.toString()\n            )\n        )\n        set(value) {\n            sharedPreference.edit().run {\n                putString(PREFERENCE_TASK_SORT_DIRECTION, value.toString())\n                apply()\n            }\n        }\n\n    var subjectConstraint: SubjectViewModel.Constraint\n        get() = SubjectViewModel.Constraint.parse(\n            sharedPreference.getString(\n                PREFERENCE_SUBJECT_FILTER_OPTION,\n                SubjectViewModel.Constraint.ALL.toString()\n            ) ?: SubjectViewModel.Constraint.ALL.toString()\n        )\n        set(value) {\n            sharedPreference.edit().run {\n                putString(PREFERENCE_SUBJECT_FILTER_OPTION, value.toString())\n                apply()\n            }\n        }\n\n    var subjectSort: SubjectViewModel.Sort\n        get() = SubjectViewModel.Sort.parse(\n            sharedPreference.getString(\n                PREFERENCE_SUBJECT_SORT_OPTION,\n                SubjectViewModel.Sort.CODE.toString()\n            ) ?: SubjectViewModel.Sort.CODE.toString()\n        )\n        set(value) {\n            sharedPreference.edit().run {\n                putString(PREFERENCE_SUBJECT_SORT_OPTION, value.toString())\n                apply()\n            }\n        }\n\n    var subjectSortDirection: SortDirection\n        get() = SortDirection.parse(\n            sharedPreference.getString(\n                PREFERENCE_SUBJECT_SORT_DIRECTION,\n                SortDirection.ASCENDING.toString()\n            ) ?: SubjectViewModel.Sort.CODE.toString()\n        )\n        set(value) {\n            sharedPreference.edit().run {\n                putString(PREFERENCE_SUBJECT_SORT_DIRECTION, value.toString())\n                apply()\n            }\n        }\n\n    val confetti: Boolean\n        get() = sharedPreference.getBoolean(PREFERENCE_CONFETTI, true)\n\n    val sounds: Boolean\n        get() = sharedPreference.getBoolean(PREFERENCE_SOUND, true)\n\n    val taskReminder: Boolean\n        get() = sharedPreference.getBoolean(PREFERENCE_TASK_NOTIFICATION, true)\n\n    val eventReminder: Boolean\n        get() = sharedPreference.getBoolean(PREFERENCE_EVENT_NOTIFICATION, true)\n\n    val subjectReminder: Boolean\n        get() = sharedPreference.getBoolean(PREFERENCE_COURSE_NOTIFICATION, true)\n\n    val useExternalBrowser: Boolean\n        get() = sharedPreference.getBoolean(PREFERENCE_USE_EXTERNAL_BROWSER, false)\n\n    val allowWeekNumbers: Boolean\n        get() = sharedPreference.getBoolean(PREFERENCE_ALLOW_WEEK_NUMBERS, false)\n\n    val reminderFrequency: String\n        get() = sharedPreference.getString(\n            PREFERENCE_REMINDER_FREQUENCY,\n            DURATION_EVERYDAY\n        ) ?: DURATION_EVERYDAY\n\n    val taskReminderInterval: String\n        get() = sharedPreference.getString(\n            PREFERENCE_TASK_NOTIFICATION_INTERVAL,\n            TASK_REMINDER_INTERVAL_3_HOURS\n        ) ?: TASK_REMINDER_INTERVAL_3_HOURS\n\n    val eventReminderInterval: String\n        get() = sharedPreference.getString(\n            PREFERENCE_EVENT_NOTIFICATION_INTERVAL,\n            EVENT_REMINDER_INTERVAL_30_MINUTES\n        ) ?: EVENT_REMINDER_INTERVAL_30_MINUTES\n\n    val subjectReminderInterval: String\n        get() = sharedPreference.getString(\n            PREFERENCE_COURSE_NOTIFICATION_INTERVAL,\n            SUBJECT_REMINDER_INTERVAL_30_MINUTES\n        ) ?: SUBJECT_REMINDER_INTERVAL_30_MINUTES\n\n\n    /* User-Defined Settings */\n    var noConfirmImport: Boolean\n        get() = sharedPreference.getBoolean(\n            PREFERENCE_NO_CONFIRM_IMPORT,\n            false\n        )\n        set(value) {\n            sharedPreference.edit().run {\n                putBoolean(PREFERENCE_NO_CONFIRM_IMPORT, value)\n                commit()\n            }\n        }\n\n    private val sharedPreference by lazy {\n        PreferenceManager.getDefaultSharedPreferences(context)\n    }\n\n    companion object {\n        const val DEFAULT_SOUND =\n            \"${ContentResolver.SCHEME_ANDROID_RESOURCE}://${BuildConfig.APPLICATION_ID}/${R.raw.fokus}\"\n\n        const val DURATION_EVERYDAY = \"EVERYDAY\"\n        const val DURATION_WEEKENDS = \"WEEKENDS\"\n\n        const val TASK_REMINDER_INTERVAL_1_HOUR = \"1\"\n        const val TASK_REMINDER_INTERVAL_3_HOURS = \"3\"\n        const val TASK_REMINDER_INTERVAL_24_HOURS = \"24\"\n\n        const val EVENT_REMINDER_INTERVAL_15_MINUTES = \"15\"\n        const val EVENT_REMINDER_INTERVAL_30_MINUTES = \"30\"\n        const val EVENT_REMINDER_INTERVAL_60_MINUTES = \"60\"\n\n        const val SUBJECT_REMINDER_INTERVAL_5_MINUTES = \"5\"\n        const val SUBJECT_REMINDER_INTERVAL_15_MINUTES = \"15\"\n        const val SUBJECT_REMINDER_INTERVAL_30_MINUTES = \"30\"\n\n        // Preferences that are visible in the SettingsActivity\n        const val PREFERENCE_THEME = \"KEY_THEME\"\n        const val PREFERENCE_CONFETTI = \"KEY_CONFETTI\"\n        const val PREFERENCE_SOUND = \"KEY_SOUND\"\n        const val PREFERENCE_REMINDER_FREQUENCY = \"KEY_REMINDER_FREQUENCY\"\n        const val PREFERENCE_REMINDER_TIME = \"KEY_REMINDER_TIME\"\n        const val PREFERENCE_TASK_NOTIFICATION = \"KEY_TASK_NOTIFICATION\"\n        const val PREFERENCE_TASK_NOTIFICATION_INTERVAL = \"KEY_TASK_NOTIFICATION_INTERVAL\"\n        const val PREFERENCE_EVENT_NOTIFICATION = \"KEY_EVENT_NOTIFICATION\"\n        const val PREFERENCE_EVENT_NOTIFICATION_INTERVAL = \"KEY_EVENT_NOTIFICATION_INTERVAL\"\n        const val PREFERENCE_COURSE_NOTIFICATION = \"KEY_COURSE_NOTIFICATION\"\n        const val PREFERENCE_COURSE_NOTIFICATION_INTERVAL = \"KEY_COURSE_NOTIFICATION_INTERVAL\"\n        const val PREFERENCE_SYSTEM_NOTIFICATION = \"KEY_SYSTEM_NOTIFICATION\"\n        const val PREFERENCE_ALLOW_WEEK_NUMBERS = \"KEY_ALLOW_WEEK_NUMBERS\"\n        const val PREFERENCE_BACKUP_RESTORE = \"KEY_BACKUP_RESTORE\"\n        const val PREFERENCE_BACKUP = \"KEY_BACKUP\"\n        const val PREFERENCE_RESTORE = \"KEY_RESTORE\"\n        const val PREFERENCE_USE_EXTERNAL_BROWSER = \"KEY_USE_EXTERNAL_BROWSER\"\n        const val PREFERENCE_BATTERY_OPTIMIZATION = \"KEY_BATTERY_OPTIMIZATION\"\n\n        // Preferences that are visible in AboutActivity\n        const val PREFERENCE_REPORT_ISSUE = \"KEY_REPORT_ISSUE\"\n        const val PREFERENCE_TRANSLATE = \"KEY_TRANSLATE\"\n        const val PREFERENCE_NOTICES = \"KEY_NOTICES\"\n        const val PREFERENCE_VERSION = \"KEY_VERSION\"\n\n        // Preferences that are visible in NoticesActivity\n        const val PREFERENCE_LIBRARIES = \"KEY_LIBRARIES\"\n        const val PREFERENCE_NOTIFICATION_SOUND = \"KEY_NOTIFICATION_SOUND\"\n        const val PREFERENCE_LAUNCHER_ICON = \"KEY_LAUNCHER_ICON\"\n        const val PREFERENCE_UI_ICONS = \"KEY_UI_ICONS\"\n\n        // Preferences that are not visible in anywhere and are only\n        // used for remembering user choices in the UI\n        const val PREFERENCE_NO_CONFIRM_IMPORT = \"KEY_NO_CONFIRM_IMPORT\"\n        const val PREFERENCE_TASK_FILTER_OPTION = \"KEY_TASKS_FILTER_OPTION\"\n        const val PREFERENCE_TASK_SORT_OPTION = \"KEY_TASK_SORT_OPTION\"\n        const val PREFERENCE_TASK_SORT_DIRECTION = \"KEY_TASK_SORT_DIRECTION\"\n        const val PREFERENCE_SUBJECT_FILTER_OPTION = \"KEY_SUBJECT_FILTER_OPTION\"\n        const val PREFERENCE_SUBJECT_SORT_OPTION = \"KEY_SUBJECT_SORT_OPTION\"\n        const val PREFERENCE_SUBJECT_SORT_DIRECTION = \"KEY_SUBJECT_SORT_DIRECTION\"\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/views/RadioButtonCompat.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.views\n\nimport android.content.Context\nimport android.os.Build\nimport android.util.AttributeSet\nimport androidx.annotation.StyleRes\nimport androidx.appcompat.widget.AppCompatRadioButton\nimport com.isaiahvonrundstedt.fokus.R\n\nopen class RadioButtonCompat @JvmOverloads constructor(\n    context: Context,\n    attributeSet: AttributeSet? = null,\n    defStyleAttr: Int = R.attr.radioButtonStyle\n) : AppCompatRadioButton(context, attributeSet, defStyleAttr) {\n\n    init {\n        val typedArray = context.obtainStyledAttributes(\n            attributeSet,\n            R.styleable.RadioButtonCompat,\n            defStyleAttr,\n            0\n        )\n\n        try {\n            val textAppearance = typedArray.getResourceId(\n                R.styleable.RadioButtonCompat_textAppearanceCompat,\n                R.style.Fokus_TextAppearance_Body_Medium\n            )\n            setTextAppearanceCompat(textAppearance)\n        } catch (e: Exception) {\n        }\n        typedArray.recycle()\n    }\n\n    @Suppress(\"DEPRECATION\")\n    fun setTextAppearanceCompat(@StyleRes resId: Int) {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)\n            this.setTextAppearance(resId)\n        else this.setTextAppearance(context, resId)\n    }\n\n    override fun onAttachedToWindow() {\n        super.onAttachedToWindow()\n        setPaddingRelative(16, 0, 16, 0)\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/views/ReactiveTextColorSwitch.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.views\n\nimport android.content.Context\nimport android.util.AttributeSet\nimport androidx.annotation.ColorRes\nimport androidx.core.content.ContextCompat\nimport com.google.android.material.switchmaterial.SwitchMaterial\nimport com.isaiahvonrundstedt.fokus.R\n\nclass ReactiveTextColorSwitch @JvmOverloads constructor(\n    context: Context,\n    attributeSet: AttributeSet? = null,\n    defStyleAttr: Int = R.attr.switchStyle\n) : SwitchMaterial(context, attributeSet, defStyleAttr) {\n\n    init {\n        setSwitchTextAppearance(context, R.style.Fokus_TextAppearance_Label_Large)\n    }\n\n    override fun setChecked(checked: Boolean) {\n        super.setChecked(checked)\n        if (checked)\n            setTextColorRes(R.color.color_primary_text)\n        else setTextColorRes(R.color.color_secondary_text)\n    }\n\n    private fun setTextColorRes(@ColorRes resId: Int) {\n        setTextColor(ContextCompat.getColor(context, resId))\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/components/views/TwoLineRadioButton.kt",
    "content": "package com.isaiahvonrundstedt.fokus.components.views\n\nimport android.content.Context\nimport android.os.Build\nimport android.text.SpannableString\nimport android.text.SpannableStringBuilder\nimport android.text.style.ForegroundColorSpan\nimport android.text.style.TextAppearanceSpan\nimport android.util.AttributeSet\nimport androidx.core.content.ContextCompat\nimport com.isaiahvonrundstedt.fokus.R\n\nclass TwoLineRadioButton @JvmOverloads constructor(\n    context: Context,\n    attributeSet: AttributeSet? = null,\n    defStyleAttr: Int = R.attr.radioButtonStyle\n) : RadioButtonCompat(context, attributeSet, defStyleAttr) {\n\n    private val titleSpan: TextAppearanceSpan\n    private val subtitleSpan: TextAppearanceSpan\n\n    private var titleTextColorSpan: ForegroundColorSpan\n    private var subtitleTextColorSpan: ForegroundColorSpan\n\n    var title: String = \"\"\n        set(value) {\n            field = value\n            renderText()\n        }\n\n    var subtitle: String? = null\n        set(value) {\n            field = value\n            renderText()\n        }\n\n    var titleTextColor: Int = ContextCompat.getColor(context, R.color.color_secondary_text)\n        set(value) {\n            field = value\n            renderText()\n        }\n\n    var subtitleTextColor: Int = ContextCompat.getColor(context, R.color.color_secondary_text)\n        set(value) {\n            field = value\n            renderText()\n        }\n\n    init {\n        val typedArray = context.obtainStyledAttributes(\n            attributeSet,\n            R.styleable.TwoLineRadioButton,\n            defStyleAttr, 0\n        )\n\n        try {\n            title = typedArray.getString(R.styleable.TwoLineRadioButton_titleText) ?: \"\"\n            subtitle = typedArray.getString(R.styleable.TwoLineRadioButton_subtitleText)\n\n            titleTextColor = typedArray.getColor(\n                R.styleable.TwoLineRadioButton_titleTextColor,\n                titleTextColor\n            )\n            subtitleTextColor = typedArray.getColor(\n                R.styleable.TwoLineRadioButton_subtitleTextColor,\n                subtitleTextColor\n            )\n\n            val titleTextAppearance = typedArray.getResourceId(\n                R.styleable.TwoLineRadioButton_titleTextAppearance,\n                R.style.TextAppearance_AppCompat_Body1\n            )\n            titleSpan = TextAppearanceSpan(context, titleTextAppearance)\n            titleTextColorSpan = ForegroundColorSpan(titleTextColor)\n\n            val subtitleTextAppearance = typedArray.getResourceId(\n                R.styleable.TwoLineRadioButton_subtitleTextAppearance,\n                R.style.TextAppearance_AppCompat_Caption\n            )\n            subtitleSpan = TextAppearanceSpan(context, subtitleTextAppearance)\n            subtitleTextColorSpan = ForegroundColorSpan(subtitleTextColor)\n\n        } finally {\n            typedArray.recycle()\n        }\n\n        renderText()\n    }\n\n    private fun renderText() {\n        titleTextColorSpan = ForegroundColorSpan(titleTextColor)\n        subtitleTextColorSpan = ForegroundColorSpan(subtitleTextColor)\n\n        val textToRender = if (subtitle.isNullOrEmpty()) title\n        else \"$title\\n$subtitle\"\n\n        val builder = SpannableStringBuilder(textToRender).apply {\n            setSpan(\n                titleSpan, 0, title.length,\n                SpannableString.SPAN_INCLUSIVE_EXCLUSIVE\n            )\n            setSpan(\n                titleTextColorSpan, 0, title.length,\n                SpannableString.SPAN_INCLUSIVE_EXCLUSIVE\n            )\n\n            subtitle?.also {\n                if (it.isNotEmpty()) {\n                    setSpan(\n                        subtitleSpan, title.length,\n                        title.length + it.length + 1, SpannableString.SPAN_EXCLUSIVE_INCLUSIVE\n                    )\n                    setSpan(\n                        subtitleTextColorSpan, title.length,\n                        title.length + it.length + 1, SpannableString.SPAN_EXCLUSIVE_INCLUSIVE\n                    )\n                }\n            }\n        }\n\n        text = if (Build.VERSION.SDK_INT == Build.VERSION_CODES.P)\n            builder.toString()\n        else builder\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/database/AppDatabase.kt",
    "content": "package com.isaiahvonrundstedt.fokus.database\r\n\r\nimport android.content.Context\r\nimport androidx.room.Database\r\nimport androidx.room.Room\r\nimport androidx.room.RoomDatabase\r\nimport androidx.room.TypeConverters\r\nimport androidx.room.migration.Migration\r\nimport androidx.sqlite.db.SupportSQLiteDatabase\r\nimport com.isaiahvonrundstedt.fokus.database.converter.ColorConverter\r\nimport com.isaiahvonrundstedt.fokus.database.converter.DateTimeConverter\r\nimport com.isaiahvonrundstedt.fokus.database.dao.*\r\nimport com.isaiahvonrundstedt.fokus.features.attachments.Attachment\r\nimport com.isaiahvonrundstedt.fokus.features.event.Event\r\nimport com.isaiahvonrundstedt.fokus.features.log.Log\r\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\r\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\r\nimport com.isaiahvonrundstedt.fokus.features.task.Task\r\nimport java.time.ZonedDateTime\r\n\r\n@Database(\r\n    entities = [Subject::class, Task::class, Attachment::class, Log::class, Event::class, Schedule::class],\r\n    version = AppDatabase.DATABASE_VERSION,\r\n    exportSchema = true\r\n)\r\n@TypeConverters(DateTimeConverter::class, ColorConverter::class)\r\nabstract class AppDatabase : RoomDatabase() {\r\n\r\n    abstract fun subjects(): SubjectDAO\r\n    abstract fun schedules(): ScheduleDAO\r\n    abstract fun tasks(): TaskDAO\r\n    abstract fun attachments(): AttachmentDAO\r\n    abstract fun events(): EventDAO\r\n    abstract fun logs(): LogDAO\r\n\r\n    companion object {\r\n        const val DATABASE_VERSION = 8\r\n        private const val DATABASE_NAME = \"fokus\"\r\n\r\n        private var instance: AppDatabase? = null\r\n\r\n        fun getInstance(context: Context): AppDatabase {\r\n            if (instance == null) {\r\n                synchronized(AppDatabase::class) {\r\n                    instance = Room.databaseBuilder(\r\n                        context.applicationContext,\r\n                        AppDatabase::class.java, DATABASE_NAME\r\n                    )\r\n                        .addMigrations(*migrations)\r\n                        .build()\r\n                }\r\n            }\r\n            return instance!!\r\n        }\r\n\r\n        private var migration_4_6 = object : Migration(4, 6) {\r\n            override fun migrate(database: SupportSQLiteDatabase) {\r\n                with(database) {\r\n                    // schedules\r\n                    execSQL(\"CREATE TABLE IF NOT EXISTS `schedules_new` (`scheduleID` TEXT NOT NULL, `daysOfWeek` INTEGER NOT NULL, `weeksOfMonth` INTEGER NOT NULL DEFAULT 15,`startTime` TEXT, `endTime` TEXT, `subject` TEXT, PRIMARY KEY(`scheduleID`), FOREIGN KEY(`subject`) REFERENCES `subjects`(`subjectID`) ON UPDATE NO ACTION ON DELETE CASCADE )\")\r\n                    execSQL(\"ALTER TABLE schedules RENAME TO schedules_old\")\r\n                    execSQL(\"ALTER TABLE schedules_new RENAME TO schedules\")\r\n                    execSQL(\"INSERT INTO schedules (`scheduleID`, `daysOfWeek`, `startTime`, `endTime`, `subject`) SELECT * FROM `schedules_old`\")\r\n                    execSQL(\"DROP TABLE schedules_old\")\r\n\r\n                    execSQL(\"ALTER TABLE tasks ADD COLUMN `isTaskArchived` INTEGER NOT NULL DEFAULT 0\")\r\n                    execSQL(\"ALTER TABLE events ADD COLUMN `isEventArchived` INTEGER NOT NULL DEFAULT 0\")\r\n                    execSQL(\"ALTER TABLE subjects ADD COLUMN `isSubjectArchived` INTEGER NOT NULL DEFAULT 0\")\r\n                }\r\n            }\r\n        }\r\n\r\n        private var migration_5_6 = object : Migration(5, 6) {\r\n            override fun migrate(database: SupportSQLiteDatabase) {\r\n                with(database) {\r\n                    execSQL(\"ALTER TABLE tasks ADD COLUMN `isTaskArchived` INTEGER NOT NULL DEFAULT 0\")\r\n                    execSQL(\"ALTER TABLE events ADD COLUMN `isEventArchived` INTEGER NOT NULL DEFAULT 0\")\r\n                    execSQL(\"ALTER TABLE subjects ADD COLUMN `isSubjectArchived` INTEGER NOT NULL DEFAULT 0\")\r\n                }\r\n            }\r\n        }\r\n\r\n        private var migration_4_7 = object : Migration(4, 7) {\r\n            override fun migrate(database: SupportSQLiteDatabase) {\r\n                with(database) {\r\n                    // schedules\r\n                    execSQL(\"CREATE TABLE IF NOT EXISTS `schedules_new` (`scheduleID` TEXT NOT NULL, `daysOfWeek` INTEGER NOT NULL, `weeksOfMonth` INTEGER NOT NULL DEFAULT 15,`startTime` TEXT, `endTime` TEXT, `subject` TEXT, PRIMARY KEY(`scheduleID`), FOREIGN KEY(`subject`) REFERENCES `subjects`(`subjectID`) ON UPDATE NO ACTION ON DELETE CASCADE )\")\r\n                    execSQL(\"ALTER TABLE schedules RENAME TO schedules_old\")\r\n                    execSQL(\"ALTER TABLE schedules_new RENAME TO schedules\")\r\n                    execSQL(\"INSERT INTO schedules (`scheduleID`, `daysOfWeek`, `startTime`, `endTime`, `subject`) SELECT * FROM `schedules_old`\")\r\n                    execSQL(\"DROP TABLE schedules_old\")\r\n\r\n                    execSQL(\"ALTER TABLE tasks ADD COLUMN `isTaskArchived` INTEGER NOT NULL DEFAULT 0\")\r\n                    execSQL(\"ALTER TABLE events ADD COLUMN `isEventArchived` INTEGER NOT NULL DEFAULT 0\")\r\n                    execSQL(\"ALTER TABLE subjects ADD COLUMN `isSubjectArchived` INTEGER NOT NULL DEFAULT 0\")\r\n                }\r\n\r\n                var cursor = database.query(\"SELECT * FROM tasks\")\r\n                cursor.moveToFirst()\r\n\r\n                val taskList = arrayListOf<Task>()\r\n                while (cursor.moveToNext()) {\r\n                    val task = Task()\r\n                    task.taskID = cursor.getString(cursor.getColumnIndex(\"taskID\"))\r\n                    task.name = cursor.getString(cursor.getColumnIndex(\"name\"))\r\n                    task.notes = cursor.getString(cursor.getColumnIndex(\"notes\"))\r\n                    task.subject = cursor.getString(cursor.getColumnIndex(\"subject\"))\r\n                    task.isFinished = cursor.getInt(cursor.getColumnIndex(\"isFinished\")) > 0\r\n                    task.isImportant = cursor.getInt(cursor.getColumnIndex(\"isImportant\")) > 0\r\n                    task.isTaskArchived = cursor.getInt(cursor.getColumnIndex(\"isTaskArchived\")) > 0\r\n                    task.dueDate =\r\n                        DateTimeConverter.toZonedDateTime(cursor.getString(cursor.getColumnIndex(\"dueDate\")))\r\n                    task.dateAdded =\r\n                        DateTimeConverter.toZonedDateTime(cursor.getString(cursor.getColumnIndex(\"dateAdded\")))\r\n                            ?: ZonedDateTime.now()\r\n\r\n                    taskList.add(task)\r\n                }\r\n                cursor.close()\r\n\r\n                database.execSQL(\"DELETE FROM tasks\")\r\n                taskList.forEach {\r\n                    val statement =\r\n                        database.compileStatement(\"INSERT INTO tasks VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\")\r\n                    with(statement) {\r\n                        bindString(1, it.taskID)\r\n                        bindString(2, it.name)\r\n                        bindString(3, it.notes)\r\n                        bindString(4, it.subject)\r\n                        bindLong(5, if (it.isImportant) 1 else 0)\r\n                        bindString(6, DateTimeConverter.fromZonedDateTime(it.dateAdded))\r\n                        bindString(7, DateTimeConverter.fromZonedDateTime(it.dueDate))\r\n                        bindLong(8, if (it.isFinished) 1 else 0)\r\n                        bindLong(9, if (it.isTaskArchived) 1 else 0)\r\n                    }\r\n                    statement.executeInsert()\r\n                }\r\n                taskList.clear()\r\n\r\n                cursor = database.query(\"SELECT * FROM events\")\r\n                cursor.moveToFirst()\r\n\r\n                val eventList = arrayListOf<Event>()\r\n                while (cursor.moveToNext()) {\r\n                    val event = Event()\r\n                    event.eventID = cursor.getString(cursor.getColumnIndex(\"eventID\"))\r\n                    event.name = cursor.getString(cursor.getColumnIndex(\"name\"))\r\n                    event.notes = cursor.getString(cursor.getColumnIndex(\"notes\"))\r\n                    event.schedule =\r\n                        DateTimeConverter.toZonedDateTime(cursor.getString(cursor.getColumnIndex(\"schedule\")))\r\n                    event.location = cursor.getString(cursor.getColumnIndex(\"location\"))\r\n                    event.isImportant = cursor.getInt(cursor.getColumnIndex(\"isImportant\")) > 0\r\n                    event.isEventArchived =\r\n                        cursor.getInt(cursor.getColumnIndex(\"isEventArchived\")) > 0\r\n                    event.dateAdded =\r\n                        DateTimeConverter.toZonedDateTime(cursor.getString(cursor.getColumnIndex(\"dateAdded\")))\r\n                            ?: ZonedDateTime.now()\r\n                }\r\n                cursor.close()\r\n\r\n                database.execSQL(\"DELETE FROM events\")\r\n                eventList.forEach {\r\n                    val statement =\r\n                        database.compileStatement(\"INSERT INTO events VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\")\r\n                    with(statement) {\r\n                        bindString(1, it.eventID)\r\n                        bindString(2, it.name)\r\n                        bindString(3, it.location)\r\n                        bindString(4, it.subject)\r\n                        bindLong(5, if (it.isImportant) 1 else 0)\r\n                        bindLong(6, if (it.isEventArchived) 1 else 0)\r\n                        bindString(7, DateTimeConverter.fromZonedDateTime(it.schedule))\r\n                        bindString(8, DateTimeConverter.fromZonedDateTime(it.dateAdded))\r\n\r\n                    }\r\n                    statement.executeInsert()\r\n                }\r\n                eventList.clear()\r\n            }\r\n        }\r\n\r\n        private var migration_5_7 = object : Migration(5, 7) {\r\n            override fun migrate(database: SupportSQLiteDatabase) {\r\n                with(database) {\r\n                    execSQL(\"ALTER TABLE tasks ADD COLUMN `isTaskArchived` INTEGER NOT NULL DEFAULT 0\")\r\n                    execSQL(\"ALTER TABLE events ADD COLUMN `isEventArchived` INTEGER NOT NULL DEFAULT 0\")\r\n                    execSQL(\"ALTER TABLE subjects ADD COLUMN `isSubjectArchived` INTEGER NOT NULL DEFAULT 0\")\r\n\r\n                    execSQL(\"CREATE TABLE IF NOT EXISTS `events_new` (`eventID` TEXT NOT NULL, `name` TEXT, `notes` TEXT, `location` TEXT, `subject` TEXT, `isImportant` INTEGER NOT NULL, `isEventArchived` INTEGER NOT NULL, `schedule` TEXT, `dateAdded` TEXT, PRIMARY KEY(`eventID`), FOREIGN KEY(`subject`) REFERENCES `subjects`(`subjectID`) ON UPDATE NO ACTION ON DELETE SET NULL )\")\r\n                    execSQL(\"INSERT INTO `events_new` SELECT * FROM `events`\")\r\n                    execSQL(\"DROP TABLE `events`\")\r\n                    execSQL(\"ALTER TABLE `events_new` RENAME TO `events`\")\r\n                }\r\n\r\n                var cursor = database.query(\"SELECT * FROM tasks\")\r\n                cursor.moveToFirst()\r\n\r\n                val taskList = arrayListOf<Task>()\r\n                while (cursor.moveToNext()) {\r\n                    val task = Task()\r\n                    task.taskID = cursor.getString(cursor.getColumnIndex(\"taskID\"))\r\n                    task.name = cursor.getString(cursor.getColumnIndex(\"name\"))\r\n                    task.notes = cursor.getString(cursor.getColumnIndex(\"notes\"))\r\n                    task.subject = cursor.getString(cursor.getColumnIndex(\"subject\"))\r\n                    task.isFinished = cursor.getInt(cursor.getColumnIndex(\"isFinished\")) > 0\r\n                    task.isImportant = cursor.getInt(cursor.getColumnIndex(\"isImportant\")) > 0\r\n                    task.isTaskArchived = cursor.getInt(cursor.getColumnIndex(\"isTaskArchived\")) > 0\r\n                    task.dueDate =\r\n                        DateTimeConverter.toZonedDateTime(cursor.getString(cursor.getColumnIndex(\"dueDate\")))\r\n                    task.dateAdded =\r\n                        DateTimeConverter.toZonedDateTime(cursor.getString(cursor.getColumnIndex(\"dateAdded\")))\r\n                            ?: ZonedDateTime.now()\r\n\r\n                    taskList.add(task)\r\n                }\r\n                cursor.close()\r\n\r\n                database.execSQL(\"DELETE FROM tasks\")\r\n                taskList.forEach {\r\n                    val statement =\r\n                        database.compileStatement(\"INSERT INTO tasks VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\")\r\n                    with(statement) {\r\n                        bindString(1, it.taskID)\r\n                        bindString(2, it.name)\r\n                        bindString(3, it.notes)\r\n                        bindString(4, it.subject)\r\n                        bindLong(5, if (it.isImportant) 1 else 0)\r\n                        bindString(6, DateTimeConverter.fromZonedDateTime(it.dateAdded))\r\n                        bindString(7, DateTimeConverter.fromZonedDateTime(it.dueDate))\r\n                        bindLong(8, if (it.isFinished) 1 else 0)\r\n                        bindLong(9, if (it.isTaskArchived) 1 else 0)\r\n                    }\r\n                    statement.executeInsert()\r\n                }\r\n                taskList.clear()\r\n\r\n                cursor = database.query(\"SELECT * FROM events\")\r\n                cursor.moveToFirst()\r\n\r\n                val eventList = arrayListOf<Event>()\r\n                while (cursor.moveToNext()) {\r\n                    val event = Event()\r\n                    event.eventID = cursor.getString(cursor.getColumnIndex(\"eventID\"))\r\n                    event.name = cursor.getString(cursor.getColumnIndex(\"name\"))\r\n                    event.notes = cursor.getString(cursor.getColumnIndex(\"notes\"))\r\n                    event.schedule =\r\n                        DateTimeConverter.toZonedDateTime(cursor.getString(cursor.getColumnIndex(\"schedule\")))\r\n                    event.location = cursor.getString(cursor.getColumnIndex(\"location\"))\r\n                    event.isImportant = cursor.getInt(cursor.getColumnIndex(\"isImportant\")) > 0\r\n                    event.isEventArchived =\r\n                        cursor.getInt(cursor.getColumnIndex(\"isEventArchived\")) > 0\r\n                    event.dateAdded =\r\n                        DateTimeConverter.toZonedDateTime(cursor.getString(cursor.getColumnIndex(\"dateAdded\")))\r\n                            ?: ZonedDateTime.now()\r\n                }\r\n                cursor.close()\r\n\r\n                database.execSQL(\"DELETE FROM events\")\r\n                eventList.forEach {\r\n                    val statement =\r\n                        database.compileStatement(\"INSERT INTO events VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\")\r\n                    with(statement) {\r\n                        bindString(1, it.eventID)\r\n                        bindString(2, it.name)\r\n                        bindString(3, it.notes)\r\n                        bindString(4, it.location)\r\n                        bindString(5, it.subject)\r\n                        bindLong(6, if (it.isImportant) 1 else 0)\r\n                        bindLong(7, if (it.isEventArchived) 1 else 0)\r\n                        bindString(8, DateTimeConverter.fromZonedDateTime(it.schedule))\r\n                        bindString(9, DateTimeConverter.fromZonedDateTime(it.dateAdded))\r\n                    }\r\n                    statement.executeInsert()\r\n                }\r\n                eventList.clear()\r\n            }\r\n        }\r\n\r\n        private var migration_6_7 = object : Migration(6, 7) {\r\n            override fun migrate(database: SupportSQLiteDatabase) {\r\n                with(database) {\r\n                    execSQL(\"CREATE TABLE IF NOT EXISTS `events_new` (`eventID` TEXT NOT NULL, `name` TEXT, `notes` TEXT, `location` TEXT, `subject` TEXT, `isImportant` INTEGER NOT NULL, `isEventArchived` INTEGER NOT NULL, `schedule` TEXT, `dateAdded` TEXT, PRIMARY KEY(`eventID`), FOREIGN KEY(`subject`) REFERENCES `subjects`(`subjectID`) ON UPDATE NO ACTION ON DELETE SET NULL )\")\r\n                    execSQL(\"INSERT INTO `events_new` SELECT * FROM `events`\")\r\n                    execSQL(\"DROP TABLE `events`\")\r\n                    execSQL(\"ALTER TABLE `events_new` RENAME TO `events`\")\r\n                }\r\n\r\n                var cursor = database.query(\"SELECT * FROM tasks\")\r\n                cursor.moveToFirst()\r\n\r\n                val taskList = arrayListOf<Task>()\r\n                while (cursor.moveToNext()) {\r\n                    val task = Task()\r\n                    task.taskID = cursor.getString(cursor.getColumnIndex(\"taskID\"))\r\n                    task.name = cursor.getString(cursor.getColumnIndex(\"name\"))\r\n                    task.notes = cursor.getString(cursor.getColumnIndex(\"notes\"))\r\n                    task.subject = cursor.getString(cursor.getColumnIndex(\"subject\"))\r\n                    task.isFinished = cursor.getInt(cursor.getColumnIndex(\"isFinished\")) > 0\r\n                    task.isImportant = cursor.getInt(cursor.getColumnIndex(\"isImportant\")) > 0\r\n                    task.isTaskArchived = cursor.getInt(cursor.getColumnIndex(\"isTaskArchived\")) > 0\r\n                    task.dueDate =\r\n                        DateTimeConverter.toZonedDateTime(cursor.getString(cursor.getColumnIndex(\"dueDate\")))\r\n                    task.dateAdded =\r\n                        DateTimeConverter.toZonedDateTime(cursor.getString(cursor.getColumnIndex(\"dateAdded\")))\r\n                            ?: ZonedDateTime.now()\r\n\r\n                    taskList.add(task)\r\n                }\r\n                cursor.close()\r\n\r\n                database.execSQL(\"DELETE FROM tasks\")\r\n                taskList.forEach {\r\n                    val statement =\r\n                        database.compileStatement(\"INSERT INTO tasks VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\")\r\n                    with(statement) {\r\n                        bindString(1, it.taskID)\r\n                        bindString(2, it.name)\r\n                        bindString(3, it.notes)\r\n                        bindString(4, it.subject ?: \"\")\r\n                        bindLong(5, if (it.isImportant) 1 else 0)\r\n                        bindString(6, DateTimeConverter.fromZonedDateTime(it.dateAdded))\r\n                        bindString(7, DateTimeConverter.fromZonedDateTime(it.dueDate))\r\n                        bindLong(8, if (it.isFinished) 1 else 0)\r\n                        bindLong(9, if (it.isTaskArchived) 1 else 0)\r\n                    }\r\n                    statement.executeInsert()\r\n                }\r\n                taskList.clear()\r\n\r\n                cursor = database.query(\"SELECT * FROM events\")\r\n                cursor.moveToFirst()\r\n\r\n                val eventList = arrayListOf<Event>()\r\n                while (cursor.moveToNext()) {\r\n                    val event = Event()\r\n                    event.eventID = cursor.getString(cursor.getColumnIndex(\"eventID\"))\r\n                    event.name = cursor.getString(cursor.getColumnIndex(\"name\"))\r\n                    event.notes = cursor.getString(cursor.getColumnIndex(\"notes\"))\r\n                    event.schedule =\r\n                        DateTimeConverter.toZonedDateTime(cursor.getString(cursor.getColumnIndex(\"schedule\")))\r\n                    event.location = cursor.getString(cursor.getColumnIndex(\"location\"))\r\n                    event.isImportant = cursor.getInt(cursor.getColumnIndex(\"isImportant\")) > 0\r\n                    event.isEventArchived =\r\n                        cursor.getInt(cursor.getColumnIndex(\"isEventArchived\")) > 0\r\n                    event.dateAdded =\r\n                        DateTimeConverter.toZonedDateTime(cursor.getString(cursor.getColumnIndex(\"dateAdded\")))\r\n                            ?: ZonedDateTime.now()\r\n                    event.subject = cursor.getString(cursor.getColumnIndex(\"subject\"))\r\n                }\r\n                cursor.close()\r\n\r\n                database.execSQL(\"DELETE FROM events\")\r\n                eventList.forEach {\r\n                    val statement =\r\n                        database.compileStatement(\"INSERT INTO events VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\")\r\n                    with(statement) {\r\n                        bindString(1, it.eventID)\r\n                        bindString(2, it.name)\r\n                        bindString(3, it.notes)\r\n                        bindString(4, it.location)\r\n                        bindString(5, it.subject ?: \"\")\r\n                        bindLong(6, if (it.isImportant) 1 else 0)\r\n                        bindLong(7, if (it.isEventArchived) 1 else 0)\r\n                        bindString(8, DateTimeConverter.fromZonedDateTime(it.schedule))\r\n                        bindString(9, DateTimeConverter.fromZonedDateTime(it.dateAdded))\r\n                    }\r\n                    statement.executeInsert()\r\n                }\r\n                eventList.clear()\r\n            }\r\n        }\r\n\r\n        private var migration_7_8 = object : Migration(7, 8) {\r\n            override fun migrate(database: SupportSQLiteDatabase) {\r\n                with(database) {\r\n                    execSQL(\"ALTER TABLE subjects ADD COLUMN `instructor` TEXT\")\r\n                    execSQL(\"ALTER TABLE schedules ADD COLUMN `classroom` TEXT\")\r\n                }\r\n            }\r\n        }\r\n\r\n        private val migrations =\r\n            arrayOf(migration_4_6, migration_5_6, migration_4_7, migration_5_7, migration_6_7, migration_7_8)\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/database/converter/ColorConverter.kt",
    "content": "package com.isaiahvonrundstedt.fokus.database.converter\r\n\r\nimport androidx.room.TypeConverter\r\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\r\n\r\nclass ColorConverter private constructor() {\r\n\r\n    companion object {\r\n        @JvmStatic\r\n        @TypeConverter\r\n        fun toColor(actualColor: Int): Subject.Tag? {\r\n            return Subject.Tag.convertColorToTag(actualColor)\r\n        }\r\n\r\n        @JvmStatic\r\n        @TypeConverter\r\n        fun fromColor(tag: Subject.Tag): Int {\r\n            return tag.color\r\n        }\r\n    }\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/database/converter/DateTimeConverter.kt",
    "content": "package com.isaiahvonrundstedt.fokus.database.converter\r\n\r\nimport android.content.Context\r\nimport android.text.format.DateFormat\r\nimport androidx.room.TypeConverter\r\nimport java.time.LocalDate\r\nimport java.time.LocalTime\r\nimport java.time.ZonedDateTime\r\nimport java.time.format.DateTimeFormatter\r\n\r\nclass DateTimeConverter private constructor() {\r\n\r\n    companion object {\r\n        private const val FORMAT_TIME_12_HOUR = \"h:mm a\"\r\n        private const val FORMAT_TIME_24_HOUR = \"H:mm\"\r\n        private const val FORMAT_DATE_TIME_12_HOUR_SHORT = \"M-d, h:mm a\"\r\n        private const val FORMAT_DATE_TIME_24_HOUR_SHORT = \"M-d, H:mm\"\r\n        private const val FORMAT_DATE_TIME_WITH_YEAR_12_HOUR_SHORT = \"M-d-yy, h:mm a\"\r\n        private const val FORMAT_DATE_TIME_WITH_YEAR_24_HOUR_SHORT = \"M-d-yy, H:mm\"\r\n        private const val FORMAT_DATE_TIME_12_HOUR = \"MMMM d, h:mm a\"\r\n        private const val FORMAT_DATE_TIME_24_HOUR = \"MMMM d, H:mm\"\r\n        private const val FORMAT_DATE_TIME_WITH_YEAR_12_HOUR = \"MM d yyyy, h:mm a\"\r\n        private const val FORMAT_DATE_TIME_WITH_YEAR_24_HOUR = \"Mm d yyyy, H:mm\"\r\n\r\n        fun getTimeFormatter(context: Context): DateTimeFormatter {\r\n            val pattern = if (DateFormat.is24HourFormat(context))\r\n                FORMAT_TIME_24_HOUR\r\n            else FORMAT_TIME_12_HOUR\r\n\r\n            return DateTimeFormatter.ofPattern(pattern)\r\n        }\r\n\r\n        fun getDateTimeFormatter(\r\n            context: Context,\r\n            isShort: Boolean = false,\r\n            withYear: Boolean = false\r\n        ): DateTimeFormatter {\r\n            val is24Hour: Boolean = DateFormat.is24HourFormat(context)\r\n\r\n            val pattern = if (isShort) {\r\n                if (withYear) {\r\n                    if (is24Hour)\r\n                        FORMAT_DATE_TIME_WITH_YEAR_24_HOUR_SHORT\r\n                    else FORMAT_DATE_TIME_WITH_YEAR_12_HOUR_SHORT\r\n                } else {\r\n                    if (is24Hour)\r\n                        FORMAT_DATE_TIME_24_HOUR_SHORT\r\n                    else FORMAT_DATE_TIME_12_HOUR_SHORT\r\n                }\r\n            } else {\r\n                if (withYear) {\r\n                    if (is24Hour)\r\n                        FORMAT_DATE_TIME_WITH_YEAR_24_HOUR\r\n                    else FORMAT_DATE_TIME_WITH_YEAR_12_HOUR\r\n                } else {\r\n                    if (is24Hour)\r\n                        FORMAT_DATE_TIME_24_HOUR\r\n                    else FORMAT_DATE_TIME_12_HOUR\r\n                }\r\n            }\r\n\r\n            return DateTimeFormatter.ofPattern(pattern)\r\n        }\r\n\r\n        @JvmStatic\r\n        @TypeConverter\r\n        fun fromLocalDate(localDate: LocalDate?): String? {\r\n            return if (localDate != null)\r\n                DateTimeFormatter.ISO_LOCAL_DATE.format(localDate)\r\n            else null\r\n        }\r\n\r\n        @JvmStatic\r\n        @TypeConverter\r\n        fun toLocalDate(date: String?): LocalDate? {\r\n            return if (date.isNullOrEmpty()) null\r\n            else LocalDate.parse(date)\r\n        }\r\n\r\n        @JvmStatic\r\n        @TypeConverter\r\n        fun toZonedDateTime(time: String?): ZonedDateTime? {\r\n            return if (time.isNullOrEmpty()) null\r\n            else ZonedDateTime.parse(time)\r\n        }\r\n\r\n        @JvmStatic\r\n        @TypeConverter\r\n        fun fromZonedDateTime(zonedDateTime: ZonedDateTime?): String? {\r\n            return if (zonedDateTime != null)\r\n                DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(zonedDateTime)\r\n            else null\r\n        }\r\n\r\n        @JvmStatic\r\n        @TypeConverter\r\n        fun toLocalTime(time: String?): LocalTime? {\r\n            return if (time.isNullOrEmpty()) null\r\n            else LocalTime.parse(time)\r\n        }\r\n\r\n        @JvmStatic\r\n        @TypeConverter\r\n        fun fromLocalTime(time: LocalTime?): String? {\r\n            return DateTimeFormatter.ISO_LOCAL_TIME.format(time)\r\n        }\r\n    }\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/database/dao/AttachmentDAO.kt",
    "content": "package com.isaiahvonrundstedt.fokus.database.dao\r\n\r\nimport androidx.room.*\r\nimport com.isaiahvonrundstedt.fokus.features.attachments.Attachment\r\n\r\n@Dao\r\ninterface AttachmentDAO {\r\n\r\n    @Insert(onConflict = OnConflictStrategy.REPLACE)\r\n    fun insert(attachment: Attachment)\r\n\r\n    @Delete\r\n    fun remove(attachment: Attachment)\r\n\r\n    @Update\r\n    fun update(attachment: Attachment)\r\n\r\n    @Query(\"SELECT * FROM attachments\")\r\n    suspend fun fetch(): List<Attachment>\r\n\r\n    @Query(\"DELETE FROM attachments WHERE task = :id\")\r\n    fun removeUsingTaskID(id: String)\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/database/dao/EventDAO.kt",
    "content": "package com.isaiahvonrundstedt.fokus.database.dao\r\n\r\nimport androidx.lifecycle.LiveData\r\nimport androidx.room.*\r\nimport com.isaiahvonrundstedt.fokus.features.event.Event\r\nimport com.isaiahvonrundstedt.fokus.features.event.EventPackage\r\n\r\n@Dao\r\ninterface EventDAO {\r\n\r\n    @Insert(onConflict = OnConflictStrategy.REPLACE)\r\n    fun insert(event: Event)\r\n\r\n    @Delete\r\n    fun remove(event: Event)\r\n\r\n    @Update\r\n    fun update(event: Event)\r\n\r\n    @Query(\"SELECT eventID FROM events WHERE name = :event AND DATE(schedule) = DATE(:schedule) COLLATE NOCASE AND eventId != :eventId\")\r\n    suspend fun checkNameUniqueness(event: String?, schedule: String?, eventId: String?): List<String>\r\n\r\n    @Query(\"SELECT * FROM events\")\r\n    suspend fun fetch(): List<Event>\r\n\r\n    @Query(\"SELECT * FROM events\")\r\n    suspend fun fetchPackage(): List<EventPackage>\r\n\r\n    @Transaction\r\n    @Query(\"SELECT * FROM events LEFT JOIN subjects ON events.subject == subjects.subjectID WHERE isEventArchived = 0 ORDER BY schedule ASC\")\r\n    fun fetchLiveData(): LiveData<List<EventPackage>>\r\n\r\n    @Transaction\r\n    @Query(\"SELECT * FROM events LEFT JOIN subjects ON events.subject == subjects.subjectID WHERE isEventArchived = 1 ORDER BY schedule ASC\")\r\n    fun fetchArchivedLiveData(): LiveData<List<EventPackage>>\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/database/dao/LogDAO.kt",
    "content": "package com.isaiahvonrundstedt.fokus.database.dao\r\n\r\nimport androidx.lifecycle.LiveData\r\nimport androidx.room.*\r\nimport com.isaiahvonrundstedt.fokus.features.log.Log\r\n\r\n@Dao\r\ninterface LogDAO {\r\n\r\n    @Insert(onConflict = OnConflictStrategy.REPLACE)\r\n    fun insert(log: Log)\r\n\r\n    @Delete\r\n    fun remove(log: Log)\r\n\r\n    @Update\r\n    fun update(log: Log)\r\n\r\n    @Query(\"SELECT * FROM logs\")\r\n    fun fetchCore(): List<Log>\r\n\r\n    @Query(\"DELETE FROM logs\")\r\n    suspend fun removeLogs()\r\n\r\n    @Query(\"SELECT * FROM logs ORDER BY dateTimeTriggered ASC\")\r\n    fun fetch(): LiveData<List<Log>>\r\n\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/database/dao/ScheduleDAO.kt",
    "content": "package com.isaiahvonrundstedt.fokus.database.dao\r\n\r\nimport androidx.room.*\r\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\r\n\r\n@Dao\r\ninterface ScheduleDAO {\r\n\r\n    @Insert(onConflict = OnConflictStrategy.REPLACE)\r\n    fun insert(vararg schedule: Schedule)\r\n\r\n    @Delete\r\n    fun remove(schedule: Schedule)\r\n\r\n    @Update\r\n    fun update(schedule: Schedule)\r\n\r\n    @Query(\"DELETE FROM schedules WHERE subject = :id\")\r\n    suspend fun removeUsingSubjectID(id: String)\r\n\r\n    @Query(\"SELECT * FROM schedules\")\r\n    suspend fun fetch(): List<Schedule>\r\n\r\n    @Query(\"SELECT * FROM schedules WHERE subject = :id\")\r\n    suspend fun fetchUsingID(id: String?): List<Schedule>\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/database/dao/SubjectDAO.kt",
    "content": "package com.isaiahvonrundstedt.fokus.database.dao\r\n\r\nimport androidx.lifecycle.LiveData\r\nimport androidx.room.*\r\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\r\nimport com.isaiahvonrundstedt.fokus.features.subject.SubjectPackage\r\n\r\n@Dao\r\ninterface SubjectDAO {\r\n\r\n    @Insert(onConflict = OnConflictStrategy.REPLACE)\r\n    suspend fun insert(subject: Subject)\r\n\r\n    @Delete\r\n    suspend fun remove(subject: Subject)\r\n\r\n    @Update\r\n    suspend fun update(subject: Subject)\r\n\r\n    @Query(\"SELECT subjectID FROM subjects WHERE code = :code COLLATE NOCASE AND subjectID != :subjectId\")\r\n    suspend fun checkCodeUniqueness(code: String?, subjectId: String?): List<String>\r\n\r\n    @Query(\"SELECT * FROM subjects\")\r\n    suspend fun fetch(): List<Subject>\r\n\r\n    @Query(\"SELECT * FROM subjects\")\r\n    suspend fun fetchAsPackage(): List<SubjectPackage>\r\n\r\n    @Transaction\r\n    @Query(\"SELECT * FROM subjects WHERE isSubjectArchived = 0 ORDER BY code ASC\")\r\n    fun fetchLiveData(): LiveData<List<SubjectPackage>>\r\n\r\n    @Transaction\r\n    @Query(\"SELECT * FROM subjects WHERE isSubjectArchived = 1 ORDER BY code ASC\")\r\n    fun fetchArchivedLiveData(): LiveData<List<SubjectPackage>>\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/database/dao/TaskDAO.kt",
    "content": "package com.isaiahvonrundstedt.fokus.database.dao\r\n\r\nimport androidx.lifecycle.LiveData\r\nimport androidx.room.*\r\nimport com.isaiahvonrundstedt.fokus.features.task.Task\r\nimport com.isaiahvonrundstedt.fokus.features.task.TaskPackage\r\n\r\n@Dao\r\ninterface TaskDAO {\r\n\r\n    @Insert(onConflict = OnConflictStrategy.REPLACE)\r\n    fun insert(task: Task)\r\n\r\n    @Delete\r\n    fun remove(task: Task)\r\n\r\n    @Update\r\n    fun update(task: Task)\r\n\r\n    @Query(\"SELECT taskID FROM tasks WHERE name = :task COLLATE NOCASE AND taskID != :taskId\")\r\n    suspend fun checkNameUniqueness(task: String?, taskId: String?): List<String>\r\n\r\n    @Query(\"UPDATE tasks SET isFinished = :status WHERE taskID = :taskID\")\r\n    suspend fun setFinished(taskID: String, status: Int)\r\n\r\n    @Query(\"SELECT * FROM tasks WHERE isFinished = 0 AND isTaskArchived = 0\")\r\n    suspend fun fetch(): List<Task>\r\n\r\n    @Query(\"SELECT COUNT(*) FROM tasks WHERE isFinished = 0 AND isTaskArchived = 0\")\r\n    suspend fun fetchCount(): Int\r\n\r\n    @Query(\"SELECT * FROM tasks WHERE isFinished = 0\")\r\n    suspend fun fetchAsPackage(): List<TaskPackage>\r\n\r\n    @Transaction\r\n    @Query(\"SELECT * FROM tasks LEFT JOIN subjects ON tasks.subject == subjects.subjectID WHERE isTaskArchived = 0 ORDER BY dueDate ASC\")\r\n    fun fetchLiveData(): LiveData<List<TaskPackage>>\r\n\r\n    @Transaction\r\n    @Query(\"SELECT * FROM tasks LEFT JOIN subjects ON tasks.subject == subjects.subjectID WHERE isTaskArchived = 1 ORDER BY dueDate ASC\")\r\n    fun fetchArchivedLiveData(): LiveData<List<TaskPackage>>\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/database/repository/EventRepository.kt",
    "content": "package com.isaiahvonrundstedt.fokus.database.repository\r\n\r\nimport android.app.NotificationManager\r\nimport android.content.Context\r\nimport androidx.lifecycle.LiveData\r\nimport androidx.work.ExistingWorkPolicy\r\nimport androidx.work.OneTimeWorkRequest\r\nimport androidx.work.WorkManager\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.isAfterNow\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.isBeforeNow\r\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\r\nimport com.isaiahvonrundstedt.fokus.database.dao.EventDAO\r\nimport com.isaiahvonrundstedt.fokus.features.event.Event\r\nimport com.isaiahvonrundstedt.fokus.features.event.EventPackage\r\nimport com.isaiahvonrundstedt.fokus.features.event.widget.EventWidgetProvider\r\nimport com.isaiahvonrundstedt.fokus.features.notifications.event.EventNotificationWorker\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseWorker\r\nimport dagger.hilt.android.qualifiers.ApplicationContext\r\nimport javax.inject.Inject\r\n\r\nclass EventRepository @Inject constructor(\r\n    @ApplicationContext\r\n    private val context: Context,\r\n    private val events: EventDAO,\r\n    private val preferenceManager: PreferenceManager,\r\n    private val workManager: WorkManager,\r\n    private val notificationManager: NotificationManager\r\n) {\r\n\r\n    fun fetchLiveData(): LiveData<List<EventPackage>> = events.fetchLiveData()\r\n\r\n    fun fetchArchivedLiveData(): LiveData<List<EventPackage>> = events.fetchArchivedLiveData()\r\n\r\n    suspend fun checkNameUniqueness(name: String?, schedule: String?, eventId: String?): List<String> =\r\n        events.checkNameUniqueness(name, schedule, eventId)\r\n\r\n    suspend fun fetch(): List<EventPackage> = events.fetchPackage()\r\n\r\n    suspend fun fetchCore(): List<Event> = events.fetch()\r\n\r\n    suspend fun insert(event: Event) {\r\n        events.insert(event)\r\n\r\n        EventWidgetProvider.triggerRefresh(context)\r\n\r\n        if (preferenceManager.eventReminder && event.schedule?.isAfterNow() == true) {\r\n            val data = BaseWorker.convertEventToData(event)\r\n            val request = OneTimeWorkRequest.Builder(EventNotificationWorker::class.java)\r\n                .setInputData(data)\r\n                .addTag(event.eventID)\r\n                .build()\r\n            workManager.enqueueUniqueWork(\r\n                event.eventID, ExistingWorkPolicy.REPLACE,\r\n                request\r\n            )\r\n        }\r\n    }\r\n\r\n    suspend fun remove(event: Event) {\r\n        events.remove(event)\r\n\r\n        EventWidgetProvider.triggerRefresh(context)\r\n\r\n        if (event.isImportant)\r\n            notificationManager.cancel(event.eventID, BaseWorker.NOTIFICATION_ID_EVENT)\r\n\r\n        workManager.cancelUniqueWork(event.eventID)\r\n    }\r\n\r\n    suspend fun update(event: Event) {\r\n        events.update(event)\r\n\r\n        EventWidgetProvider.triggerRefresh(context)\r\n\r\n        if (event.schedule?.isBeforeNow() == true || !event.isImportant)\r\n            notificationManager.cancel(event.eventID, BaseWorker.NOTIFICATION_ID_EVENT)\r\n\r\n        if (preferenceManager.eventReminder && event.schedule?.isAfterNow() == true) {\r\n            val data = BaseWorker.convertEventToData(event)\r\n            val request = OneTimeWorkRequest.Builder(EventNotificationWorker::class.java)\r\n                .setInputData(data)\r\n                .addTag(event.eventID)\r\n                .build()\r\n            workManager.enqueueUniqueWork(\r\n                event.eventID, ExistingWorkPolicy.REPLACE,\r\n                request\r\n            )\r\n        }\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/database/repository/LogRepository.kt",
    "content": "package com.isaiahvonrundstedt.fokus.database.repository\r\n\r\nimport androidx.lifecycle.LiveData\r\nimport com.isaiahvonrundstedt.fokus.database.dao.LogDAO\r\nimport com.isaiahvonrundstedt.fokus.features.log.Log\r\nimport javax.inject.Inject\r\n\r\nclass LogRepository @Inject constructor(private val logs: LogDAO) {\r\n\r\n    fun fetch(): LiveData<List<Log>> = logs.fetch()\r\n\r\n    suspend fun insert(log: Log) {\r\n        logs.insert(log)\r\n    }\r\n\r\n    suspend fun remove(log: Log) {\r\n        logs.remove(log)\r\n    }\r\n\r\n    suspend fun update(log: Log) {\r\n        logs.update(log)\r\n    }\r\n\r\n    suspend fun removeLogs() {\r\n        logs.removeLogs()\r\n    }\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/database/repository/SubjectRepository.kt",
    "content": "package com.isaiahvonrundstedt.fokus.database.repository\r\n\r\nimport android.content.Context\r\nimport androidx.lifecycle.LiveData\r\nimport androidx.work.ExistingWorkPolicy\r\nimport androidx.work.OneTimeWorkRequest\r\nimport androidx.work.WorkManager\r\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\r\nimport com.isaiahvonrundstedt.fokus.database.dao.ScheduleDAO\r\nimport com.isaiahvonrundstedt.fokus.database.dao.SubjectDAO\r\nimport com.isaiahvonrundstedt.fokus.features.notifications.subject.ClassNotificationWorker\r\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseWorker\r\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\r\nimport com.isaiahvonrundstedt.fokus.features.subject.SubjectPackage\r\nimport com.isaiahvonrundstedt.fokus.features.subject.widget.SubjectWidgetProvider\r\nimport dagger.hilt.android.qualifiers.ApplicationContext\r\nimport javax.inject.Inject\r\n\r\nclass SubjectRepository @Inject constructor(\r\n    @ApplicationContext\r\n    private val context: Context,\r\n    private val subjects: SubjectDAO,\r\n    private val schedules: ScheduleDAO,\r\n    private val preferenceManager: PreferenceManager,\r\n    private val workManager: WorkManager\r\n) {\r\n\r\n    fun fetchLiveData(): LiveData<List<SubjectPackage>> = subjects.fetchLiveData()\r\n\r\n    fun fetchArchivedLiveData(): LiveData<List<SubjectPackage>> = subjects.fetchArchivedLiveData()\r\n\r\n    suspend fun fetch(): List<SubjectPackage> = subjects.fetchAsPackage()\r\n\r\n    suspend fun checkCodeExists(code: String?, subjectId: String?): List<String> = subjects.checkCodeUniqueness(code, subjectId)\r\n\r\n    suspend fun insert(subject: Subject, scheduleList: List<Schedule>) {\r\n        subjects.insert(subject)\r\n        scheduleList.forEach {\r\n            schedules.insert(it)\r\n        }\r\n\r\n        SubjectWidgetProvider.triggerRefresh(context)\r\n\r\n        if (preferenceManager.subjectReminder) {\r\n            scheduleList.forEach {\r\n                it.subject = subject.code\r\n\r\n                val data = BaseWorker.convertScheduleToData(it)\r\n                val request = OneTimeWorkRequest.Builder(ClassNotificationWorker::class.java)\r\n                    .setInputData(data)\r\n                    .addTag(subject.subjectID)\r\n                    .addTag(it.scheduleID)\r\n                    .build()\r\n\r\n                workManager.enqueueUniqueWork(\r\n                    it.scheduleID, ExistingWorkPolicy.REPLACE,\r\n                    request\r\n                )\r\n            }\r\n        }\r\n    }\r\n\r\n    suspend fun remove(subject: Subject) {\r\n        subjects.remove(subject)\r\n\r\n        SubjectWidgetProvider.triggerRefresh(context)\r\n\r\n        workManager.cancelAllWorkByTag(subject.subjectID)\r\n    }\r\n\r\n    suspend fun update(subject: Subject, scheduleList: List<Schedule> = emptyList()) {\r\n        subjects.update(subject)\r\n        schedules.removeUsingSubjectID(subject.subjectID)\r\n        if (scheduleList.isNotEmpty())\r\n            scheduleList.forEach { schedules.insert(it) }\r\n\r\n        SubjectWidgetProvider.triggerRefresh(context)\r\n\r\n        if (preferenceManager.subjectReminder) {\r\n            scheduleList.forEach {\r\n                workManager.cancelAllWorkByTag(it.scheduleID)\r\n\r\n                it.subject = subject.code\r\n                val data = BaseWorker.convertScheduleToData(it)\r\n                val request = OneTimeWorkRequest.Builder(ClassNotificationWorker::class.java)\r\n                    .setInputData(data)\r\n                    .addTag(subject.subjectID)\r\n                    .addTag(it.scheduleID)\r\n                    .build()\r\n                workManager.enqueueUniqueWork(\r\n                    it.scheduleID, ExistingWorkPolicy.REPLACE,\r\n                    request\r\n                )\r\n            }\r\n        }\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/database/repository/TaskRepository.kt",
    "content": "package com.isaiahvonrundstedt.fokus.database.repository\r\n\r\nimport android.app.NotificationManager\r\nimport android.content.Context\r\nimport androidx.lifecycle.LiveData\r\nimport androidx.work.ExistingWorkPolicy\r\nimport androidx.work.OneTimeWorkRequest\r\nimport androidx.work.WorkManager\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.isBeforeNow\r\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\r\nimport com.isaiahvonrundstedt.fokus.database.dao.AttachmentDAO\r\nimport com.isaiahvonrundstedt.fokus.database.dao.TaskDAO\r\nimport com.isaiahvonrundstedt.fokus.features.attachments.Attachment\r\nimport com.isaiahvonrundstedt.fokus.features.notifications.task.TaskNotificationWorker\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseWorker\r\nimport com.isaiahvonrundstedt.fokus.features.task.Task\r\nimport com.isaiahvonrundstedt.fokus.features.task.TaskPackage\r\nimport com.isaiahvonrundstedt.fokus.features.task.widget.TaskWidgetProvider\r\nimport dagger.hilt.android.qualifiers.ApplicationContext\r\nimport javax.inject.Inject\r\n\r\nclass TaskRepository @Inject constructor(\r\n    @ApplicationContext\r\n    private val context: Context,\r\n    private val tasks: TaskDAO,\r\n    private val attachments: AttachmentDAO,\r\n    private val preferenceManager: PreferenceManager,\r\n    private val workManager: WorkManager,\r\n    private val notificationManager: NotificationManager\r\n) {\r\n\r\n    fun fetchLiveData(): LiveData<List<TaskPackage>> = tasks.fetchLiveData()\r\n\r\n    fun fetchArchived(): LiveData<List<TaskPackage>> = tasks.fetchArchivedLiveData()\r\n\r\n    suspend fun fetchCore(): List<Task> = tasks.fetch()\r\n\r\n    suspend fun fetchCount(): Int = tasks.fetchCount()\r\n\r\n    suspend fun fetchAsPackage(): List<TaskPackage> = tasks.fetchAsPackage()\r\n\r\n    suspend fun checkNameUniqueness(name: String?, id: String?): List<String> = tasks.checkNameUniqueness(name, id)\r\n\r\n    suspend fun insert(task: Task, attachmentList: List<Attachment> = emptyList()) {\r\n        tasks.insert(task)\r\n        if (attachmentList.isNotEmpty())\r\n            attachmentList.forEach { attachments.insert(it) }\r\n\r\n        TaskWidgetProvider.triggerRefresh(context)\r\n\r\n        // Check if notifications for tasks are turned on and check if\r\n        // the task is not finished, then schedule a notification\r\n        if (preferenceManager.taskReminder && !task.isFinished && task.isDueDateInFuture() &&\r\n            task.hasDueDate()\r\n        ) {\r\n\r\n            val data = BaseWorker.convertTaskToData(task)\r\n            val request = OneTimeWorkRequest.Builder(TaskNotificationWorker::class.java)\r\n                .setInputData(data)\r\n                .addTag(task.taskID)\r\n                .build()\r\n            workManager.enqueueUniqueWork(\r\n                task.taskID, ExistingWorkPolicy.REPLACE,\r\n                request\r\n            )\r\n        }\r\n    }\r\n\r\n    suspend fun remove(task: Task) {\r\n        tasks.remove(task)\r\n\r\n        TaskWidgetProvider.triggerRefresh(context)\r\n\r\n        // If the task is important, its persistent notification should\r\n        // be canceled.\r\n        if (task.isImportant)\r\n            notificationManager.cancel(task.taskID, BaseWorker.NOTIFICATION_ID_TASK)\r\n\r\n        workManager.cancelUniqueWork(task.taskID)\r\n    }\r\n\r\n    suspend fun update(task: Task, attachmentList: List<Attachment> = emptyList()) {\r\n        tasks.update(task)\r\n        attachments.removeUsingTaskID(task.taskID)\r\n        if (attachmentList.isNotEmpty())\r\n            attachmentList.forEach { attachments.insert(it) }\r\n\r\n        TaskWidgetProvider.triggerRefresh(context)\r\n\r\n        // If we have a persistent notification,\r\n        // we should dismiss it when the user updates\r\n        // the task to finish\r\n        if (task.isFinished || !task.isImportant || task.dueDate?.isBeforeNow() == true)\r\n            notificationManager.cancel(task.taskID, BaseWorker.NOTIFICATION_ID_TASK)\r\n\r\n        // Check if notifications for tasks is turned on and if the task\r\n        // is not finished then reschedule the notification from\r\n        // WorkManager\r\n        if (preferenceManager.taskReminder && !task.isFinished) {\r\n\r\n            workManager.cancelUniqueWork(task.taskID)\r\n            val data = BaseWorker.convertTaskToData(task)\r\n            val request = OneTimeWorkRequest.Builder(TaskNotificationWorker::class.java)\r\n                .setInputData(data)\r\n                .addTag(task.taskID)\r\n                .build()\r\n            workManager.enqueueUniqueWork(\r\n                task.taskID, ExistingWorkPolicy.REPLACE,\r\n                request\r\n            )\r\n        }\r\n    }\r\n\r\n    suspend fun setFinished(taskID: String, status: Boolean) {\r\n        if (status)\r\n            tasks.setFinished(taskID, 1)\r\n        else tasks.setFinished(taskID, 0)\r\n    }\r\n\r\n    suspend fun addAttachment(attachment: Attachment) {\r\n        attachments.insert(attachment)\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/about/AboutFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.about\n\nimport android.content.Intent\nimport android.net.Uri\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.browser.customtabs.CustomTabsIntent\nimport androidx.navigation.NavController\nimport androidx.navigation.Navigation\nimport androidx.navigation.fragment.findNavController\nimport androidx.preference.Preference\nimport com.isaiahvonrundstedt.fokus.BuildConfig\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\nimport com.isaiahvonrundstedt.fokus.databinding.FragmentAboutBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseFragment\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BasePreference\n\nclass AboutFragment : BaseFragment() {\n    private var _binding: FragmentAboutBinding? = null\n    private var controller: NavController? = null\n\n    private val binding get() = _binding!!\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        _binding = FragmentAboutBinding.inflate(inflater, container, false)\n        return binding.root\n    }\n\n    override fun onDestroy() {\n        _binding = null\n        super.onDestroy()\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        setInsets(binding.root, binding.appBarLayout.toolbar)\n\n        with(binding.appBarLayout.toolbar) {\n            setTitle(R.string.activity_about)\n            setupNavigation(this, R.drawable.ic_outline_arrow_back_24) {\n                controller?.navigateUp()\n            }\n        }\n    }\n\n    override fun onStart() {\n        super.onStart()\n        controller = findNavController()\n    }\n\n    companion object {\n        const val ABOUT_ISSUE_URL = \"https://github.com/icabetong/fokus-android/issues/new\"\n        const val ABOUT_RELEASE_URL = \"https://github.com/icabetong/fokus-android/releases\"\n        const val ABOUT_DEVELOPER_EMAIL = \"isaiahcollins_02@live.com\"\n\n        class AboutFragment : BasePreference() {\n            private var controller: NavController? = null\n\n            override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {\n                setPreferencesFromResource(R.xml.xml_about_main, rootKey)\n            }\n\n            override fun onStart() {\n                super.onStart()\n                controller = Navigation.findNavController(requireActivity(),\n                    R.id.navigationHostFragment)\n\n                findPreference<Preference>(PreferenceManager.PREFERENCE_NOTICES)\n                    ?.setOnPreferenceClickListener {\n                        controller?.navigate(R.id.navigation_notices)\n                        true\n                    }\n\n                findPreference<Preference>(PreferenceManager.PREFERENCE_TRANSLATE)\n                    ?.setOnPreferenceClickListener {\n                        val intent = Intent(Intent.ACTION_VIEW).apply {\n                            data = Uri.parse(\"mailto:${ABOUT_DEVELOPER_EMAIL}\")\n                        }\n\n                        if (intent.resolveActivity(requireContext().packageManager) != null)\n                            startActivity(intent)\n                        true\n                    }\n\n                findPreference<Preference>(PreferenceManager.PREFERENCE_REPORT_ISSUE)\n                    ?.setOnPreferenceClickListener {\n                        CustomTabsIntent.Builder().build()\n                            .launchUrl(requireContext(), Uri.parse(ABOUT_ISSUE_URL))\n\n                        true\n                    }\n\n                setPreferenceSummary(PreferenceManager.PREFERENCE_VERSION, BuildConfig.VERSION_NAME)\n                findPreference<Preference>(PreferenceManager.PREFERENCE_VERSION)\n                    ?.setOnPreferenceClickListener {\n                        CustomTabsIntent.Builder().build()\n                            .launchUrl(requireContext(), Uri.parse(ABOUT_RELEASE_URL))\n\n                        true\n                    }\n            }\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/about/LibrariesFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.about\n\nimport android.os.Build\nimport android.os.Bundle\nimport android.text.Html\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.navigation.NavController\nimport androidx.navigation.Navigation\nimport androidx.recyclerview.widget.LinearLayoutManager\nimport androidx.recyclerview.widget.RecyclerView\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.databinding.FragmentLibrariesBinding\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutItemLibraryBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseFragment\nimport com.mikepenz.aboutlibraries.Libs\nimport com.mikepenz.aboutlibraries.entity.Library\n\nclass LibrariesFragment : BaseFragment() {\n    private var _binding: FragmentLibrariesBinding? = null\n    private var controller: NavController? = null\n\n    private val binding get() = _binding!!\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        _binding = FragmentLibrariesBinding.inflate(inflater, container, false)\n        return binding.root\n    }\n\n    override fun onDestroy() {\n        _binding = null\n        super.onDestroy()\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        setInsets(binding.root, binding.appBarLayout.toolbar, arrayOf(binding.recyclerView))\n        controller = Navigation.findNavController(view)\n\n        with(binding.appBarLayout.toolbar) {\n            setTitle(R.string.activity_open_source_licenses)\n            setupNavigation(this, R.drawable.ic_outline_arrow_back_24) {\n                controller?.navigateUp()\n            }\n        }\n\n        with(binding.recyclerView) {\n            layoutManager = LinearLayoutManager(context)\n            adapter = LibraryAdapter(Libs(context).libraries)\n        }\n    }\n\n    class LibraryAdapter(private val itemList: List<Library>) :\n        RecyclerView.Adapter<LibraryAdapter.LibraryViewHolder>() {\n\n\n        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LibraryViewHolder {\n            val rowView: View = LayoutInflater.from(parent.context).inflate(\n                R.layout.layout_item_library,\n                parent, false\n            )\n            return LibraryViewHolder(rowView)\n        }\n\n        override fun onBindViewHolder(holder: LibraryViewHolder, position: Int) {\n            holder.onBind(itemList[position])\n        }\n\n        override fun getItemCount(): Int = itemList.size\n\n        class LibraryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {\n\n            private val binding = LayoutItemLibraryBinding.bind(itemView)\n\n            @Suppress(\"DEPRECATION\")\n            fun onBind(library: Library) {\n\n                binding.nameTextView.text = library.libraryName\n                binding.versionTextView.text = library.libraryVersion\n\n                if (library.author.isNotEmpty())\n                    binding.authorTextView.text = library.author\n                else binding.authorTextView.visibility = View.GONE\n\n                val license = library.licenses?.firstOrNull()\n                if (license != null) {\n                    binding.licenseNameTextView.text = license.licenseName\n                    binding.licenseDescriptionTextView.text =\n                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)\n                            Html.fromHtml(\n                                license.licenseShortDescription,\n                                Html.FROM_HTML_MODE_COMPACT\n                            )\n                        else Html.fromHtml(license.licenseShortDescription)\n                } else {\n                    binding.licenseNameTextView.visibility = View.GONE\n                    binding.licenseDescriptionTextView.visibility = View.GONE\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/about/NoticesFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.about\n\nimport android.content.Intent\nimport android.net.Uri\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.browser.customtabs.CustomTabsIntent\nimport androidx.navigation.NavController\nimport androidx.navigation.Navigation\nimport androidx.preference.Preference\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\nimport com.isaiahvonrundstedt.fokus.databinding.FragmentNoticesBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseFragment\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BasePreference\n\nclass NoticesFragment : BaseFragment() {\n    private var _binding: FragmentNoticesBinding? = null\n    private var controller: NavController? = null\n\n    private val binding get() = _binding!!\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        _binding = FragmentNoticesBinding.inflate(inflater, container, false)\n        return binding.root\n    }\n\n    override fun onDestroy() {\n        _binding = null\n        super.onDestroy()\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        setInsets(binding.root, binding.appBarLayout.toolbar)\n        controller = Navigation.findNavController(view)\n\n        with(binding.appBarLayout.toolbar) {\n            setTitle(R.string.activity_notices)\n            setupNavigation(this, R.drawable.ic_outline_arrow_back_24) {\n                controller?.navigateUp()\n            }\n        }\n    }\n\n    companion object {\n\n        const val URL_LAUNCHER_ICON_BASE = \"https://flaticon.com/authors/freepik\"\n        const val URL_NOTIFICATION_SOUND =\n            \"https://www.zapsplat.com/music/ui-alert-prompt-warm-wooden-mallet-style-notification-tone-generic-11/\"\n        const val URL_USER_INTERFACE_ICONS = \"https://heroicons.dev\"\n\n        class NoticesFragment : BasePreference() {\n            private var controller: NavController? = null\n\n            override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {\n                setPreferencesFromResource(R.xml.xml_about_notices, rootKey)\n            }\n\n            override fun onStart() {\n                super.onStart()\n                controller = Navigation.findNavController(requireView())\n\n                findPreference<Preference>(PreferenceManager.PREFERENCE_LIBRARIES)\n                    ?.setOnPreferenceClickListener {\n                        controller?.navigate(R.id.navigation_libraries)\n                        true\n                    }\n\n\n                findPreference<Preference>(PreferenceManager.PREFERENCE_NOTIFICATION_SOUND)\n                    ?.setOnPreferenceClickListener {\n                        CustomTabsIntent.Builder().build()\n                            .launchUrl(requireContext(), Uri.parse(URL_NOTIFICATION_SOUND))\n\n                        true\n                    }\n\n\n                findPreference<Preference>(PreferenceManager.PREFERENCE_LAUNCHER_ICON)\n                    ?.setOnPreferenceClickListener {\n                        CustomTabsIntent.Builder().build()\n                            .launchUrl(requireContext(), Uri.parse(URL_LAUNCHER_ICON_BASE))\n\n                        true\n                    }\n\n                findPreference<Preference>(PreferenceManager.PREFERENCE_UI_ICONS)\n                    ?.setOnPreferenceClickListener {\n                        CustomTabsIntent.Builder().build()\n                            .launchUrl(requireContext(), Uri.parse(URL_USER_INTERFACE_ICONS))\n\n                        true\n                    }\n\n            }\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/attachments/Attachment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.attachments\r\n\r\nimport android.content.Context\r\nimport android.os.Parcelable\r\nimport androidx.annotation.DrawableRes\r\nimport androidx.recyclerview.widget.DiffUtil\r\nimport androidx.room.Entity\r\nimport androidx.room.ForeignKey\r\nimport androidx.room.PrimaryKey\r\nimport androidx.room.TypeConverters\r\nimport com.isaiahvonrundstedt.fokus.R\r\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Streamable\r\nimport com.isaiahvonrundstedt.fokus.components.json.JsonDataStreamer\r\nimport com.isaiahvonrundstedt.fokus.database.converter.DateTimeConverter\r\nimport com.isaiahvonrundstedt.fokus.features.task.Task\r\nimport com.squareup.moshi.JsonClass\r\nimport kotlinx.parcelize.Parcelize\r\nimport okio.buffer\r\nimport okio.sink\r\nimport java.io.File\r\nimport java.net.URLConnection\r\nimport java.time.ZonedDateTime\r\nimport java.util.*\r\n\r\n@Parcelize\r\n@JsonClass(generateAdapter = true)\r\n@Entity(\r\n    tableName = \"attachments\", foreignKeys = [ForeignKey(\r\n        entity = Task::class,\r\n        parentColumns = arrayOf(\"taskID\"), childColumns = arrayOf(\"task\"),\r\n        onDelete = ForeignKey.CASCADE\r\n    )\r\n    ]\r\n)\r\ndata class Attachment @JvmOverloads constructor(\r\n    @PrimaryKey\r\n    var attachmentID: String = UUID.randomUUID().toString(),\r\n    var name: String? = null,\r\n    var target: String? = null,\r\n    var task: String = \"\",\r\n    var type: Int = 0,\r\n    @TypeConverters(DateTimeConverter::class)\r\n    var dateAttached: ZonedDateTime? = ZonedDateTime.now()\r\n) : Parcelable {\r\n\r\n    @DrawableRes\r\n    fun getIconResource(): Int {\r\n        return when (type) {\r\n            TYPE_WEBSITE_LINK -> R.drawable.ic_outline_link_24\r\n            else -> R.drawable.ic_outline_file_open_24\r\n        }\r\n    }\r\n\r\n    companion object {\r\n        const val TYPE_UNKNOWN = 0\r\n        const val TYPE_CONTENT_URI = 1\r\n        const val TYPE_IMPORTED_FILE = 2\r\n        const val TYPE_WEBSITE_LINK = 3\r\n\r\n        val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Attachment>() {\r\n            override fun areItemsTheSame(oldItem: Attachment, newItem: Attachment): Boolean {\r\n                return oldItem.attachmentID == newItem.attachmentID\r\n            }\r\n\r\n            override fun areContentsTheSame(oldItem: Attachment, newItem: Attachment): Boolean {\r\n                return oldItem == newItem\r\n            }\r\n        }\r\n\r\n        fun isImage(path: String): Boolean {\r\n            val mimeType = URLConnection.guessContentTypeFromName(path)\r\n            return mimeType != null && mimeType.startsWith(\"image\")\r\n        }\r\n\r\n        fun generateId(): String {\r\n            return UUID.randomUUID().toString()\r\n        }\r\n\r\n        fun getTargetDirectory(context: Context?): File {\r\n            return File(context?.getExternalFilesDir(null), Streamable.DIRECTORY_ATTACHMENTS)\r\n        }\r\n\r\n        fun toJsonFile(\r\n            items: List<Attachment>,\r\n            destination: File,\r\n            name: String = Streamable.FILE_NAME_ATTACHMENT\r\n        ): File {\r\n            return File(destination, name).apply {\r\n                this.sink().buffer().use {\r\n                    JsonDataStreamer.encodeToJson(items, Attachment::class.java)?.also { json ->\r\n                        it.write(json.toByteArray())\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/attachments/AttachmentOptionSheet.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.attachments\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.os.bundleOf\nimport androidx.fragment.app.FragmentManager\nimport androidx.fragment.app.setFragmentResult\nimport androidx.recyclerview.widget.LinearLayoutManager\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutSheetOptionsBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseBottomSheet\nimport com.isaiahvonrundstedt.fokus.features.shared.adapters.MenuAdapter\n\nclass AttachmentOptionSheet(manager: FragmentManager) : BaseBottomSheet(manager),\n    MenuAdapter.MenuItemListener {\n\n    private var _binding: LayoutSheetOptionsBinding? = null\n    private val binding get() = _binding!!\n\n    override fun onCreateView(\n        inflater: LayoutInflater, container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        _binding = LayoutSheetOptionsBinding.inflate(inflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n\n        binding.menuTitleView.text = getString(R.string.dialog_new_attachment)\n\n        with(binding.recyclerView) {\n            layoutManager = LinearLayoutManager(context)\n            adapter = MenuAdapter(\n                activity, R.menu.menu_attachment,\n                this@AttachmentOptionSheet\n            )\n        }\n    }\n\n    override fun onItemSelected(id: Int) {\n        setFragmentResult(\n            REQUEST_KEY, bundleOf(\n                EXTRA_OPTION to id\n            )\n        )\n    }\n\n    override fun onDestroy() {\n        super.onDestroy()\n        _binding = null\n    }\n\n    companion object {\n        const val REQUEST_KEY = \"request:attachment\"\n        const val EXTRA_OPTION = \"extra:option\"\n\n        fun show(manager: FragmentManager) {\n            AttachmentOptionSheet(manager)\n                .show()\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/attachments/attach/AttachToTaskActivity.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.attachments.attach\n\nimport android.content.Intent\nimport android.os.Bundle\nimport androidx.activity.viewModels\nimport androidx.recyclerview.widget.LinearLayoutManager\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.custom.ItemDecoration\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.createToast\nimport com.isaiahvonrundstedt.fokus.databinding.ActivityAttachToTaskBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseActivity\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\nimport com.isaiahvonrundstedt.fokus.features.task.TaskPackage\nimport dagger.hilt.android.AndroidEntryPoint\n\n@AndroidEntryPoint\nclass AttachToTaskActivity : BaseActivity(), BaseAdapter.SelectListener {\n    private lateinit var binding: ActivityAttachToTaskBinding\n\n    private val attachAdapter = AttachToTaskAdapter(this)\n    private val viewModel: AttachToTaskViewModel by viewModels()\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        binding = ActivityAttachToTaskBinding.inflate(layoutInflater)\n        setContentView(binding.root)\n        setPersistentActionBar(binding.appBarLayout.toolbar)\n        setToolbarTitle(R.string.sharing_attach_to_task)\n\n        intent?.also {\n            viewModel.subject = it.getStringExtra(Intent.EXTRA_SUBJECT)\n            viewModel.url = it.getStringExtra(Intent.EXTRA_TEXT)\n        }\n\n        with(binding.recyclerView) {\n            addItemDecoration(ItemDecoration(context))\n            layoutManager = LinearLayoutManager(context)\n            adapter = attachAdapter\n        }\n    }\n\n    override fun onStart() {\n        super.onStart()\n\n        binding.titleView.text = viewModel.subject\n        binding.summaryView.text = viewModel.url\n\n        viewModel.tasks.observe(this) {\n            attachAdapter.submitList(it)\n        }\n    }\n\n    override fun <T> onItemSelected(t: T) {\n        if (t is TaskPackage) {\n            viewModel.addAttachment(t.task.taskID)\n            createToast(R.string.feedback_attachment_added)\n            finish()\n        }\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/attachments/attach/AttachToTaskAdapter.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.attachments.attach\n\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutItemTaskSendBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\nimport com.isaiahvonrundstedt.fokus.features.task.TaskPackage\n\nclass AttachToTaskAdapter(private val selectListener: SelectListener) :\n    BaseAdapter<TaskPackage, AttachToTaskAdapter.TaskViewHolder>(TaskPackage.DIFF_CALLBACK) {\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TaskViewHolder {\n        val binding = LayoutItemTaskSendBinding.inflate(\n            LayoutInflater.from(parent.context),\n            parent, false\n        )\n        return TaskViewHolder(binding.root, selectListener)\n    }\n\n    override fun onBindViewHolder(holder: TaskViewHolder, position: Int) {\n        holder.onBind(getItem(position))\n    }\n\n    class TaskViewHolder(\n        itemView: View,\n        private val selectListener: SelectListener\n    ) : BaseAdapter.BaseViewHolder(itemView) {\n        private val binding = LayoutItemTaskSendBinding.bind(itemView)\n\n        override fun <T> onBind(data: T) {\n            if (data is TaskPackage) {\n                binding.titleView.text = data.task.name\n                binding.summaryView.text = data.task.formatDueDate(itemView.context)\n\n                binding.addButton.setOnClickListener {\n                    selectListener.onItemSelected(data)\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/attachments/attach/AttachToTaskViewModel.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.attachments.attach\n\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.Transformations\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.viewModelScope\nimport com.isaiahvonrundstedt.fokus.database.repository.TaskRepository\nimport com.isaiahvonrundstedt.fokus.features.attachments.Attachment\nimport com.isaiahvonrundstedt.fokus.features.task.TaskPackage\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport kotlinx.coroutines.launch\nimport javax.inject.Inject\n\n@HiltViewModel\nclass AttachToTaskViewModel @Inject constructor(\n    private val repository: TaskRepository\n) : ViewModel() {\n\n    val tasks: LiveData<List<TaskPackage>> = repository.fetchLiveData()\n    val isEmpty: LiveData<Boolean> = Transformations.map(tasks) { it.isNullOrEmpty() }\n\n    var attachment = Attachment()\n    var subject: String? = null\n        set(value) {\n            field = value\n            attachment.name = value\n        }\n    var url: String? = null\n        set(value) {\n            field = value\n            attachment.target = value\n        }\n\n    init {\n        attachment.type = Attachment.TYPE_WEBSITE_LINK\n    }\n\n    fun addAttachment(taskID: String) = viewModelScope.launch {\n        attachment.task = taskID\n        repository.addAttachment(attachment)\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/core/activities/MainActivity.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.core.activities\r\n\r\nimport android.Manifest\r\nimport android.app.NotificationManager\r\nimport android.content.Context\r\nimport android.os.Build\r\nimport android.os.Bundle\r\nimport androidx.activity.result.ActivityResultLauncher\r\nimport androidx.activity.result.contract.ActivityResultContracts\r\nimport androidx.core.os.bundleOf\r\nimport androidx.navigation.NavController\r\nimport androidx.navigation.findNavController\r\nimport com.isaiahvonrundstedt.fokus.R\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.createSnackbar\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.getParcelableListExtra\r\nimport com.isaiahvonrundstedt.fokus.components.utils.NotificationChannelManager\r\nimport com.isaiahvonrundstedt.fokus.databinding.ActivityMainBinding\r\nimport com.isaiahvonrundstedt.fokus.features.attachments.Attachment\r\nimport com.isaiahvonrundstedt.fokus.features.event.Event\r\nimport com.isaiahvonrundstedt.fokus.features.event.editor.EventEditorFragment\r\nimport com.isaiahvonrundstedt.fokus.features.notifications.task.TaskReminderWorker\r\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseActivity\r\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\r\nimport com.isaiahvonrundstedt.fokus.features.subject.editor.SubjectEditorFragment\r\nimport com.isaiahvonrundstedt.fokus.features.task.Task\r\nimport com.isaiahvonrundstedt.fokus.features.task.editor.TaskEditorFragment\r\nimport dagger.hilt.android.AndroidEntryPoint\r\n\r\n@AndroidEntryPoint\r\nclass MainActivity : BaseActivity() {\r\n    private var controller: NavController? = null\r\n    private lateinit var binding: ActivityMainBinding\r\n    private lateinit var requestPermissionLauncher: ActivityResultLauncher<String>\r\n    private val notificationManager: NotificationManager by lazy {\r\n        getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager\r\n    }\r\n\r\n    override fun onCreate(savedInstanceState: Bundle?) {\r\n        super.onCreate(savedInstanceState)\r\n        binding = ActivityMainBinding.inflate(layoutInflater)\r\n        setContentView(binding.root)\r\n        controller = findNavController(R.id.navigationHostFragment)\r\n\r\n        requestPermissionLauncher =\r\n            registerForActivityResult(ActivityResultContracts.RequestPermission()) { enabled ->\r\n                if (enabled) createSnackbar(R.string.notifications_are_now_enabled_for_this_app)\r\n                else createSnackbar(R.string.notifications_are_not_enabled_for_this_app)\r\n            }\r\n        intent?.also { intent ->\r\n            when (intent.action) {\r\n                ACTION_WIDGET_TASK -> {\r\n                    val task: Task? = intent.getParcelableExtra(EXTRA_TASK)\r\n                    val subject: Subject? = intent.getParcelableExtra(EXTRA_SUBJECT)\r\n                    val attachments: List<Attachment>? =\r\n                        intent.getParcelableListExtra(EXTRA_ATTACHMENTS)\r\n\r\n                    val args = bundleOf(\r\n                        TaskEditorFragment.EXTRA_TASK to task?.let { Task.toBundle(it) },\r\n                        TaskEditorFragment.EXTRA_SUBJECT to subject?.let { Subject.toBundle(it) },\r\n                        TaskEditorFragment.EXTRA_ATTACHMENTS to attachments\r\n                    )\r\n\r\n                    controller?.navigate(R.id.navigation_editor_task, args)\r\n                }\r\n                ACTION_WIDGET_EVENT -> {\r\n                    val event: Event? = intent.getParcelableExtra(EXTRA_EVENT)\r\n                    val subject: Subject? = intent.getParcelableExtra(EXTRA_SUBJECT)\r\n\r\n                    val args = bundleOf(\r\n                        EventEditorFragment.EXTRA_EVENT to event?.let { Event.toBundle(it) },\r\n                        EventEditorFragment.EXTRA_SUBJECT to subject?.let { Subject.toBundle(it) }\r\n                    )\r\n\r\n                    controller?.navigate(R.id.navigation_editor_event, args)\r\n                }\r\n                ACTION_WIDGET_SUBJECT -> {\r\n                    val subject: Subject? = intent.getParcelableExtra(EXTRA_SUBJECT)\r\n                    val schedules: List<Schedule>? = intent.getParcelableListExtra(EXTRA_SCHEDULES)\r\n\r\n                    val args = bundleOf(\r\n                        SubjectEditorFragment.EXTRA_SUBJECT to subject?.let { Subject.toBundle(it) },\r\n                        SubjectEditorFragment.EXTRA_SCHEDULE to schedules\r\n                    )\r\n                    controller?.navigate(R.id.navigation_editor_subject, args)\r\n                }\r\n                ACTION_SHORTCUT_TASK -> {\r\n                    controller?.navigate(R.id.navigation_editor_task)\r\n                }\r\n                ACTION_SHORTCUT_EVENT -> {\r\n                    controller?.navigate(R.id.navigation_editor_event)\r\n                }\r\n                ACTION_SHORTCUT_SUBJECT -> {\r\n                    controller?.navigate(R.id.navigation_editor_subject)\r\n                }\r\n                ACTION_NAVIGATION_TASK -> {\r\n                    //controller?.navigate(R.id.navigation_tasks)\r\n                }\r\n                ACTION_NAVIGATION_EVENT -> {\r\n                    //controller?.navigate(R.id.navigation_events)\r\n                }\r\n                ACTION_NAVIGATION_SUBJECT -> {\r\n                    //controller?.navigate(R.id.navigation_subjects)\r\n                }\r\n            }\r\n        }\r\n\r\n        TaskReminderWorker.reschedule(this.applicationContext)\r\n    }\r\n\r\n    override fun onStart() {\r\n        super.onStart()\r\n        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.TIRAMISU && !notificationManager.areNotificationsEnabled()) {\r\n            requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)\r\n        } else {\r\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\r\n                with(NotificationChannelManager(this)) {\r\n                    register(\r\n                        NotificationChannelManager.CHANNEL_ID_GENERIC,\r\n                        NotificationManager.IMPORTANCE_DEFAULT\r\n                    )\r\n                    register(\r\n                        NotificationChannelManager.CHANNEL_ID_TASK,\r\n                        groupID = NotificationChannelManager.CHANNEL_GROUP_ID_REMINDERS\r\n                    )\r\n                    register(\r\n                        NotificationChannelManager.CHANNEL_ID_EVENT,\r\n                        groupID = NotificationChannelManager.CHANNEL_GROUP_ID_REMINDERS\r\n                    )\r\n                    register(\r\n                        NotificationChannelManager.CHANNEL_ID_CLASS,\r\n                        groupID = NotificationChannelManager.CHANNEL_GROUP_ID_REMINDERS\r\n                    )\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    override fun onSupportNavigateUp(): Boolean = controller?.navigateUp() ?: false\r\n\r\n    companion object {\r\n        const val ACTION_SHORTCUT_TASK = \"action:shortcut:task\"\r\n        const val ACTION_SHORTCUT_EVENT = \"action:shortcut:event\"\r\n        const val ACTION_SHORTCUT_SUBJECT = \"action:shortcut:subject\"\r\n\r\n        const val ACTION_WIDGET_TASK = \"action:widget:task\"\r\n        const val ACTION_WIDGET_EVENT = \"action:widget:event\"\r\n        const val ACTION_WIDGET_SUBJECT = \"action:widget:subject\"\r\n\r\n        const val ACTION_NAVIGATION_TASK = \"action:navigation:task\"\r\n        const val ACTION_NAVIGATION_EVENT = \"action:navigation:event\"\r\n        const val ACTION_NAVIGATION_SUBJECT = \"action:navigation:subject\"\r\n\r\n        const val EXTRA_TASK = \"extra:task\"\r\n        const val EXTRA_EVENT = \"extra:event\"\r\n        const val EXTRA_SUBJECT = \"extra:subject\"\r\n        const val EXTRA_ATTACHMENTS = \"extra:attachments\"\r\n        const val EXTRA_SCHEDULES = \"extra:schedules\"\r\n    }\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/core/fragment/RootFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.core.fragment\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.view.GravityCompat\nimport androidx.core.view.doOnPreDraw\nimport androidx.navigation.NavController\nimport androidx.navigation.fragment.NavHostFragment\nimport androidx.navigation.fragment.findNavController\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.databinding.FragmentRootBinding\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutNavigationHeaderBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseFragment\nimport java.time.LocalTime\n\nclass RootFragment: BaseFragment() {\n    private var _binding: FragmentRootBinding? = null\n    private var _headerBinding: LayoutNavigationHeaderBinding? = null\n    private var controller: NavController? = null\n    private var mainController: NavController? = null\n\n    private val binding get() = _binding!!\n    private val headerBinding get() = _headerBinding!!\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        _binding = FragmentRootBinding.inflate(inflater, container, false)\n        return binding.root\n    }\n\n    override fun onDestroy() {\n        _binding = null\n        _headerBinding = null\n        super.onDestroy()\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        mainController = requireActivity().supportFragmentManager\n            .findFragmentById(R.id.navigationHostFragment)?.findNavController()\n\n        /**\n         *  Get this fragment's NavController\n         *  to control what fragment will show up\n         *  depending on what directions is on the\n         *  NavigationViewModel\n         */\n        controller = (childFragmentManager.findFragmentById(R.id.fragmentContainerView)\n                as? NavHostFragment)?.navController\n        if (binding.navigationView.headerCount > 0) {\n            _headerBinding = LayoutNavigationHeaderBinding\n                .bind(binding.navigationView.getHeaderView(0))\n            headerBinding.menuTitleView.text = when (LocalTime.now().hour) {\n                in 0..6 -> getString(R.string.greeting_default)\n                in 7..12 -> getString(R.string.greeting_morning)\n                in 13..18 -> getString(R.string.greeting_afternoon)\n                in 19..23 -> getString(R.string.greeting_evening)\n                else -> getString(R.string.greeting_default)\n            }\n        }\n\n        postponeEnterTransition()\n        view.doOnPreDraw { startPostponedEnterTransition() }\n    }\n\n    override fun onResume() {\n        super.onResume()\n\n        binding.navigationView.setNavigationItemSelectedListener {\n            binding.navigationView.setCheckedItem(it.itemId)\n            try {\n                controller?.navigate(it.itemId)\n                binding.drawerLayout.closeDrawer(GravityCompat.START)\n            } catch (exception: Exception) {\n                mainController?.navigate(it.itemId)\n            }\n            true\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/core/worker/ActionWorker.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.core.worker\n\nimport android.content.Context\nimport androidx.hilt.work.HiltWorker\nimport androidx.work.WorkerParameters\nimport com.isaiahvonrundstedt.fokus.components.service.NotificationActionService\nimport com.isaiahvonrundstedt.fokus.database.repository.TaskRepository\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseWorker\nimport dagger.assisted.Assisted\nimport dagger.assisted.AssistedInject\n\n// This worker's primary function perform the action\n// at is triggered in the fokus such as 'Mark as Finished'\n\n@HiltWorker\nclass ActionWorker @AssistedInject constructor(\n    @Assisted context: Context,\n    @Assisted workerParameters: WorkerParameters,\n    private val repository: TaskRepository\n) : BaseWorker(context, workerParameters) {\n\n    override suspend fun doWork(): Result {\n        val action = inputData.getString(NotificationActionService.EXTRA_ACTION)\n        val taskID = inputData.getString(NotificationActionService.EXTRA_TASK_ID)\n        if (action.isNullOrBlank() || taskID.isNullOrBlank())\n            return Result.success()\n\n        if (action == NotificationActionService.ACTION_FINISHED)\n            repository.setFinished(taskID, true)\n\n        return Result.success()\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/event/Event.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.event\r\n\r\nimport android.content.Context\r\nimport android.os.Bundle\r\nimport android.os.Parcelable\r\nimport android.text.format.DateFormat\r\nimport androidx.core.os.bundleOf\r\nimport androidx.room.Entity\r\nimport androidx.room.ForeignKey\r\nimport androidx.room.PrimaryKey\r\nimport androidx.room.TypeConverters\r\nimport com.isaiahvonrundstedt.fokus.R\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.isToday\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.isTomorrow\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.isYesterday\r\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Streamable\r\nimport com.isaiahvonrundstedt.fokus.components.json.JsonDataStreamer\r\nimport com.isaiahvonrundstedt.fokus.database.converter.DateTimeConverter\r\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\r\nimport com.squareup.moshi.JsonClass\r\nimport kotlinx.parcelize.Parcelize\r\nimport okio.buffer\r\nimport okio.sink\r\nimport java.io.File\r\nimport java.io.InputStream\r\nimport java.time.ZonedDateTime\r\nimport java.time.format.DateTimeFormatter\r\nimport java.util.*\r\n\r\n@Parcelize\r\n@JsonClass(generateAdapter = true)\r\n@Entity(\r\n    tableName = \"events\", foreignKeys = [\r\n        ForeignKey(\r\n            entity = Subject::class, parentColumns = arrayOf(\"subjectID\"),\r\n            childColumns = arrayOf(\"subject\"), onDelete = ForeignKey.SET_NULL\r\n        )\r\n    ]\r\n)\r\ndata class Event @JvmOverloads constructor(\r\n    @PrimaryKey\r\n    var eventID: String = UUID.randomUUID().toString(),\r\n    var name: String? = null,\r\n    var notes: String? = null,\r\n    var location: String? = null,\r\n    var subject: String? = null,\r\n    var isImportant: Boolean = false,\r\n    var isEventArchived: Boolean = false,\r\n    @TypeConverters(DateTimeConverter::class)\r\n    var schedule: ZonedDateTime? = null,\r\n    @TypeConverters(DateTimeConverter::class)\r\n    var dateAdded: ZonedDateTime? = ZonedDateTime.now()\r\n) : Parcelable, Streamable {\r\n\r\n    fun isToday(): Boolean {\r\n        return schedule?.isToday() == true\r\n    }\r\n\r\n    fun formatScheduleTime(context: Context): String? {\r\n        return schedule?.format(DateTimeConverter.getTimeFormatter(context))\r\n    }\r\n\r\n    fun formatSchedule(context: Context): String? {\r\n        val datePattern = if (DateFormat.is24HourFormat(context))\r\n            FORMAT_DATE_WITH_WEEKDAY_24_HOUR\r\n        else FORMAT_DATE_WITH_WEEKDAY_12_HOUR\r\n\r\n        return if (schedule?.isToday() == true)\r\n            String.format(\r\n                context.getString(R.string.today_at),\r\n                schedule?.format(DateTimeConverter.getTimeFormatter(context))\r\n            )\r\n        else if (schedule?.isYesterday() == true)\r\n            String.format(\r\n                context.getString(R.string.yesterday_at),\r\n                schedule?.format(DateTimeConverter.getTimeFormatter(context))\r\n            )\r\n        else if (schedule?.isTomorrow() == true)\r\n            String.format(\r\n                context.getString(R.string.tomorrow_at),\r\n                schedule?.format(DateTimeConverter.getTimeFormatter(context))\r\n            )\r\n        else schedule?.format(DateTimeFormatter.ofPattern(datePattern))\r\n    }\r\n\r\n    override fun toJsonString(): String? = JsonDataStreamer.encodeToJson(this, Event::class.java)\r\n\r\n    override fun toJsonFile(destination: File, name: String): File {\r\n        return File(destination, name).apply {\r\n            this.sink().buffer().use {\r\n                toJsonString()?.also { json -> it.write(json.toByteArray()) }\r\n            }\r\n        }\r\n    }\r\n\r\n    override fun fromInputStream(inputStream: InputStream) {\r\n        JsonDataStreamer.decodeOnceFromJson(inputStream, Event::class.java)?.also {\r\n            eventID = it.eventID\r\n            name = it.name\r\n            location = it.location\r\n            schedule = it.schedule\r\n            dateAdded = it.dateAdded\r\n            isImportant = it.isImportant\r\n            notes = it.notes\r\n            subject = it.subject\r\n        }\r\n    }\r\n\r\n    companion object {\r\n        const val EXTRA_ID = \"extra:id\"\r\n        const val EXTRA_NAME = \"extra:name\"\r\n        const val EXTRA_NOTES = \"extra:notes\"\r\n        const val EXTRA_SCHEDULE = \"extra:schedule\"\r\n        const val EXTRA_LOCATION = \"extra:location\"\r\n        const val EXTRA_SUBJECT = \"extra:subject\"\r\n        const val EXTRA_IS_IMPORTANT = \"extra:important\"\r\n        const val EXTRA_IS_ARCHIVED = \"extra:archived\"\r\n        const val EXTRA_DATE_ADDED = \"extra:added\"\r\n\r\n        const val FORMAT_DATE_WITH_WEEKDAY_12_HOUR = \"EEE - MMMM d, h:mm a\"\r\n        const val FORMAT_DATE_WITH_WEEKDAY_24_HOUR = \"EEE - MMMM d, H:mm\"\r\n\r\n        fun toBundle(event: Event): Bundle {\r\n            return bundleOf(\r\n                EXTRA_ID to event.eventID,\r\n                EXTRA_NAME to event.name,\r\n                EXTRA_LOCATION to event.location,\r\n                EXTRA_SCHEDULE to event.schedule,\r\n                EXTRA_NOTES to event.notes,\r\n                EXTRA_IS_IMPORTANT to event.isImportant,\r\n                EXTRA_IS_ARCHIVED to event.isEventArchived,\r\n                EXTRA_DATE_ADDED to event.dateAdded,\r\n                EXTRA_SUBJECT to event.subject\r\n            )\r\n        }\r\n\r\n        fun fromBundle(bundle: Bundle): Event? {\r\n            if (!bundle.containsKey(EXTRA_ID))\r\n                return null\r\n\r\n            return Event(\r\n                eventID = bundle.getString(EXTRA_ID)!!,\r\n                name = bundle.getString(EXTRA_NAME),\r\n                location = bundle.getString(EXTRA_LOCATION),\r\n                schedule = bundle.getSerializable(EXTRA_SCHEDULE) as? ZonedDateTime,\r\n                notes = bundle.getString(EXTRA_NOTES),\r\n                isImportant = bundle.getBoolean(EXTRA_IS_IMPORTANT),\r\n                isEventArchived = bundle.getBoolean(EXTRA_IS_ARCHIVED),\r\n                subject = bundle.getString(EXTRA_SUBJECT)\r\n            )\r\n        }\r\n\r\n        fun fromInputStream(inputStream: InputStream): Event {\r\n            return Event().apply {\r\n                this.fromInputStream(inputStream)\r\n            }\r\n        }\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/event/EventAdapter.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.event\r\n\r\nimport android.view.LayoutInflater\r\nimport android.view.View\r\nimport android.view.ViewGroup\r\nimport androidx.core.view.isVisible\r\nimport androidx.recyclerview.widget.ItemTouchHelper\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.getCompoundDrawableAtStart\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.setCompoundDrawableAtStart\r\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Swipeable\r\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutItemEventBinding\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseFragment\r\n\r\nclass EventAdapter(\r\n    private val actionListener: ActionListener,\r\n    private val archiveListener: ArchiveListener\r\n) : BaseAdapter<EventPackage, EventAdapter.EventViewHolder>(EventPackage.DIFF_CALLBACK), Swipeable {\r\n\r\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EventViewHolder {\r\n        val binding = LayoutItemEventBinding.inflate(\r\n            LayoutInflater.from(parent.context),\r\n            parent, false\r\n        )\r\n        return EventViewHolder(binding.root, actionListener)\r\n    }\r\n\r\n    override fun onBindViewHolder(holder: EventViewHolder, position: Int) {\r\n        holder.onBind(getItem(position))\r\n    }\r\n\r\n    override fun onSwipe(position: Int, direction: Int) {\r\n        when (direction) {\r\n            ItemTouchHelper.START ->\r\n                actionListener.onActionPerformed(\r\n                    getItem(position), ActionListener.Action.DELETE,\r\n                    null\r\n                )\r\n            ItemTouchHelper.END ->\r\n                archiveListener.onItemArchive(getItem(position))\r\n        }\r\n    }\r\n\r\n    class EventViewHolder(\r\n        itemView: View,\r\n        private val actionListener: ActionListener\r\n    ) : BaseViewHolder(itemView) {\r\n        private val binding = LayoutItemEventBinding.bind(itemView)\r\n\r\n        override fun <T> onBind(data: T) {\r\n            if (data is EventPackage) {\r\n                with(data.event) {\r\n                    binding.root.transitionName =\r\n                        BaseFragment.TRANSITION_ELEMENT_ROOT + data.event.eventID\r\n\r\n                    binding.locationView.text = location\r\n                    binding.nameView.text = name\r\n                    binding.timeView.text = formatScheduleTime(binding.root.context)\r\n                }\r\n\r\n                if (data.subject != null) {\r\n                    with(binding.subjectView) {\r\n                        text = data.subject?.code\r\n                        setCompoundDrawableAtStart(\r\n                            data.subject?.tintDrawable(\r\n                                getCompoundDrawableAtStart()\r\n                            )\r\n                        )\r\n                    }\r\n                } else binding.subjectView.isVisible = false\r\n\r\n                binding.root.setOnClickListener {\r\n                    actionListener.onActionPerformed(data, ActionListener.Action.SELECT, it)\r\n                }\r\n            }\r\n        }\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/event/EventFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.event\r\n\r\nimport android.os.Bundle\r\nimport android.view.LayoutInflater\r\nimport android.view.MenuItem\r\nimport android.view.View\r\nimport android.view.ViewGroup\r\nimport android.widget.LinearLayout\r\nimport android.widget.TextView\r\nimport androidx.core.os.bundleOf\r\nimport androidx.core.view.children\r\nimport androidx.core.view.doOnPreDraw\r\nimport androidx.core.view.isVisible\r\nimport androidx.fragment.app.viewModels\r\nimport androidx.navigation.NavController\r\nimport androidx.navigation.Navigation\r\nimport androidx.navigation.fragment.FragmentNavigatorExtras\r\nimport androidx.recyclerview.widget.ItemTouchHelper\r\nimport androidx.recyclerview.widget.LinearLayoutManager\r\nimport com.isaiahvonrundstedt.fokus.R\r\nimport com.isaiahvonrundstedt.fokus.components.custom.ItemDecoration\r\nimport com.isaiahvonrundstedt.fokus.components.custom.ItemSwipeCallback\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.createSnackbar\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.isDark\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.setTextColorFromResource\r\nimport com.isaiahvonrundstedt.fokus.databinding.FragmentEventBinding\r\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutCalendarDayBinding\r\nimport com.isaiahvonrundstedt.fokus.features.event.editor.EventEditorFragment\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseFragment\r\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\r\nimport com.kizitonwose.calendarview.model.CalendarDay\r\nimport com.kizitonwose.calendarview.model.CalendarMonth\r\nimport com.kizitonwose.calendarview.model.DayOwner\r\nimport com.kizitonwose.calendarview.ui.DayBinder\r\nimport com.kizitonwose.calendarview.ui.MonthHeaderFooterBinder\r\nimport com.kizitonwose.calendarview.ui.ViewContainer\r\nimport dagger.hilt.android.AndroidEntryPoint\r\nimport me.saket.cascade.overrideOverflowMenu\r\nimport java.time.DayOfWeek\r\nimport java.time.LocalDate\r\nimport java.time.format.DateTimeFormatter\r\nimport java.time.temporal.WeekFields\r\nimport java.util.*\r\n\r\n@AndroidEntryPoint\r\nclass EventFragment : BaseFragment(), BaseAdapter.ActionListener, BaseAdapter.ArchiveListener {\r\n\r\n    private var daysOfWeek: Array<DayOfWeek> = emptyArray()\r\n    private var _binding: FragmentEventBinding? = null\r\n    private var controller: NavController? = null\r\n\r\n    private val binding get() = _binding!!\r\n    private val eventAdapter = EventAdapter(this, this)\r\n    private val monthYearFormatter = DateTimeFormatter.ofPattern(\"MMMM yyyy\")\r\n    private val dateFormatter = DateTimeFormatter.ofPattern(\"d MMMM yyyy\")\r\n    private val viewModel: EventViewModel by viewModels()\r\n\r\n    override fun onCreateView(\r\n        inflater: LayoutInflater, container: ViewGroup?,\r\n        savedInstanceState: Bundle?\r\n    ): View {\r\n        _binding = FragmentEventBinding.inflate(inflater)\r\n        return binding.root\r\n    }\r\n\r\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\r\n        super.onViewCreated(view, savedInstanceState)\r\n        binding.actionButton.transitionName = TRANSITION_ELEMENT_ROOT\r\n        setInsets(binding.root, binding.appBarLayout.toolbar, arrayOf(binding.containerLayout),\r\n            binding.actionButton)\r\n\r\n        with(binding.appBarLayout.toolbar) {\r\n            title = viewModel.currentMonth.format(monthYearFormatter)\r\n            menu?.clear()\r\n            inflateMenu(R.menu.menu_events)\r\n            overrideOverflowMenu(::customPopupProvider)\r\n            setOnMenuItemClickListener(::onMenuItemClicked)\r\n            setupNavigation(this)\r\n        }\r\n\r\n        with(binding.recyclerView) {\r\n            addItemDecoration(ItemDecoration(context))\r\n            layoutManager = LinearLayoutManager(context)\r\n            adapter = eventAdapter\r\n\r\n            ItemTouchHelper(ItemSwipeCallback(context, eventAdapter))\r\n                .attachToRecyclerView(this)\r\n        }\r\n\r\n        postponeEnterTransition()\r\n        view.doOnPreDraw { startPostponedEnterTransition() }\r\n\r\n        daysOfWeek = daysOfWeekFromLocale()\r\n        binding.calendarView.apply {\r\n            setup(\r\n                viewModel.startMonth, viewModel.endMonth,\r\n                daysOfWeek.first()\r\n            )\r\n            scrollToMonth(viewModel.currentMonth)\r\n        }\r\n\r\n        if (savedInstanceState == null)\r\n            binding.calendarView.post { setCurrentDate(viewModel.today) }\r\n    }\r\n\r\n    override fun onStart() {\r\n        super.onStart()\r\n\r\n        /**\r\n         * Get the NavController here so\r\n         * that it doesn't crash when\r\n         * the host activity is recreated.\r\n         */\r\n        controller = Navigation.findNavController(requireActivity(), R.id.navigationHostFragment)\r\n\r\n        class DayViewContainer(view: View) : ViewContainer(view) {\r\n            lateinit var day: CalendarDay\r\n\r\n            val textView: TextView = LayoutCalendarDayBinding.bind(view).calendarDayView\r\n            val dotView: View = LayoutCalendarDayBinding.bind(view).calendarDotView\r\n\r\n            init {\r\n                view.setOnClickListener {\r\n                    if (day.owner == DayOwner.THIS_MONTH)\r\n                        setCurrentDate(day.date)\r\n                }\r\n            }\r\n        }\r\n\r\n        viewModel.events.observe(viewLifecycleOwner) {\r\n            eventAdapter.submitList(it)\r\n        }\r\n        viewModel.eventsEmpty.observe(viewLifecycleOwner) {\r\n            binding.emptyView.isVisible = it\r\n        }\r\n\r\n        class MonthViewContainer(view: View) : ViewContainer(view) {\r\n            val headerLayout: LinearLayout = view.findViewById(R.id.headerLayout)\r\n        }\r\n\r\n        binding.calendarView.dayBinder = object : DayBinder<DayViewContainer> {\r\n            override fun create(view: View): DayViewContainer = DayViewContainer(view)\r\n            override fun bind(container: DayViewContainer, day: CalendarDay) {\r\n                container.day = day\r\n                bindToCalendar(day, container.textView, container.dotView)\r\n            }\r\n        }\r\n\r\n        binding.calendarView.monthHeaderBinder =\r\n            object : MonthHeaderFooterBinder<MonthViewContainer> {\r\n                override fun create(view: View): MonthViewContainer = MonthViewContainer(view)\r\n\r\n                override fun bind(container: MonthViewContainer, month: CalendarMonth) {\r\n                    val headerLayout = container.headerLayout\r\n                    if (container.headerLayout.tag == null) {\r\n                        headerLayout.tag = month.yearMonth\r\n                        headerLayout.children.map { it as TextView }\r\n                            .forEachIndexed { index, textView ->\r\n                                textView.text = daysOfWeek[index].name.first().toString()\r\n                            }\r\n                    }\r\n                }\r\n            }\r\n\r\n        binding.calendarView.monthScrollListener = {\r\n            setCurrentDate(it.yearMonth.atDay(1))\r\n            binding.appBarLayout.toolbar.title = it.yearMonth.format(monthYearFormatter)\r\n\r\n            // Check if the user is nearing the end of the month list.\r\n            // Then continually add more months so that the user\r\n            // can scroll infinitely.\r\n            if (it.yearMonth.minusMonths(2) == viewModel.startMonth) {\r\n                // The user is two months away from the starting month in the CalendarView\r\n                // we'll need to add more months at the start\r\n                viewModel.startMonth = viewModel.startMonth.minusMonths(2)\r\n                binding.calendarView.updateMonthRange(startMonth = viewModel.startMonth)\r\n\r\n            } else if (it.yearMonth.plusMonths(2) == viewModel.endMonth) {\r\n                // The user is two months away from the ending month in the CalendarView\r\n                // we'll need to add more months at the end\r\n                viewModel.endMonth = viewModel.endMonth.plusMonths(2)\r\n                binding.calendarView.updateMonthRange(endMonth = viewModel.endMonth)\r\n            }\r\n        }\r\n\r\n        // Observe dates with events then rebind the\r\n        // dayBinder to the Calendar.\r\n        viewModel.dates.observe(viewLifecycleOwner) { dates ->\r\n            binding.calendarView.dayBinder = object : DayBinder<DayViewContainer> {\r\n                override fun create(view: View): DayViewContainer {\r\n                    return DayViewContainer(view)\r\n                }\r\n\r\n                override fun bind(container: DayViewContainer, day: CalendarDay) {\r\n                    container.day = day\r\n                    bindToCalendar(day, container.textView, container.dotView, dates)\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    override fun onResume() {\r\n        super.onResume()\r\n\r\n        binding.calendarView.scrollToMonth(viewModel.currentMonth)\r\n        binding.calendarView.scrollToDate(viewModel.today)\r\n        setCurrentDate(viewModel.today)\r\n\r\n        binding.actionButton.setOnClickListener {\r\n            it.transitionName = TRANSITION_ELEMENT_ROOT\r\n\r\n            controller?.navigate(\r\n                R.id.navigation_editor_event, null, null,\r\n                FragmentNavigatorExtras(it to TRANSITION_ELEMENT_ROOT)\r\n            )\r\n        }\r\n    }\r\n\r\n    override fun <T> onItemArchive(t: T) {\r\n        if (t is EventPackage) {\r\n            t.event.isEventArchived = true\r\n            viewModel.update(t.event)\r\n        }\r\n    }\r\n\r\n    override fun <T> onActionPerformed(\r\n        t: T, action: BaseAdapter.ActionListener.Action,\r\n        container: View?\r\n    ) {\r\n        if (t is EventPackage) {\r\n            when (action) {\r\n                // Show up the editorUI and pass the extra\r\n                BaseAdapter.ActionListener.Action.SELECT -> {\r\n                    val transitionName = TRANSITION_ELEMENT_ROOT + t.event.eventID\r\n\r\n                    val args = bundleOf(\r\n                        EventEditorFragment.EXTRA_EVENT to Event.toBundle(t.event),\r\n                        EventEditorFragment.EXTRA_SUBJECT to t.subject?.let { Subject.toBundle(it) }\r\n                    )\r\n\r\n                    controller?.navigate(\r\n                        R.id.navigation_editor_event, args, null,\r\n                        FragmentNavigatorExtras(container!! to transitionName)\r\n                    )\r\n                }\r\n                // Item has been swiped, notify database for deletion\r\n                BaseAdapter.ActionListener.Action.DELETE -> {\r\n                    viewModel.remove(t.event)\r\n\r\n                    createSnackbar(R.string.feedback_event_removed, binding.recyclerView).run {\r\n                        setAction(R.string.button_undo) { viewModel.insert(t.event) }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    private fun onMenuItemClicked(item: MenuItem): Boolean {\r\n        when (item.itemId) {\r\n            R.id.action_archived -> {\r\n                controller?.navigate(R.id.navigation_archived_event)\r\n            }\r\n        }\r\n        return true\r\n    }\r\n\r\n    private fun bindToCalendar(\r\n        day: CalendarDay, textView: TextView, view: View,\r\n        dates: List<LocalDate> = emptyList()\r\n    ) {\r\n\r\n        textView.text = day.date.dayOfMonth.toString()\r\n        if (day.owner == DayOwner.THIS_MONTH) {\r\n            when (day.date) {\r\n                viewModel.today -> {\r\n                    val color = if (requireContext().isDark()) android.R.color.system_accent1_50\r\n                        else android.R.color.system_accent1_500\r\n                    textView.setTextColorFromResource(color)\r\n                    textView.setBackgroundResource(R.drawable.shape_calendar_current_day)\r\n                    view.isVisible = false\r\n                }\r\n                viewModel.selectedDate -> {\r\n                    textView.setTextColorFromResource(R.color.theme_on_primary_container)\r\n                    textView.setBackgroundResource(R.drawable.shape_calendar_selected_day)\r\n                    view.isVisible = false\r\n                }\r\n                else -> {\r\n                    textView.setTextColorFromResource(R.color.color_primary_text)\r\n                    textView.background = null\r\n                    view.isVisible = dates.contains(day.date)\r\n                }\r\n            }\r\n        } else {\r\n            textView.setTextColorFromResource(R.color.color_secondary_text)\r\n            view.isVisible = false\r\n        }\r\n    }\r\n\r\n    private fun setCurrentDate(date: LocalDate) {\r\n        if (viewModel.selectedDate != date) {\r\n            val oldDate = viewModel.selectedDate\r\n\r\n            viewModel.selectedDate = date\r\n            binding.calendarView.notifyDateChanged(oldDate)\r\n            binding.calendarView.notifyDateChanged(date)\r\n        }\r\n        binding.currentDateTextView.text = date.format(dateFormatter)\r\n    }\r\n\r\n    private fun daysOfWeekFromLocale(): Array<DayOfWeek> {\r\n        val firstDayOfWeek = WeekFields.of(Locale.getDefault()).firstDayOfWeek\r\n        var daysOfWeek = DayOfWeek.values()\r\n        // Order `daysOfWeek` array so that firstDayOfWeek is at index 0.\r\n        // Only necessary if firstDayOfWeek != DayOfWeek.MONDAY which has ordinal 0.\r\n        if (firstDayOfWeek != DayOfWeek.MONDAY) {\r\n            val rhs = daysOfWeek.sliceArray(firstDayOfWeek.ordinal..daysOfWeek.indices.last)\r\n            val lhs = daysOfWeek.sliceArray(0 until firstDayOfWeek.ordinal)\r\n            daysOfWeek = rhs + lhs\r\n        }\r\n        return daysOfWeek\r\n    }\r\n\r\n    override fun onDestroy() {\r\n        super.onDestroy()\r\n        _binding = null\r\n    }\r\n}\r\n"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/event/EventPackage.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.event\n\nimport android.os.Parcelable\nimport androidx.recyclerview.widget.DiffUtil\nimport androidx.room.Embedded\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\nimport kotlinx.android.parcel.Parcelize\n\n/**\n *   Data class used for the presentation of\n *   events and subject in the UI\n */\n@Parcelize\ndata class EventPackage(\n    @Embedded\n    var event: Event,\n    @Embedded\n    var subject: Subject? = null\n) : Parcelable {\n\n    companion object {\n        val DIFF_CALLBACK = object : DiffUtil.ItemCallback<EventPackage>() {\n            override fun areItemsTheSame(oldItem: EventPackage, newItem: EventPackage): Boolean {\n                return oldItem.event.eventID == newItem.event.eventID\n            }\n\n            override fun areContentsTheSame(oldItem: EventPackage, newItem: EventPackage): Boolean {\n                return oldItem == newItem\n            }\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/event/EventViewModel.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.event\r\n\r\nimport androidx.lifecycle.*\r\nimport com.isaiahvonrundstedt.fokus.database.repository.EventRepository\r\nimport dagger.hilt.android.lifecycle.HiltViewModel\r\nimport kotlinx.coroutines.Dispatchers\r\nimport kotlinx.coroutines.NonCancellable\r\nimport kotlinx.coroutines.launch\r\nimport java.time.LocalDate\r\nimport java.time.YearMonth\r\nimport javax.inject.Inject\r\n\r\n@HiltViewModel\r\nclass EventViewModel @Inject constructor(\r\n    private val repository: EventRepository\r\n) : ViewModel() {\r\n\r\n    private val _events: LiveData<List<EventPackage>> = repository.fetchLiveData()\r\n\r\n    val dates: MediatorLiveData<List<LocalDate>> = MediatorLiveData()\r\n    val events: MediatorLiveData<List<EventPackage>> = MediatorLiveData()\r\n    val eventsEmpty: LiveData<Boolean> = Transformations.map(events) { it.isNullOrEmpty() }\r\n\r\n    val today: LocalDate\r\n        get() = LocalDate.now()\r\n    val currentMonth: YearMonth\r\n        get() = YearMonth.now()\r\n\r\n    var selectedDate: LocalDate = today\r\n        set(value) {\r\n            field = value\r\n            events.value =\r\n                _events.value?.filter { it.event.schedule!!.toLocalDate() == selectedDate }\r\n        }\r\n\r\n    var startMonth: YearMonth = currentMonth.minusMonths(1)\r\n    var endMonth: YearMonth = currentMonth.plusMonths(1)\r\n\r\n    init {\r\n        events.addSource(_events) { items ->\r\n            events.value = items.filter { it.event.schedule!!.toLocalDate() == selectedDate }\r\n        }\r\n        dates.addSource(_events) { items ->\r\n            dates.value = items.map { it.event.schedule!!.toLocalDate() }.distinct()\r\n        }\r\n    }\r\n\r\n    fun insert(event: Event) = viewModelScope.launch(Dispatchers.IO + NonCancellable) {\r\n        repository.insert(event)\r\n    }\r\n\r\n    fun remove(event: Event) = viewModelScope.launch(Dispatchers.IO + NonCancellable) {\r\n        repository.remove(event)\r\n    }\r\n\r\n    fun update(event: Event) = viewModelScope.launch(Dispatchers.IO + NonCancellable) {\r\n        repository.update(event)\r\n    }\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/event/archived/ArchivedEventAdapter.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.event.archived\n\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.view.isVisible\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.getCompoundDrawableAtStart\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.setCompoundDrawableAtStart\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutItemArchivedEventBinding\nimport com.isaiahvonrundstedt.fokus.features.event.EventPackage\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseFragment\n\nclass ArchivedEventAdapter(private val listener: SelectListener) :\n    BaseAdapter<EventPackage, ArchivedEventAdapter.ArchivedEventViewHolder>(EventPackage.DIFF_CALLBACK) {\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArchivedEventViewHolder {\n        val binding = LayoutItemArchivedEventBinding.inflate(\n            LayoutInflater.from(parent.context),\n            parent, false\n        )\n        return ArchivedEventViewHolder(binding.root, listener)\n    }\n\n    override fun onBindViewHolder(holder: ArchivedEventViewHolder, position: Int) {\n        holder.onBind(getItem(position))\n    }\n\n    class ArchivedEventViewHolder(\n        itemView: View,\n        private val listener: SelectListener\n    ) : BaseViewHolder(itemView) {\n        private val binding = LayoutItemArchivedEventBinding.bind(itemView)\n\n        override fun <T> onBind(data: T) {\n            if (data is EventPackage) {\n                with(data.event) {\n                    binding.root.transitionName = BaseFragment.TRANSITION_ELEMENT_ROOT + eventID\n\n                    binding.locationView.text = location\n                    binding.nameView.text = name\n                    binding.timeView.text = formatScheduleTime(binding.root.context)\n                }\n\n                binding.root.setOnClickListener {\n                    listener.onItemSelected(data)\n                }\n\n                if (data.subject != null) {\n                    with(binding.subjectView) {\n                        text = data.subject?.code\n                        setCompoundDrawableAtStart(\n                            data.subject?.tintDrawable(\n                                getCompoundDrawableAtStart()\n                            )\n                        )\n                    }\n                } else binding.subjectView.isVisible = false\n            }\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/event/archived/ArchivedEventFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.event.archived\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.view.isVisible\nimport androidx.fragment.app.viewModels\nimport androidx.navigation.NavController\nimport androidx.navigation.Navigation\nimport androidx.recyclerview.widget.LinearLayoutManager\nimport com.afollestad.materialdialogs.MaterialDialog\nimport com.afollestad.materialdialogs.lifecycle.lifecycleOwner\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.custom.ItemDecoration\nimport com.isaiahvonrundstedt.fokus.databinding.FragmentArchivedEventBinding\nimport com.isaiahvonrundstedt.fokus.features.event.EventPackage\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseFragment\nimport dagger.hilt.android.AndroidEntryPoint\n\n@AndroidEntryPoint\nclass ArchivedEventFragment : BaseFragment(), BaseAdapter.SelectListener {\n    private var _binding: FragmentArchivedEventBinding? = null\n    private var controller: NavController? = null\n\n    private val archivedEventAdapter = ArchivedEventAdapter(this)\n    private val viewModel: ArchivedEventViewModel by viewModels()\n    private val binding get() = _binding!!\n\n    override fun onCreateView(\n        inflater: LayoutInflater, container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        _binding = FragmentArchivedEventBinding.inflate(layoutInflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        setInsets(binding.root, binding.appBarLayout.toolbar,\n            arrayOf(binding.recyclerView, binding.emptyView))\n        controller = Navigation.findNavController(view)\n\n        with(binding.appBarLayout.toolbar) {\n            setTitle(R.string.activity_archives)\n            setNavigationIcon(R.drawable.ic_outline_arrow_back_24)\n            setNavigationOnClickListener { controller?.navigateUp() }\n        }\n\n        with(binding.recyclerView) {\n            addItemDecoration(ItemDecoration(context))\n            layoutManager = LinearLayoutManager(context)\n            adapter = archivedEventAdapter\n        }\n    }\n\n    override fun <T> onItemSelected(t: T) {\n        if (t is EventPackage) {\n            MaterialDialog(requireContext()).show {\n                lifecycleOwner(viewLifecycleOwner)\n                title(R.string.dialog_confirm_unarchive_title)\n                message(R.string.dialog_confirm_unarchive_summary)\n                positiveButton {\n                    viewModel.removeFromArchive(t)\n                }\n                negativeButton(R.string.button_cancel)\n            }\n        }\n    }\n\n    override fun onStart() {\n        super.onStart()\n\n        viewModel.items.observe(viewLifecycleOwner) {\n            archivedEventAdapter.submitList(it)\n        }\n        viewModel.isEmpty.observe(viewLifecycleOwner) {\n            binding.emptyView.isVisible = it\n        }\n    }\n\n    override fun onDestroy() {\n        super.onDestroy()\n        _binding = null\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/event/archived/ArchivedEventViewModel.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.event.archived\n\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.Transformations\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.viewModelScope\nimport com.isaiahvonrundstedt.fokus.database.repository.EventRepository\nimport com.isaiahvonrundstedt.fokus.features.event.EventPackage\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport kotlinx.coroutines.launch\nimport javax.inject.Inject\n\n@HiltViewModel\nclass ArchivedEventViewModel @Inject constructor(\n    private val eventRepository: EventRepository\n) : ViewModel() {\n\n    val items: LiveData<List<EventPackage>> = eventRepository.fetchArchivedLiveData()\n    val isEmpty: LiveData<Boolean> = Transformations.map(items) { it.isEmpty() }\n\n    fun removeFromArchive(eventPackage: EventPackage) = viewModelScope.launch {\n        eventPackage.event.isEventArchived = false\n        eventRepository.update(eventPackage.event)\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/event/editor/EventEditorContainer.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.event.editor\n\nimport android.os.Bundle\nimport com.isaiahvonrundstedt.fokus.databinding.ActivityContainerEventBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseActivity\nimport dagger.hilt.android.AndroidEntryPoint\n\n/**\n * This activity acts as a container\n * for the editor fragment. This is\n * used when needing to show the\n * editor ui without needing a fragment\n * transaction.\n */\n@AndroidEntryPoint\nclass EventEditorContainer : BaseActivity() {\n    private lateinit var binding: ActivityContainerEventBinding\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        binding = ActivityContainerEventBinding.inflate(layoutInflater)\n        setContentView(binding.root)\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/event/editor/EventEditorFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.event.editor\n\nimport android.content.BroadcastReceiver\nimport android.content.Context\nimport android.content.Intent\nimport android.content.IntentFilter\nimport android.os.Bundle\nimport android.text.format.DateFormat.is24HourFormat\nimport android.view.LayoutInflater\nimport android.view.MenuItem\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.activity.result.ActivityResultLauncher\nimport androidx.activity.result.contract.ActivityResultContracts\nimport androidx.appcompat.widget.AppCompatTextView\nimport androidx.core.app.ShareCompat\nimport androidx.core.content.ContextCompat\nimport androidx.core.view.children\nimport androidx.core.view.isVisible\nimport androidx.fragment.app.FragmentResultListener\nimport androidx.fragment.app.viewModels\nimport androidx.localbroadcastmanager.content.LocalBroadcastManager\nimport androidx.navigation.NavController\nimport androidx.navigation.Navigation\nimport com.afollestad.materialdialogs.MaterialDialog\nimport com.afollestad.materialdialogs.datetime.dateTimePicker\nimport com.afollestad.materialdialogs.lifecycle.lifecycleOwner\nimport com.google.android.material.snackbar.Snackbar\nimport com.google.android.material.textfield.TextInputEditText\nimport com.isaiahvonrundstedt.fokus.Fokus\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.createSnackbar\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.removeCompoundDrawableAtStart\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.setCompoundDrawableAtStart\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.setTextColorFromResource\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.toCalendar\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.toZonedDateTime\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Streamable\nimport com.isaiahvonrundstedt.fokus.components.service.DataExporterService\nimport com.isaiahvonrundstedt.fokus.components.service.DataImporterService\nimport com.isaiahvonrundstedt.fokus.components.views.TwoLineRadioButton\nimport com.isaiahvonrundstedt.fokus.databinding.FragmentEditorEventBinding\nimport com.isaiahvonrundstedt.fokus.features.event.Event\nimport com.isaiahvonrundstedt.fokus.features.event.EventPackage\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\nimport com.isaiahvonrundstedt.fokus.features.schedule.picker.SchedulePickerSheet\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseEditorFragment\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseService\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\nimport com.isaiahvonrundstedt.fokus.features.subject.SubjectPackage\nimport com.isaiahvonrundstedt.fokus.features.subject.picker.SubjectPickerFragment\nimport dagger.hilt.android.AndroidEntryPoint\nimport me.saket.cascade.overrideOverflowMenu\nimport java.io.File\nimport java.time.ZoneId\nimport java.time.ZonedDateTime\n\n@AndroidEntryPoint\nclass EventEditorFragment : BaseEditorFragment(), FragmentResultListener {\n    private var _binding: FragmentEditorEventBinding? = null\n    private var controller: NavController? = null\n    private var requestKey = REQUEST_KEY_INSERT\n\n    private val viewModel: EventEditorViewModel by viewModels()\n    private val binding get() = _binding!!\n\n    private lateinit var exportLauncher: ActivityResultLauncher<Intent>\n    private lateinit var importLauncher: ActivityResultLauncher<Intent>\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        sharedElementEnterTransition = buildContainerTransform()\n        sharedElementReturnTransition = buildContainerTransform()\n\n        exportLauncher =\n            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {\n                context?.startService(Intent(context, DataExporterService::class.java).apply {\n                    this.data = it.data?.data\n                    action = DataExporterService.ACTION_EXPORT_EVENT\n                    putExtra(DataExporterService.EXTRA_EXPORT_SOURCE, viewModel.getEvent())\n                })\n            }\n\n        importLauncher =\n            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {\n                context?.startService(Intent(context, DataImporterService::class.java).apply {\n                    this.data = it.data?.data\n                    action = DataImporterService.ACTION_IMPORT_EVENT\n                })\n            }\n\n    }\n\n    override fun onCreateView(\n        inflater: LayoutInflater, container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        _binding = FragmentEditorEventBinding.inflate(inflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        binding.root.transitionName = TRANSITION_ELEMENT_ROOT\n        setInsets(binding.root, binding.appBarLayout.toolbar, arrayOf(binding.contentView),\n            binding.actionButton)\n        controller = Navigation.findNavController(view)\n\n        with(binding.appBarLayout.toolbar) {\n            inflateMenu(R.menu.menu_editor)\n            setNavigationOnClickListener {\n                if (controller?.graph?.id == R.id.navigation_container_event)\n                    requireActivity().finish()\n                else controller?.navigateUp()\n            }\n\n            overrideOverflowMenu(::customPopupProvider)\n            setOnMenuItemClickListener(::onMenuItemClicked)\n        }\n\n        arguments?.getBundle(EXTRA_EVENT)?.also {\n            requestKey = REQUEST_KEY_UPDATE\n\n            Event.fromBundle(it)?.also { event ->\n                viewModel.setEvent(event)\n                binding.root.transitionName = TRANSITION_ELEMENT_ROOT + event.eventID\n                binding.priorityCard.isVisible = event.isImportant\n            }\n        }\n        arguments?.getBundle(EXTRA_SUBJECT)?.also {\n            viewModel.setSubject(Subject.fromBundle(it))\n        }\n\n        registerForFragmentResult(\n            arrayOf(\n                SubjectPickerFragment.REQUEST_KEY_PICK,\n                SchedulePickerSheet.REQUEST_KEY\n            ), this\n        )\n    }\n\n    override fun onStart() {\n        super.onStart()\n\n        LocalBroadcastManager.getInstance(requireContext())\n            .registerReceiver(receiver, IntentFilter(BaseService.ACTION_SERVICE_BROADCAST))\n\n        if (requestKey == REQUEST_KEY_UPDATE) {\n            binding.eventNameTextInput.setText(viewModel.getName())\n            binding.locationTextInput.setText(viewModel.getLocation())\n            binding.notesTextInput.setText(viewModel.getNotes())\n        }\n\n        viewModel.event.observe(viewLifecycleOwner) {\n            if (requestKey == REQUEST_KEY_UPDATE && it != null) {\n                with(it) {\n                    binding.scheduleTextView.text = formatSchedule(requireContext())\n                    binding.prioritySwitch.isChecked = isImportant\n                }\n            }\n        }\n\n        viewModel.subject.observe(viewLifecycleOwner) {\n            binding.removeButton.isVisible = it != null\n            binding.scheduleTextView.isVisible = it == null\n            binding.dateTimeRadioGroup.isVisible = it != null\n\n            if (it != null) {\n                with(binding.subjectTextView) {\n                    text = it.code\n                    setTextColorFromResource(R.color.color_primary_text)\n                    ContextCompat.getDrawable(context, R.drawable.shape_color_holder)\n                        ?.also { shape ->\n                            this.setCompoundDrawableAtStart(it.tintDrawable(shape))\n                        }\n                }\n\n                if (viewModel.schedules.isNotEmpty()) {\n                    with(binding.customDateTimeRadio) {\n                        isChecked = true\n                        titleTextColor = ContextCompat.getColor(\n                            context,\n                            R.color.color_primary_text\n                        )\n                        subtitle = viewModel.getEvent()?.formatSchedule(context)\n                    }\n                }\n            } else {\n                with(binding.subjectTextView) {\n                    removeCompoundDrawableAtStart()\n                    setText(R.string.field_subject)\n                    setTextColorFromResource(R.color.color_secondary_text)\n                }\n\n                if (viewModel.schedules.isNotEmpty()) {\n                    with(binding.scheduleTextView) {\n                        text = viewModel.getEvent()?.formatSchedule(context)\n                        setTextColorFromResource(R.color.color_primary_text)\n                    }\n                }\n            }\n        }\n\n        viewModel.isNameTaken.observe(this) {\n            binding.eventNameTextInputLayout.error =\n                if (it) getString(R.string.feedback_event_name_exists)\n                else null\n        }\n\n        binding.eventNameTextInput.setOnFocusChangeListener { v, hasFocus ->\n            if (!hasFocus && v is TextInputEditText) {\n                viewModel.setName(v.text.toString())\n            }\n        }\n\n        binding.locationTextInput.setOnFocusChangeListener { v, hasFocus ->\n            if (!hasFocus && v is TextInputEditText) {\n                viewModel.setLocation(v.text.toString())\n            }\n        }\n\n        binding.notesTextInput.setOnFocusChangeListener { v, hasFocus ->\n            if (!hasFocus && v is TextInputEditText) {\n                viewModel.setNotes(v.text.toString())\n            }\n        }\n\n        binding.prioritySwitch.setOnCheckedChangeListener { _, isChecked ->\n            viewModel.setImportant(isChecked)\n            binding.priorityCard.isVisible = isChecked\n        }\n\n        binding.scheduleTextView.setOnClickListener { v ->\n            MaterialDialog(requireContext()).show {\n                lifecycleOwner(viewLifecycleOwner)\n                dateTimePicker(\n                    requireFutureDateTime = true,\n                    currentDateTime = viewModel.getSchedule()?.toCalendar(),\n                    show24HoursView = is24HourFormat(requireContext())\n                ) { _, datetime ->\n                    viewModel.setSchedule(datetime.toZonedDateTime())\n                }\n                positiveButton(R.string.button_done) {\n                    if (v is AppCompatTextView) {\n                        v.text = viewModel.getEvent()?.formatSchedule(context)\n                        v.setTextColorFromResource(R.color.color_primary_text)\n                    }\n                }\n            }\n        }\n\n        binding.subjectTextView.setOnClickListener {\n            SubjectPickerFragment(childFragmentManager)\n                .show()\n        }\n\n        binding.removeButton.setOnClickListener {\n            binding.subjectTextView.startAnimation(animation)\n            viewModel.setSubject(null)\n        }\n\n        binding.dateTimeRadioGroup.setOnCheckedChangeListener { radioGroup, _ ->\n            for (v: View in radioGroup.children) {\n                if (v is TwoLineRadioButton && !v.isChecked) {\n                    v.titleTextColor = ContextCompat.getColor(\n                        v.context,\n                        R.color.color_secondary_text\n                    )\n                    v.subtitle = null\n                }\n            }\n        }\n\n        binding.inNextMeetingRadio.setOnClickListener {\n            viewModel.setNextMeetingForDueDate()\n\n            with(binding.inNextMeetingRadio) {\n                titleTextColor = ContextCompat.getColor(context, R.color.color_primary_text)\n                subtitle = viewModel.getEvent()?.formatSchedule(context)\n            }\n        }\n\n        binding.pickDateTimeRadio.setOnClickListener {\n            hideKeyboardFromCurrentFocus(requireView())\n\n            SchedulePickerSheet\n                .show(viewModel.schedules, childFragmentManager)\n        }\n\n        binding.customDateTimeRadio.setOnClickListener {\n            MaterialDialog(requireContext()).show {\n                lifecycleOwner(viewLifecycleOwner)\n                dateTimePicker(\n                    requireFutureDateTime = true,\n                    currentDateTime = viewModel.getSchedule()?.toCalendar(),\n                    show24HoursView = is24HourFormat(requireContext())\n                ) { _, datetime ->\n                    viewModel.setSchedule(\n                        ZonedDateTime.ofInstant(\n                            datetime.toInstant(),\n                            ZoneId.systemDefault()\n                        )\n                    )\n                }\n                positiveButton(R.string.button_done) {\n\n                    with(binding.customDateTimeRadio) {\n                        titleTextColor = ContextCompat.getColor(\n                            context,\n                            R.color.color_primary_text\n                        )\n                        subtitle = viewModel.getEvent()?.formatSchedule(context)\n                    }\n                }\n                negativeButton { binding.customDateTimeRadio.isChecked = false }\n            }\n        }\n\n        binding.actionButton.setOnClickListener {\n            viewModel.setName(binding.eventNameTextInput.text.toString())\n            viewModel.setLocation(binding.locationTextInput.text.toString())\n\n            // Conditions to check if the fields are null or blank\n            // then if resulted true, show a feedback then direct\n            // user focus to the field and stop code execution.\n            if (viewModel.getName()?.isEmpty() == true) {\n                createSnackbar(R.string.feedback_event_empty_name, binding.root)\n                binding.eventNameTextInput.requestFocus()\n                return@setOnClickListener\n            }\n\n            if (viewModel.getLocation()?.isEmpty() == true) {\n                createSnackbar(R.string.feedback_event_empty_location, binding.root)\n                binding.locationTextInput.requestFocus()\n                return@setOnClickListener\n            }\n\n            if (viewModel.getSchedule() == null) {\n                createSnackbar(R.string.feedback_event_empty_schedule, binding.root)\n                binding.scheduleTextView.performClick()\n                return@setOnClickListener\n            }\n\n            viewModel.setImportant(binding.prioritySwitch.isChecked)\n\n            if (requestKey == REQUEST_KEY_INSERT)\n                viewModel.insert()\n            else viewModel.update()\n\n            if (controller?.graph?.id == R.id.navigation_container_event)\n                requireActivity().finish()\n            else controller?.navigateUp()\n        }\n    }\n\n    override fun onFragmentResult(requestKey: String, result: Bundle) {\n        when (requestKey) {\n            SubjectPickerFragment.REQUEST_KEY_PICK -> {\n                result.getParcelable<SubjectPackage>(SubjectPickerFragment.EXTRA_SELECTED_SUBJECT)?.let {\n                    viewModel.setSubject(it.subject)\n                    viewModel.schedules = it.schedules\n                }\n            }\n            SchedulePickerSheet.REQUEST_KEY -> {\n                result.getParcelable<Schedule>(SchedulePickerSheet.EXTRA_SCHEDULE)?.also {\n                    viewModel.setClassScheduleAsDueDate(it)\n\n                    with(binding.pickDateTimeRadio) {\n                        titleTextColor = ContextCompat.getColor(\n                            context,\n                            R.color.color_primary_text\n                        )\n                        subtitle = viewModel.getEvent()?.formatSchedule(context)\n                    }\n                }\n            }\n        }\n    }\n\n    override fun onStop() {\n        super.onStop()\n\n        /**\n         * Check if the soft keyboard is visible\n         * then hide it before the user leaves\n         * the fragment\n         */\n        hideKeyboardFromCurrentFocus(requireView())\n    }\n\n    override fun onDestroy() {\n        super.onDestroy()\n\n        _binding = null\n        LocalBroadcastManager.getInstance(requireContext())\n            .unregisterReceiver(receiver)\n    }\n\n    private var receiver = object : BroadcastReceiver() {\n        override fun onReceive(context: Context?, intent: Intent?) {\n            if (intent?.action == BaseService.ACTION_SERVICE_BROADCAST) {\n                when (intent.getStringExtra(BaseService.EXTRA_BROADCAST_STATUS)) {\n                    DataExporterService.BROADCAST_EXPORT_ONGOING -> {\n                        createSnackbar(\n                            R.string.feedback_export_ongoing, binding.root,\n                            Snackbar.LENGTH_INDEFINITE\n                        )\n                    }\n                    DataExporterService.BROADCAST_EXPORT_COMPLETED -> {\n                        createSnackbar(R.string.feedback_export_completed, binding.root)\n\n                        intent.getStringExtra(BaseService.EXTRA_BROADCAST_DATA)?.also {\n                            val uri = Fokus.obtainUriForFile(requireContext(), File(it))\n\n                            startActivity(\n                                ShareCompat.IntentBuilder.from(requireActivity())\n                                    .addStream(uri)\n                                    .setType(Streamable.MIME_TYPE_ZIP)\n                                    .setChooserTitle(R.string.dialog_send_to)\n                                    .intent\n                            )\n                        }\n                    }\n                    DataExporterService.BROADCAST_EXPORT_FAILED -> {\n                        createSnackbar(R.string.feedback_export_failed, binding.root)\n                    }\n                    DataImporterService.BROADCAST_IMPORT_ONGOING -> {\n                        createSnackbar(R.string.feedback_import_ongoing, binding.root)\n                    }\n                    DataImporterService.BROADCAST_IMPORT_COMPLETED -> {\n                        createSnackbar(R.string.feedback_import_completed, binding.root)\n\n                        intent.getParcelableExtra<EventPackage>(BaseService.EXTRA_BROADCAST_DATA)\n                            ?.also {\n                                viewModel.setEvent(it.event)\n                            }\n                    }\n                    DataImporterService.BROADCAST_IMPORT_FAILED -> {\n                        createSnackbar(R.string.feedback_import_failed, binding.root)\n                    }\n                }\n            }\n        }\n    }\n\n    private fun onMenuItemClicked(item: MenuItem): Boolean {\n        when (item.itemId) {\n            R.id.action_export -> {\n                val fileName = getSharingName()\n                if (fileName == null) {\n                    MaterialDialog(requireContext()).show {\n                        lifecycleOwner(viewLifecycleOwner)\n                        title(R.string.feedback_unable_to_share_title)\n                        message(R.string.feedback_unable_to_share_message)\n                        positiveButton(R.string.button_done) { dismiss() }\n                    }\n                    return false\n                }\n\n                /**\n                 * Make the user specify where to save\n                 * the exported file\n                 */\n                exportLauncher.launch(Intent(Intent.ACTION_CREATE_DOCUMENT).apply {\n                    addCategory(Intent.CATEGORY_OPENABLE)\n                    putExtra(Intent.EXTRA_TITLE, fileName)\n                    type = Streamable.MIME_TYPE_ZIP\n                })\n            }\n            R.id.action_share -> {\n                val fileName = getSharingName()\n                if (fileName == null) {\n                    MaterialDialog(requireContext()).show {\n                        lifecycleOwner(viewLifecycleOwner)\n                        title(R.string.feedback_unable_to_share_title)\n                        message(R.string.feedback_unable_to_share_message)\n                        positiveButton(R.string.button_done) { dismiss() }\n                    }\n                    return false\n                }\n\n                /**\n                 * We need first to export the data as a raw file\n                 * then pass it onto the system sharing component\n                 */\n                context?.startService(Intent(context, DataExporterService::class.java).apply {\n                    action = DataExporterService.ACTION_EXPORT_EVENT\n                    putExtra(\n                        DataExporterService.EXTRA_EXPORT_SOURCE,\n                        viewModel.getEvent()\n                    )\n                })\n            }\n            R.id.action_import -> {\n                val chooser = Intent.createChooser(Intent(Intent.ACTION_OPEN_DOCUMENT).apply {\n                    type = Streamable.MIME_TYPE_ZIP\n                }, getString(R.string.dialog_select_file_import))\n\n                importLauncher.launch(chooser)\n            }\n        }\n        return true\n    }\n\n    override fun onSaveInstanceState(outState: Bundle) {\n        with(outState) {\n            putParcelable(EXTRA_EVENT, viewModel.getEvent())\n            putParcelable(EXTRA_SUBJECT, viewModel.getSubject())\n        }\n        super.onSaveInstanceState(outState)\n    }\n\n    override fun onViewStateRestored(savedInstanceState: Bundle?) {\n        super.onViewStateRestored(savedInstanceState)\n        savedInstanceState?.run {\n            viewModel.setEvent(getParcelable(EXTRA_EVENT))\n            viewModel.setSubject(getParcelable(EXTRA_SUBJECT))\n        }\n    }\n\n    private fun getSharingName(): String? {\n        return when (requestKey) {\n            REQUEST_KEY_INSERT -> {\n                if (viewModel.getName()?.isEmpty() == true || viewModel.getLocation()\n                        ?.isEmpty() == true ||\n                    viewModel.getSchedule() == null\n                ) {\n                    MaterialDialog(requireContext()).show {\n                        title(R.string.feedback_unable_to_share_title)\n                        message(R.string.feedback_unable_to_share_message)\n                        positiveButton(R.string.button_dismiss) { dismiss() }\n                    }\n                    return null\n                }\n\n                viewModel.getName() ?: Streamable.ARCHIVE_NAME_GENERIC\n            }\n            REQUEST_KEY_UPDATE -> {\n                viewModel.getName() ?: Streamable.ARCHIVE_NAME_GENERIC\n            }\n            else -> null\n        }\n    }\n\n    companion object {\n        const val REQUEST_KEY_INSERT = \"request:insert\"\n        const val REQUEST_KEY_UPDATE = \"request:update\"\n\n        const val EXTRA_EVENT = \"extra:event\"\n        const val EXTRA_SUBJECT = \"extra:subject\"\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/event/editor/EventEditorViewModel.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.event.editor\n\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.viewModelScope\nimport com.isaiahvonrundstedt.fokus.database.converter.DateTimeConverter\nimport com.isaiahvonrundstedt.fokus.database.dao.ScheduleDAO\nimport com.isaiahvonrundstedt.fokus.database.repository.EventRepository\nimport com.isaiahvonrundstedt.fokus.features.event.Event\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.NonCancellable\nimport kotlinx.coroutines.launch\nimport java.time.LocalDate\nimport java.time.ZonedDateTime\nimport javax.inject.Inject\n\n@HiltViewModel\nclass EventEditorViewModel @Inject constructor(\n    private val scheduleDao: ScheduleDAO,\n    private val repository: EventRepository\n) : ViewModel() {\n\n    private val _event: MutableLiveData<Event> = MutableLiveData(Event())\n    private val _subject: MutableLiveData<Subject> = MutableLiveData(null)\n    private val _isNameTaken: MutableLiveData<Boolean> = MutableLiveData(false)\n\n    val event: LiveData<Event> = _event\n    val subject: LiveData<Subject> = _subject\n    val isNameTaken: LiveData<Boolean> = _isNameTaken\n\n    var schedules: List<Schedule> = emptyList()\n\n    fun getEvent(): Event? {\n        return event.value\n    }\n\n    fun setEvent(event: Event?) {\n        _event.value = event\n    }\n\n    fun getSubject(): Subject? {\n        return subject.value\n    }\n\n    fun setSubject(subject: Subject?) {\n        _subject.value = subject\n        if (subject != null) {\n            fetchSchedulesFromDatabase(subject.subjectID)\n            setEventSubjectID(subject.subjectID)\n        } else {\n            schedules = emptyList()\n            setEventSubjectID(null)\n        }\n    }\n\n    fun checkNameUniqueness(name: String? = null, schedule: ZonedDateTime? = null) =\n        viewModelScope.launch {\n            val result = repository.checkNameUniqueness(\n                name ?: getName(),\n                DateTimeConverter.fromLocalDate(\n                    schedule?.toLocalDate() ?: getSchedule()?.toLocalDate()\n                ),\n                getEvent()?.eventID\n            )\n            _isNameTaken.value = result.isNotEmpty()\n        }\n\n    fun getID(): String? {\n        return getEvent()?.eventID\n    }\n\n    fun getName(): String? {\n        return getEvent()?.name\n    }\n\n    fun setName(name: String?) {\n        // Check if the same value is being set\n        if (name == getName())\n            return\n\n        val event = getEvent()\n        event?.name = name\n        setEvent(event)\n    }\n\n    fun getSchedule(): ZonedDateTime? {\n        return getEvent()?.schedule\n    }\n\n    fun setSchedule(schedule: ZonedDateTime?) {\n        val event = getEvent()\n        event?.schedule = schedule\n        setEvent(event)\n    }\n\n    fun getLocation(): String? {\n        return getEvent()?.location\n    }\n\n    fun setLocation(location: String?) {\n        // Check if the same value is being set\n        if (location == getLocation())\n            return\n\n        val event = getEvent()\n        event?.location = location\n        setEvent(event)\n    }\n\n    fun getEventSubjectID(): String? {\n        return getEvent()?.eventID\n    }\n\n    fun setEventSubjectID(id: String?) {\n        val event = getEvent()\n        event?.subject = id\n        setEvent(event)\n    }\n\n    fun getImportant(): Boolean {\n        return getEvent()?.isImportant == true\n    }\n\n    fun setImportant(isImportant: Boolean) {\n        val event = getEvent()\n        event?.isImportant = isImportant\n        setEvent(event)\n    }\n\n    fun getNotes(): String? {\n        return getEvent()?.notes\n    }\n\n    fun setNotes(notes: String) {\n        if (notes == getNotes())\n            return\n\n        val event = getEvent()\n        event?.notes = notes\n        setEvent(event)\n    }\n\n    fun setNextMeetingForDueDate() {\n        setSchedule(getNextMeetingForSchedule())\n    }\n\n    fun setClassScheduleAsDueDate(schedule: Schedule) {\n        setSchedule(schedule.startTime?.let {\n            Schedule.getNearestDateTime(\n                schedule.daysOfWeek,\n                it\n            )\n        })\n    }\n\n    private fun getNextMeetingForSchedule(): ZonedDateTime? {\n        val currentDate = LocalDate.now()\n        val individualDates = mutableListOf<Schedule>()\n\n        // Create new instances of Schedule\n        // with individual day of week values\n        schedules.forEach {\n            it.parseDaysOfWeek().forEach { day ->\n                val newSchedule = Schedule(\n                    startTime = it.startTime,\n                    endTime = it.endTime\n                )\n                newSchedule.daysOfWeek = day\n                individualDates.add(newSchedule)\n            }\n        }\n\n        // Map the schedule instances to\n        // a ZonedDateTime instance\n        val dates = individualDates.map {\n            it.startTime?.let { time ->\n                Schedule.getNearestDateTime(\n                    it.daysOfWeek,\n                    time\n                )\n            }\n        }\n        if (dates.isEmpty())\n            return null\n\n        return dates.singleOrNull {\n            currentDate.isAfter(it?.toLocalDate()) || currentDate.isEqual(it?.toLocalDate())\n        } ?: dates[0]\n    }\n\n    private fun fetchSchedulesFromDatabase(id: String) = viewModelScope.launch {\n        schedules = scheduleDao.fetchUsingID(id)\n    }\n\n    fun insert() = viewModelScope.launch(Dispatchers.IO + NonCancellable) {\n        getEvent()?.let {\n            repository.insert(it)\n        }\n    }\n\n    fun update() = viewModelScope.launch(Dispatchers.IO + NonCancellable) {\n        getEvent()?.let {\n            repository.update(it)\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/event/widget/EventWidgetProvider.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.event.widget\n\nimport android.app.PendingIntent\nimport android.appwidget.AppWidgetManager\nimport android.appwidget.AppWidgetProvider\nimport android.content.ComponentName\nimport android.content.Context\nimport android.content.Intent\nimport android.widget.RemoteViews\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.features.core.activities.MainActivity\nimport com.isaiahvonrundstedt.fokus.features.event.editor.EventEditorContainer\n\nclass EventWidgetProvider : AppWidgetProvider() {\n\n    override fun onReceive(context: Context?, intent: Intent?) {\n        super.onReceive(context, intent)\n\n        if (intent?.action == WIDGET_ACTION_UPDATE) {\n            val manager = AppWidgetManager.getInstance(context)\n            val component = ComponentName(context!!, EventWidgetProvider::class.java)\n\n            manager.notifyAppWidgetViewDataChanged(\n                manager.getAppWidgetIds(component),\n                R.id.listView\n            )\n        }\n    }\n\n    override fun onUpdate(\n        context: Context?, appWidgetManager: AppWidgetManager?,\n        appWidgetIds: IntArray?\n    ) {\n        super.onUpdate(context, appWidgetManager, appWidgetIds)\n        appWidgetIds?.forEach {\n            onUpdateWidget(context, appWidgetManager, it)\n        }\n    }\n\n    private fun onUpdateWidget(context: Context?, manager: AppWidgetManager?, id: Int) {\n        val mainIntent = PendingIntent.getActivity(\n            context, 0,\n            Intent(context, MainActivity::class.java).apply {\n                action = MainActivity.ACTION_NAVIGATION_EVENT\n            }, PendingIntent.FLAG_IMMUTABLE\n        )\n\n        val itemIntent = PendingIntent.getActivity(\n            context, 0,\n            Intent(context, MainActivity::class.java).apply {\n                action = MainActivity.ACTION_WIDGET_EVENT\n            }, PendingIntent.FLAG_IMMUTABLE\n        )\n\n        val addIntent = PendingIntent.getActivity(\n            context, 0,\n            Intent(context, EventEditorContainer::class.java), PendingIntent.FLAG_IMMUTABLE\n        )\n\n        val views = RemoteViews(context?.packageName, R.layout.layout_widget_events)\n        with(views) {\n            setOnClickPendingIntent(R.id.rootView, mainIntent)\n            setOnClickPendingIntent(R.id.actionButton, addIntent)\n            setRemoteAdapter(R.id.listView, Intent(context, EventWidgetService::class.java))\n            setPendingIntentTemplate(R.id.listView, itemIntent)\n            setEmptyView(R.id.listView, R.id.emptyView)\n        }\n\n        manager?.notifyAppWidgetViewDataChanged(id, R.id.listView)\n        manager?.updateAppWidget(id, views)\n    }\n\n    companion object {\n        private const val WIDGET_ACTION_UPDATE = \"widget:event:update\"\n\n        fun triggerRefresh(context: Context?) {\n            context?.sendBroadcast(Intent(WIDGET_ACTION_UPDATE).apply {\n                component = ComponentName(context, EventWidgetProvider::class.java)\n            })\n        }\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/event/widget/EventWidgetRemoteViewFactory.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.event.widget\n\nimport android.content.Context\nimport android.content.Intent\nimport android.view.View\nimport android.widget.RemoteViews\nimport android.widget.RemoteViewsService\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.database.AppDatabase\nimport com.isaiahvonrundstedt.fokus.features.core.activities.MainActivity\nimport com.isaiahvonrundstedt.fokus.features.event.EventPackage\nimport kotlinx.coroutines.async\nimport kotlinx.coroutines.runBlocking\n\nclass EventWidgetRemoteViewFactory(private var context: Context) :\n    RemoteViewsService.RemoteViewsFactory {\n\n    private var itemList = mutableListOf<EventPackage>()\n\n    private fun fetch() {\n        itemList.clear()\n\n        val events = AppDatabase.getInstance(context).events()\n        var items = emptyList<EventPackage>()\n        runBlocking {\n            val job = async { events.fetchPackage() }\n            items = job.await() ?: emptyList()\n            items.forEach { if (it.event.isToday()) itemList.add(it) }\n        }\n    }\n\n    override fun onDataSetChanged() = fetch()\n\n    override fun getLoadingView(): RemoteViews =\n        RemoteViews(context.packageName, R.layout.layout_widget_progress)\n\n    override fun getItemId(position: Int): Long = position.toLong()\n\n    override fun hasStableIds(): Boolean = true\n\n    override fun getViewAt(position: Int): RemoteViews {\n        val event = itemList[position].event\n        val subject = itemList[position].subject\n\n        val itemIntent = Intent().apply {\n            putExtra(MainActivity.EXTRA_EVENT, event)\n            putExtra(MainActivity.EXTRA_SUBJECT, subject)\n        }\n\n        val views = RemoteViews(context.packageName, R.layout.layout_item_widget)\n        with(views) {\n            setTextViewText(R.id.titleView, event.name)\n            setTextViewText(R.id.summaryView, event.formatSchedule(context))\n            setOnClickFillInIntent(R.id.rootView, itemIntent)\n            if (subject != null)\n                setInt(R.id.imageView, \"setColorFilter\", subject.tag.color)\n            else setViewVisibility(R.id.imageView, View.GONE)\n        }\n        return views\n    }\n\n    override fun getCount(): Int = itemList.size\n\n    override fun getViewTypeCount(): Int = 1\n\n    override fun onCreate() {}\n    override fun onDestroy() {}\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/event/widget/EventWidgetService.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.event.widget\n\nimport android.content.Intent\nimport android.widget.RemoteViewsService\n\nclass EventWidgetService : RemoteViewsService() {\n\n    override fun onGetViewFactory(intent: Intent?): RemoteViewsFactory {\n        return EventWidgetRemoteViewFactory(applicationContext)\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/log/Log.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.log\r\n\r\nimport android.content.Context\r\nimport android.os.Parcelable\r\nimport androidx.annotation.DrawableRes\r\nimport androidx.recyclerview.widget.DiffUtil\r\nimport androidx.room.Entity\r\nimport androidx.room.PrimaryKey\r\nimport androidx.room.TypeConverters\r\nimport com.isaiahvonrundstedt.fokus.R\r\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Streamable\r\nimport com.isaiahvonrundstedt.fokus.components.json.JsonDataStreamer\r\nimport com.isaiahvonrundstedt.fokus.database.converter.DateTimeConverter\r\nimport com.squareup.moshi.JsonClass\r\nimport kotlinx.parcelize.Parcelize\r\nimport okio.buffer\r\nimport okio.sink\r\nimport java.io.File\r\nimport java.io.InputStream\r\nimport java.time.LocalDate\r\nimport java.time.ZonedDateTime\r\nimport java.util.*\r\n\r\n@Parcelize\r\n@JsonClass(generateAdapter = true)\r\n@Entity(tableName = \"logs\")\r\ndata class Log @JvmOverloads constructor(\r\n    @PrimaryKey\r\n    var logID: String = UUID.randomUUID().toString(),\r\n    var title: String? = null,\r\n    var content: String? = null,\r\n    var data: String? = null,\r\n    var type: Int = TYPE_GENERIC,\r\n    var isImportant: Boolean = false,\r\n    @TypeConverters(DateTimeConverter::class)\r\n    var dateTimeTriggered: ZonedDateTime? = null\r\n) : Parcelable, Streamable {\r\n\r\n    fun formatDateTime(context: Context): String? {\r\n        val currentDateTime = LocalDate.now()\r\n\r\n        // Formats the dateTime object for human reading\r\n        return if (dateTimeTriggered!!.toLocalDate().isEqual(currentDateTime))\r\n            dateTimeTriggered?.format(DateTimeConverter.getDateTimeFormatter(context, true))\r\n        else if (dateTimeTriggered!!.toLocalDate().year == currentDateTime.year)\r\n            dateTimeTriggered?.format(DateTimeConverter.getDateTimeFormatter(context, true))\r\n        else dateTimeTriggered?.format(\r\n            DateTimeConverter.getDateTimeFormatter(\r\n                context, isShort = true,\r\n                withYear = true\r\n            )\r\n        )\r\n    }\r\n\r\n    @DrawableRes\r\n    fun getIconResource(): Int {\r\n        return when (type) {\r\n            TYPE_TASK -> R.drawable.ic_outline_check_24\r\n            TYPE_EVENT -> R.drawable.ic_outline_event_24\r\n            TYPE_CLASS -> R.drawable.ic_outline_settings_24\r\n            TYPE_GENERIC -> R.drawable.ic_outline_lightbulb_24\r\n            else -> R.drawable.ic_outline_lightbulb_24\r\n        }\r\n    }\r\n\r\n    override fun toJsonString(): String? = JsonDataStreamer.encodeToJson(this, Log::class.java)\r\n\r\n    override fun toJsonFile(destination: File, name: String): File {\r\n        return File(destination, name).apply {\r\n            this.sink().buffer().use {\r\n                toJsonString()?.also { json -> it.write(json.toByteArray()) }\r\n                it.flush()\r\n            }\r\n        }\r\n    }\r\n\r\n    override fun fromInputStream(inputStream: InputStream) {\r\n        JsonDataStreamer.decodeOnceFromJson(inputStream, Log::class.java)?.also {\r\n            logID = it.logID\r\n            title = it.title\r\n            content = it.content\r\n            type = it.type\r\n            isImportant = it.isImportant\r\n            data = it.data\r\n            dateTimeTriggered = it.dateTimeTriggered\r\n        }\r\n    }\r\n\r\n    companion object {\r\n        const val TYPE_GENERIC = 0\r\n        const val TYPE_TASK = 1\r\n        const val TYPE_EVENT = 2\r\n        const val TYPE_CLASS = 3\r\n\r\n        val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Log>() {\r\n            override fun areItemsTheSame(oldItem: Log, newItem: Log): Boolean {\r\n                return oldItem.logID == newItem.logID\r\n            }\r\n\r\n            override fun areContentsTheSame(oldItem: Log, newItem: Log): Boolean {\r\n                return oldItem == newItem\r\n            }\r\n        }\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/log/LogAdapter.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.log\r\n\r\nimport android.view.LayoutInflater\r\nimport android.view.View\r\nimport android.view.ViewGroup\r\nimport androidx.recyclerview.widget.ItemTouchHelper\r\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Swipeable\r\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutItemLogBinding\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\r\n\r\nclass LogAdapter(private var actionListener: ActionListener) :\r\n    BaseAdapter<Log, LogAdapter.ViewHolder>(Log.DIFF_CALLBACK), Swipeable {\r\n\r\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {\r\n        val binding = LayoutItemLogBinding.inflate(\r\n            LayoutInflater.from(parent.context), parent,\r\n            false\r\n        )\r\n        return ViewHolder(binding.root)\r\n    }\r\n\r\n    override fun onBindViewHolder(holder: ViewHolder, position: Int) {\r\n        holder.onBind(getItem(position))\r\n    }\r\n\r\n    override fun onSwipe(position: Int, direction: Int) {\r\n        if (direction == ItemTouchHelper.START)\r\n            actionListener.onActionPerformed(\r\n                getItem(position), ActionListener.Action.DELETE,\r\n                null\r\n            )\r\n    }\r\n\r\n    class ViewHolder(itemView: View) : BaseViewHolder(itemView) {\r\n\r\n        private val binding = LayoutItemLogBinding.bind(itemView)\r\n\r\n        override fun <T> onBind(data: T) {\r\n            if (data is Log) {\r\n                with(data) {\r\n                    binding.titleView.text = title\r\n                    binding.summaryView.text = content\r\n                    binding.dateTimeView.text = data.formatDateTime(binding.root.context)\r\n                    binding.iconView.setImageResource(getIconResource())\r\n                }\r\n            }\r\n        }\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/log/LogFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.log\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.MenuItem\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.view.isVisible\nimport androidx.fragment.app.viewModels\nimport androidx.navigation.NavController\nimport androidx.navigation.Navigation\nimport androidx.navigation.fragment.findNavController\nimport androidx.recyclerview.widget.ItemTouchHelper\nimport androidx.recyclerview.widget.LinearLayoutManager\nimport com.google.android.material.snackbar.Snackbar\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.custom.ItemDecoration\nimport com.isaiahvonrundstedt.fokus.components.custom.ItemSwipeCallback\nimport com.isaiahvonrundstedt.fokus.databinding.FragmentLogsBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseFragment\nimport dagger.hilt.android.AndroidEntryPoint\nimport me.saket.cascade.overrideOverflowMenu\n\n@AndroidEntryPoint\nclass LogFragment : BaseFragment(), BaseAdapter.ActionListener {\n    private var _binding: FragmentLogsBinding? = null\n    private var controller: NavController? = null\n\n    private val logAdapter = LogAdapter(this)\n    private val viewModel: LogViewModel by viewModels()\n    private val binding get() = _binding!!\n\n    override fun onCreateView(\n        inflater: LayoutInflater, container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        _binding = FragmentLogsBinding.inflate(inflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        setInsets(binding.root, binding.appBarLayout.toolbar, arrayOf(binding.emptyView))\n\n        with(binding.appBarLayout.toolbar) {\n            setTitle(R.string.activity_logs)\n            inflateMenu(R.menu.menu_logs)\n            overrideOverflowMenu(::customPopupProvider)\n            setOnMenuItemClickListener(::onMenuItemClicked)\n            setupNavigation(this, R.drawable.ic_outline_arrow_back_24) {\n                controller?.navigateUp()\n            }\n        }\n\n        with(binding.recyclerView) {\n            addItemDecoration(ItemDecoration(context))\n            layoutManager = LinearLayoutManager(context)\n            adapter = logAdapter\n\n            ItemTouchHelper(ItemSwipeCallback(context, logAdapter))\n                .attachToRecyclerView(this)\n        }\n    }\n\n    override fun onStart() {\n        super.onStart()\n        controller = findNavController()\n\n        viewModel.logs.observe(viewLifecycleOwner) {\n            logAdapter.submitList(it)\n        }\n        viewModel.isEmpty.observe(viewLifecycleOwner) {\n            binding.emptyView.isVisible = it\n        }\n    }\n\n    override fun <T> onActionPerformed(\n        t: T, action: BaseAdapter.ActionListener.Action,\n        container: View?\n    ) {\n        if (t is Log) {\n            when (action) {\n                BaseAdapter.ActionListener.Action.DELETE -> {\n                    viewModel.remove(t)\n                    val snackbar = Snackbar.make(\n                        binding.recyclerView, R.string.feedback_log_removed,\n                        Snackbar.LENGTH_SHORT\n                    )\n                    snackbar.setAction(R.string.button_undo) {\n                        viewModel.insert(t)\n                    }\n                    snackbar.show()\n                }\n                BaseAdapter.ActionListener.Action.SELECT -> {\n                }\n            }\n        }\n    }\n\n    private fun onMenuItemClicked(item: MenuItem): Boolean {\n        when (item.itemId) {\n            R.id.action_clear_items -> viewModel.removeLogs()\n        }\n        return true\n    }\n\n    override fun onDestroy() {\n        super.onDestroy()\n        _binding = null\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/log/LogViewModel.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.log\r\n\r\nimport androidx.lifecycle.LiveData\r\nimport androidx.lifecycle.Transformations\r\nimport androidx.lifecycle.ViewModel\r\nimport androidx.lifecycle.viewModelScope\r\nimport com.isaiahvonrundstedt.fokus.database.repository.LogRepository\r\nimport dagger.hilt.android.lifecycle.HiltViewModel\r\nimport kotlinx.coroutines.launch\r\nimport javax.inject.Inject\r\n\r\n@HiltViewModel\r\nclass LogViewModel @Inject constructor(\r\n    private val repository: LogRepository\r\n) : ViewModel() {\r\n\r\n    val logs: LiveData<List<Log>> = repository.fetch()\r\n    val isEmpty: LiveData<Boolean> = Transformations.map(logs) { it.isNullOrEmpty() }\r\n\r\n    fun insert(log: Log) = viewModelScope.launch {\r\n        repository.insert(log)\r\n    }\r\n\r\n    fun remove(log: Log) = viewModelScope.launch {\r\n        repository.remove(log)\r\n    }\r\n\r\n    fun removeLogs() = viewModelScope.launch {\r\n        repository.removeLogs()\r\n    }\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/notifications/NotificationWorker.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.notifications\n\nimport android.app.NotificationManager\nimport android.content.Context\nimport androidx.hilt.work.HiltWorker\nimport androidx.work.WorkerParameters\nimport com.isaiahvonrundstedt.fokus.database.repository.LogRepository\nimport com.isaiahvonrundstedt.fokus.features.log.Log\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseWorker\nimport dagger.assisted.Assisted\nimport dagger.assisted.AssistedInject\nimport java.time.ZonedDateTime\n\n// This worker fetches the fokus passed by various\n// worker classes. It's primary purpose is to only trigger\n// and to show the fokus. Also to insert the fokus\n// object to the database.\n@HiltWorker\nclass NotificationWorker @AssistedInject constructor(\n    @Assisted context: Context,\n    @Assisted workerParameters: WorkerParameters,\n    private val repository: LogRepository,\n    private val notificationManager: NotificationManager\n) : BaseWorker(context, workerParameters) {\n\n    override suspend fun doWork(): Result {\n        val log: Log = convertDataToLog(inputData)\n        log.dateTimeTriggered = ZonedDateTime.now()\n\n        repository.insert(log)\n        if (log.isImportant)\n            sendNotification(log, notificationManager, log.data)\n        else sendNotification(log, notificationManager)\n\n        return Result.success()\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/notifications/event/EventNotificationScheduler.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.notifications.event\n\nimport android.content.Context\nimport androidx.hilt.work.HiltWorker\nimport androidx.work.ExistingWorkPolicy\nimport androidx.work.OneTimeWorkRequest\nimport androidx.work.WorkManager\nimport androidx.work.WorkerParameters\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.isAfterNow\nimport com.isaiahvonrundstedt.fokus.database.repository.EventRepository\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseWorker\nimport dagger.assisted.Assisted\nimport dagger.assisted.AssistedInject\n\n// This worker's function is to reschedule all pending workers\n// that is supposed to trigger at its due minus the interval\n// This only triggers when the user has changed the fokus interval\n// for tasks in the Settings\n\n@HiltWorker\nclass EventNotificationScheduler @AssistedInject constructor(\n    @Assisted context: Context,\n    @Assisted workerParameters: WorkerParameters,\n    private val repository: EventRepository\n) : BaseWorker(context, workerParameters) {\n\n    override suspend fun doWork(): Result {\n        val items = repository.fetchCore()\n\n        items.forEach { event ->\n            if (event.schedule?.isAfterNow() == true) {\n                val request = OneTimeWorkRequest.Builder(EventNotificationWorker::class.java)\n                    .setInputData(convertEventToData(event))\n                    .build()\n                WorkManager.getInstance(applicationContext).enqueueUniqueWork(\n                    event.eventID,\n                    ExistingWorkPolicy.REPLACE, request\n                )\n            }\n        }\n        return Result.success()\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/notifications/event/EventNotificationWorker.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.notifications.event\n\nimport android.content.Context\nimport androidx.hilt.work.HiltWorker\nimport androidx.work.ExistingWorkPolicy\nimport androidx.work.OneTimeWorkRequest\nimport androidx.work.WorkManager\nimport androidx.work.WorkerParameters\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.isAfterNow\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\nimport com.isaiahvonrundstedt.fokus.features.log.Log\nimport com.isaiahvonrundstedt.fokus.features.notifications.NotificationWorker\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseWorker\nimport dagger.assisted.Assisted\nimport dagger.assisted.AssistedInject\nimport java.time.Duration\nimport java.time.ZonedDateTime\nimport java.util.concurrent.TimeUnit\n\n// This worker's function is to schedule the fokus worker\n// for the event schedule minus the interval.\n\n@HiltWorker\nclass EventNotificationWorker @AssistedInject constructor(\n    @Assisted context: Context,\n    @Assisted workerParameters: WorkerParameters,\n    private val preferenceManager: PreferenceManager,\n    private val workManager: WorkManager\n) : BaseWorker(context, workerParameters) {\n\n    override suspend fun doWork(): Result {\n\n        val event = convertDataToEvent(inputData)\n        val notification = Log().apply {\n            title = event.name\n            content = event.formatSchedule(applicationContext)\n            type = Log.TYPE_EVENT\n            data = event.eventID\n            isImportant = event.isImportant\n        }\n\n        val request = OneTimeWorkRequest.Builder(NotificationWorker::class.java)\n        request.setInputData(convertLogToData(notification))\n\n        if (notification.isImportant) {\n            workManager.enqueueUniqueWork(\n                event.eventID, ExistingWorkPolicy.REPLACE,\n                request.build()\n            )\n            return Result.success()\n        }\n\n        var executionTime = event.schedule\n        when (preferenceManager.eventReminderInterval) {\n            PreferenceManager.EVENT_REMINDER_INTERVAL_15_MINUTES ->\n                executionTime = event.schedule?.minusMinutes(15)\n            PreferenceManager.EVENT_REMINDER_INTERVAL_30_MINUTES ->\n                executionTime = event.schedule?.minusMinutes(30)\n            PreferenceManager.EVENT_REMINDER_INTERVAL_60_MINUTES ->\n                executionTime = event.schedule?.minusMinutes(60)\n        }\n\n        if (executionTime?.isAfterNow() == true)\n            request.setInitialDelay(\n                Duration.between(ZonedDateTime.now(), executionTime).toMinutes(),\n                TimeUnit.MINUTES\n            )\n\n        workManager.enqueueUniqueWork(\n            event.eventID, ExistingWorkPolicy.REPLACE,\n            request.build()\n        )\n\n        return Result.success()\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/notifications/subject/ClassNotificationScheduler.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.notifications.subject\n\nimport android.content.Context\nimport androidx.hilt.work.HiltWorker\nimport androidx.work.ExistingWorkPolicy\nimport androidx.work.OneTimeWorkRequest\nimport androidx.work.WorkManager\nimport androidx.work.WorkerParameters\nimport com.isaiahvonrundstedt.fokus.database.repository.SubjectRepository\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseWorker\nimport dagger.assisted.Assisted\nimport dagger.assisted.AssistedInject\n\n@HiltWorker\nclass ClassNotificationScheduler @AssistedInject constructor(\n    @Assisted context: Context,\n    @Assisted workerParameters: WorkerParameters,\n    private val repository: SubjectRepository,\n    private val workManager: WorkManager\n) : BaseWorker(context, workerParameters) {\n\n    override suspend fun doWork(): Result {\n        val subjectList = repository.fetch()\n\n        subjectList.forEach { resource ->\n            resource.schedules.forEach {\n                it.subject = resource.subject.code\n\n                val request = OneTimeWorkRequest.Builder(ClassNotificationWorker::class.java)\n                    .setInputData(convertScheduleToData(it))\n                workManager.enqueueUniqueWork(\n                    it.scheduleID, ExistingWorkPolicy.REPLACE,\n                    request.build()\n                )\n            }\n        }\n        return Result.success()\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/notifications/subject/ClassNotificationWorker.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.notifications.subject\n\nimport android.content.Context\nimport androidx.hilt.work.HiltWorker\nimport androidx.work.*\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.isAfterNow\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\nimport com.isaiahvonrundstedt.fokus.features.log.Log\nimport com.isaiahvonrundstedt.fokus.features.notifications.NotificationWorker\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseWorker\nimport dagger.assisted.Assisted\nimport dagger.assisted.AssistedInject\nimport java.time.Duration\nimport java.time.ZonedDateTime\nimport java.time.temporal.WeekFields\nimport java.util.*\nimport java.util.concurrent.TimeUnit\n\n@HiltWorker\nclass ClassNotificationWorker @AssistedInject constructor(\n    @Assisted context: Context,\n    @Assisted workerParameters: WorkerParameters,\n    private val preferenceManager: PreferenceManager,\n    private val workManager: WorkManager\n) : BaseWorker(context, workerParameters) {\n\n    override suspend fun doWork(): Result {\n\n        val schedule = convertDataToSchedule(inputData)\n        val log = Log().apply {\n            title = schedule.subject\n            content = schedule.format(applicationContext)\n            type = Log.TYPE_CLASS\n            isImportant = false\n            data = schedule.scheduleID\n        }\n\n        val request = OneTimeWorkRequest.Builder(NotificationWorker::class.java)\n        request.setInputData(convertLogToData(log))\n\n        schedule.parseDaysOfWeek().forEach {\n            var triggerTime = schedule.startTime?.let { time -> Schedule.getNextWeekDay(it, time) }\n\n            when (preferenceManager.subjectReminderInterval) {\n                PreferenceManager.SUBJECT_REMINDER_INTERVAL_5_MINUTES ->\n                    triggerTime = triggerTime?.minusMinutes(5)\n                PreferenceManager.SUBJECT_REMINDER_INTERVAL_15_MINUTES ->\n                    triggerTime = triggerTime?.minusMinutes(15)\n                PreferenceManager.SUBJECT_REMINDER_INTERVAL_30_MINUTES ->\n                    triggerTime = triggerTime?.minusMinutes(30)\n            }\n\n            if (triggerTime?.isAfterNow() == true)\n                request.setInitialDelay(\n                    Duration.between(ZonedDateTime.now(), triggerTime).toMinutes(),\n                    TimeUnit.MINUTES\n                )\n\n            val weekFields = WeekFields.of(Locale.getDefault())\n            val weekNumber = triggerTime?.get(weekFields.weekOfMonth())\n            if (!schedule.hasWeek(weekNumber!!))\n                return@forEach\n\n            workManager.enqueueUniqueWork(\n                schedule.scheduleID, ExistingWorkPolicy.APPEND,\n                request.build()\n            )\n            reschedule(schedule.scheduleID, inputData, triggerTime)\n        }\n\n        return Result.success()\n    }\n\n    private fun reschedule(tag: String, data: Data, triggerTime: ZonedDateTime?) {\n        val request = OneTimeWorkRequest.Builder(ClassNotificationWorker::class.java)\n            .setInputData(data)\n            .setInitialDelay(\n                Duration.between(ZonedDateTime.now(), triggerTime).toMinutes(),\n                TimeUnit.MINUTES\n            )\n        workManager.enqueueUniqueWork(\n            tag, ExistingWorkPolicy.APPEND,\n            request.build()\n        )\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/notifications/task/TaskNotificationScheduler.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.notifications.task\n\nimport android.content.Context\nimport androidx.hilt.work.HiltWorker\nimport androidx.work.ExistingWorkPolicy\nimport androidx.work.OneTimeWorkRequest\nimport androidx.work.WorkManager\nimport androidx.work.WorkerParameters\nimport com.isaiahvonrundstedt.fokus.database.repository.TaskRepository\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseWorker\nimport com.isaiahvonrundstedt.fokus.features.task.Task\nimport dagger.assisted.Assisted\nimport dagger.assisted.AssistedInject\n\n// This worker's function is to reschedule all pending workers\n// that is supposed to trigger at its due minus the interval\n// This only triggers when the user has changed the fokus interval\n// for tasks in the Settings\n@HiltWorker\nclass TaskNotificationScheduler @AssistedInject constructor(\n    @Assisted context: Context,\n    @Assisted workerParameters: WorkerParameters,\n    private val repository: TaskRepository,\n    private val workManager: WorkManager\n) : BaseWorker(context, workerParameters) {\n\n    override suspend fun doWork(): Result {\n        val tasks: List<Task> = repository.fetchCore()\n\n        tasks.forEach { task ->\n            val request = OneTimeWorkRequest.Builder(TaskNotificationWorker::class.java)\n                .setInputData(convertTaskToData(task))\n                .build()\n            workManager.enqueueUniqueWork(task.taskID, ExistingWorkPolicy.REPLACE, request)\n        }\n\n        return Result.success()\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/notifications/task/TaskNotificationWorker.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.notifications.task\n\nimport android.content.Context\nimport androidx.hilt.work.HiltWorker\nimport androidx.work.ExistingWorkPolicy\nimport androidx.work.OneTimeWorkRequest\nimport androidx.work.WorkManager\nimport androidx.work.WorkerParameters\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.isAfterNow\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\nimport com.isaiahvonrundstedt.fokus.database.converter.DateTimeConverter\nimport com.isaiahvonrundstedt.fokus.features.log.Log\nimport com.isaiahvonrundstedt.fokus.features.notifications.NotificationWorker\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseWorker\nimport dagger.assisted.Assisted\nimport dagger.assisted.AssistedInject\nimport java.time.Duration\nimport java.time.ZonedDateTime\nimport java.util.concurrent.TimeUnit\n\n// This worker's function is to schedule the fokus worker\n// for the task minus the interval.\n@HiltWorker\nclass TaskNotificationWorker @AssistedInject constructor(\n    @Assisted context: Context,\n    @Assisted workerParameters: WorkerParameters,\n    private val preferenceManager: PreferenceManager,\n    private val workManager: WorkManager\n) : BaseWorker(context, workerParameters) {\n\n    override suspend fun doWork(): Result {\n\n        val task = convertDataToTask(inputData)\n        val resID = if (task.isDueToday()) R.string.due_today_at else R.string.due_at\n        val log = Log().apply {\n            title = task.name\n            content = if (task.hasDueDate()) String.format(\n                applicationContext.getString(resID),\n                task.dueDate?.format(DateTimeConverter.getDateTimeFormatter(applicationContext))\n            )\n            else null\n            type = Log.TYPE_TASK\n            isImportant = task.isImportant\n            data = task.taskID\n        }\n\n        if (!task.isImportant && !task.hasDueDate())\n            return Result.success()\n\n        val request = OneTimeWorkRequest.Builder(NotificationWorker::class.java)\n            .setInputData(convertLogToData(log))\n\n        if (log.isImportant) {\n            workManager.enqueueUniqueWork(\n                task.taskID, ExistingWorkPolicy.REPLACE,\n                request.build()\n            )\n            return Result.success()\n        }\n\n        var executionTime = task.dueDate\n        when (preferenceManager.taskReminderInterval) {\n            PreferenceManager.TASK_REMINDER_INTERVAL_1_HOUR ->\n                executionTime = task.dueDate?.minusHours(1)\n            PreferenceManager.TASK_REMINDER_INTERVAL_3_HOURS ->\n                executionTime = task.dueDate?.minusHours(3)\n            PreferenceManager.TASK_REMINDER_INTERVAL_24_HOURS ->\n                executionTime = task.dueDate?.minusHours(24)\n        }\n\n        if (executionTime?.isAfterNow() == true)\n            request.setInitialDelay(\n                Duration.between(ZonedDateTime.now(), executionTime).toMinutes(),\n                TimeUnit.MINUTES\n            )\n\n        workManager.enqueueUniqueWork(\n            task.taskID, ExistingWorkPolicy.REPLACE,\n            request.build()\n        )\n\n        return Result.success()\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/notifications/task/TaskReminderWorker.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.notifications.task\n\nimport android.app.NotificationManager\nimport android.content.Context\nimport androidx.hilt.work.HiltWorker\nimport androidx.work.OneTimeWorkRequest\nimport androidx.work.WorkManager\nimport androidx.work.WorkerParameters\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\nimport com.isaiahvonrundstedt.fokus.database.repository.LogRepository\nimport com.isaiahvonrundstedt.fokus.database.repository.TaskRepository\nimport com.isaiahvonrundstedt.fokus.features.log.Log\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseWorker\nimport dagger.assisted.Assisted\nimport dagger.assisted.AssistedInject\nimport java.time.*\nimport java.util.concurrent.TimeUnit\n\n// This worker's function is to only show reminders\n// based on the frequency the user has selected; daily or every weekends\n// This will show a reminders for pending tasks.\n@HiltWorker\nclass TaskReminderWorker @AssistedInject constructor(\n    @Assisted context: Context,\n    @Assisted workerParameters: WorkerParameters,\n    private val taskRepository: TaskRepository,\n    private val logRepository: LogRepository,\n    private val preferenceManager: PreferenceManager,\n    private val notificationManager: NotificationManager\n) : BaseWorker(context, workerParameters) {\n\n    override suspend fun doWork(): Result {\n        val currentTime = ZonedDateTime.now()\n        reschedule(applicationContext)\n\n        val taskSize: Int = taskRepository.fetchCount()\n        var log: Log? = null\n        if (taskSize > 0) {\n            log = Log().apply {\n                title = String.format(\n                    applicationContext.getString(R.string.notification_pending_tasks_title),\n                    taskSize\n                )\n                content = applicationContext.getString(R.string.notification_pending_tasks_summary)\n                type = Log.TYPE_TASK\n                dateTimeTriggered = ZonedDateTime.now()\n            }\n        }\n\n        if (preferenceManager.reminderFrequency == PreferenceManager.DURATION_WEEKENDS\n            && !(currentTime.dayOfWeek == DayOfWeek.SUNDAY\n                    || currentTime.dayOfWeek == DayOfWeek.SATURDAY)\n        )\n            return Result.success()\n\n        if (log != null) {\n            logRepository.insert(log)\n            sendNotification(log, notificationManager)\n        }\n\n        return Result.success()\n    }\n\n    companion object {\n        fun reschedule(context: Context) {\n            val manager = WorkManager.getInstance(context)\n            val preferences = PreferenceManager(context)\n\n            val reminderTime: ZonedDateTime? = ZonedDateTime.of(\n                LocalDate.now(),\n                preferences.reminderTime, ZoneId.systemDefault()\n            )\n\n            val executionTime: ZonedDateTime? = if (ZonedDateTime.now().isBefore(reminderTime))\n                LocalDate.now().atStartOfDay(ZoneId.systemDefault())\n                    .plusHours((reminderTime?.hour ?: 8).toLong())\n                    .plusMinutes((reminderTime?.minute ?: 30).toLong())\n                    .plusMinutes(1)\n            else\n                LocalDate.now().atStartOfDay(ZoneId.systemDefault())\n                    .plusDays(1)\n                    .plusHours((reminderTime?.hour ?: 8).toLong())\n                    .plusMinutes((reminderTime?.minute ?: 30).toLong())\n\n            manager.cancelAllWorkByTag(this::class.java.simpleName)\n\n            val request = OneTimeWorkRequest.Builder(TaskReminderWorker::class.java)\n                .setInitialDelay(\n                    Duration.between(ZonedDateTime.now(), executionTime).toMinutes(),\n                    TimeUnit.MINUTES\n                )\n                .addTag(this::class.java.simpleName)\n                .build()\n            manager.enqueue(request)\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/schedule/Schedule.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.schedule\r\n\r\nimport android.content.Context\r\nimport android.os.Parcelable\r\nimport androidx.annotation.StringRes\r\nimport androidx.recyclerview.widget.DiffUtil\r\nimport androidx.room.Entity\r\nimport androidx.room.ForeignKey\r\nimport androidx.room.PrimaryKey\r\nimport androidx.room.TypeConverters\r\nimport com.isaiahvonrundstedt.fokus.R\r\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Streamable\r\nimport com.isaiahvonrundstedt.fokus.components.json.JsonDataStreamer\r\nimport com.isaiahvonrundstedt.fokus.database.converter.DateTimeConverter\r\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\r\nimport com.squareup.moshi.JsonClass\r\nimport kotlinx.parcelize.Parcelize\r\nimport okio.buffer\r\nimport okio.sink\r\nimport java.io.File\r\nimport java.io.InputStream\r\nimport java.time.*\r\nimport java.util.*\r\n\r\n@Parcelize\r\n@JsonClass(generateAdapter = true)\r\n@Entity(\r\n    tableName = \"schedules\", foreignKeys = [ForeignKey(\r\n        entity = Subject::class,\r\n        parentColumns = arrayOf(\"subjectID\"), childColumns = arrayOf(\"subject\"),\r\n        onDelete = ForeignKey.CASCADE\r\n    )]\r\n)\r\ndata class Schedule @JvmOverloads constructor(\r\n    @PrimaryKey\r\n    var scheduleID: String = UUID.randomUUID().toString(),\r\n    var classroom: String? = null,\r\n    var daysOfWeek: Int = 0,\r\n    var weeksOfMonth: Int = 0,\r\n    @TypeConverters(DateTimeConverter::class)\r\n    var startTime: LocalTime? = null,\r\n    @TypeConverters(DateTimeConverter::class)\r\n    var endTime: LocalTime? = null,\r\n    var subject: String? = null\r\n) : Parcelable, Streamable {\r\n\r\n    fun isToday(): Boolean {\r\n        val currentDate = LocalDate.now()\r\n\r\n        parseDaysOfWeek().forEach {\r\n            if (it == currentDate.dayOfWeek.value)\r\n                return@isToday true\r\n        }\r\n        return false\r\n    }\r\n\r\n    fun isTomorrow(): Boolean {\r\n        val currentDate = LocalDate.now()\r\n\r\n        parseDaysOfWeek().forEach {\r\n            if (it == currentDate.plusDays(1).dayOfWeek.value)\r\n                return@isTomorrow true\r\n        }\r\n        return false\r\n    }\r\n\r\n    fun format(context: Context, isAbbreviated: Boolean = false): String {\r\n        return StringBuilder().apply {\r\n            append(formatDaysOfWeek(context, isAbbreviated))\r\n            append(\", \")\r\n            append(formatBothTime(context))\r\n        }.toString()\r\n    }\r\n\r\n    fun formatBothTime(context: Context): String {\r\n        return \"${formatStartTime(context)} - ${formatEndTime(context)}\"\r\n    }\r\n\r\n    fun formatStartTime(context: Context): String? {\r\n        return formatTime(context, startTime)\r\n    }\r\n\r\n    fun formatEndTime(context: Context): String? {\r\n        return formatTime(context, endTime)\r\n    }\r\n\r\n    /**\r\n     *   Function to format the daysOfWeek attribute\r\n     *   to human readable form\r\n     *   @param context used to fetch the appropriate string localization\r\n     *                  for the string resource id\r\n     *   @return the formatted days of week\r\n     *           (e.g. \"Sunday, Monday and Thursday\")\r\n     */\r\n    fun formatDaysOfWeek(context: Context, isAbbreviated: Boolean): String {\r\n        val builder = StringBuilder()\r\n        val list = parseDaysOfWeek()\r\n        list.forEachIndexed { index, i ->\r\n            // Append the appropriate day name string from string resource\r\n            val resID = if (isAbbreviated)\r\n                getStringResourceForDayAbbreviated(i)\r\n            else getStringResourceForDay(i)\r\n\r\n            builder.append(context.getString(resID))\r\n\r\n            // Check if the item's index is second to last,\r\n            // if it is, then add an \"and\" from string resource\r\n            // and if not, just append a comma\r\n            if (index == list.size - 2)\r\n                builder.append(context.getString(R.string.and))\r\n            else if (index < list.size - 2)\r\n                builder.append(\", \")\r\n        }\r\n        return builder.toString()\r\n    }\r\n\r\n    @StringRes\r\n    fun getStringResourceForDayAbbreviated(day: Int): Int {\r\n        return when (day) {\r\n            DayOfWeek.SUNDAY.value -> R.string.days_of_week_item_sunday_short\r\n            DayOfWeek.MONDAY.value -> R.string.days_of_week_item_monday_short\r\n            DayOfWeek.TUESDAY.value -> R.string.days_of_week_item_tuesday_short\r\n            DayOfWeek.WEDNESDAY.value -> R.string.days_of_week_item_wednesday_short\r\n            DayOfWeek.THURSDAY.value -> R.string.days_of_week_item_thursday_short\r\n            DayOfWeek.FRIDAY.value -> R.string.days_of_week_item_friday_short\r\n            DayOfWeek.SATURDAY.value -> R.string.days_of_week_item_saturday_short\r\n            else -> 0\r\n        }\r\n    }\r\n\r\n    @StringRes\r\n    fun getStringResourceForDay(day: Int): Int {\r\n        return when (day) {\r\n            DayOfWeek.SUNDAY.value -> R.string.days_of_week_item_sunday\r\n            DayOfWeek.MONDAY.value -> R.string.days_of_week_item_monday\r\n            DayOfWeek.TUESDAY.value -> R.string.days_of_week_item_tuesday\r\n            DayOfWeek.WEDNESDAY.value -> R.string.days_of_week_item_wednesday\r\n            DayOfWeek.THURSDAY.value -> R.string.days_of_week_item_thursday\r\n            DayOfWeek.FRIDAY.value -> R.string.days_of_week_item_friday\r\n            DayOfWeek.SATURDAY.value -> R.string.days_of_week_item_saturday\r\n            else -> 0\r\n        }\r\n    }\r\n\r\n    fun parseDaysOfWeek(): List<Int> {\r\n        return Companion.parseDaysOfWeek(daysOfWeek)\r\n    }\r\n\r\n    fun hasWeek(week: Int): Boolean {\r\n        return weeksOfMonth and week == week\r\n    }\r\n\r\n    override fun toJsonString(): String? = JsonDataStreamer.encodeToJson(this, Schedule::class.java)\r\n\r\n    override fun toJsonFile(destination: File, name: String): File {\r\n        return File(destination, name).apply {\r\n            this.sink().buffer().use {\r\n                toJsonString()?.also { json -> it.write(json.toByteArray()) }\r\n            }\r\n        }\r\n    }\r\n\r\n    override fun fromInputStream(inputStream: InputStream) {\r\n        JsonDataStreamer.decodeOnceFromJson(inputStream, Schedule::class.java)?.also {\r\n            scheduleID = it.scheduleID\r\n            daysOfWeek = it.daysOfWeek\r\n            startTime = it.startTime\r\n            classroom = it.classroom\r\n            endTime = it.endTime\r\n            subject = it.subject\r\n        }\r\n    }\r\n\r\n    companion object {\r\n        const val BIT_VALUE_SUNDAY = 1\r\n        const val BIT_VALUE_MONDAY = 2\r\n        const val BIT_VALUE_TUESDAY = 4\r\n        const val BIT_VALUE_WEDNESDAY = 8\r\n        const val BIT_VALUE_THURSDAY = 16\r\n        const val BIT_VALUE_FRIDAY = 32\r\n        const val BIT_VALUE_SATURDAY = 64\r\n\r\n        const val BIT_VALUE_WEEK_ONE = 1\r\n        const val BIT_VALUE_WEEK_TWO = 2\r\n        const val BIT_VALUE_WEEK_THREE = 4\r\n        const val BIT_VALUE_WEEK_FOUR = 8\r\n\r\n        val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Schedule>() {\r\n            override fun areItemsTheSame(oldItem: Schedule, newItem: Schedule): Boolean {\r\n                return oldItem.scheduleID == newItem.scheduleID\r\n            }\r\n\r\n            override fun areContentsTheSame(oldItem: Schedule, newItem: Schedule): Boolean {\r\n                return oldItem.scheduleID == newItem.scheduleID\r\n                        && oldItem.startTime == newItem.startTime\r\n                        && oldItem.endTime == newItem.endTime\r\n                        && oldItem.daysOfWeek == newItem.daysOfWeek\r\n                        && oldItem.weeksOfMonth == newItem.weeksOfMonth\r\n                        && oldItem.subject == newItem.subject\r\n            }\r\n        }\r\n\r\n        fun formatTime(context: Context, time: LocalTime?): String? {\r\n            return time?.format(DateTimeConverter.getTimeFormatter(context))\r\n        }\r\n\r\n        fun parseDaysOfWeek(daysOfWeek: Int): List<Int> {\r\n            val days = mutableListOf<Int>()\r\n\r\n            if (daysOfWeek and 1 == BIT_VALUE_SUNDAY) days.add(DayOfWeek.SUNDAY.value)\r\n            if (daysOfWeek and 2 == BIT_VALUE_MONDAY) days.add(DayOfWeek.MONDAY.value)\r\n            if (daysOfWeek and 4 == BIT_VALUE_TUESDAY) days.add(DayOfWeek.TUESDAY.value)\r\n            if (daysOfWeek and 8 == BIT_VALUE_WEDNESDAY) days.add(DayOfWeek.WEDNESDAY.value)\r\n            if (daysOfWeek and 16 == BIT_VALUE_THURSDAY) days.add(DayOfWeek.THURSDAY.value)\r\n            if (daysOfWeek and 32 == BIT_VALUE_FRIDAY) days.add(DayOfWeek.FRIDAY.value)\r\n            if (daysOfWeek and 64 == BIT_VALUE_SATURDAY) days.add(DayOfWeek.SATURDAY.value)\r\n\r\n            return days\r\n        }\r\n\r\n        fun getNearestDateTime(day: Int, time: LocalTime): ZonedDateTime {\r\n            val currentDate = LocalDate.now().atStartOfDay(ZoneId.systemDefault())\r\n            val currentDayOfWeek = currentDate.dayOfWeek.value\r\n            var targetDay: Long = day.toLong()\r\n\r\n            if (day < currentDayOfWeek)\r\n                targetDay += 7\r\n\r\n            return currentDate.plusDays(targetDay - currentDayOfWeek)\r\n                .withHour(time.hour)\r\n                .withMinute(time.minute)\r\n                .withSecond(time.second)\r\n        }\r\n\r\n        fun getNextWeekDay(day: Int, time: LocalTime): ZonedDateTime? {\r\n            var currentDate = LocalDate.now().atStartOfDay(ZoneId.systemDefault())\r\n                .plusHours(time.hour.toLong())\r\n                .plusMinutes(time.minute.toLong())\r\n            if (currentDate.dayOfWeek.value >= day)\r\n                currentDate = currentDate.plusWeeks(1)\r\n            return currentDate.with(DayOfWeek.of(day))\r\n        }\r\n\r\n        fun toJsonFile(\r\n            items: List<Schedule>, destination: File,\r\n            name: String = Streamable.FILE_NAME_SCHEDULE\r\n        ): File {\r\n            return File(destination, name).apply {\r\n                this.sink().buffer().use {\r\n                    JsonDataStreamer.encodeToJson(items, Schedule::class.java)?.also { json ->\r\n                        it.write(json.toByteArray())\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/schedule/ScheduleEditor.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.schedule\r\n\r\nimport android.os.Bundle\r\nimport android.text.format.DateFormat.is24HourFormat\r\nimport android.view.LayoutInflater\r\nimport android.view.View\r\nimport android.view.ViewGroup\r\nimport androidx.appcompat.widget.AppCompatTextView\r\nimport androidx.core.os.bundleOf\r\nimport androidx.core.view.forEach\r\nimport androidx.core.view.isVisible\r\nimport androidx.fragment.app.FragmentManager\r\nimport androidx.fragment.app.setFragmentResult\r\nimport com.afollestad.materialdialogs.MaterialDialog\r\nimport com.afollestad.materialdialogs.datetime.timePicker\r\nimport com.afollestad.materialdialogs.lifecycle.lifecycleOwner\r\nimport com.google.android.material.chip.Chip\r\nimport com.isaiahvonrundstedt.fokus.R\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.createToast\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.setTextColorFromResource\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.toCalendar\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.toLocalTime\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.toZonedDateTimeToday\r\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\r\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutSheetScheduleEditorBinding\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseBottomSheet\r\nimport java.time.DayOfWeek\r\nimport java.time.LocalTime\r\nimport java.util.*\r\n\r\nclass ScheduleEditor(manager: FragmentManager) : BaseBottomSheet(manager) {\r\n\r\n    private var id: String? = null\r\n    private var classroom: String? = null\r\n    private var startTime: LocalTime? = null\r\n    private var endTime: LocalTime? = null\r\n    private var daysOfWeek: Int = 0\r\n    private var weeksOfMonth: Int = 0\r\n    private var subjectID: String? = null\r\n\r\n    private var requestKey: String = REQUEST_KEY_INSERT\r\n    private var _binding: LayoutSheetScheduleEditorBinding? = null\r\n\r\n    private val binding get() = _binding!!\r\n\r\n    override fun onCreateView(\r\n        inflater: LayoutInflater, container: ViewGroup?,\r\n        savedInstanceState: Bundle?\r\n    ): View? {\r\n        _binding = LayoutSheetScheduleEditorBinding.inflate(inflater, container, false)\r\n        return binding.root\r\n    }\r\n\r\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\r\n        super.onViewCreated(view, savedInstanceState)\r\n\r\n        if (!PreferenceManager(requireContext()).allowWeekNumbers) {\r\n            binding.weekOfMonthGroup.isVisible = false\r\n            binding.weekNumbersHeader.isVisible = false\r\n        }\r\n\r\n        arguments?.also {\r\n            subjectID = it.getString(EXTRA_SUBJECT_ID)\r\n\r\n            it.getParcelable<Schedule>(EXTRA_SCHEDULE)?.also { schedule ->\r\n                id = schedule.scheduleID\r\n                classroom = schedule.classroom\r\n                startTime = schedule.startTime\r\n                endTime = schedule.endTime\r\n                daysOfWeek = schedule.daysOfWeek\r\n                weeksOfMonth = schedule.weeksOfMonth\r\n                subjectID = schedule.subject\r\n                requestKey = REQUEST_KEY_UPDATE\r\n\r\n                binding.classroomTextInput.setText(classroom)\r\n                binding.startTimeTextView.text = Schedule.formatTime(view.context, startTime)\r\n                binding.endTimeTextView.text = Schedule.formatTime(view.context, endTime)\r\n\r\n                binding.startTimeTextView.setTextColorFromResource(R.color.color_primary_text)\r\n                binding.endTimeTextView.setTextColorFromResource(R.color.color_primary_text)\r\n\r\n                binding.weekOneChip.isChecked = schedule.hasWeek(Schedule.BIT_VALUE_WEEK_ONE)\r\n                binding.weekTwoChip.isChecked = schedule.hasWeek(Schedule.BIT_VALUE_WEEK_TWO)\r\n                binding.weekThreeChip.isChecked = schedule.hasWeek(Schedule.BIT_VALUE_WEEK_THREE)\r\n                binding.weekFourChip.isChecked = schedule.hasWeek(Schedule.BIT_VALUE_WEEK_FOUR)\r\n\r\n                Schedule.parseDaysOfWeek(daysOfWeek).forEach { day ->\r\n                    when (day) {\r\n                        DayOfWeek.SUNDAY.value -> binding.sundayChip.isChecked = true\r\n                        DayOfWeek.MONDAY.value -> binding.mondayChip.isChecked = true\r\n                        DayOfWeek.TUESDAY.value -> binding.tuesdayChip.isChecked = true\r\n                        DayOfWeek.WEDNESDAY.value -> binding.wednesdayChip.isChecked = true\r\n                        DayOfWeek.THURSDAY.value -> binding.thursdayChip.isChecked = true\r\n                        DayOfWeek.FRIDAY.value -> binding.fridayChip.isChecked = true\r\n                        DayOfWeek.SATURDAY.value -> binding.saturdayChip.isChecked = true\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        binding.startTimeTextView.setOnClickListener {\r\n            MaterialDialog(it.context).show {\r\n                lifecycleOwner(this@ScheduleEditor)\r\n                title(R.string.dialog_pick_start_time)\r\n                timePicker(\r\n                    show24HoursView = is24HourFormat(requireContext()),\r\n                    currentTime = startTime?.toZonedDateTimeToday()?.toCalendar()\r\n                ) { _, time ->\r\n                    startTime = time.toLocalTime()\r\n                    if (endTime == null)\r\n                        endTime = startTime\r\n\r\n                    if (startTime!!.isAfter(endTime)\r\n                        || startTime!!.compareTo(endTime) == 0\r\n                    ) {\r\n\r\n                        endTime = startTime\r\n                            ?.plusHours(1)\r\n                            ?.plusMinutes(30)\r\n                        binding.endTimeTextView.text = Schedule.formatTime(it.context, endTime)\r\n                    }\r\n                }\r\n                positiveButton(R.string.button_done) { _ ->\r\n                    if (it is AppCompatTextView) {\r\n                        it.text = Schedule.formatTime(it.context, startTime)\r\n                        it.setTextColorFromResource(R.color.color_primary_text)\r\n                        binding.endTimeTextView.setTextColorFromResource(R.color.color_primary_text)\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n\r\n        binding.endTimeTextView.setOnClickListener {\r\n            MaterialDialog(it.context).show {\r\n                lifecycleOwner(this@ScheduleEditor)\r\n                title(R.string.dialog_pick_end_time)\r\n                timePicker(\r\n                    show24HoursView = is24HourFormat(requireContext()),\r\n                    currentTime = endTime?.toZonedDateTimeToday()?.toCalendar()\r\n                ) { _, time ->\r\n                    endTime = time.toLocalTime()\r\n\r\n                    if (startTime == null)\r\n                        startTime = endTime\r\n\r\n                    if (endTime!!.isBefore(startTime)\r\n                        || endTime!!.compareTo(startTime) == 0\r\n                    ) {\r\n\r\n                        startTime = endTime\r\n                            ?.minusHours(1)\r\n                            ?.minusMinutes(30)\r\n                        binding.startTimeTextView.text = Schedule.formatTime(it.context, startTime)\r\n                    }\r\n                }\r\n                positiveButton(R.string.button_done) { _ ->\r\n                    if (it is AppCompatTextView) {\r\n                        it.text = Schedule.formatTime(it.context, endTime)\r\n                        it.setTextColorFromResource(R.color.color_primary_text)\r\n                        binding.startTimeTextView.setTextColorFromResource(R.color.color_primary_text)\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        binding.actionButton.setOnClickListener {\r\n            // reset the variables\r\n            if (requestKey == REQUEST_KEY_UPDATE) {\r\n                daysOfWeek = 0\r\n                weeksOfMonth = 0\r\n            }\r\n\r\n            binding.daysOfWeekGroup.forEach {\r\n                if ((it as? Chip)?.isChecked == true) {\r\n                    daysOfWeek += when (it.id) {\r\n                        R.id.sundayChip -> Schedule.BIT_VALUE_SUNDAY\r\n                        R.id.mondayChip -> Schedule.BIT_VALUE_MONDAY\r\n                        R.id.tuesdayChip -> Schedule.BIT_VALUE_TUESDAY\r\n                        R.id.wednesdayChip -> Schedule.BIT_VALUE_WEDNESDAY\r\n                        R.id.thursdayChip -> Schedule.BIT_VALUE_THURSDAY\r\n                        R.id.fridayChip -> Schedule.BIT_VALUE_FRIDAY\r\n                        R.id.saturdayChip -> Schedule.BIT_VALUE_SATURDAY\r\n                        else -> 0\r\n                    }\r\n                }\r\n            }\r\n\r\n            binding.weekOfMonthGroup.forEach {\r\n                if ((it as? Chip)?.isChecked == true) {\r\n                    weeksOfMonth += when (it.id) {\r\n                        R.id.weekOneChip -> Schedule.BIT_VALUE_WEEK_ONE\r\n                        R.id.weekTwoChip -> Schedule.BIT_VALUE_WEEK_TWO\r\n                        R.id.weekThreeChip -> Schedule.BIT_VALUE_WEEK_THREE\r\n                        R.id.weekFourChip -> Schedule.BIT_VALUE_WEEK_FOUR\r\n                        else -> 0\r\n                    }\r\n                }\r\n            }\r\n\r\n            // This conditions is used to check if some fields are\r\n            // blank or null, if these returned true,\r\n            // we'll show a Toast then direct the focus to\r\n            // the corresponding field then return to stop\r\n            // the execution of the code\r\n\r\n            if (startTime == null) {\r\n                createToast(R.string.feedback_schedule_empty_start_time)\r\n                binding.startTimeTextView.performClick()\r\n                return@setOnClickListener\r\n            }\r\n\r\n            if (endTime == null) {\r\n                createToast(R.string.feedback_schedule_empty_end_time)\r\n                binding.endTimeTextView.performClick()\r\n                return@setOnClickListener\r\n            }\r\n\r\n            if (daysOfWeek == 0) {\r\n                createToast(R.string.feedback_schedule_empty_days)\r\n                return@setOnClickListener\r\n            }\r\n\r\n            if (weeksOfMonth == 0) {\r\n                createToast(R.string.feedback_schedule_empty_days)\r\n                return@setOnClickListener\r\n            }\r\n\r\n            val schedule = Schedule(\r\n                scheduleID = id ?: UUID.randomUUID().toString(),\r\n                classroom = binding.classroomTextInput.text.toString(),\r\n                daysOfWeek = daysOfWeek,\r\n                weeksOfMonth = weeksOfMonth,\r\n                startTime = startTime,\r\n                endTime = endTime,\r\n                subject = subjectID\r\n            )\r\n\r\n            setFragmentResult(requestKey, bundleOf(EXTRA_SCHEDULE to schedule))\r\n            this.dismiss()\r\n        }\r\n    }\r\n\r\n    override fun onDestroy() {\r\n        super.onDestroy()\r\n        _binding = null\r\n    }\r\n\r\n    companion object {\r\n        const val REQUEST_KEY_INSERT = \"request:insert\"\r\n        const val REQUEST_KEY_UPDATE = \"request:update\"\r\n        const val EXTRA_SCHEDULE = \"extra:schedule\"\r\n        const val EXTRA_SUBJECT_ID = \"extra:subject:id\"\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/schedule/picker/SchedulePickerAdapter.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.schedule.picker\n\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutItemScheduleBinding\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\nimport java.time.DayOfWeek\n\nclass SchedulePickerAdapter(private val actionListener: ActionListener) :\n    BaseAdapter<Schedule, SchedulePickerAdapter.ViewHolder>(Schedule.DIFF_CALLBACK) {\n\n    private val itemList = mutableListOf<Schedule>()\n\n    fun setItems(items: List<Schedule>) {\n        itemList.clear()\n        items.forEach {\n            it.parseDaysOfWeek().forEach { day ->\n                if (day <= DayOfWeek.SUNDAY.value) {\n                    val newSchedule = Schedule(\n                        startTime = it.startTime,\n                        endTime = it.endTime\n                    )\n                    newSchedule.daysOfWeek = day\n                    itemList.add(newSchedule)\n                }\n            }\n        }\n        submitList(itemList)\n    }\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {\n        val binding = LayoutItemScheduleBinding.inflate(\n            LayoutInflater.from(parent.context),\n            parent, false\n        )\n        return ViewHolder(binding.root)\n    }\n\n    override fun onBindViewHolder(holder: ViewHolder, position: Int) {\n        holder.onBind(getItem(position))\n    }\n\n    inner class ViewHolder(itemView: View) : BaseViewHolder(itemView) {\n\n        private val binding = LayoutItemScheduleBinding.bind(itemView)\n\n        override fun <T> onBind(t: T) {\n            if (t is Schedule) {\n                binding.titleView.text =\n                    binding.root.context.getString(t.getStringResourceForDay(t.daysOfWeek))\n                binding.summaryView.text = t.formatBothTime(binding.root.context)\n            }\n\n            binding.root.setOnClickListener {\n                actionListener.onActionPerformed(t, ActionListener.Action.SELECT, null)\n            }\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/schedule/picker/SchedulePickerSheet.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.schedule.picker\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.os.bundleOf\nimport androidx.fragment.app.FragmentManager\nimport androidx.fragment.app.setFragmentResult\nimport androidx.recyclerview.widget.LinearLayoutManager\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutSheetScheduleBinding\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseBottomSheet\n\nclass SchedulePickerSheet(private val items: List<Schedule>, manager: FragmentManager) :\n    BaseBottomSheet(manager), BaseAdapter.ActionListener {\n\n    private var _binding: LayoutSheetScheduleBinding? = null\n    private val binding get() = _binding!!\n\n    override fun onCreateView(\n        inflater: LayoutInflater, container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View? {\n        _binding = LayoutSheetScheduleBinding.inflate(inflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n\n        with(binding.recyclerView) {\n            layoutManager = LinearLayoutManager(context)\n            adapter = SchedulePickerAdapter(this@SchedulePickerSheet).apply {\n                setItems(items)\n            }\n        }\n    }\n\n    override fun <T> onActionPerformed(\n        t: T, action: BaseAdapter.ActionListener.Action,\n        container: View?\n    ) {\n        if (t is Schedule) {\n            when (action) {\n                BaseAdapter.ActionListener.Action.SELECT -> {\n                    setFragmentResult(\n                        REQUEST_KEY, bundleOf(\n                            EXTRA_SCHEDULE to t\n                        )\n                    )\n                    this.dismiss()\n                }\n                BaseAdapter.ActionListener.Action.DELETE -> {\n                }\n            }\n        }\n    }\n\n    override fun onDestroy() {\n        super.onDestroy()\n        _binding = null\n    }\n\n    companion object {\n        const val REQUEST_KEY = \"request:pick\"\n        const val EXTRA_SCHEDULE = \"extra:schedule\"\n\n        fun show(items: List<Schedule>, manager: FragmentManager) {\n            SchedulePickerSheet(items, manager).show()\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/schedule/viewer/ScheduleViewerAdapter.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.schedule.viewer\n\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutItemScheduleBinding\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\n\nclass ScheduleViewerAdapter(items: List<Schedule>) : BaseAdapter<Schedule,\n        ScheduleViewerAdapter.ScheduleViewHolder>(Schedule.DIFF_CALLBACK) {\n\n    init {\n        submitList(items)\n    }\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ScheduleViewHolder {\n        val binding = LayoutItemScheduleBinding.inflate(\n            LayoutInflater.from(parent.context),\n            parent, false\n        )\n        return ScheduleViewHolder(binding.root)\n    }\n\n    override fun onBindViewHolder(holder: ScheduleViewHolder, position: Int) {\n        holder.onBind(getItem(position))\n    }\n\n    class ScheduleViewHolder(itemView: View) : BaseAdapter.BaseViewHolder(itemView) {\n\n        private val binding = LayoutItemScheduleBinding.bind(itemView)\n\n        override fun <T> onBind(t: T) {\n            if (t is Schedule) {\n                binding.titleView.text = t.formatDaysOfWeek(binding.root.context, false)\n                binding.summaryView.text = t.formatBothTime(binding.root.context)\n            }\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/schedule/viewer/ScheduleViewerSheet.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.schedule.viewer\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.fragment.app.FragmentManager\nimport androidx.recyclerview.widget.LinearLayoutManager\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutSheetScheduleBinding\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseBottomSheet\n\nclass ScheduleViewerSheet(private val items: List<Schedule>, manager: FragmentManager) :\n    BaseBottomSheet(manager) {\n\n    private var _binding: LayoutSheetScheduleBinding? = null\n    private val binding get() = _binding!!\n\n    override fun onCreateView(\n        inflater: LayoutInflater, container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View? {\n        _binding = LayoutSheetScheduleBinding.inflate(inflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n\n        with(binding.recyclerView) {\n            layoutManager = LinearLayoutManager(context)\n            adapter = ScheduleViewerAdapter(items)\n        }\n    }\n\n    override fun onDestroy() {\n        super.onDestroy()\n        _binding = null\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/settings/BackupFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.settings\n\nimport android.content.BroadcastReceiver\nimport android.content.Context\nimport android.content.Intent\nimport android.content.IntentFilter\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.activity.result.ActivityResultLauncher\nimport androidx.activity.result.contract.ActivityResultContracts\nimport androidx.localbroadcastmanager.content.LocalBroadcastManager\nimport androidx.navigation.NavController\nimport androidx.navigation.fragment.findNavController\nimport androidx.preference.Preference\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.createSnackbar\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.startForegroundServiceCompat\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Streamable\nimport com.isaiahvonrundstedt.fokus.components.service.BackupRestoreService\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\nimport com.isaiahvonrundstedt.fokus.database.converter.DateTimeConverter\nimport com.isaiahvonrundstedt.fokus.databinding.FragmentBackupBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseFragment\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BasePreference\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseService\nimport dagger.hilt.android.AndroidEntryPoint\nimport java.time.LocalDate\nimport java.time.ZonedDateTime\nimport javax.inject.Inject\n\n@AndroidEntryPoint\nclass BackupFragment : BaseFragment() {\n    private var _binding: FragmentBackupBinding? = null\n    private var controller: NavController? = null\n\n    private val binding get() = _binding!!\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        _binding = FragmentBackupBinding.inflate(inflater, container, false)\n        return binding.root\n    }\n\n    override fun onDestroy() {\n        _binding = null\n        super.onDestroy()\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        setInsets(binding.root, binding.appBarLayout.toolbar, emptyArray())\n\n        with(binding.appBarLayout.toolbar) {\n            setTitle(R.string.activity_backup)\n            setupNavigation(this, R.drawable.ic_outline_arrow_back_24) {\n                controller?.navigateUp()\n            }\n        }\n    }\n\n    override fun onStart() {\n        super.onStart()\n        controller = findNavController()\n    }\n\n    companion object {\n        @AndroidEntryPoint\n        class BackupPreference : BasePreference() {\n\n            private lateinit var createLauncher: ActivityResultLauncher<Intent>\n            private lateinit var restoreLauncher: ActivityResultLauncher<Intent>\n\n            @Inject\n            lateinit var manager: PreferenceManager\n\n            override fun onCreate(savedInstanceState: Bundle?) {\n                super.onCreate(savedInstanceState)\n\n                createLauncher =\n                    registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {\n                        val service = Intent(context, BackupRestoreService::class.java).apply {\n                            action = BackupRestoreService.ACTION_BACKUP\n                            data = it.data?.data\n                        }\n\n                        context?.startForegroundServiceCompat(service)\n                    }\n\n                restoreLauncher =\n                    registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {\n                        val service = Intent(context, BackupRestoreService::class.java).apply {\n                            action = BackupRestoreService.ACTION_RESTORE\n                            data = it.data?.data\n                        }\n\n                        context?.startForegroundServiceCompat(service)\n                    }\n\n                LocalBroadcastManager.getInstance(requireContext())\n                    .registerReceiver(receiver, IntentFilter(BaseService.ACTION_SERVICE_BROADCAST))\n            }\n\n            override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {\n                setPreferencesFromResource(R.xml.xml_settings_backups, rootKey)\n            }\n\n            private var receiver = object : BroadcastReceiver() {\n                override fun onReceive(context: Context?, intent: Intent?) {\n                    if (intent?.action == BaseService.ACTION_SERVICE_BROADCAST) {\n                        when (intent.getStringExtra(BaseService.EXTRA_BROADCAST_STATUS)) {\n                            BackupRestoreService.BROADCAST_BACKUP_SUCCESS ->\n                                setPreferenceSummary(\n                                    PreferenceManager.PREFERENCE_BACKUP,\n                                    manager.previousBackupDate.parseForSummary()\n                                )\n                            BackupRestoreService.BROADCAST_BACKUP_FAILED ->\n                                createSnackbar(R.string.feedback_backup_failed, requireView())\n                            BackupRestoreService.BROADCAST_BACKUP_EMPTY ->\n                                createSnackbar(R.string.feedback_backup_empty, requireView())\n                        }\n                    }\n                }\n            }\n\n            override fun onStart() {\n                super.onStart()\n\n                setPreferenceSummary(\n                    PreferenceManager.PREFERENCE_BACKUP,\n                    manager.previousBackupDate.parseForSummary()\n                )\n                findPreference<Preference>(PreferenceManager.PREFERENCE_BACKUP)\n                    ?.setOnPreferenceClickListener {\n                        val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {\n                            addCategory(Intent.CATEGORY_OPENABLE)\n                            putExtra(Intent.EXTRA_TITLE, BackupRestoreService.FILE_BACKUP_NAME)\n                            type = Streamable.MIME_TYPE_ZIP\n                        }\n\n                        createLauncher.launch(intent)\n                        true\n                    }\n\n\n                findPreference<Preference>(PreferenceManager.PREFERENCE_RESTORE)\n                    ?.setOnPreferenceClickListener {\n                        val intent =\n                            Intent.createChooser(Intent(Intent.ACTION_OPEN_DOCUMENT).apply {\n                                type = Streamable.MIME_TYPE_ZIP\n                            }, getString(R.string.dialog_choose_backup))\n\n                        restoreLauncher.launch(intent)\n                        true\n                    }\n\n            }\n\n            override fun onDestroy() {\n                LocalBroadcastManager.getInstance(requireContext())\n                    .unregisterReceiver(receiver)\n                super.onDestroy()\n            }\n\n            private fun ZonedDateTime?.parseForSummary(): String? {\n                if (this == null)\n                    return getString(R.string.settings_backup_summary_no_previous)\n\n                val currentDateTime = ZonedDateTime.now()\n\n                return if (this.toLocalDate().isEqual(LocalDate.now()))\n                    String.format(\n                        getString(R.string.today_at),\n                        format(DateTimeConverter.getTimeFormatter(requireContext()))\n                    )\n                else if (this.minusDays(1)?.compareTo(currentDateTime) == 0)\n                    String.format(\n                        getString(R.string.yesterday_at),\n                        format(DateTimeConverter.getTimeFormatter(requireContext()))\n                    )\n                else if (this.plusDays(1)?.compareTo(currentDateTime) == 0)\n                    String.format(\n                        getString(R.string.tomorrow_at),\n                        format(DateTimeConverter.getTimeFormatter(requireContext()))\n                    )\n                else format(DateTimeConverter.getDateTimeFormatter(requireContext()))\n            }\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/settings/SettingsFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.settings\n\nimport android.content.Intent\nimport android.net.Uri\nimport android.os.Build\nimport android.os.Bundle\nimport android.provider.Settings\nimport android.text.format.DateFormat.is24HourFormat\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.appcompat.app.AppCompatDelegate\nimport androidx.browser.customtabs.CustomTabsIntent\nimport androidx.navigation.NavController\nimport androidx.navigation.Navigation\nimport androidx.navigation.fragment.findNavController\nimport androidx.preference.ListPreference\nimport androidx.preference.Preference\nimport androidx.preference.SwitchPreferenceCompat\nimport androidx.work.OneTimeWorkRequest\nimport androidx.work.WorkManager\nimport com.afollestad.materialdialogs.MaterialDialog\nimport com.afollestad.materialdialogs.datetime.timePicker\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.toLocalTime\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\nimport com.isaiahvonrundstedt.fokus.database.converter.DateTimeConverter\nimport com.isaiahvonrundstedt.fokus.databinding.FragmentSettingsBinding\nimport com.isaiahvonrundstedt.fokus.features.notifications.event.EventNotificationScheduler\nimport com.isaiahvonrundstedt.fokus.features.notifications.subject.ClassNotificationScheduler\nimport com.isaiahvonrundstedt.fokus.features.notifications.task.TaskNotificationScheduler\nimport com.isaiahvonrundstedt.fokus.features.notifications.task.TaskReminderWorker\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseFragment\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BasePreference\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseWorker\nimport java.util.*\n\nclass SettingsFragment : BaseFragment() {\n    private var _binding: FragmentSettingsBinding? = null\n    private var controller: NavController? = null\n\n    private val binding get() = _binding!!\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        _binding = FragmentSettingsBinding.inflate(inflater, container, false)\n        return binding.root\n    }\n\n    override fun onDestroy() {\n        _binding = null\n        super.onDestroy()\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        setInsets(binding.root, binding.appBarLayout.toolbar, emptyArray())\n\n        with(binding.appBarLayout.toolbar) {\n            setTitle(R.string.activity_settings)\n            setupNavigation(this, R.drawable.ic_outline_arrow_back_24) {\n                controller?.navigateUp()\n            }\n        }\n    }\n\n    override fun onStart() {\n        super.onStart()\n        controller = findNavController()\n    }\n\n    companion object {\n        class SettingsFragment : BasePreference() {\n            private var controller: NavController? = null\n\n            override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {\n                setPreferencesFromResource(R.xml.xml_settings_main, rootKey)\n            }\n\n            override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n                super.onViewCreated(view, savedInstanceState)\n\n                findPreference<ListPreference>(PreferenceManager.PREFERENCE_THEME)\n                    ?.setOnPreferenceChangeListener { _, value ->\n                        if (value is String) {\n                            val theme = value.toString()\n                            notifyThemeChanged(PreferenceManager.Theme.parse(theme))\n                        }\n                        true\n                    }\n\n                findPreference<SwitchPreferenceCompat>(PreferenceManager.PREFERENCE_TASK_NOTIFICATION)\n                    ?.setOnPreferenceChangeListener { _, isChecked ->\n                        if (isChecked is Boolean) {\n                            val workerClass = TaskNotificationScheduler::class.java\n                            if (isChecked)\n                                scheduleWorker(workerClass)\n                            else cancelWorker(workerClass)\n                        } else false\n                    }\n\n                findPreference<SwitchPreferenceCompat>(PreferenceManager.PREFERENCE_EVENT_NOTIFICATION)\n                    ?.setOnPreferenceChangeListener { _, isChecked ->\n                        if (isChecked is Boolean) {\n                            val workerClass = EventNotificationScheduler::class.java\n                            if (isChecked)\n                                scheduleWorker(workerClass)\n                            else cancelWorker(workerClass)\n                        } else false\n                    }\n\n                findPreference<SwitchPreferenceCompat>(PreferenceManager.PREFERENCE_COURSE_NOTIFICATION)\n                    ?.setOnPreferenceChangeListener { _, isChecked ->\n                        if (isChecked is Boolean) {\n                            val workerClass = ClassNotificationScheduler::class.java\n                            if (isChecked)\n                                scheduleWorker(workerClass)\n                            else cancelWorker(workerClass)\n                        } else false\n                    }\n\n                findPreference<Preference>(PreferenceManager.PREFERENCE_TASK_NOTIFICATION_INTERVAL)\n                    ?.setOnPreferenceChangeListener { _, _ ->\n                        scheduleWorker(TaskNotificationScheduler::class.java)\n                    }\n\n\n                findPreference<Preference>(PreferenceManager.PREFERENCE_EVENT_NOTIFICATION_INTERVAL)\n                    ?.setOnPreferenceChangeListener { _, _ ->\n                        scheduleWorker(EventNotificationScheduler::class.java)\n                    }\n\n                findPreference<Preference>(PreferenceManager.PREFERENCE_COURSE_NOTIFICATION_INTERVAL)\n                    ?.setOnPreferenceChangeListener { _, _ ->\n                        scheduleWorker(ClassNotificationScheduler::class.java)\n                    }\n\n                setPreferenceSummary(\n                    PreferenceManager.PREFERENCE_REMINDER_TIME,\n                    preferences.reminderTime?.format(\n                        DateTimeConverter.getTimeFormatter(\n                            requireContext()\n                        )\n                    )\n                )\n                findPreference<Preference>(PreferenceManager.PREFERENCE_REMINDER_TIME)\n                    ?.setOnPreferenceClickListener {\n                        MaterialDialog(requireContext()).show {\n                            timePicker(\n                                show24HoursView = is24HourFormat(requireContext())\n                            ) { _, time ->\n                                preferences.reminderTime = time.toLocalTime()\n\n                                TaskReminderWorker.reschedule(requireContext())\n                            }\n                            positiveButton(R.string.button_done) { _ ->\n                                it.summary = preferences.reminderTime\n                                    ?.format(DateTimeConverter.getTimeFormatter(requireContext()))\n                            }\n                        }\n                        true\n                    }\n\n                findPreference<Preference>(PreferenceManager.PREFERENCE_SYSTEM_NOTIFICATION)\n                    ?.setOnPreferenceClickListener {\n                        val intent = Intent()\n                        with(intent) {\n                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n                                action = Settings.ACTION_APP_NOTIFICATION_SETTINGS\n                                putExtra(Settings.EXTRA_APP_PACKAGE, context?.packageName)\n                            } else {\n                                action = \"android.settings.APP_NOTIFICATION_SETTINGS\"\n                                putExtra(\"app_package\", context?.packageName)\n                                putExtra(\"app_uid\", context?.applicationInfo?.uid)\n                            }\n                            startActivity(this)\n                        }\n                        true\n                    }\n\n\n                findPreference<Preference>(PreferenceManager.PREFERENCE_BACKUP_RESTORE)\n                    ?.setOnPreferenceClickListener {\n                        controller?.navigate(R.id.navigation_backup)\n                        true\n                    }\n\n\n                findPreference<Preference>(PreferenceManager.PREFERENCE_BATTERY_OPTIMIZATION)\n                    ?.setOnPreferenceClickListener {\n                        val manufacturerArray =\n                            resources.getStringArray(R.array.oem_battery_optimization)\n\n                        var manufacturer = Build.MANUFACTURER.toLowerCase(Locale.getDefault())\n                        if (!manufacturerArray.contains(manufacturer))\n                            manufacturer = \"generic\"\n\n                        CustomTabsIntent.Builder().build()\n                            .launchUrl(\n                                requireContext(),\n                                Uri.parse(SETTINGS_URL_BATTERY_OPTIMIZATION + manufacturer)\n                            )\n\n                        true\n                    }\n            }\n\n            private fun notifyThemeChanged(theme: PreferenceManager.Theme) {\n                when (theme) {\n                    PreferenceManager.Theme.DARK ->\n                        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)\n                    PreferenceManager.Theme.LIGHT ->\n                        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)\n                    PreferenceManager.Theme.SYSTEM -> {\n                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)\n                            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)\n                        else AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY)\n                    }\n                }\n            }\n\n            private fun <T : BaseWorker> cancelWorker(worker: Class<T>): Boolean {\n                try {\n                    WorkManager.getInstance(requireContext())\n                        .cancelAllWorkByTag(worker.simpleName)\n\n                    return true\n                } catch (e: Exception) {\n                    e.printStackTrace()\n                }\n                return false\n            }\n\n            private fun <T : BaseWorker> scheduleWorker(worker: Class<T>): Boolean {\n                try {\n                    val request = OneTimeWorkRequest.Builder(worker)\n                        .addTag(worker.simpleName)\n                        .build()\n\n                    WorkManager.getInstance(requireContext())\n                        .enqueue(request)\n\n                    return true\n                } catch (e: Exception) {\n                    e.printStackTrace()\n                }\n                return false\n            }\n\n            override fun onStart() {\n                super.onStart()\n                controller = Navigation.findNavController(requireActivity(),\n                    R.id.navigationHostFragment)\n            }\n\n            private val preferences by lazy {\n                PreferenceManager(requireContext())\n            }\n\n            companion object {\n                const val SETTINGS_URL_BATTERY_OPTIMIZATION = \"https://www.dontkillmyapp.com/\"\n            }\n        }\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/shared/abstracts/BaseActivity.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.shared.abstracts\r\n\r\nimport android.os.Build\r\nimport android.os.Bundle\r\nimport androidx.annotation.StringRes\r\nimport androidx.appcompat.app.AppCompatActivity\r\nimport androidx.appcompat.app.AppCompatDelegate\r\nimport androidx.core.view.WindowCompat\r\nimport com.google.android.material.appbar.MaterialToolbar\r\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\r\n\r\nabstract class BaseActivity : AppCompatActivity() {\r\n\r\n    override fun onCreate(savedInstanceState: Bundle?) {\r\n        window.sharedElementsUseOverlay = false\r\n        super.onCreate(savedInstanceState)\r\n        WindowCompat.setDecorFitsSystemWindows(window, false)\r\n    }\r\n\r\n    override fun onResume() {\r\n        super.onResume()\r\n\r\n        when (PreferenceManager(this).theme) {\r\n            PreferenceManager.Theme.LIGHT ->\r\n                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)\r\n            PreferenceManager.Theme.DARK ->\r\n                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)\r\n            PreferenceManager.Theme.SYSTEM -> {\r\n                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)\r\n                    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)\r\n                else AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY)\r\n            }\r\n        }\r\n    }\r\n\r\n    private var toolbar: MaterialToolbar? = null\r\n\r\n    protected fun setPersistentActionBar(toolbar: MaterialToolbar?) {\r\n        this.toolbar = toolbar\r\n\r\n        setSupportActionBar(toolbar)\r\n        this.toolbar?.setNavigationOnClickListener { onBackPressed() }\r\n        supportActionBar?.setDisplayShowTitleEnabled(false)\r\n        supportActionBar?.setDisplayHomeAsUpEnabled(true)\r\n    }\r\n\r\n    protected fun setToolbarTitle(@StringRes id: Int) {\r\n        this.toolbar?.title = getString(id)\r\n    }\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/shared/abstracts/BaseAdapter.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.shared.abstracts\r\n\r\nimport android.view.View\r\nimport androidx.recyclerview.widget.DiffUtil\r\nimport androidx.recyclerview.widget.ListAdapter\r\nimport androidx.recyclerview.widget.RecyclerView\r\n\r\nabstract class BaseAdapter<T, VH : RecyclerView.ViewHolder?>(callback: DiffUtil.ItemCallback<T>) :\r\n    ListAdapter<T, VH>(callback) {\r\n\r\n    /**\r\n     * interface used when triggering\r\n     * an archive swipe in adapter.\r\n     */\r\n    interface ArchiveListener {\r\n        /**\r\n         * @param t the item that will be archived.\r\n         */\r\n        fun <T> onItemArchive(t: T)\r\n    }\r\n\r\n    /**\r\n     * interface used when the adapter needs\r\n     * both SELECT and DELETE actions into one\r\n     * unified listener\r\n     */\r\n    interface ActionListener {\r\n        /**\r\n         * @param t the data that will be passed by the adapter to the view\r\n         *\r\n         * @param action the action triggered by the user, e.g. SELECT or DELETE\r\n         *\r\n         * @param container the root view of the item view that is needed to perform\r\n         * transitions\r\n         */\r\n        fun <T> onActionPerformed(t: T, action: Action, container: View?)\r\n\r\n        /**\r\n         * Actions used by the listener\r\n         */\r\n        enum class Action { SELECT, DELETE }\r\n    }\r\n\r\n    /**\r\n     * interface used when the adapter only needs\r\n     * the SELECT action\r\n     */\r\n    interface SelectListener {\r\n        /**\r\n         * @param t the data that will be passed to the view or presenter\r\n         */\r\n        fun <T> onItemSelected(t: T)\r\n    }\r\n\r\n    abstract class BaseViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {\r\n\r\n        abstract fun <T> onBind(data: T)\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/shared/abstracts/BaseBasicAdapter.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.shared.abstracts\n\nimport android.view.View\nimport androidx.recyclerview.widget.RecyclerView\n\nabstract class BaseBasicAdapter<T, VH : BaseBasicAdapter.BaseBasicViewHolder<T>>\n    : RecyclerView.Adapter<VH>() {\n\n    protected val items = arrayListOf<T>()\n\n    fun submitList(list: List<T>) {\n        items.clear()\n        items.addAll(list)\n        notifyDataSetChanged()\n    }\n\n    interface ActionListener<T> {\n        fun onActionPerformed(t: T, position: Int, action: Action)\n\n        enum class Action { SELECT, DELETE }\n    }\n\n    abstract class BaseBasicViewHolder<T>(itemView: View) : RecyclerView.ViewHolder(itemView) {\n        abstract fun onBind(t: T, position: Int)\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/shared/abstracts/BaseBottomSheet.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.shared.abstracts\r\n\r\nimport android.app.Dialog\r\nimport android.os.Bundle\r\nimport android.view.View\r\nimport android.widget.FrameLayout\r\nimport androidx.fragment.app.FragmentManager\r\nimport com.google.android.material.bottomsheet.BottomSheetBehavior\r\nimport com.google.android.material.bottomsheet.BottomSheetDialog\r\nimport com.google.android.material.bottomsheet.BottomSheetDialogFragment\r\nimport com.isaiahvonrundstedt.fokus.R\r\n\r\nabstract class BaseBottomSheet(private val manager: FragmentManager) : BottomSheetDialogFragment() {\r\n\r\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\r\n        dialog?.setOnShowListener {\r\n            val bottomSheetDialog = dialog as BottomSheetDialog\r\n            val bottomSheet =\r\n                bottomSheetDialog.findViewById<View>(R.id.design_bottom_sheet) as FrameLayout\r\n            with(BottomSheetBehavior.from(bottomSheet)) {\r\n                state = BottomSheetBehavior.STATE_EXPANDED\r\n            }\r\n        }\r\n        super.onViewCreated(view, savedInstanceState)\r\n    }\r\n\r\n    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog =\r\n        BottomSheetDialog(requireContext(), theme)\r\n\r\n    fun show() {\r\n        if (!this.isAdded || !this.isVisible)\r\n            show(manager, this::class.java.name)\r\n    }\r\n\r\n    inline fun show(sheet: BaseBottomSheet.() -> Unit) {\r\n        this.sheet()\r\n        this.show()\r\n    }\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/shared/abstracts/BaseEditorFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.shared.abstracts\n\nimport android.os.Bundle\nimport android.view.animation.Animation\nimport android.view.animation.AnimationUtils\nimport com.google.android.material.transition.platform.MaterialElevationScale\nimport com.isaiahvonrundstedt.fokus.R\n\nabstract class BaseEditorFragment : BaseFragment() {\n\n    protected val animation: Animation\n        get() = AnimationUtils.loadAnimation(requireContext(), R.anim.anim_fade_in)\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        exitTransition = MaterialElevationScale(false).apply {\n            duration = TRANSITION_DURATION\n        }\n        reenterTransition = MaterialElevationScale(true).apply {\n            duration = TRANSITION_DURATION\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/shared/abstracts/BaseFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.shared.abstracts\r\n\r\nimport android.content.Context\r\nimport android.graphics.Color\r\nimport android.os.Bundle\r\nimport android.view.View\r\nimport android.view.ViewGroup\r\nimport android.view.inputmethod.InputMethodManager\r\nimport androidx.annotation.DrawableRes\r\nimport androidx.annotation.IdRes\r\nimport androidx.core.content.ContextCompat\r\nimport androidx.core.view.*\r\nimport androidx.drawerlayout.widget.DrawerLayout\r\nimport androidx.fragment.app.Fragment\r\nimport androidx.fragment.app.FragmentResultListener\r\nimport androidx.interpolator.view.animation.FastOutSlowInInterpolator\r\nimport com.google.android.material.appbar.MaterialToolbar\r\nimport com.google.android.material.color.MaterialColors\r\nimport com.google.android.material.transition.MaterialContainerTransform\r\nimport com.google.android.material.transition.MaterialElevationScale\r\nimport com.google.android.material.transition.MaterialFadeThrough\r\nimport com.isaiahvonrundstedt.fokus.R\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.getDimension\r\nimport me.saket.cascade.CascadePopupMenu\r\n\r\nabstract class BaseFragment : Fragment() {\r\n\r\n    private val parentDrawer: DrawerLayout?\r\n        get() = getParentView()?.findViewById(R.id.drawerLayout) as? DrawerLayout\r\n\r\n    override fun onCreate(savedInstanceState: Bundle?) {\r\n        super.onCreate(savedInstanceState)\r\n        enterTransition = MaterialFadeThrough()\r\n        returnTransition = MaterialFadeThrough()\r\n    }\r\n\r\n    /**\r\n     *  @returns the view of the outermost fragment\r\n     *  on the nested fragment setup\r\n     */\r\n    private fun getParentView(): View? {\r\n        return parentFragment?.parentFragment?.view\r\n    }\r\n\r\n    /**\r\n     *  @param toolbar adds the navigation icon at the start of\r\n     *  the toolbar and registers an onClick callback on it\r\n     */\r\n    protected fun setupNavigation(toolbar: MaterialToolbar,\r\n                                  @DrawableRes iconRes: Int? = null,\r\n                                  onNavigate: (() -> Unit)? = null) {\r\n        with(toolbar) {\r\n            setNavigationIcon(iconRes ?: R.drawable.ic_outline_menu_24)\r\n            setNavigationOnClickListener {\r\n               if (onNavigate != null) {\r\n                   onNavigate()\r\n               } else {\r\n                   triggerNavigationDrawer()\r\n               }\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     *  This function triggers the drawerLayout in the\r\n     *  outermost layer of the nested fragment setup\r\n     */\r\n    private fun triggerNavigationDrawer() {\r\n        if (parentDrawer?.isDrawerOpen(GravityCompat.START) == true)\r\n            parentDrawer?.closeDrawer(GravityCompat.START)\r\n        else parentDrawer?.openDrawer(GravityCompat.START)\r\n    }\r\n\r\n    /**\r\n     *  This function will set the insets (padding) required\r\n     *  to the individual views so that they won't overlap with\r\n     *  Android's Status and Navigation Bars\r\n     *  @param root the parent view or layout\r\n     *  @param topView the topmost view in the layout such as the AppBar\r\n     *  @param contentViews the views which contains the contents in the layout\r\n     *  such as the RecyclerView and empty views.\r\n     *  @param bottomView views such as the FABs.\r\n     */\r\n    protected fun setInsets(\r\n        root: View,\r\n        topView: View,\r\n        contentViews: Array<View> = emptyArray(),\r\n        bottomView: View? = null\r\n    ) {\r\n        ViewCompat.setOnApplyWindowInsetsListener(root) { view, insets ->\r\n            val windowInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())\r\n            topView.updateLayoutParams<ViewGroup.MarginLayoutParams> {\r\n                topMargin = windowInsets.top\r\n            }\r\n            bottomView?.updateLayoutParams<ViewGroup.MarginLayoutParams> {\r\n                bottomMargin = windowInsets.bottom + view.context.getDimension(R.dimen.container_padding_medium)\r\n            }\r\n            contentViews.forEach { contentView ->\r\n                contentView.updateLayoutParams<ViewGroup.MarginLayoutParams> {\r\n                    bottomMargin = windowInsets.bottom\r\n                }\r\n            }\r\n            WindowInsetsCompat.CONSUMED\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @param view the root view of the fragment\r\n     */\r\n    protected fun hideKeyboardFromCurrentFocus(view: View) {\r\n        if (view is ViewGroup)\r\n            findCurrentFocus(view)\r\n    }\r\n\r\n    /**\r\n     * @param viewGroup check if any of its children has focus then\r\n     * hide the keyboard\r\n     */\r\n    private fun findCurrentFocus(viewGroup: ViewGroup) {\r\n        viewGroup.children.forEach {\r\n            if (it is ViewGroup)\r\n            // If the current children is an instance of\r\n            // a ViewGroup, then iterate its children too.\r\n                findCurrentFocus(it)\r\n            else {\r\n                if (it.hasFocus()) {\r\n                    hideKeyboardFromView(it)\r\n                    return\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @param view the view which has the focus\r\n     * then get the inputMethodManager service then\r\n     * try to hide the soft keyboard with the view's\r\n     * window token\r\n     */\r\n    private fun hideKeyboardFromView(view: View) {\r\n        (requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).run {\r\n            hideSoftInputFromWindow(view.windowToken, 0)\r\n        }\r\n    }\r\n\r\n    protected fun registerForFragmentResult(keys: Array<String>, listener: FragmentResultListener) {\r\n        keys.forEach {\r\n            childFragmentManager.setFragmentResultListener(it, viewLifecycleOwner, listener)\r\n        }\r\n    }\r\n\r\n    fun buildContainerTransform(@IdRes id: Int = R.id.navigationHostFragment) =\r\n        MaterialContainerTransform().apply {\r\n            drawingViewId = id\r\n            duration = TRANSITION_DURATION\r\n            scrimColor = Color.TRANSPARENT\r\n            fadeMode = MaterialContainerTransform.FADE_MODE_OUT\r\n            interpolator = FastOutSlowInInterpolator()\r\n            setAllContainerColors(\r\n                MaterialColors.getColor(\r\n                    requireContext(), R.attr.colorSurface,\r\n                    ContextCompat.getColor(requireContext(), R.color.theme_background)\r\n                )\r\n            )\r\n        }\r\n\r\n    fun customPopupProvider(context: Context, anchor: View) =\r\n        CascadePopupMenu(context, anchor,\r\n            styler = CascadePopupMenu.Styler(\r\n                background = {\r\n                    ContextCompat.getDrawable(requireContext(), R.drawable.shape_cascade_background)\r\n                },\r\n\r\n            ))\r\n\r\n    companion object {\r\n        const val TRANSITION_DURATION = 300L\r\n        const val TRANSITION_ELEMENT_ROOT = \"transition:root:\"\r\n    }\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/shared/abstracts/BasePickerFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.shared.abstracts\n\nimport android.os.Bundle\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.annotation.MenuRes\nimport androidx.annotation.StringRes\nimport androidx.fragment.app.DialogFragment\nimport androidx.fragment.app.FragmentManager\nimport com.google.android.material.appbar.MaterialToolbar\nimport com.isaiahvonrundstedt.fokus.R\n\nabstract class BasePickerFragment(private val manager: FragmentManager): DialogFragment() {\n\n    private var toolbar: MaterialToolbar? = null\n\n    protected fun setupToolbar(toolbar: MaterialToolbar,\n                               @StringRes titleRes: Int = 0,\n                               @MenuRes menuRes: Int = 0,\n                               onNavigate: (() -> Unit)? = null,\n                               onMenuItemClicked: ((id: Int) -> Unit)? = null) {\n        this.toolbar = toolbar\n        with(toolbar) {\n            setTitle(titleRes)\n            setNavigationIcon(R.drawable.ic_outline_close_24)\n            setNavigationOnClickListener { if (onNavigate != null) onNavigate() }\n            setOnMenuItemClickListener {\n                if (onMenuItemClicked != null) onMenuItemClicked(it.itemId);\n                true\n            }\n            if (menuRes != 0) inflateMenu(menuRes)\n        }\n    }\n    \n    fun show() {\n        if (!isAdded || !isVisible) {\n            show(manager, this::class.java.simpleName)\n        }\n    }\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setStyle(STYLE_NORMAL, R.style.Fokus_Component_Viewer)\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        dialog?.window?.run {\n            setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)\n            setWindowAnimations(R.style.Fokus_Animations_Slide)\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/shared/abstracts/BasePreference.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.shared.abstracts\r\n\r\nimport androidx.preference.Preference\r\nimport androidx.preference.PreferenceFragmentCompat\r\n\r\nabstract class BasePreference : PreferenceFragmentCompat() {\r\n\r\n    fun setPreferenceSummary(key: String, summary: String?) {\r\n        findPreference<Preference>(key)?.summary = summary\r\n    }\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/shared/abstracts/BaseService.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.shared.abstracts\n\nimport android.app.Notification\nimport android.app.NotificationManager\nimport android.app.Service\nimport android.content.Context\nimport android.content.Intent\nimport android.os.Build\nimport androidx.annotation.DrawableRes\nimport androidx.annotation.StringRes\nimport androidx.core.app.NotificationCompat\nimport androidx.core.content.ContextCompat\nimport androidx.localbroadcastmanager.content.LocalBroadcastManager\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.utils.NotificationChannelManager\n\nabstract class BaseService : Service() {\n\n    protected fun startForegroundCompat(id: Int, notification: Notification) {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)\n            startForeground(id, notification)\n        else manager?.notify(id, notification)\n    }\n\n    protected fun stopForegroundCompat(id: Int) {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)\n            stopForeground(true)\n        else manager?.cancel(id)\n    }\n\n    protected fun createNotification(\n        ongoing: Boolean = false,\n        @StringRes titleRes: Int,\n        @StringRes contentRes: Int = 0,\n        @DrawableRes iconRes: Int = R.drawable.ic_outline_check_24\n    ): Notification {\n\n        return NotificationCompat.Builder(\n            this,\n            NotificationChannelManager.CHANNEL_ID_GENERIC\n        ).apply {\n            setSmallIcon(iconRes)\n            setContentTitle(getString(titleRes))\n            if (contentRes != 0) setContentText(getString(contentRes))\n            setOngoing(ongoing)\n            setCategory(Notification.CATEGORY_SERVICE)\n            setChannelId(NotificationChannelManager.CHANNEL_ID_GENERIC)\n            if (ongoing) setProgress(0, 0, true)\n            color = ContextCompat.getColor(this@BaseService, R.color.theme_primary)\n        }.build()\n    }\n\n    protected fun terminateService(status: String? = null, data: String? = null) {\n        if (status != null)\n            sendLocalBroadcast(status, data)\n        stopSelf()\n    }\n\n    protected fun sendLocalBroadcast(status: String, data: String? = null) {\n        LocalBroadcastManager.getInstance(this)\n            .sendBroadcast(Intent(ACTION_SERVICE_BROADCAST).apply {\n                putExtra(EXTRA_BROADCAST_STATUS, status)\n                if (data != null)\n                    putExtra(EXTRA_BROADCAST_DATA, data)\n            })\n    }\n\n    protected val manager by lazy {\n        getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager\n    }\n\n    companion object {\n        const val ACTION_SERVICE_BROADCAST = \"action:service:status\"\n        const val EXTRA_BROADCAST_STATUS = \"extra:broadcast:status\"\n        const val EXTRA_BROADCAST_DATA = \"extra:broadcast:data\"\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/shared/abstracts/BaseViewerFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.shared.abstracts\n\nimport android.os.Bundle\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.fragment.app.DialogFragment\nimport androidx.fragment.app.FragmentManager\nimport com.isaiahvonrundstedt.fokus.R\n\nabstract class BaseViewerFragment(private val manager: FragmentManager) : DialogFragment() {\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setStyle(STYLE_NORMAL, R.style.Fokus_Component_Viewer)\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n\n        dialog?.window?.run {\n            setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)\n            setWindowAnimations(R.style.Fokus_Animations_Slide)\n        }\n    }\n\n    fun show() {\n        show(manager, this::class.java.simpleName)\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/shared/abstracts/BaseWorker.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.shared.abstracts\r\n\r\nimport android.app.Notification\r\nimport android.app.NotificationManager\r\nimport android.app.PendingIntent\r\nimport android.content.Context\r\nimport android.content.Intent\r\nimport android.net.Uri\r\nimport androidx.core.app.NotificationCompat\r\nimport androidx.core.content.ContextCompat\r\nimport androidx.work.CoroutineWorker\r\nimport androidx.work.Data\r\nimport androidx.work.WorkerParameters\r\nimport com.isaiahvonrundstedt.fokus.R\r\nimport com.isaiahvonrundstedt.fokus.components.service.NotificationActionService\r\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\r\nimport com.isaiahvonrundstedt.fokus.database.converter.DateTimeConverter\r\nimport com.isaiahvonrundstedt.fokus.features.core.activities.MainActivity\r\nimport com.isaiahvonrundstedt.fokus.features.event.Event\r\nimport com.isaiahvonrundstedt.fokus.features.log.Log\r\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\r\nimport com.isaiahvonrundstedt.fokus.features.task.Task\r\n\r\nabstract class BaseWorker(context: Context, workerParameters: WorkerParameters) :\r\n    CoroutineWorker(context, workerParameters) {\r\n\r\n    companion object {\r\n        const val NOTIFICATION_ID_EVENT = 14\r\n        const val NOTIFICATION_TAG_EVENT = \"com:isaiahvonrundstedt:fokus:event\"\r\n        const val NOTIFICATION_CHANNEL_ID_EVENT = \"channel:event\"\r\n        const val NOTIFICATION_ID_TASK = 27\r\n        const val NOTIFICATION_TAG_TASK = \"com:isaiahvonrundstedt:fokus:task\"\r\n        const val NOTIFICATION_CHANNEL_ID_TASK = \"channel:task\"\r\n        const val NOTIFICATION_ID_GENERIC = 38\r\n        const val NOTIFICATION_TAG_GENERIC = \"com:isaiahvonrundstedt:fokus:generic\"\r\n        const val NOTIFICATION_CHANNEL_ID_GENERIC = \"channel:generic\"\r\n\r\n        private const val EXTRA_LOG_ID = \"extra:history:id\"\r\n        private const val EXTRA_LOG_TITLE = \"extra:history:title\"\r\n        private const val EXTRA_LOG_CONTENT = \"extra:history:content\"\r\n        private const val EXTRA_LOG_TYPE = \"extra:history:type\"\r\n        private const val EXTRA_LOG_DATA = \"extra:history:data\"\r\n        private const val EXTRA_LOG_PERSISTENCE = \"extra:history:persistence\"\r\n\r\n        private const val EXTRA_TASK_ID = \"extra:task:id\"\r\n        private const val EXTRA_TASK_NAME = \"extra:task:name\"\r\n        private const val EXTRA_TASK_NOTES = \"extra:task:notes\"\r\n        private const val EXTRA_TASK_SUBJECT = \"extra:task:subject\"\r\n        private const val EXTRA_TASK_DUE = \"extra:task:due\"\r\n        private const val EXTRA_TASK_IMPORTANCE = \"extra:task:importance\"\r\n\r\n        private const val EXTRA_EVENT_ID = \"extra:event:id\"\r\n        private const val EXTRA_EVENT_NAME = \"extra:event:name\"\r\n        private const val EXTRA_EVENT_NOTES = \"extra:event:notes\"\r\n        private const val EXTRA_EVENT_LOCATION = \"extra:event:location\"\r\n        private const val EXTRA_EVENT_SCHEDULE = \"extra:event:schedule\"\r\n        private const val EVENT_EVENT_IMPORTANCE = \"extra:event:isImportant\"\r\n\r\n        private const val EXTRA_SCHEDULE_ID = \"extra:schedule:id\"\r\n        private const val EXTRA_SCHEDULE_DAY_OF_WEEK = \"extra:schedule:day\"\r\n        private const val EXTRA_SCHEDULE_START_TIME = \"extra:schedule:start:time\"\r\n        private const val EXTRA_SCHEDULE_END_TIME = \"extra:schedule:end:time\"\r\n        private const val EXTRA_SCHEDULE_SUBJECT = \"extra:schedule:subject\"\r\n\r\n        fun convertLogToData(log: Log): Data {\r\n            return Data.Builder().apply {\r\n                putString(EXTRA_LOG_ID, log.logID)\r\n                putString(EXTRA_LOG_TITLE, log.title)\r\n                putString(EXTRA_LOG_CONTENT, log.content)\r\n                putString(EXTRA_LOG_DATA, log.data)\r\n                putInt(EXTRA_LOG_TYPE, log.type)\r\n                putBoolean(EXTRA_LOG_PERSISTENCE, log.isImportant)\r\n            }.build()\r\n        }\r\n\r\n        fun convertTaskToData(task: Task): Data {\r\n            return Data.Builder().apply {\r\n                putString(EXTRA_TASK_ID, task.taskID)\r\n                putString(EXTRA_TASK_NAME, task.name)\r\n                putString(EXTRA_TASK_NOTES, task.notes)\r\n                putString(EXTRA_TASK_SUBJECT, task.subject)\r\n                putString(EXTRA_TASK_DUE, DateTimeConverter.fromZonedDateTime(task.dueDate))\r\n                putBoolean(EXTRA_TASK_IMPORTANCE, task.isImportant)\r\n            }.build()\r\n        }\r\n\r\n        fun convertEventToData(event: Event): Data {\r\n            return Data.Builder().apply {\r\n                putString(EXTRA_EVENT_ID, event.eventID)\r\n                putString(EXTRA_EVENT_NAME, event.name)\r\n                putString(EXTRA_EVENT_NOTES, event.notes)\r\n                putString(EXTRA_EVENT_LOCATION, event.location)\r\n                putString(EXTRA_EVENT_SCHEDULE, DateTimeConverter.fromZonedDateTime(event.schedule))\r\n                putBoolean(EVENT_EVENT_IMPORTANCE, event.isImportant)\r\n            }.build()\r\n        }\r\n\r\n        fun convertScheduleToData(schedule: Schedule): Data {\r\n            return Data.Builder().apply {\r\n                putString(EXTRA_SCHEDULE_ID, schedule.scheduleID)\r\n                putString(EXTRA_SCHEDULE_SUBJECT, schedule.subject)\r\n                putString(\r\n                    EXTRA_SCHEDULE_START_TIME,\r\n                    DateTimeConverter.fromLocalTime(schedule.startTime)\r\n                )\r\n                putString(\r\n                    EXTRA_SCHEDULE_END_TIME,\r\n                    DateTimeConverter.fromLocalTime(schedule.endTime)\r\n                )\r\n                putInt(EXTRA_SCHEDULE_DAY_OF_WEEK, schedule.daysOfWeek)\r\n            }.build()\r\n        }\r\n\r\n        fun convertDataToLog(workerData: Data): Log {\r\n            return Log().apply {\r\n                workerData.getString(EXTRA_LOG_ID)?.let { logID = it }\r\n                title = workerData.getString(EXTRA_LOG_TITLE)\r\n                content = workerData.getString(EXTRA_LOG_CONTENT)\r\n                data = workerData.getString(EXTRA_LOG_DATA)\r\n                type = workerData.getInt(EXTRA_LOG_TYPE, Log.TYPE_GENERIC)\r\n                isImportant = workerData.getBoolean(EXTRA_LOG_PERSISTENCE, false)\r\n            }\r\n        }\r\n\r\n        fun convertDataToTask(workerData: Data): Task {\r\n            return Task().apply {\r\n                workerData.getString(EXTRA_TASK_ID)?.let { taskID = it }\r\n                name = workerData.getString(EXTRA_TASK_NAME)\r\n                notes = workerData.getString(EXTRA_TASK_NOTES)\r\n                subject = workerData.getString(EXTRA_TASK_SUBJECT)\r\n                isImportant = workerData.getBoolean(EXTRA_TASK_IMPORTANCE, false)\r\n                dueDate = DateTimeConverter.toZonedDateTime(workerData.getString(EXTRA_TASK_DUE))\r\n            }\r\n        }\r\n\r\n        fun convertDataToEvent(workerData: Data): Event {\r\n            return Event().apply {\r\n                workerData.getString(EXTRA_EVENT_ID)?.let { eventID = it }\r\n                name = workerData.getString(EXTRA_EVENT_NAME)\r\n                notes = workerData.getString(EXTRA_EVENT_NOTES)\r\n                location = workerData.getString(EXTRA_EVENT_LOCATION)\r\n                schedule =\r\n                    DateTimeConverter.toZonedDateTime(workerData.getString(EXTRA_EVENT_SCHEDULE))\r\n                isImportant = workerData.getBoolean(EVENT_EVENT_IMPORTANCE, false)\r\n            }\r\n        }\r\n\r\n        fun convertDataToSchedule(workerData: Data): Schedule {\r\n            return Schedule().apply {\r\n                workerData.getString(EXTRA_SCHEDULE_ID)?.let { scheduleID = it }\r\n                subject = workerData.getString(EXTRA_SCHEDULE_SUBJECT)\r\n                startTime =\r\n                    DateTimeConverter.toLocalTime(workerData.getString(EXTRA_SCHEDULE_START_TIME))\r\n                endTime =\r\n                    DateTimeConverter.toLocalTime(workerData.getString(EXTRA_SCHEDULE_END_TIME))\r\n                daysOfWeek = workerData.getInt(EXTRA_SCHEDULE_DAY_OF_WEEK, 0)\r\n            }\r\n        }\r\n    }\r\n\r\n    protected fun sendNotification(log: Log, manager: NotificationManager, tag: String? = null) {\r\n        if (log.type == Log.TYPE_TASK && log.data != null) {\r\n            val intent = PendingIntent.getService(\r\n                applicationContext,\r\n                NotificationActionService.NOTIFICATION_ID_FINISH,\r\n                Intent(applicationContext, NotificationActionService::class.java).apply {\r\n                    putExtra(NotificationActionService.EXTRA_TASK_ID, log.data)\r\n                    putExtra(NotificationActionService.EXTRA_IS_PERSISTENT, log.isImportant)\r\n                    action = NotificationActionService.ACTION_FINISHED\r\n                },\r\n                PendingIntent.FLAG_IMMUTABLE\r\n            )\r\n\r\n            manager.notify(\r\n                tag ?: NOTIFICATION_TAG_TASK, NOTIFICATION_ID_TASK,\r\n                createNotification(\r\n                    log, NOTIFICATION_CHANNEL_ID_TASK,\r\n                    NotificationCompat.Action(\r\n                        R.drawable.ic_outline_check_24,\r\n                        applicationContext.getString(R.string.button_mark_as_finished), intent\r\n                    )\r\n                )\r\n            )\r\n        } else if (log.type == Log.TYPE_EVENT)\r\n            manager.notify(\r\n                tag ?: NOTIFICATION_TAG_EVENT, NOTIFICATION_ID_EVENT,\r\n                createNotification(log, NOTIFICATION_CHANNEL_ID_EVENT)\r\n            )\r\n        else manager.notify(\r\n            tag ?: NOTIFICATION_TAG_GENERIC, NOTIFICATION_ID_GENERIC,\r\n            createNotification(log, NOTIFICATION_CHANNEL_ID_GENERIC)\r\n        )\r\n    }\r\n\r\n    private fun createNotification(\r\n        log: Log?,\r\n        channelID: String,\r\n        action: NotificationCompat.Action? = null\r\n    ): Notification {\r\n        return NotificationCompat.Builder(applicationContext, channelID).apply {\r\n            setSound(notificationSoundUri)\r\n            setSmallIcon(log?.getIconResource() ?: R.drawable.ic_outline_check_24)\r\n            setContentIntent(contentIntent)\r\n            setContentTitle(log?.title)\r\n            if (log?.content != null) setContentText(log.content)\r\n            setOngoing(log?.isImportant == true)\r\n            if (action != null)\r\n                addAction(action)\r\n            color = ContextCompat.getColor(applicationContext, R.color.theme_primary)\r\n        }.build()\r\n    }\r\n\r\n    private val contentIntent: PendingIntent\r\n        get() {\r\n            return PendingIntent.getActivity(\r\n                applicationContext, 0,\r\n                Intent(applicationContext, MainActivity::class.java), PendingIntent.FLAG_IMMUTABLE\r\n            )\r\n        }\r\n\r\n    private val notificationSoundUri: Uri\r\n        get() = Uri.parse(PreferenceManager.DEFAULT_SOUND)\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/shared/adapters/MenuAdapter.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.shared.adapters\n\nimport android.app.Activity\nimport android.graphics.drawable.Drawable\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.PopupMenu\nimport androidx.annotation.MenuRes\nimport androidx.recyclerview.widget.RecyclerView\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutItemMenuBinding\n\nclass MenuAdapter(\n    activity: Activity?,\n    @MenuRes\n    private val resId: Int,\n    private val menuItemListener: MenuItemListener\n) : RecyclerView.Adapter<MenuAdapter.ViewHolder>() {\n\n    private var itemList = mutableListOf<MenuItem>()\n\n    init {\n        val temp = PopupMenu(activity, null).menu\n        activity?.menuInflater?.inflate(resId, temp)\n\n        for (i in 0 until temp.size()) {\n            val item = temp.getItem(i)\n            itemList.add(MenuItem(item.itemId, item.icon, item.title.toString()))\n        }\n        notifyDataSetChanged()\n    }\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {\n        val binding = LayoutItemMenuBinding.inflate(\n            LayoutInflater.from(parent.context),\n            parent, false\n        )\n        return ViewHolder(binding.root)\n    }\n\n    override fun getItemCount(): Int = itemList.size\n\n    override fun onBindViewHolder(holder: ViewHolder, position: Int) {\n        holder.onBind(itemList[position])\n    }\n\n    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {\n\n        private val binding = LayoutItemMenuBinding.bind(itemView)\n\n        fun onBind(item: MenuItem) {\n            binding.iconView.setImageDrawable(item.icon)\n            binding.titleView.text = item.title\n            binding.root.setOnClickListener { menuItemListener.onItemSelected(item.id) }\n        }\n    }\n\n    data class MenuItem(var id: Int, var icon: Drawable?, var title: String)\n\n    interface MenuItemListener {\n        fun onItemSelected(id: Int)\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/subject/Subject.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.subject\r\n\r\nimport android.graphics.Color\r\nimport android.graphics.drawable.Drawable\r\nimport android.os.Bundle\r\nimport android.os.Parcelable\r\nimport androidx.core.graphics.BlendModeColorFilterCompat\r\nimport androidx.core.graphics.BlendModeCompat\r\nimport androidx.core.os.bundleOf\r\nimport androidx.room.ColumnInfo\r\nimport androidx.room.Entity\r\nimport androidx.room.PrimaryKey\r\nimport androidx.room.TypeConverters\r\nimport com.isaiahvonrundstedt.fokus.R\r\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Streamable\r\nimport com.isaiahvonrundstedt.fokus.components.json.JsonDataStreamer\r\nimport com.isaiahvonrundstedt.fokus.database.converter.ColorConverter\r\nimport com.squareup.moshi.JsonClass\r\nimport kotlinx.parcelize.Parcelize\r\nimport okio.buffer\r\nimport okio.sink\r\nimport java.io.File\r\nimport java.io.InputStream\r\nimport java.util.*\r\n\r\n@Parcelize\r\n@JsonClass(generateAdapter = true)\r\n@Entity(tableName = \"subjects\")\r\ndata class Subject @JvmOverloads constructor(\r\n    @PrimaryKey\r\n    @ColumnInfo(index = true)\r\n    var subjectID: String = UUID.randomUUID().toString(),\r\n    var code: String? = null,\r\n    var description: String? = null,\r\n    var instructor: String? = null,\r\n    @TypeConverters(ColorConverter::class)\r\n    var tag: Tag = Tag.SKY,\r\n    var isSubjectArchived: Boolean = false,\r\n) : Parcelable, Streamable {\r\n\r\n    // Used for the color tag of the subject\r\n    @JsonClass(generateAdapter = false)\r\n    enum class Tag(val color: Int) {\r\n        SKY(Color.parseColor(\"#2196f3\")),\r\n        GRASS(Color.parseColor(\"#71a234\")),\r\n        SUNSET(Color.parseColor(\"#ff7e0f\")),\r\n        LEMON(Color.parseColor(\"#ffb600\")),\r\n        SEA(Color.parseColor(\"#01b1af\")),\r\n        GRAPE(Color.parseColor(\"#9c27b0\")),\r\n        CHERRY(Color.parseColor(\"#f50057\")),\r\n        CORAL(Color.parseColor(\"#f15b8d\")),\r\n        MIDNIGHT(Color.parseColor(\"#1a237e\")),\r\n        LAVENDER(Color.parseColor(\"#b39ddb\")),\r\n        MINT(Color.parseColor(\"#009c56\")),\r\n        GRAPHITE(Color.parseColor(\"#757575\"));\r\n\r\n        fun getNameResource(): Int {\r\n            return when (this) {\r\n                SKY -> R.string.color_sky\r\n                GRASS -> R.string.color_grass\r\n                SUNSET -> R.string.color_sunset\r\n                LEMON -> R.string.color_lemon\r\n                SEA -> R.string.color_sea\r\n                GRAPE -> R.string.color_grape\r\n                CHERRY -> R.string.color_cherry\r\n                CORAL -> R.string.color_coral\r\n                MIDNIGHT -> R.string.color_midnight\r\n                MINT -> R.string.color_mint\r\n                LAVENDER -> R.string.color_lavender\r\n                GRAPHITE -> R.string.color_graphite\r\n            }\r\n        }\r\n\r\n        companion object {\r\n            private val colors: MutableMap<Int, Tag> = HashMap()\r\n\r\n            init {\r\n                for (i in values())\r\n                    colors[i.color] = i\r\n            }\r\n\r\n            fun convertColorToTag(int: Int): Tag? = colors[int]\r\n\r\n            fun getColors(): IntArray = colors.keys.toIntArray()\r\n        }\r\n    }\r\n\r\n    fun tintDrawable(drawable: Drawable?): Drawable? {\r\n        return drawable?.also {\r\n            it.mutate()\r\n            it.colorFilter = BlendModeColorFilterCompat\r\n                .createBlendModeColorFilterCompat(tag.color, BlendModeCompat.SRC_ATOP)\r\n        }\r\n    }\r\n\r\n    override fun toJsonString(): String? = JsonDataStreamer.encodeToJson(this, Subject::class.java)\r\n\r\n    override fun toJsonFile(destination: File, name: String): File {\r\n        return File(destination, name).apply {\r\n            this.sink().buffer().use {\r\n                toJsonString()?.also { json -> it.write(json.toByteArray()) }\r\n            }\r\n        }\r\n    }\r\n\r\n    override fun fromInputStream(inputStream: InputStream) {\r\n        JsonDataStreamer.decodeOnceFromJson(inputStream, Subject::class.java)?.also {\r\n            subjectID = it.subjectID\r\n            code = it.code\r\n            description = it.description\r\n            instructor = it.instructor\r\n            tag = it.tag\r\n        }\r\n    }\r\n\r\n    companion object {\r\n        const val EXTRA_ID = \"extra:id\"\r\n        const val EXTRA_CODE = \"extra:code\"\r\n        const val EXTRA_DESCRIPTION = \"extra:description\"\r\n        const val EXTRA_INSTRUCTOR = \"extra:instructor\"\r\n        const val EXTRA_COLOR = \"extra:color\"\r\n        const val EXTRA_IS_ARCHIVED = \"extra:archived\"\r\n\r\n        fun toBundle(subject: Subject): Bundle {\r\n            return bundleOf(\r\n                EXTRA_ID to subject.subjectID,\r\n                EXTRA_CODE to subject.code,\r\n                EXTRA_DESCRIPTION to subject.description,\r\n                EXTRA_INSTRUCTOR to subject.instructor,\r\n                EXTRA_COLOR to ColorConverter.fromColor(subject.tag),\r\n                EXTRA_IS_ARCHIVED to subject.isSubjectArchived\r\n            )\r\n        }\r\n\r\n        fun fromBundle(bundle: Bundle): Subject? {\r\n            if (!bundle.containsKey(EXTRA_ID))\r\n                return null\r\n\r\n            return Subject(\r\n                subjectID = bundle.getString(EXTRA_ID)!!,\r\n                code = bundle.getString(EXTRA_CODE),\r\n                description = bundle.getString(EXTRA_DESCRIPTION),\r\n                instructor = bundle.getString(EXTRA_INSTRUCTOR),\r\n                tag = ColorConverter.toColor(bundle.getInt(EXTRA_COLOR)) ?: Tag.SKY,\r\n                isSubjectArchived = bundle.getBoolean(EXTRA_IS_ARCHIVED)\r\n            )\r\n        }\r\n\r\n        fun fromInputStream(inputStream: InputStream): Subject {\r\n            return Subject().apply {\r\n                this.fromInputStream(inputStream)\r\n            }\r\n        }\r\n    }\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/subject/SubjectAdapter.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.subject\r\n\r\nimport android.view.LayoutInflater\r\nimport android.view.View\r\nimport android.view.ViewGroup\r\nimport androidx.recyclerview.widget.ItemTouchHelper\r\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Swipeable\r\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutItemSubjectBinding\r\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutItemSubjectSingleBinding\r\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseFragment\r\n\r\nclass SubjectAdapter(\r\n    private val actionListener: ActionListener,\r\n    private val scheduleListener: ScheduleListener,\r\n    private val archiveListener: ArchiveListener\r\n) : BaseAdapter<SubjectPackage, BaseAdapter.BaseViewHolder>(SubjectPackage.DIFF_CALLBACK),\r\n    Swipeable {\r\n\r\n    var constraint = SubjectViewModel.Constraint.TODAY\r\n\r\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {\r\n        return when (viewType) {\r\n            ITEM_TYPE_ALL_SCHEDULE -> {\r\n                val binding = LayoutItemSubjectBinding.inflate(\r\n                    LayoutInflater.from(parent.context),\r\n                    parent, false\r\n                )\r\n                CoreViewHolder(binding.root, actionListener, scheduleListener)\r\n            }\r\n            ITEM_TYPE_SINGLE_SCHEDULE_TODAY -> {\r\n                val binding = LayoutItemSubjectSingleBinding.inflate(\r\n                    LayoutInflater.from(parent.context),\r\n                    parent, false\r\n                )\r\n                TodayViewHolder(binding.root, actionListener)\r\n            }\r\n            ITEM_TYPE_SINGLE_SCHEDULE_TOMORROW -> {\r\n                val binding = LayoutItemSubjectSingleBinding.inflate(\r\n                    LayoutInflater.from(parent.context),\r\n                    parent, false\r\n                )\r\n                TomorrowViewHolder(binding.root, actionListener)\r\n            }\r\n            else -> throw IllegalStateException(\"Unknown Item type\")\r\n        }\r\n    }\r\n\r\n    override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {\r\n        holder.onBind(getItem(position))\r\n    }\r\n\r\n    override fun getItemViewType(position: Int): Int {\r\n        return when (constraint) {\r\n            SubjectViewModel.Constraint.ALL -> ITEM_TYPE_ALL_SCHEDULE\r\n            SubjectViewModel.Constraint.TODAY -> ITEM_TYPE_SINGLE_SCHEDULE_TODAY\r\n            SubjectViewModel.Constraint.TOMORROW -> ITEM_TYPE_SINGLE_SCHEDULE_TOMORROW\r\n        }\r\n    }\r\n\r\n    override fun onSwipe(position: Int, direction: Int) {\r\n        if (direction == ItemTouchHelper.START)\r\n            actionListener.onActionPerformed(\r\n                getItem(position), ActionListener.Action.DELETE,\r\n                null\r\n            )\r\n        else if (direction == ItemTouchHelper.END)\r\n            archiveListener.onItemArchive(getItem(position))\r\n    }\r\n\r\n    class CoreViewHolder(\r\n        itemView: View,\r\n        private val actionListener: ActionListener,\r\n        private val scheduleListener: ScheduleListener\r\n    ) : BaseViewHolder(itemView) {\r\n        private val binding = LayoutItemSubjectBinding.bind(itemView)\r\n\r\n        override fun <T> onBind(data: T) {\r\n            if (data is SubjectPackage) {\r\n                with(data.subject) {\r\n                    binding.root.transitionName = BaseFragment.TRANSITION_ELEMENT_ROOT + subjectID\r\n\r\n                    binding.tagView.setImageDrawable(tintDrawable(binding.tagView.drawable))\r\n                    binding.nameView.text = code\r\n                    binding.descriptionView.text = description\r\n                }\r\n\r\n                binding.scheduleView.setOnClickListener {\r\n                    scheduleListener.onScheduleListener(data.schedules)\r\n                }\r\n\r\n                binding.root.setOnClickListener {\r\n                    actionListener.onActionPerformed(data, ActionListener.Action.SELECT, it)\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    class TodayViewHolder(\r\n        itemView: View,\r\n        private val actionListener: ActionListener\r\n    ) : BaseViewHolder(itemView) {\r\n\r\n        private val binding = LayoutItemSubjectSingleBinding.bind(itemView)\r\n\r\n        override fun <T> onBind(data: T) {\r\n            if (data is SubjectPackage) {\r\n                with(data.subject) {\r\n                    binding.root.transitionName = BaseFragment.TRANSITION_ELEMENT_ROOT + subjectID\r\n\r\n                    binding.tagView.setImageDrawable(tintDrawable(binding.tagView.drawable))\r\n                    binding.nameView.text = code\r\n                    binding.descriptionView.text = description\r\n                }\r\n\r\n                val todaySchedule = data.getScheduleToday()\r\n                binding.scheduleView.text = todaySchedule?.formatBothTime(binding.root.context)\r\n\r\n                binding.root.setOnClickListener {\r\n                    actionListener.onActionPerformed(data, ActionListener.Action.SELECT, it)\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    class TomorrowViewHolder(\r\n        itemView: View,\r\n        private val actionListener: ActionListener\r\n    ) : BaseViewHolder(itemView) {\r\n\r\n        private val binding = LayoutItemSubjectSingleBinding.bind(itemView)\r\n\r\n        override fun <T> onBind(data: T) {\r\n            if (data is SubjectPackage) {\r\n                with(data.subject) {\r\n                    binding.root.transitionName = BaseFragment.TRANSITION_ELEMENT_ROOT + subjectID\r\n\r\n                    binding.tagView.setImageDrawable(tintDrawable(binding.tagView.drawable))\r\n                    binding.nameView.text = code\r\n                    binding.descriptionView.text = description\r\n                }\r\n\r\n                val tomorrowSchedule = data.getScheduleTomorrow()\r\n                binding.scheduleView.text = tomorrowSchedule?.format(itemView.context)\r\n\r\n                binding.root.setOnClickListener {\r\n                    actionListener.onActionPerformed(data, ActionListener.Action.SELECT, it)\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    interface ScheduleListener {\r\n        fun onScheduleListener(items: List<Schedule>)\r\n    }\r\n\r\n    companion object {\r\n        const val ITEM_TYPE_ALL_SCHEDULE = 0\r\n        const val ITEM_TYPE_SINGLE_SCHEDULE_TODAY = 1\r\n        const val ITEM_TYPE_SINGLE_SCHEDULE_TOMORROW = 2\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/subject/SubjectFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.subject\r\n\r\nimport android.os.Bundle\r\nimport android.view.LayoutInflater\r\nimport android.view.MenuItem\r\nimport android.view.View\r\nimport android.view.ViewGroup\r\nimport androidx.annotation.StringRes\r\nimport androidx.core.os.bundleOf\r\nimport androidx.core.view.doOnPreDraw\r\nimport androidx.core.view.isVisible\r\nimport androidx.fragment.app.viewModels\r\nimport androidx.navigation.NavController\r\nimport androidx.navigation.Navigation\r\nimport androidx.navigation.fragment.FragmentNavigatorExtras\r\nimport androidx.recyclerview.widget.ItemTouchHelper\r\nimport androidx.recyclerview.widget.LinearLayoutManager\r\nimport com.isaiahvonrundstedt.fokus.R\r\nimport com.isaiahvonrundstedt.fokus.components.custom.ItemDecoration\r\nimport com.isaiahvonrundstedt.fokus.components.custom.ItemSwipeCallback\r\nimport com.isaiahvonrundstedt.fokus.components.enums.SortDirection\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.createSnackbar\r\nimport com.isaiahvonrundstedt.fokus.databinding.FragmentSubjectBinding\r\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\r\nimport com.isaiahvonrundstedt.fokus.features.schedule.viewer.ScheduleViewerSheet\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseFragment\r\nimport com.isaiahvonrundstedt.fokus.features.subject.editor.SubjectEditorFragment\r\nimport dagger.hilt.android.AndroidEntryPoint\r\nimport me.saket.cascade.overrideOverflowMenu\r\n\r\n\r\n@AndroidEntryPoint\r\nclass SubjectFragment : BaseFragment(), BaseAdapter.ActionListener, SubjectAdapter.ScheduleListener,\r\n    BaseAdapter.ArchiveListener {\r\n\r\n    private var _binding: FragmentSubjectBinding? = null\r\n    private var controller: NavController? = null\r\n\r\n    private val binding get() = _binding!!\r\n    private val subjectAdapter = SubjectAdapter(this, this, this)\r\n    private val viewModel: SubjectViewModel by viewModels()\r\n\r\n    override fun onCreateView(\r\n        inflater: LayoutInflater, container: ViewGroup?,\r\n        savedInstanceState: Bundle?\r\n    ): View {\r\n        _binding = FragmentSubjectBinding.inflate(inflater)\r\n        return binding.root\r\n    }\r\n\r\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\r\n        super.onViewCreated(view, savedInstanceState)\r\n        binding.actionButton.transitionName = TRANSITION_ELEMENT_ROOT\r\n        setInsets(binding.root, binding.appBarLayout.toolbar,\r\n            arrayOf(\r\n                binding.recyclerView,\r\n                binding.emptyViewSubjectsToday,\r\n                binding.emptyViewSubjectsAll,\r\n                binding.emptyViewSubjectsTomorrow\r\n            ), binding.actionButton\r\n        )\r\n\r\n        with(binding.appBarLayout.toolbar) {\r\n            setTitle(getToolbarTitle())\r\n            menu?.clear()\r\n            inflateMenu(R.menu.menu_subjects)\r\n            overrideOverflowMenu(::customPopupProvider)\r\n            setOnMenuItemClickListener(::onMenuItemClicked)\r\n            setupNavigation(this)\r\n\r\n            menu.findItem(R.id.action_sort_schedule)\r\n                ?.isVisible = viewModel.constraint != SubjectViewModel.Constraint.ALL\r\n        }\r\n\r\n        with(binding.recyclerView) {\r\n            addItemDecoration(ItemDecoration(context))\r\n            layoutManager = LinearLayoutManager(context)\r\n            adapter = subjectAdapter\r\n\r\n            ItemTouchHelper(ItemSwipeCallback(context, subjectAdapter))\r\n                .attachToRecyclerView(this)\r\n        }\r\n\r\n        postponeEnterTransition()\r\n        view.doOnPreDraw { startPostponedEnterTransition() }\r\n    }\r\n\r\n    override fun onStart() {\r\n        super.onStart()\r\n\r\n        /**\r\n         * Get the NavController here so\r\n         * that it doesn't crash when\r\n         * the host activity is recreated.\r\n         */\r\n        controller = Navigation.findNavController(requireActivity(), R.id.navigationHostFragment)\r\n\r\n        subjectAdapter.constraint = viewModel.constraint\r\n        viewModel.subjects.observe(viewLifecycleOwner) {\r\n            subjectAdapter.submitList(it)\r\n        }\r\n        viewModel.isEmpty.observe(viewLifecycleOwner) {\r\n            when (viewModel.constraint) {\r\n                SubjectViewModel.Constraint.ALL -> {\r\n                    binding.emptyViewSubjectsAll.isVisible = it\r\n                    binding.emptyViewSubjectsToday.isVisible = false\r\n                    binding.emptyViewSubjectsTomorrow.isVisible = false\r\n                }\r\n                SubjectViewModel.Constraint.TODAY -> {\r\n                    binding.emptyViewSubjectsAll.isVisible = false\r\n                    binding.emptyViewSubjectsToday.isVisible = it\r\n                    binding.emptyViewSubjectsTomorrow.isVisible = false\r\n                }\r\n                SubjectViewModel.Constraint.TOMORROW -> {\r\n                    binding.emptyViewSubjectsAll.isVisible = false\r\n                    binding.emptyViewSubjectsToday.isVisible = false\r\n                    binding.emptyViewSubjectsTomorrow.isVisible = it\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    override fun onResume() {\r\n        super.onResume()\r\n\r\n        binding.actionButton.setOnClickListener {\r\n            controller?.navigate(\r\n                R.id.navigation_editor_subject, null, null,\r\n                FragmentNavigatorExtras(it to TRANSITION_ELEMENT_ROOT)\r\n            )\r\n        }\r\n    }\r\n\r\n    override fun <T> onActionPerformed(\r\n        t: T, action: BaseAdapter.ActionListener.Action,\r\n        container: View?\r\n    ) {\r\n        if (t is SubjectPackage) {\r\n            when (action) {\r\n                // Create the intent for the editorUI and pass the extras\r\n                // and wait for the result\r\n                BaseAdapter.ActionListener.Action.SELECT -> {\r\n                    val transitionName = TRANSITION_ELEMENT_ROOT + t.subject.subjectID\r\n\r\n                    val args = bundleOf(\r\n                        SubjectEditorFragment.EXTRA_SUBJECT to Subject.toBundle(t.subject),\r\n                        SubjectEditorFragment.EXTRA_SCHEDULE to t.schedules\r\n                    )\r\n\r\n                    container?.also {\r\n                        controller?.navigate(\r\n                            R.id.navigation_editor_subject, args, null,\r\n                            FragmentNavigatorExtras(it to transitionName)\r\n                        )\r\n                    }\r\n                }\r\n                // Item has been swiped from the RecyclerView, notify user action\r\n                // in the ViewModel to delete it from the database\r\n                // then show a SnackBar feedback\r\n                BaseAdapter.ActionListener.Action.DELETE -> {\r\n                    viewModel.remove(t.subject)\r\n\r\n                    createSnackbar(R.string.feedback_subject_removed, binding.recyclerView).run {\r\n                        setAction(R.string.button_undo) { viewModel.insert(t.subject, t.schedules) }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    override fun <T> onItemArchive(t: T) {\r\n        if (t is SubjectPackage) {\r\n            t.subject.isSubjectArchived = true\r\n            viewModel.update(t.subject)\r\n        }\r\n    }\r\n\r\n    private fun onMenuItemClicked(item: MenuItem): Boolean {\r\n        when (item.itemId) {\r\n            R.id.action_code_sort_ascending -> {\r\n                viewModel.sort = SubjectViewModel.Sort.CODE\r\n                viewModel.direction = SortDirection.ASCENDING\r\n            }\r\n            R.id.action_code_sort_descending -> {\r\n                viewModel.sort = SubjectViewModel.Sort.CODE\r\n                viewModel.direction = SortDirection.DESCENDING\r\n            }\r\n            R.id.action_description_sort_ascending -> {\r\n                viewModel.sort = SubjectViewModel.Sort.DESCRIPTION\r\n                viewModel.direction = SortDirection.ASCENDING\r\n            }\r\n            R.id.action_description_sort_descending -> {\r\n                viewModel.sort = SubjectViewModel.Sort.DESCRIPTION\r\n                viewModel.direction = SortDirection.DESCENDING\r\n            }\r\n            R.id.action_schedule_sort_ascending -> {\r\n                viewModel.sort = SubjectViewModel.Sort.SCHEDULE\r\n                viewModel.direction = SortDirection.ASCENDING\r\n            }\r\n            R.id.action_schedule_sort_descending -> {\r\n                viewModel.sort = SubjectViewModel.Sort.SCHEDULE\r\n                viewModel.direction = SortDirection.DESCENDING\r\n            }\r\n            R.id.action_filter_all -> {\r\n                viewModel.constraint = SubjectViewModel.Constraint.ALL\r\n                subjectAdapter.constraint = viewModel.constraint\r\n\r\n                with(binding.appBarLayout.toolbar) {\r\n                    setTitle(getToolbarTitle())\r\n                    menu?.findItem(R.id.action_sort_schedule)?.isVisible = false\r\n                }\r\n            }\r\n            R.id.action_filter_today -> {\r\n                viewModel.constraint = SubjectViewModel.Constraint.TODAY\r\n                subjectAdapter.constraint = viewModel.constraint\r\n\r\n                with(binding.appBarLayout.toolbar) {\r\n                    setTitle(getToolbarTitle())\r\n                    menu?.findItem(R.id.action_sort_schedule)?.isVisible = false\r\n                }\r\n            }\r\n            R.id.action_filter_tomorrow -> {\r\n                viewModel.constraint = SubjectViewModel.Constraint.TOMORROW\r\n                subjectAdapter.constraint = viewModel.constraint\r\n                with(binding.appBarLayout.toolbar) {\r\n                    setTitle(getToolbarTitle())\r\n                    menu?.findItem(R.id.action_sort_schedule)?.isVisible = true\r\n                }\r\n            }\r\n            R.id.action_archived -> {\r\n                controller?.navigate(R.id.navigation_archived_subject)\r\n            }\r\n        }\r\n        return true\r\n    }\r\n\r\n    override fun onScheduleListener(items: List<Schedule>) {\r\n        ScheduleViewerSheet(items, childFragmentManager)\r\n            .show()\r\n    }\r\n\r\n    @StringRes\r\n    private fun getToolbarTitle(): Int {\r\n        return when (viewModel.constraint) {\r\n            SubjectViewModel.Constraint.ALL -> R.string.activity_subjects\r\n            SubjectViewModel.Constraint.TODAY -> R.string.activity_subjects_today\r\n            SubjectViewModel.Constraint.TOMORROW -> R.string.activity_subjects_tomorrow\r\n        }\r\n    }\r\n\r\n    override fun onDestroy() {\r\n        super.onDestroy()\r\n        _binding = null\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/subject/SubjectPackage.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.subject\n\nimport android.os.Parcelable\nimport androidx.recyclerview.widget.DiffUtil\nimport androidx.room.Embedded\nimport androidx.room.Relation\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\nimport kotlinx.android.parcel.Parcelize\n\n@Parcelize\ndata class SubjectPackage(\n    @Embedded\n    var subject: Subject,\n    @Relation(entity = Schedule::class, parentColumn = \"subjectID\", entityColumn = \"subject\")\n    var schedules: List<Schedule> = emptyList()\n) : Parcelable {\n\n    fun hasScheduleToday(): Boolean {\n        for (s: Schedule in schedules)\n            if (s.isToday()) return true\n        return false\n    }\n\n    fun getScheduleToday(): Schedule? {\n        for (s: Schedule in schedules)\n            if (s.isToday()) return s\n        return null\n    }\n\n    fun hasScheduleTomorrow(): Boolean {\n        for (s: Schedule in schedules)\n            if (s.isTomorrow()) return true\n        return false\n    }\n\n    fun getScheduleTomorrow(): Schedule? {\n        for (s: Schedule in schedules)\n            if (s.isTomorrow()) return s\n        return null\n    }\n\n    companion object {\n        val DIFF_CALLBACK = object : DiffUtil.ItemCallback<SubjectPackage>() {\n            override fun areItemsTheSame(\n                oldItem: SubjectPackage,\n                newItem: SubjectPackage\n            ): Boolean {\n                return oldItem.subject.subjectID == newItem.subject.subjectID\n            }\n\n            override fun areContentsTheSame(\n                oldItem: SubjectPackage,\n                newItem: SubjectPackage\n            ): Boolean {\n                return oldItem == newItem\n            }\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/subject/SubjectViewModel.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.subject\r\n\r\nimport androidx.lifecycle.*\r\nimport com.isaiahvonrundstedt.fokus.components.enums.SortDirection\r\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\r\nimport com.isaiahvonrundstedt.fokus.database.repository.SubjectRepository\r\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\r\nimport dagger.hilt.android.lifecycle.HiltViewModel\r\nimport kotlinx.coroutines.Dispatchers\r\nimport kotlinx.coroutines.NonCancellable\r\nimport kotlinx.coroutines.launch\r\nimport javax.inject.Inject\r\n\r\n@HiltViewModel\r\nclass SubjectViewModel @Inject constructor(\r\n    private val repository: SubjectRepository,\r\n    private val preferenceManager: PreferenceManager\r\n) : ViewModel() {\r\n\r\n    private val _subjects: LiveData<List<SubjectPackage>> = repository.fetchLiveData()\r\n\r\n    val subjects: MediatorLiveData<List<SubjectPackage>> = MediatorLiveData()\r\n    val isEmpty: LiveData<Boolean> = Transformations.map(subjects) { it.isNullOrEmpty() }\r\n\r\n    var constraint: Constraint = preferenceManager.subjectConstraint\r\n        set(value) {\r\n            field = value\r\n            preferenceManager.subjectConstraint = value\r\n            if (constraint == Constraint.ALL)\r\n                sort = Sort.CODE\r\n            rearrange(value, sort, direction)\r\n        }\r\n\r\n    var sort: Sort = preferenceManager.subjectSort\r\n        set(value) {\r\n            field = value\r\n            preferenceManager.subjectSort = value\r\n            rearrange(constraint, value, direction)\r\n        }\r\n\r\n    var direction: SortDirection = preferenceManager.subjectSortDirection\r\n        set(value) {\r\n            field = value\r\n            preferenceManager.subjectSortDirection = value\r\n            rearrange(constraint, sort, value)\r\n        }\r\n\r\n    init {\r\n        subjects.addSource(_subjects) { items ->\r\n            when (constraint) {\r\n                Constraint.ALL ->\r\n                    subjects.value = items\r\n                Constraint.TODAY ->\r\n                    subjects.value = items.filter { it.hasScheduleToday() }\r\n                Constraint.TOMORROW ->\r\n                    subjects.value = items.filter { it.hasScheduleTomorrow() }\r\n            }\r\n        }\r\n    }\r\n\r\n    fun insert(subject: Subject, schedules: List<Schedule>) =\r\n        viewModelScope.launch(Dispatchers.IO + NonCancellable) {\r\n            repository.insert(subject, schedules)\r\n        }\r\n\r\n    fun remove(subject: Subject) = viewModelScope.launch(Dispatchers.IO + NonCancellable) {\r\n        repository.remove(subject)\r\n    }\r\n\r\n    fun update(subject: Subject, schedules: List<Schedule> = emptyList()) =\r\n        viewModelScope.launch(Dispatchers.IO + NonCancellable) {\r\n            repository.update(subject, schedules)\r\n        }\r\n\r\n    private fun rearrange(filter: Constraint, sort: Sort, direction: SortDirection) =\r\n        when (filter) {\r\n            Constraint.ALL -> {\r\n                _subjects.value?.let { items ->\r\n                    subjects.value = when (sort) {\r\n                        Sort.CODE -> {\r\n                            when (direction) {\r\n                                SortDirection.ASCENDING ->\r\n                                    items.sortedBy { it.subject.code }\r\n                                SortDirection.DESCENDING ->\r\n                                    items.sortedByDescending { it.subject.code }\r\n                            }\r\n                        }\r\n                        Sort.DESCRIPTION -> {\r\n                            when (direction) {\r\n                                SortDirection.ASCENDING ->\r\n                                    items.sortedBy { it.subject.description }\r\n                                SortDirection.DESCENDING ->\r\n                                    items.sortedByDescending { it.subject.description }\r\n                            }\r\n                        }\r\n                        Sort.SCHEDULE -> items.sortedBy { it.subject.code }\r\n                    }\r\n                }\r\n            }\r\n            Constraint.TODAY -> {\r\n                _subjects.value?.let { items ->\r\n                    subjects.value = when (sort) {\r\n                        Sort.CODE -> {\r\n                            when (direction) {\r\n                                SortDirection.ASCENDING ->\r\n                                    items.filter { it.hasScheduleToday() }\r\n                                        .sortedBy { it.subject.code }\r\n                                SortDirection.DESCENDING ->\r\n                                    items.filter { it.hasScheduleToday() }\r\n                                        .sortedByDescending { it.subject.code }\r\n                            }\r\n                        }\r\n                        Sort.DESCRIPTION -> {\r\n                            when (direction) {\r\n                                SortDirection.ASCENDING ->\r\n                                    items.filter { it.hasScheduleToday() }\r\n                                        .sortedBy { it.subject.description }\r\n                                SortDirection.DESCENDING ->\r\n                                    items.filter { it.hasScheduleToday() }\r\n                                        .sortedByDescending { it.subject.description }\r\n                            }\r\n                        }\r\n                        Sort.SCHEDULE -> {\r\n                            when (direction) {\r\n                                SortDirection.ASCENDING ->\r\n                                    items.filter { it.hasScheduleToday() }\r\n                                        .sortedBy { it.getScheduleToday()?.startTime }\r\n                                SortDirection.DESCENDING ->\r\n                                    items.filter { it.hasScheduleToday() }\r\n                                        .sortedByDescending { it.getScheduleToday()?.startTime }\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n            Constraint.TOMORROW -> {\r\n                _subjects.value?.let { items ->\r\n                    subjects.value = when (sort) {\r\n                        Sort.CODE -> {\r\n                            when (direction) {\r\n                                SortDirection.ASCENDING ->\r\n                                    items.filter { it.hasScheduleTomorrow() }\r\n                                        .sortedBy { it.subject.code }\r\n                                SortDirection.DESCENDING ->\r\n                                    items.filter { it.hasScheduleTomorrow() }\r\n                                        .sortedByDescending { it.subject.code }\r\n                            }\r\n                        }\r\n                        Sort.DESCRIPTION -> {\r\n                            when (direction) {\r\n                                SortDirection.ASCENDING ->\r\n                                    items.filter { it.hasScheduleTomorrow() }\r\n                                        .sortedBy { it.subject.description }\r\n                                SortDirection.DESCENDING ->\r\n                                    items.filter { it.hasScheduleTomorrow() }\r\n                                        .sortedByDescending { it.subject.description }\r\n                            }\r\n                        }\r\n                        Sort.SCHEDULE -> {\r\n                            when (direction) {\r\n                                SortDirection.ASCENDING ->\r\n                                    items.filter { it.hasScheduleTomorrow() }\r\n                                        .sortedBy { it.getScheduleTomorrow()?.startTime }\r\n                                SortDirection.DESCENDING ->\r\n                                    items.filter { it.hasScheduleTomorrow() }\r\n                                        .sortedByDescending { it.getScheduleTomorrow()?.startTime }\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n    enum class Sort {\r\n        CODE, DESCRIPTION, SCHEDULE;\r\n\r\n        companion object {\r\n            fun parse(value: String): Sort {\r\n                return when (value) {\r\n                    CODE.toString() -> CODE\r\n                    DESCRIPTION.toString() -> DESCRIPTION\r\n                    SCHEDULE.toString() -> SCHEDULE\r\n                    else -> CODE\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    enum class Constraint {\r\n        ALL, TODAY, TOMORROW;\r\n\r\n        companion object {\r\n            fun parse(value: String): Constraint {\r\n                return when (value) {\r\n                    ALL.toString() -> ALL\r\n                    TODAY.toString() -> TODAY\r\n                    TOMORROW.toString() -> TOMORROW\r\n                    else -> TODAY\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/subject/archived/ArchivedSubjectAdapter.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.subject.archived\n\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutItemArchivedSubjectBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\nimport com.isaiahvonrundstedt.fokus.features.subject.SubjectPackage\n\nclass ArchivedSubjectAdapter(private val listener: SelectListener) :\n    BaseAdapter<SubjectPackage, ArchivedSubjectAdapter.ArchivedSubjectViewHolder>(SubjectPackage.DIFF_CALLBACK) {\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArchivedSubjectViewHolder {\n        val binding = LayoutItemArchivedSubjectBinding.inflate(\n            LayoutInflater.from(parent.context),\n            parent, false\n        )\n        return ArchivedSubjectViewHolder(binding.root, listener)\n    }\n\n    override fun onBindViewHolder(holder: ArchivedSubjectViewHolder, position: Int) {\n        holder.onBind(getItem(position))\n    }\n\n    class ArchivedSubjectViewHolder(\n        itemView: View,\n        private val listener: SelectListener\n    ) : BaseViewHolder(itemView) {\n        private val binding = LayoutItemArchivedSubjectBinding.bind(itemView)\n\n        override fun <T> onBind(data: T) {\n            if (data is SubjectPackage) {\n                with(data.subject) {\n                    binding.root.transitionName = subjectID\n                    binding.tagView.setImageDrawable(tintDrawable(binding.tagView.drawable))\n                    binding.titleView.text = code\n                    binding.summaryView.text = description\n                }\n\n                binding.root.setOnClickListener {\n                    listener.onItemSelected(data)\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/subject/archived/ArchivedSubjectFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.subject.archived\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.view.isVisible\nimport androidx.fragment.app.viewModels\nimport androidx.navigation.NavController\nimport androidx.navigation.Navigation\nimport androidx.recyclerview.widget.LinearLayoutManager\nimport com.afollestad.materialdialogs.MaterialDialog\nimport com.afollestad.materialdialogs.lifecycle.lifecycleOwner\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.custom.ItemDecoration\nimport com.isaiahvonrundstedt.fokus.databinding.FragmentArchivedSubjectBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseFragment\nimport com.isaiahvonrundstedt.fokus.features.subject.SubjectPackage\nimport dagger.hilt.android.AndroidEntryPoint\n\n@AndroidEntryPoint\nclass ArchivedSubjectFragment : BaseFragment(), BaseAdapter.SelectListener {\n    private var _binding: FragmentArchivedSubjectBinding? = null\n    private var controller: NavController? = null\n\n    private val archivedSubjectAdapter = ArchivedSubjectAdapter(this)\n    private val viewModel: ArchivedSubjectViewModel by viewModels()\n    private val binding get() = _binding!!\n\n    override fun onCreateView(\n        inflater: LayoutInflater, container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        _binding = FragmentArchivedSubjectBinding.inflate(layoutInflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        setInsets(binding.root, binding.appBarLayout.toolbar,\n            arrayOf(binding.recyclerView, binding.emptyView))\n        controller = Navigation.findNavController(view)\n\n        with(binding.appBarLayout.toolbar) {\n            setTitle(R.string.activity_archives)\n            setNavigationIcon(R.drawable.ic_outline_arrow_back_24)\n            setNavigationOnClickListener { controller?.navigateUp() }\n        }\n\n        with(binding.recyclerView) {\n            addItemDecoration(ItemDecoration(context))\n            layoutManager = LinearLayoutManager(context)\n            adapter = archivedSubjectAdapter\n        }\n    }\n\n    override fun <T> onItemSelected(t: T) {\n        if (t is SubjectPackage) {\n            MaterialDialog(requireContext()).show {\n                lifecycleOwner(viewLifecycleOwner)\n                title(R.string.dialog_confirm_unarchive_title)\n                message(R.string.dialog_confirm_unarchive_summary)\n                positiveButton {\n                    viewModel.removeFromArchive(t)\n                }\n                negativeButton(R.string.button_cancel)\n            }\n        }\n    }\n\n    override fun onStart() {\n        super.onStart()\n\n        viewModel.items.observe(viewLifecycleOwner) {\n            archivedSubjectAdapter.submitList(it)\n        }\n        viewModel.isEmpty.observe(viewLifecycleOwner) {\n            binding.emptyView.isVisible = it\n        }\n    }\n\n    override fun onDestroy() {\n        super.onDestroy()\n        _binding = null\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/subject/archived/ArchivedSubjectViewModel.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.subject.archived\n\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.Transformations\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.viewModelScope\nimport com.isaiahvonrundstedt.fokus.database.repository.SubjectRepository\nimport com.isaiahvonrundstedt.fokus.features.subject.SubjectPackage\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport kotlinx.coroutines.launch\nimport javax.inject.Inject\n\n@HiltViewModel\nclass ArchivedSubjectViewModel @Inject constructor(\n    private val subjectRepository: SubjectRepository\n) : ViewModel() {\n\n    val items: LiveData<List<SubjectPackage>> = subjectRepository.fetchArchivedLiveData()\n    val isEmpty: LiveData<Boolean> = Transformations.map(items) { it.isEmpty() }\n\n    fun removeFromArchive(subjectPackage: SubjectPackage) = viewModelScope.launch {\n        subjectPackage.subject.isSubjectArchived = false\n        subjectRepository.update(subjectPackage.subject)\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/subject/editor/SubjectEditorContainer.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.subject.editor\n\nimport android.os.Bundle\nimport com.isaiahvonrundstedt.fokus.databinding.ActivityContainerSubjectBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseActivity\nimport dagger.hilt.android.AndroidEntryPoint\n\n/**\n * This activity acts as a container\n * for the editor fragment. This is\n * used when needing to show the\n * editor ui without needing a fragment\n * transaction.\n */\n@AndroidEntryPoint\nclass SubjectEditorContainer : BaseActivity() {\n    private lateinit var binding: ActivityContainerSubjectBinding\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        binding = ActivityContainerSubjectBinding.inflate(layoutInflater)\n        setContentView(binding.root)\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/subject/editor/SubjectEditorFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.subject.editor\n\nimport android.app.Activity\nimport android.content.BroadcastReceiver\nimport android.content.Context\nimport android.content.Intent\nimport android.content.IntentFilter\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.MenuItem\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.TextView\nimport androidx.activity.result.ActivityResultLauncher\nimport androidx.activity.result.contract.ActivityResultContracts\nimport androidx.core.app.ShareCompat\nimport androidx.core.os.bundleOf\nimport androidx.core.view.children\nimport androidx.core.widget.doAfterTextChanged\nimport androidx.fragment.app.FragmentResultListener\nimport androidx.fragment.app.viewModels\nimport androidx.localbroadcastmanager.content.LocalBroadcastManager\nimport androidx.navigation.NavController\nimport androidx.navigation.Navigation\nimport com.afollestad.materialdialogs.MaterialDialog\nimport com.afollestad.materialdialogs.color.colorChooser\nimport com.afollestad.materialdialogs.lifecycle.lifecycleOwner\nimport com.google.android.material.chip.Chip\nimport com.google.android.material.snackbar.Snackbar\nimport com.google.android.material.textfield.TextInputEditText\nimport com.isaiahvonrundstedt.fokus.Fokus\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.createSnackbar\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.getCompoundDrawableAtStart\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.setCompoundDrawableAtStart\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.setTextColorFromResource\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Streamable\nimport com.isaiahvonrundstedt.fokus.components.service.DataExporterService\nimport com.isaiahvonrundstedt.fokus.components.service.DataImporterService\nimport com.isaiahvonrundstedt.fokus.databinding.FragmentEditorSubjectBinding\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\nimport com.isaiahvonrundstedt.fokus.features.schedule.ScheduleEditor\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseEditorFragment\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseService\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\nimport com.isaiahvonrundstedt.fokus.features.subject.SubjectPackage\nimport dagger.hilt.android.AndroidEntryPoint\nimport me.saket.cascade.overrideOverflowMenu\nimport java.io.File\n\n@AndroidEntryPoint\nclass SubjectEditorFragment : BaseEditorFragment(),  FragmentResultListener {\n    private var _binding: FragmentEditorSubjectBinding? = null\n    private var controller: NavController? = null\n    private var requestKey = REQUEST_KEY_INSERT\n\n    private val viewModel: SubjectEditorViewModel by viewModels()\n    private val binding get() = _binding!!\n\n    private lateinit var importLauncher: ActivityResultLauncher<Intent>\n    private lateinit var exportLauncher: ActivityResultLauncher<Intent>\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        sharedElementEnterTransition = buildContainerTransform()\n        sharedElementReturnTransition = buildContainerTransform()\n\n        importLauncher =\n            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {\n                if (it.resultCode == Activity.RESULT_OK) {\n                    context?.startService(Intent(context, DataImporterService::class.java).apply {\n                        this.data = it.data?.data\n                        action = DataImporterService.ACTION_IMPORT_SUBJECT\n                    })\n                }\n            }\n\n        exportLauncher =\n            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {\n                if (it.resultCode == Activity.RESULT_OK) {\n                    context?.startService(Intent(context, DataExporterService::class.java).apply {\n                        this.data = it.data?.data\n                        action = DataExporterService.ACTION_EXPORT_SUBJECT\n                        putExtra(DataExporterService.EXTRA_EXPORT_SOURCE, viewModel.getSubject())\n                        putExtra(\n                            DataExporterService.EXTRA_EXPORT_DEPENDENTS,\n                            viewModel.getSchedules()\n                        )\n                    })\n                }\n            }\n    }\n\n    override fun onCreateView(\n        inflater: LayoutInflater, container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        _binding = FragmentEditorSubjectBinding.inflate(inflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        binding.root.transitionName = TRANSITION_ELEMENT_ROOT\n        setInsets(binding.root, binding.appBarLayout.toolbar, arrayOf(binding.contentView),\n            binding.actionButton)\n        controller = Navigation.findNavController(view)\n\n        with(binding.appBarLayout.toolbar) {\n            inflateMenu(R.menu.menu_editor)\n            setNavigationOnClickListener {\n                if (controller?.graph?.id == R.id.navigation_container_subject)\n                    requireActivity().finish()\n                else controller?.navigateUp()\n            }\n\n            overrideOverflowMenu(::customPopupProvider)\n            setOnMenuItemClickListener(::onMenuItemClicked)\n        }\n\n        arguments?.getBundle(EXTRA_SUBJECT)?.also {\n            requestKey = REQUEST_KEY_UPDATE\n\n            Subject.fromBundle(it)?.also { subject ->\n                viewModel.setSubject(subject)\n                binding.root.transitionName = TRANSITION_ELEMENT_ROOT + subject.subjectID\n            }\n        }\n        arguments?.getParcelableArrayList<Schedule>(EXTRA_SCHEDULE)?.also {\n            viewModel.setSchedules(it)\n        }\n\n        registerForFragmentResult(\n            arrayOf(\n                ScheduleEditor.REQUEST_KEY_INSERT,\n                ScheduleEditor.REQUEST_KEY_UPDATE\n            ), this\n        )\n    }\n\n    override fun onStart() {\n        super.onStart()\n\n        LocalBroadcastManager.getInstance(requireContext())\n            .registerReceiver(receiver, IntentFilter(BaseService.ACTION_SERVICE_BROADCAST))\n\n        if (requestKey == REQUEST_KEY_UPDATE) {\n            binding.codeTextInput.setText(viewModel.getCode())\n            binding.descriptionTextInput.setText(viewModel.getDescription())\n            binding.instructorTextInput.setText(viewModel.getInstructor())\n        }\n\n        viewModel.subject.observe(this) {\n            if (requestKey == REQUEST_KEY_UPDATE && it != null) {\n                with(it) {\n                    binding.codeTextInput.setText(code)\n                    binding.descriptionTextInput.setText(description)\n                    binding.instructorTextInput.setText(instructor)\n                    binding.tagView.setCompoundDrawableAtStart(binding.tagView.getCompoundDrawableAtStart()\n                        ?.let { drawable -> tintDrawable(drawable) })\n                    binding.tagView.setText(tag.getNameResource())\n                }\n\n                binding.tagView.setTextColorFromResource(R.color.color_primary_text)\n            }\n        }\n\n        viewModel.schedules.observe(this) {\n            binding.schedulesChipGroup.removeAllViews()\n            it.forEach { schedule ->\n                binding.schedulesChipGroup.addView(Chip(requireContext()).apply {\n                    text = schedule.formatDaysOfWeek(requireContext(), true)\n                    tag = schedule.scheduleID\n                    isCloseIconVisible = true\n                    setCloseIconResource(R.drawable.ic_outline_close_24)\n                    setOnClickListener {\n                        ScheduleEditor(childFragmentManager).show {\n                            arguments = bundleOf(\n                                ScheduleEditor.EXTRA_SUBJECT_ID to viewModel.getID(),\n                                ScheduleEditor.EXTRA_SCHEDULE to schedule\n                            )\n                        }\n                    }\n                    setOnCloseIconClickListener {\n                        viewModel.removeSchedule(schedule)\n                        createSnackbar(R.string.feedback_schedule_removed, binding.root).run {\n                            setAction(R.string.button_undo) { viewModel.addSchedule(schedule) }\n                        }\n                    }\n                })\n            }\n        }\n\n        viewModel.isCodeExists.observe(this) {\n            binding.codeTextInputLayout.error =\n                if (it) getString(R.string.feedback_subject_code_exists)\n                else null\n        }\n\n        binding.codeTextInput.doAfterTextChanged {\n            viewModel.checkCodeUniqueness(it.toString())\n        }\n\n        binding.codeTextInput.setOnFocusChangeListener { v, hasFocus ->\n            if (!hasFocus && v is TextInputEditText) {\n                viewModel.setCode(v.text.toString())\n            }\n        }\n\n        binding.descriptionTextInput.setOnFocusChangeListener { v, hasFocus ->\n            if (!hasFocus && v is TextInputEditText) {\n                viewModel.setDescription(v.text.toString())\n            }\n        }\n\n        binding.instructorTextInput.setOnFocusChangeListener { v, hasFocus ->\n            if (!hasFocus && v is TextInputEditText) {\n                viewModel.setInstructor(v.text.toString())\n            }\n        }\n\n        binding.addActionChip.setOnClickListener {\n            hideKeyboardFromCurrentFocus(requireView())\n\n            ScheduleEditor(childFragmentManager).show {\n                arguments = bundleOf(\n                    ScheduleEditor.EXTRA_SUBJECT_ID to viewModel.getID()\n                )\n            }\n        }\n\n        binding.tagView.setOnClickListener {\n            MaterialDialog(requireContext()).show {\n                lifecycleOwner(this@SubjectEditorFragment)\n                title(R.string.dialog_pick_color_tag)\n                colorChooser(Subject.Tag.getColors(), waitForPositiveButton = false) { _, color ->\n                    viewModel.setTag(Subject.Tag.convertColorToTag(color) ?: Subject.Tag.SKY)\n\n                    with(it as TextView) {\n                        text = getString(viewModel.getTag()!!.getNameResource())\n                        setTextColorFromResource(R.color.color_primary_text)\n                        setCompoundDrawableAtStart(\n                            viewModel.getSubject()?.tintDrawable(getCompoundDrawableAtStart())\n                        )\n                    }\n                    this.dismiss()\n                }\n            }\n        }\n\n        binding.actionButton.setOnClickListener {\n            viewModel.setCode(binding.codeTextInput.text.toString())\n            viewModel.setDescription(binding.descriptionTextInput.text.toString())\n            viewModel.setInstructor(binding.instructorTextInput.text.toString())\n\n            if (viewModel.getCode()?.isEmpty() == true) {\n                createSnackbar(R.string.feedback_subject_empty_name, binding.root)\n                binding.codeTextInput.requestFocus()\n                return@setOnClickListener\n            }\n\n            if (viewModel.getDescription()?.isEmpty() == true) {\n                createSnackbar(R.string.feedback_subject_empty_description, binding.root)\n                binding.descriptionTextInput.requestFocus()\n                return@setOnClickListener\n            }\n\n            if (viewModel.getSchedules().size < 1) {\n                createSnackbar(R.string.feedback_subject_no_schedule, binding.root).show()\n                return@setOnClickListener\n            }\n\n\n            if (requestKey == REQUEST_KEY_INSERT)\n                viewModel.insert()\n            else viewModel.update()\n\n            if (controller?.graph?.id == R.id.navigation_container_subject)\n                requireActivity().finish()\n            else controller?.navigateUp()\n        }\n    }\n\n    override fun onStop() {\n        super.onStop()\n\n        /**\n         * Check if the soft keyboard is visible\n         * then hide it before the user leaves\n         * the fragment\n         */\n        hideKeyboardFromCurrentFocus(requireView())\n    }\n\n    override fun onFragmentResult(requestKey: String, result: Bundle) {\n        when (requestKey) {\n            ScheduleEditor.REQUEST_KEY_INSERT -> {\n                result.getParcelable<Schedule>(ScheduleEditor.EXTRA_SCHEDULE)?.also {\n                    viewModel.addSchedule(it)\n                }\n            }\n            ScheduleEditor.REQUEST_KEY_UPDATE -> {\n                result.getParcelable<Schedule>(ScheduleEditor.EXTRA_SCHEDULE)?.also {\n                    viewModel.updateSchedule(it)\n                }\n            }\n        }\n    }\n\n    private fun onMenuItemClicked(item: MenuItem): Boolean {\n        when (item.itemId) {\n            R.id.action_export -> {\n                val fileName = getSharingName()\n                if (fileName == null) {\n                    MaterialDialog(requireContext()).show {\n                        lifecycleOwner(viewLifecycleOwner)\n                        title(R.string.feedback_unable_to_share_title)\n                        message(R.string.feedback_unable_to_share_message)\n                        positiveButton(R.string.button_done) { dismiss() }\n                    }\n                    return false\n                }\n\n                /**\n                 * Make the user specify where to save\n                 * the exported file\n                 */\n                exportLauncher.launch(Intent(Intent.ACTION_CREATE_DOCUMENT).apply {\n                    addCategory(Intent.CATEGORY_OPENABLE)\n                    putExtra(Intent.EXTRA_TITLE, fileName)\n                    type = Streamable.MIME_TYPE_ZIP\n                })\n            }\n            R.id.action_share -> {\n                val fileName = getSharingName()\n                if (fileName == null) {\n                    MaterialDialog(requireContext()).show {\n                        lifecycleOwner(viewLifecycleOwner)\n                        title(R.string.feedback_unable_to_share_title)\n                        message(R.string.feedback_unable_to_share_message)\n                        positiveButton(R.string.button_done) { dismiss() }\n                    }\n                    return false\n                }\n\n                /**\n                 * We need first to export the data as a raw file\n                 * then pass it onto the system sharing component\n                 */\n                context?.startService(Intent(context, DataExporterService::class.java).apply {\n                    action = DataExporterService.ACTION_EXPORT_SUBJECT\n                    putExtra(\n                        DataExporterService.EXTRA_EXPORT_SOURCE,\n                        viewModel.getSubject()\n                    )\n                    putExtra(\n                        DataExporterService.EXTRA_EXPORT_DEPENDENTS,\n                        viewModel.getSchedules()\n                    )\n                })\n            }\n            R.id.action_import -> {\n                val chooser = Intent.createChooser(Intent(Intent.ACTION_OPEN_DOCUMENT).apply {\n                    type = Streamable.MIME_TYPE_ZIP\n                }, getString(R.string.dialog_select_file_import))\n\n                importLauncher.launch(chooser)\n            }\n        }\n        return true\n    }\n\n    override fun onDestroy() {\n        super.onDestroy()\n\n        _binding = null\n        LocalBroadcastManager.getInstance(requireContext())\n            .unregisterReceiver(receiver)\n    }\n\n    private var receiver = object : BroadcastReceiver() {\n        override fun onReceive(context: Context?, intent: Intent?) {\n            if (intent?.action == BaseService.ACTION_SERVICE_BROADCAST) {\n                when (intent.getStringExtra(BaseService.EXTRA_BROADCAST_STATUS)) {\n                    DataExporterService.BROADCAST_EXPORT_ONGOING -> {\n                        createSnackbar(\n                            R.string.feedback_export_ongoing, binding.root,\n                            Snackbar.LENGTH_INDEFINITE\n                        )\n                    }\n                    DataExporterService.BROADCAST_EXPORT_COMPLETED -> {\n                        createSnackbar(R.string.feedback_export_completed, binding.root)\n\n                        intent.getStringExtra(BaseService.EXTRA_BROADCAST_DATA)?.also {\n                            val uri = Fokus.obtainUriForFile(requireContext(), File(it))\n\n                            startActivity(\n                                ShareCompat.IntentBuilder.from(requireActivity())\n                                    .addStream(uri)\n                                    .setType(Streamable.MIME_TYPE_ZIP)\n                                    .setChooserTitle(R.string.dialog_send_to)\n                                    .intent\n                            )\n                        }\n                    }\n                    DataExporterService.BROADCAST_EXPORT_FAILED -> {\n                        createSnackbar(R.string.feedback_export_failed, binding.root)\n                    }\n                    DataImporterService.BROADCAST_IMPORT_ONGOING -> {\n                        createSnackbar(R.string.feedback_import_ongoing, binding.root)\n                    }\n                    DataImporterService.BROADCAST_IMPORT_COMPLETED -> {\n                        createSnackbar(R.string.feedback_import_completed, binding.root)\n\n                        intent.getParcelableExtra<SubjectPackage>(BaseService.EXTRA_BROADCAST_DATA)\n                            ?.also {\n                                viewModel.setSubject(it.subject)\n                                viewModel.setSchedules(ArrayList(it.schedules))\n                            }\n                    }\n                    DataImporterService.BROADCAST_IMPORT_FAILED -> {\n                        createSnackbar(R.string.feedback_import_failed, binding.root)\n                    }\n                }\n            }\n        }\n    }\n\n    private fun getSharingName(): String? {\n        return when (requestKey) {\n            REQUEST_KEY_INSERT -> {\n                if (binding.codeTextInput.text.isNullOrEmpty() ||\n                    binding.descriptionTextInput.text.isNullOrEmpty()\n                    || binding.schedulesChipGroup.children.none()\n                ) {\n                    MaterialDialog(requireContext()).show {\n                        title(R.string.feedback_unable_to_share_title)\n                        message(R.string.feedback_unable_to_share_message)\n                        positiveButton(R.string.button_dismiss) { dismiss() }\n                    }\n                    return null\n                }\n                binding.codeTextInput.text.toString()\n            }\n            REQUEST_KEY_UPDATE -> {\n                viewModel.getCode() ?: Streamable.ARCHIVE_NAME_GENERIC\n            }\n            else -> null\n        }\n    }\n\n    override fun onSaveInstanceState(outState: Bundle) {\n        with(outState) {\n            putParcelable(EXTRA_SUBJECT, viewModel.getSubject())\n            putParcelableArrayList(EXTRA_SCHEDULE, viewModel.getSchedules())\n        }\n        super.onSaveInstanceState(outState)\n    }\n\n    override fun onViewStateRestored(savedInstanceState: Bundle?) {\n        super.onViewStateRestored(savedInstanceState)\n        savedInstanceState?.run {\n            viewModel.setSubject(getParcelable(EXTRA_SUBJECT))\n            viewModel.setSchedules(getParcelableArrayList(EXTRA_SCHEDULE) ?: arrayListOf())\n        }\n    }\n\n    companion object {\n        const val REQUEST_KEY_INSERT = \"request:insert\"\n        const val REQUEST_KEY_UPDATE = \"request:update\"\n\n        const val EXTRA_SUBJECT = \"extra:subject\"\n        const val EXTRA_SCHEDULE = \"extra:schedule\"\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/subject/editor/SubjectEditorViewModel.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.subject.editor\n\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.viewModelScope\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.getIndexByID\nimport com.isaiahvonrundstedt.fokus.database.repository.SubjectRepository\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.NonCancellable\nimport kotlinx.coroutines.launch\nimport javax.inject.Inject\n\n@HiltViewModel\nclass SubjectEditorViewModel @Inject constructor(\n    private val repository: SubjectRepository\n) : ViewModel() {\n\n    private val _subject: MutableLiveData<Subject> = MutableLiveData(Subject())\n    private val _schedules: MutableLiveData<ArrayList<Schedule>> = MutableLiveData(arrayListOf())\n    private val _isCodeExists: MutableLiveData<Boolean> = MutableLiveData(false)\n\n    val subject: LiveData<Subject> = _subject\n    val schedules: LiveData<ArrayList<Schedule>> = _schedules\n    val isCodeExists: LiveData<Boolean> = _isCodeExists\n\n    fun getSubject(): Subject? {\n        return subject.value\n    }\n\n    fun setSubject(data: Subject?) {\n        _subject.value = data\n    }\n\n    fun getSchedules(): ArrayList<Schedule> {\n        return schedules.value ?: arrayListOf()\n    }\n\n    fun setSchedules(items: ArrayList<Schedule>) {\n        _schedules.value = items\n    }\n\n    fun addSchedule(schedule: Schedule) {\n        val items = ArrayList(getSchedules())\n        items.add(schedule)\n        setSchedules(items)\n    }\n\n    fun removeSchedule(schedule: Schedule) {\n        val items = ArrayList(getSchedules())\n        items.remove(schedule)\n        setSchedules(items)\n    }\n\n    fun updateSchedule(schedule: Schedule) {\n        val items = ArrayList(getSchedules())\n        val index: Int = items.getIndexByID(schedule.scheduleID)\n\n        if (index != -1) {\n            items[index] = schedule\n            setSchedules(items)\n        }\n    }\n\n    fun checkCodeUniqueness(code: String?) = viewModelScope.launch {\n        val result = repository.checkCodeExists(code, getSubject()?.subjectID)\n        _isCodeExists.value = !result.contains(getID()) && result.isNotEmpty()\n    }\n\n    fun getID(): String? {\n        return getSubject()?.subjectID\n    }\n\n    fun getCode(): String? {\n        return getSubject()?.code\n    }\n\n    fun setCode(code: String) {\n        if (code == getCode())\n            return\n\n        val subject = getSubject()\n        subject?.code = code\n        setSubject(subject)\n\n    }\n\n    fun getDescription(): String? {\n        return getSubject()?.description\n    }\n\n    fun setDescription(description: String) {\n        if (description == getDescription())\n            return\n\n        val subject = getSubject()\n        subject?.description = description\n        setSubject(subject)\n    }\n\n    fun getInstructor(): String? {\n        return getSubject()?.instructor\n    }\n    fun setInstructor(instructor: String?) {\n        if (instructor == getInstructor())\n            return\n\n        val subject = getSubject()\n        subject?.instructor = instructor\n        android.util.Log.e(\"DEBUG\", instructor ?: \"null\")\n        setSubject(subject)\n    }\n\n    fun getTag(): Subject.Tag? {\n        return getSubject()?.tag\n    }\n\n    fun setTag(tag: Subject.Tag) {\n        val subject = getSubject()\n        subject?.tag = tag\n        setSubject(subject)\n    }\n\n    fun insert() = viewModelScope.launch(Dispatchers.IO + NonCancellable) {\n        getSubject()?.let {\n            repository.insert(it, getSchedules())\n        }\n    }\n\n    fun update() = viewModelScope.launch(Dispatchers.IO + NonCancellable) {\n        getSubject()?.let {\n            repository.update(it, getSchedules())\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/subject/picker/SubjectPickerAdapter.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.subject.picker\n\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Swipeable\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutItemSubjectPickerBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\nimport com.isaiahvonrundstedt.fokus.features.subject.SubjectPackage\n\nclass SubjectPickerAdapter(private val actionListener: ActionListener) :\n    BaseAdapter<SubjectPackage, SubjectPickerAdapter.ViewHolder>(SubjectPackage.DIFF_CALLBACK),\n    Swipeable {\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {\n        val binding = LayoutItemSubjectPickerBinding.inflate(\n            LayoutInflater.from(parent.context),\n            parent, false\n        )\n        return ViewHolder(binding.root)\n    }\n\n    override fun onBindViewHolder(holder: ViewHolder, position: Int) {\n        holder.onBind(getItem(position))\n    }\n\n    override fun onSwipe(position: Int, direction: Int) {\n        actionListener.onActionPerformed(getItem(position), ActionListener.Action.DELETE, null)\n    }\n\n    inner class ViewHolder(itemView: View) : BaseViewHolder(itemView) {\n\n        private val binding = LayoutItemSubjectPickerBinding.bind(itemView)\n\n        override fun <T> onBind(t: T) {\n            if (t is SubjectPackage) {\n                with(t.subject) {\n                    binding.root.transitionName = subjectID\n                    binding.tagView.setImageDrawable(tintDrawable(binding.tagView.drawable))\n                    binding.titleView.text = code\n                    binding.summaryView.text = description\n                }\n\n                binding.root.setOnClickListener {\n                    actionListener.onActionPerformed(t, ActionListener.Action.SELECT, null)\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/subject/picker/SubjectPickerFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.subject.picker\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.os.bundleOf\nimport androidx.core.view.isVisible\nimport androidx.fragment.app.FragmentManager\nimport androidx.fragment.app.setFragmentResult\nimport androidx.fragment.app.viewModels\nimport androidx.recyclerview.widget.ItemTouchHelper\nimport androidx.recyclerview.widget.LinearLayoutManager\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.custom.ItemDecoration\nimport com.isaiahvonrundstedt.fokus.components.custom.ItemSwipeCallback\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.createSnackbar\nimport com.isaiahvonrundstedt.fokus.databinding.FragmentPickerSubjectBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BasePickerFragment\nimport com.isaiahvonrundstedt.fokus.features.subject.SubjectPackage\nimport dagger.hilt.android.AndroidEntryPoint\n\n@AndroidEntryPoint\nclass SubjectPickerFragment(fragmentManager: FragmentManager): BasePickerFragment(fragmentManager),\n    BaseAdapter.ActionListener {\n    private var _binding: FragmentPickerSubjectBinding? = null\n\n    private val binding get() = _binding!!\n    private val pickerAdapter = SubjectPickerAdapter(this)\n    private val viewModel: SubjectPickerViewModel by viewModels()\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        _binding = FragmentPickerSubjectBinding.inflate(inflater, container, false)\n        return binding.root\n    }\n\n    override fun onDestroy() {\n        _binding = null\n        super.onDestroy()\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        setupToolbar(binding.appBarLayout.toolbar, R.string.dialog_assign_subject, onNavigate = { dismiss() })\n\n        with(binding.recyclerView) {\n            addItemDecoration(ItemDecoration(context))\n            layoutManager = LinearLayoutManager(context)\n            adapter = pickerAdapter\n\n            ItemTouchHelper(ItemSwipeCallback(context, pickerAdapter))\n                .attachToRecyclerView(binding.recyclerView)\n        }\n    }\n\n    override fun onStart() {\n        super.onStart()\n\n        viewModel.subjects.observe(this) { pickerAdapter.submitList(it) }\n        viewModel.isEmpty.observe(this) { binding.emptyView.isVisible = it }\n    }\n\n    override fun <T> onActionPerformed(\n        t: T, action: BaseAdapter.ActionListener.Action,\n        container: View?\n    ) {\n        if (t is SubjectPackage) {\n            when (action) {\n                BaseAdapter.ActionListener.Action.SELECT -> {\n                    setFragmentResult(REQUEST_KEY_PICK,\n                        bundleOf(EXTRA_SELECTED_SUBJECT to t))\n                    dismiss()\n                }\n                BaseAdapter.ActionListener.Action.DELETE -> {\n                    viewModel.remove(t.subject)\n\n                    createSnackbar(R.string.feedback_subject_removed).run {\n                        setAction(R.string.button_undo) {\n                            viewModel.insert(t.subject, t.schedules)\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    companion object {\n        const val REQUEST_KEY_PICK = \"request:pick:subject\"\n        const val EXTRA_SELECTED_SUBJECT = \"extra:subject\"\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/subject/picker/SubjectPickerViewModel.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.subject.picker\n\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.Transformations\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.viewModelScope\nimport com.isaiahvonrundstedt.fokus.database.repository.SubjectRepository\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\nimport com.isaiahvonrundstedt.fokus.features.subject.SubjectPackage\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport kotlinx.coroutines.launch\nimport javax.inject.Inject\n\n@HiltViewModel\nclass SubjectPickerViewModel @Inject constructor(\n    private val repository: SubjectRepository,\n) : ViewModel() {\n\n    val subjects: LiveData<List<SubjectPackage>> = repository.fetchLiveData()\n    val isEmpty: LiveData<Boolean> = Transformations.map(subjects) { it.isEmpty() }\n\n    fun insert(subject: Subject, scheduleList: List<Schedule>) = viewModelScope.launch {\n        repository.insert(subject, scheduleList)\n    }\n\n    fun remove(subject: Subject) = viewModelScope.launch {\n        repository.remove(subject)\n    }\n\n    fun update(subject: Subject, scheduleList: List<Schedule>) = viewModelScope.launch {\n        repository.update(subject, scheduleList)\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/subject/widget/SubjectWidgetProvider.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.subject.widget\n\nimport android.app.PendingIntent\nimport android.appwidget.AppWidgetManager\nimport android.appwidget.AppWidgetProvider\nimport android.content.ComponentName\nimport android.content.Context\nimport android.content.Intent\nimport android.widget.RemoteViews\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.features.core.activities.MainActivity\nimport com.isaiahvonrundstedt.fokus.features.subject.editor.SubjectEditorContainer\n\nclass SubjectWidgetProvider : AppWidgetProvider() {\n\n    override fun onReceive(context: Context?, intent: Intent?) {\n        super.onReceive(context, intent)\n\n        if (intent?.action == WIDGET_ACTION_UPDATE) {\n            val manager = AppWidgetManager.getInstance(context)\n            val component = ComponentName(context!!, SubjectWidgetProvider::class.java)\n\n            manager.notifyAppWidgetViewDataChanged(\n                manager.getAppWidgetIds(component),\n                R.id.listView\n            )\n        }\n    }\n\n    override fun onUpdate(\n        context: Context?, appWidgetManager: AppWidgetManager?,\n        appWidgetIds: IntArray?\n    ) {\n        super.onUpdate(context, appWidgetManager, appWidgetIds)\n        appWidgetIds?.forEach {\n            onUpdateWidget(context, appWidgetManager, it)\n        }\n    }\n\n    private fun onUpdateWidget(context: Context?, manager: AppWidgetManager?, id: Int) {\n        val mainIntent = PendingIntent.getActivity(\n            context, 0,\n            Intent(context, MainActivity::class.java).apply {\n                action = MainActivity.ACTION_NAVIGATION_SUBJECT\n            }, PendingIntent.FLAG_IMMUTABLE\n        )\n\n        val itemIntent = PendingIntent.getActivity(\n            context, 0,\n            Intent(context, MainActivity::class.java).apply {\n                action = MainActivity.ACTION_WIDGET_SUBJECT\n            }, PendingIntent.FLAG_IMMUTABLE\n        )\n\n        val addIntent = PendingIntent.getActivity(\n            context, 0,\n            Intent(context, SubjectEditorContainer::class.java), PendingIntent.FLAG_IMMUTABLE\n        )\n\n        val views = RemoteViews(context?.packageName, R.layout.layout_widget_subjects)\n        with(views) {\n            setOnClickPendingIntent(R.id.rootView, mainIntent)\n            setOnClickPendingIntent(R.id.actionButton, addIntent)\n            setRemoteAdapter(R.id.listView, Intent(context, SubjectWidgetService::class.java))\n            setPendingIntentTemplate(R.id.listView, itemIntent)\n            setEmptyView(R.id.listView, R.id.emptyView)\n        }\n\n        manager?.notifyAppWidgetViewDataChanged(id, R.id.listView)\n        manager?.updateAppWidget(id, views)\n    }\n\n    companion object {\n        private const val WIDGET_ACTION_UPDATE = \"widget:event:update\"\n\n        fun triggerRefresh(context: Context?) {\n            context?.sendBroadcast(Intent(WIDGET_ACTION_UPDATE).apply {\n                component = ComponentName(context, SubjectWidgetProvider::class.java)\n            })\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/subject/widget/SubjectWidgetRemoteViewFactory.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.subject.widget\n\nimport android.content.Context\nimport android.content.Intent\nimport android.widget.RemoteViews\nimport android.widget.RemoteViewsService\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.database.AppDatabase\nimport com.isaiahvonrundstedt.fokus.features.core.activities.MainActivity\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\nimport com.isaiahvonrundstedt.fokus.features.subject.SubjectPackage\nimport kotlinx.coroutines.async\nimport kotlinx.coroutines.runBlocking\n\nclass SubjectWidgetRemoteViewFactory(private var context: Context) :\n    RemoteViewsService.RemoteViewsFactory {\n\n    private var itemList = mutableListOf<SubjectPackage>()\n\n    private fun fetch() {\n        itemList.clear()\n\n        val subjects = AppDatabase.getInstance(context)?.subjects()\n        var items = emptyList<SubjectPackage>()\n        runBlocking {\n            val job = async { subjects?.fetchAsPackage() }\n            items = job.await() ?: emptyList()\n            items.forEach { resource ->\n                resource.schedules.forEach {\n                    if (it.isToday()) itemList.add(resource)\n                }\n            }\n        }\n    }\n\n    override fun onDataSetChanged() = fetch()\n\n    override fun getLoadingView(): RemoteViews =\n        RemoteViews(context.packageName, R.layout.layout_widget_progress)\n\n    override fun getItemId(position: Int): Long = position.toLong()\n\n    override fun hasStableIds(): Boolean = true\n\n    override fun getViewAt(position: Int): RemoteViews {\n        val subject = itemList[position].subject\n        val schedules = itemList[position].schedules\n        val schedule: Schedule? = schedules.run {\n            forEach {\n                if (it.isToday())\n                    return@run it\n            }\n            return@run null\n        }\n\n        val itemIntent = Intent().apply {\n            putExtra(MainActivity.EXTRA_SUBJECT, subject)\n            putExtra(MainActivity.EXTRA_SCHEDULES, schedule)\n        }\n\n        val views = RemoteViews(context.packageName, R.layout.layout_item_widget)\n        with(views) {\n            setTextViewText(R.id.titleView, subject.code)\n            setTextViewText(R.id.summaryView, schedule?.formatBothTime(context))\n            setOnClickFillInIntent(R.id.listView, itemIntent)\n            setInt(R.id.imageView, \"setColorFilter\", subject.tag.color)\n        }\n        return views\n    }\n\n    override fun getCount(): Int = itemList.size\n\n    override fun getViewTypeCount(): Int = 1\n\n    override fun onCreate() {}\n    override fun onDestroy() {}\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/subject/widget/SubjectWidgetService.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.subject.widget\n\nimport android.content.Intent\nimport android.widget.RemoteViewsService\n\nclass SubjectWidgetService : RemoteViewsService() {\n\n    override fun onGetViewFactory(intent: Intent?): RemoteViewsFactory {\n        return SubjectWidgetRemoteViewFactory(applicationContext)\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/task/Task.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.task\r\n\r\nimport android.content.Context\r\nimport android.os.Bundle\r\nimport android.os.Parcelable\r\nimport androidx.core.os.bundleOf\r\nimport androidx.room.*\r\nimport com.isaiahvonrundstedt.fokus.R\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.isAfterNow\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.isToday\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.isTomorrow\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.isYesterday\r\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Streamable\r\nimport com.isaiahvonrundstedt.fokus.components.json.JsonDataStreamer\r\nimport com.isaiahvonrundstedt.fokus.database.converter.DateTimeConverter\r\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\r\nimport com.squareup.moshi.JsonClass\r\nimport kotlinx.parcelize.Parcelize\r\nimport okio.buffer\r\nimport okio.sink\r\nimport java.io.File\r\nimport java.io.InputStream\r\nimport java.time.ZonedDateTime\r\nimport java.util.*\r\n\r\n@Parcelize\r\n@JsonClass(generateAdapter = true)\r\n@Entity(\r\n    tableName = \"tasks\", foreignKeys = [\r\n        ForeignKey(\r\n            entity = Subject::class, parentColumns = arrayOf(\"subjectID\"),\r\n            childColumns = arrayOf(\"subject\"), onDelete = ForeignKey.SET_NULL\r\n        )]\r\n)\r\ndata class Task @JvmOverloads constructor(\r\n    @PrimaryKey\r\n    @ColumnInfo(index = true)\r\n    var taskID: String = UUID.randomUUID().toString(),\r\n    var name: String? = null,\r\n    var notes: String? = null,\r\n    var subject: String? = null,\r\n    var isImportant: Boolean = false,\r\n    @TypeConverters(DateTimeConverter::class)\r\n    var dueDate: ZonedDateTime? = null,\r\n    var isFinished: Boolean = false,\r\n    var isTaskArchived: Boolean = false,\r\n    @TypeConverters(DateTimeConverter::class)\r\n    var dateAdded: ZonedDateTime? = ZonedDateTime.now(),\r\n) : Parcelable, Streamable {\r\n\r\n    fun hasDueDate(): Boolean {\r\n        return dueDate != null\r\n    }\r\n\r\n    fun isDueDateInFuture(): Boolean {\r\n        return dueDate?.isAfterNow() == true\r\n    }\r\n\r\n    fun isDueToday(): Boolean {\r\n        return dueDate?.isToday() == true\r\n    }\r\n\r\n    fun formatDueDate(context: Context): String? {\r\n        if (dueDate == null)\r\n            return \"\"\r\n\r\n        // Check if the day on the task's due is today\r\n        return if (dueDate?.isToday() == true)\r\n            String.format(\r\n                context.getString(R.string.today_at),\r\n                dueDate?.format(DateTimeConverter.getTimeFormatter(context))\r\n            )\r\n        // Now check if the day is yesterday\r\n        else if (dueDate?.isYesterday() == true)\r\n            String.format(\r\n                context.getString(R.string.yesterday_at),\r\n                dueDate?.format(DateTimeConverter.getTimeFormatter(context))\r\n            )\r\n        // Now check if its tomorrow\r\n        else if (dueDate?.isTomorrow() == true)\r\n            String.format(\r\n                context.getString(R.string.tomorrow_at),\r\n                dueDate?.format(DateTimeConverter.getTimeFormatter(context))\r\n            )\r\n        // Just print the date what could go wrong?\r\n        else dueDate?.format(DateTimeConverter.getDateTimeFormatter(context))\r\n    }\r\n\r\n    override fun toJsonString(): String? = JsonDataStreamer.encodeToJson(this, Task::class.java)\r\n\r\n    override fun toJsonFile(destination: File, name: String): File {\r\n        return File(destination, name).apply {\r\n            this.sink().buffer().use {\r\n                toJsonString()?.also { json -> it.write(json.toByteArray()) }\r\n            }\r\n        }\r\n    }\r\n\r\n    override fun fromInputStream(inputStream: InputStream) {\r\n        JsonDataStreamer.decodeOnceFromJson(inputStream, Task::class.java)?.also {\r\n            taskID = it.taskID\r\n            name = it.name\r\n            dueDate = it.dueDate\r\n            notes = it.notes\r\n            subject = it.subject\r\n            dateAdded = it.dateAdded\r\n            isImportant = it.isImportant\r\n            isFinished = it.isFinished\r\n        }\r\n    }\r\n\r\n    companion object {\r\n        const val EXTRA_ID = \"extra:id\"\r\n        const val EXTRA_NAME = \"extra:name\"\r\n        const val EXTRA_DUE_DATE = \"extra:due\"\r\n        const val EXTRA_NOTES = \"extra:notes\"\r\n        const val EXTRA_SUBJECT = \"extra:subject\"\r\n        const val EXTRA_DATE_ADDED = \"extra:added\"\r\n        const val EXTRA_IS_IMPORTANT = \"extra:important\"\r\n        const val EXTRA_IS_FINISHED = \"extra:finished\"\r\n        const val EXTRA_IS_ARCHIVED = \"extra:archived\"\r\n\r\n        fun toBundle(task: Task): Bundle {\r\n            return bundleOf(\r\n                EXTRA_ID to task.taskID,\r\n                EXTRA_NAME to task.name,\r\n                EXTRA_DUE_DATE to task.dueDate,\r\n                EXTRA_NOTES to task.notes,\r\n                EXTRA_SUBJECT to task.subject,\r\n                EXTRA_DATE_ADDED to task.dateAdded,\r\n                EXTRA_IS_FINISHED to task.isFinished,\r\n                EXTRA_IS_IMPORTANT to task.isImportant,\r\n                EXTRA_IS_ARCHIVED to task.isTaskArchived\r\n            )\r\n        }\r\n\r\n        fun fromBundle(bundle: Bundle): Task? {\r\n            if (!bundle.containsKey(EXTRA_ID))\r\n                return null\r\n\r\n            return Task(\r\n                taskID = bundle.getString(EXTRA_ID)!!,\r\n                name = bundle.getString(EXTRA_NAME),\r\n                dueDate = bundle.getSerializable(EXTRA_DUE_DATE) as? ZonedDateTime,\r\n                notes = bundle.getString(EXTRA_NOTES),\r\n                subject = bundle.getString(EXTRA_SUBJECT),\r\n                dateAdded = bundle.getSerializable(EXTRA_DATE_ADDED) as ZonedDateTime,\r\n                isFinished = bundle.getBoolean(EXTRA_IS_FINISHED),\r\n                isImportant = bundle.getBoolean(EXTRA_IS_IMPORTANT),\r\n                isTaskArchived = bundle.getBoolean(EXTRA_IS_ARCHIVED)\r\n            )\r\n        }\r\n\r\n        fun fromInputStream(inputStream: InputStream): Task {\r\n            return Task().apply {\r\n                this.fromInputStream(inputStream)\r\n            }\r\n        }\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/task/TaskAdapter.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.task\r\n\r\nimport android.view.LayoutInflater\r\nimport android.view.View\r\nimport android.view.ViewGroup\r\nimport androidx.appcompat.widget.AppCompatCheckBox\r\nimport androidx.core.view.isVisible\r\nimport androidx.recyclerview.widget.ItemTouchHelper\r\nimport com.isaiahvonrundstedt.fokus.R\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.getCompoundDrawableAtStart\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.setCompoundDrawableAtStart\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.setStrikeThroughEffect\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.setTextColorFromResource\r\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Swipeable\r\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutItemTaskBinding\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseFragment\r\n\r\nclass TaskAdapter(\r\n    private val actionListener: ActionListener,\r\n    private val statusListener: TaskStatusListener,\r\n    private val archiveListener: ArchiveListener\r\n) : BaseAdapter<TaskPackage, TaskAdapter.TaskViewHolder>(TaskPackage.DIFF_CALLBACK), Swipeable {\r\n\r\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TaskViewHolder {\r\n        val binding = LayoutItemTaskBinding.inflate(\r\n            LayoutInflater.from(parent.context),\r\n            parent, false\r\n        )\r\n        return TaskViewHolder(binding.root, actionListener, statusListener)\r\n    }\r\n\r\n    override fun onBindViewHolder(holder: TaskViewHolder, position: Int) {\r\n        holder.onBind(getItem(position))\r\n    }\r\n\r\n    override fun onSwipe(position: Int, direction: Int) {\r\n        when (direction) {\r\n            ItemTouchHelper.START -> {\r\n                actionListener.onActionPerformed(\r\n                    getItem(position), ActionListener.Action.DELETE,\r\n                    null\r\n                )\r\n            }\r\n            ItemTouchHelper.END -> {\r\n                archiveListener.onItemArchive(getItem(position))\r\n            }\r\n        }\r\n    }\r\n\r\n    class TaskViewHolder(\r\n        itemView: View,\r\n        private val actionListener: ActionListener,\r\n        private val statusListener: TaskStatusListener\r\n    ) : BaseViewHolder(itemView) {\r\n        private val binding = LayoutItemTaskBinding.bind(itemView)\r\n\r\n        override fun <T> onBind(data: T) {\r\n            if (data is TaskPackage) {\r\n                with(data.task) {\r\n                    binding.root.transitionName = BaseFragment.TRANSITION_ELEMENT_ROOT + taskID\r\n\r\n                    val textColorRes = if (isFinished)\r\n                        R.color.color_secondary_text\r\n                    else R.color.color_primary_text\r\n\r\n                    binding.checkBox.isChecked = isFinished\r\n                    binding.taskNameView.text = name\r\n                    binding.taskNameView.setTextColorFromResource(textColorRes)\r\n                    binding.taskNameView.setStrikeThroughEffect(isFinished)\r\n\r\n                    if (hasDueDate())\r\n                        binding.dueDateView.text = formatDueDate(binding.root.context)\r\n                    else binding.dueDateView.isVisible = false\r\n                }\r\n\r\n                if (data.subject != null) {\r\n                    with(binding.subjectView) {\r\n                        text = data.subject?.code\r\n                        setCompoundDrawableAtStart(\r\n                            data.subject?.tintDrawable(\r\n                                getCompoundDrawableAtStart()\r\n                            )\r\n                        )\r\n                    }\r\n                } else binding.subjectView.isVisible = false\r\n\r\n                binding.checkBox.setOnClickListener { view ->\r\n                    with(view as AppCompatCheckBox) {\r\n                        data.task.isFinished = isChecked\r\n                        binding.taskNameView.setStrikeThroughEffect(isChecked)\r\n                        if (isChecked)\r\n                            binding.taskNameView.setTextColorFromResource(R.color.color_secondary_text)\r\n                    }\r\n                    statusListener.onStatusChanged(data, view.isChecked)\r\n                }\r\n\r\n                binding.root.setOnClickListener {\r\n                    actionListener.onActionPerformed(data, ActionListener.Action.SELECT, it)\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    interface TaskStatusListener {\r\n        fun onStatusChanged(taskPackage: TaskPackage, isFinished: Boolean)\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/task/TaskFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.task\r\n\r\nimport android.graphics.Color\r\nimport android.media.RingtoneManager\r\nimport android.net.Uri\r\nimport android.os.Bundle\r\nimport android.view.LayoutInflater\r\nimport android.view.MenuItem\r\nimport android.view.View\r\nimport android.view.ViewGroup\r\nimport androidx.annotation.StringRes\r\nimport androidx.core.os.bundleOf\r\nimport androidx.core.view.doOnPreDraw\r\nimport androidx.core.view.isVisible\r\nimport androidx.fragment.app.viewModels\r\nimport androidx.navigation.NavController\r\nimport androidx.navigation.Navigation\r\nimport androidx.navigation.fragment.FragmentNavigatorExtras\r\nimport androidx.recyclerview.widget.ItemTouchHelper\r\nimport androidx.recyclerview.widget.LinearLayoutManager\r\nimport com.google.android.material.snackbar.Snackbar\r\nimport com.isaiahvonrundstedt.fokus.R\r\nimport com.isaiahvonrundstedt.fokus.components.custom.ItemDecoration\r\nimport com.isaiahvonrundstedt.fokus.components.custom.ItemSwipeCallback\r\nimport com.isaiahvonrundstedt.fokus.components.enums.SortDirection\r\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.createSnackbar\r\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\r\nimport com.isaiahvonrundstedt.fokus.databinding.FragmentTaskBinding\r\nimport com.isaiahvonrundstedt.fokus.features.attachments.Attachment\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\r\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseFragment\r\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\r\nimport com.isaiahvonrundstedt.fokus.features.task.editor.TaskEditorFragment\r\nimport dagger.hilt.android.AndroidEntryPoint\r\nimport me.saket.cascade.overrideOverflowMenu\r\nimport nl.dionsegijn.konfetti.core.Party\r\nimport nl.dionsegijn.konfetti.core.Position\r\nimport nl.dionsegijn.konfetti.core.emitter.Emitter\r\nimport nl.dionsegijn.konfetti.core.models.Shape\r\nimport nl.dionsegijn.konfetti.core.models.Size\r\nimport java.io.File\r\nimport java.util.concurrent.TimeUnit\r\n\r\n@AndroidEntryPoint\r\nclass TaskFragment : BaseFragment(), BaseAdapter.ActionListener, TaskAdapter.TaskStatusListener,\r\n    BaseAdapter.ArchiveListener {\r\n    private var _binding: FragmentTaskBinding? = null\r\n    private var controller: NavController? = null\r\n\r\n    private val binding get() = _binding!!\r\n    private val taskAdapter = TaskAdapter(this, this, this)\r\n    private val viewModel: TaskViewModel by viewModels()\r\n\r\n    override fun onCreateView(\r\n        inflater: LayoutInflater, container: ViewGroup?,\r\n        savedInstanceState: Bundle?\r\n    ): View {\r\n        _binding = FragmentTaskBinding.inflate(inflater)\r\n        return binding.root\r\n    }\r\n\r\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\r\n        super.onViewCreated(view, savedInstanceState)\r\n        binding.actionButton.transitionName = TRANSITION_ELEMENT_ROOT\r\n        setInsets(binding.root, binding.appBarLayout.toolbar,\r\n            arrayOf(\r\n                binding.recyclerView,\r\n                binding.emptyViewPendingTasks,\r\n                binding.emptyViewFinishedTasks),\r\n            binding.actionButton\r\n        )\r\n\r\n        with(binding.appBarLayout.toolbar) {\r\n            setTitle(getToolbarTitle())\r\n            inflateMenu(R.menu.menu_tasks)\r\n            overrideOverflowMenu(::customPopupProvider)\r\n            setOnMenuItemClickListener(::onMenuItemClicked)\r\n            setupNavigation(this)\r\n        }\r\n\r\n        with(binding.recyclerView) {\r\n            addItemDecoration(ItemDecoration(context))\r\n            layoutManager = LinearLayoutManager(context)\r\n            adapter = taskAdapter\r\n\r\n            ItemTouchHelper(ItemSwipeCallback(context, taskAdapter))\r\n                .attachToRecyclerView(this)\r\n        }\r\n\r\n        postponeEnterTransition()\r\n        view.doOnPreDraw { startPostponedEnterTransition() }\r\n\r\n        ItemTouchHelper(ItemSwipeCallback(requireContext(), taskAdapter))\r\n            .attachToRecyclerView(binding.recyclerView)\r\n    }\r\n\r\n    override fun onStart() {\r\n        super.onStart()\r\n        /**\r\n         * Get the NavController here so\r\n         * that it doesn't crash when\r\n         * the host activity is recreated.\r\n         */\r\n        controller = Navigation.findNavController(requireActivity(), R.id.navigationHostFragment)\r\n\r\n        viewModel.tasks.observe(viewLifecycleOwner) {\r\n            taskAdapter.submitList(it)\r\n        }\r\n        viewModel.isEmpty.observe(viewLifecycleOwner) {\r\n            when (viewModel.filterOption) {\r\n                TaskViewModel.Constraint.ALL -> {\r\n                    binding.emptyViewPendingTasks.isVisible = it\r\n                    binding.emptyViewFinishedTasks.isVisible = false\r\n                }\r\n                TaskViewModel.Constraint.PENDING -> {\r\n                    binding.emptyViewPendingTasks.isVisible = it\r\n                    binding.emptyViewFinishedTasks.isVisible = false\r\n                }\r\n                TaskViewModel.Constraint.FINISHED -> {\r\n                    binding.emptyViewPendingTasks.isVisible = false\r\n                    binding.emptyViewFinishedTasks.isVisible = it\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    override fun onResume() {\r\n        super.onResume()\r\n\r\n        binding.actionButton.setOnClickListener {\r\n            controller?.navigate(\r\n                R.id.navigation_editor_task, null, null,\r\n                FragmentNavigatorExtras(it to TRANSITION_ELEMENT_ROOT)\r\n            )\r\n        }\r\n    }\r\n\r\n    // Update the task in the database then show\r\n    // snackbar feedback and also if the sounds if turned on\r\n    // play a fokus sound.\r\n    override fun onStatusChanged(taskPackage: TaskPackage, isFinished: Boolean) {\r\n        viewModel.update(taskPackage.task)\r\n        if (isFinished) {\r\n            createSnackbar(R.string.feedback_task_marked_as_finished, binding.recyclerView)\r\n\r\n            with(PreferenceManager(requireContext())) {\r\n                if (confetti) {\r\n                    binding.confettiView.start(Party(\r\n                        colors = listOf(Color.YELLOW, Color.MAGENTA, Color.CYAN),\r\n                        shapes = listOf(Shape.Square, Shape.Circle),\r\n                        speed = 1f,\r\n                        maxSpeed = 5f,\r\n                        damping = 0.9f,\r\n                        fadeOutEnabled = true,\r\n                        timeToLive = 1000L,\r\n                        spread = 360,\r\n                        position = Position.Relative(0.5, 0.3),\r\n                        size = listOf(Size(12, 5f)),\r\n                        emitter = Emitter(duration = 100, TimeUnit.MILLISECONDS).max(100),\r\n                    ))\r\n                }\r\n\r\n                if (sounds)\r\n                    RingtoneManager.getRingtone(\r\n                        requireContext(),\r\n                        Uri.parse(PreferenceManager.DEFAULT_SOUND)\r\n                    ).play()\r\n            }\r\n        }\r\n    }\r\n\r\n    // Callback from the RecyclerView Adapter\r\n    override fun <T> onActionPerformed(\r\n        t: T, action: BaseAdapter.ActionListener.Action,\r\n        container: View?\r\n    ) {\r\n        if (t is TaskPackage) {\r\n            when (action) {\r\n                // Create the intent to the editorUI and pass the extras\r\n                // and wait for the result.\r\n                BaseAdapter.ActionListener.Action.SELECT -> {\r\n                    val transitionName = TRANSITION_ELEMENT_ROOT + t.task.taskID\r\n\r\n                    val args = bundleOf(\r\n                        TaskEditorFragment.EXTRA_TASK to Task.toBundle(t.task),\r\n                        TaskEditorFragment.EXTRA_ATTACHMENTS to t.attachments,\r\n                        TaskEditorFragment.EXTRA_SUBJECT to t.subject?.let { Subject.toBundle(it) }\r\n                    )\r\n\r\n                    container?.also {\r\n                        controller?.navigate(\r\n                            R.id.navigation_editor_task, args, null,\r\n                            FragmentNavigatorExtras(it to transitionName)\r\n                        )\r\n                    }\r\n                }\r\n                // The item has been swiped down from the recyclerView\r\n                // remove the item from the database and show a snackbar\r\n                // feedback\r\n                BaseAdapter.ActionListener.Action.DELETE -> {\r\n                    viewModel.remove(t.task)\r\n\r\n                    createSnackbar(R.string.feedback_task_removed, binding.recyclerView).run {\r\n                        addCallback(object : Snackbar.Callback() {\r\n                            override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {\r\n                                super.onDismissed(transientBottomBar, event)\r\n\r\n                                if (event != DISMISS_EVENT_ACTION)\r\n                                    t.attachments.forEach { attachment ->\r\n                                        if (attachment.type == Attachment.TYPE_IMPORTED_FILE)\r\n                                            attachment.target?.also { File(it).delete() }\r\n                                    }\r\n                            }\r\n                        })\r\n                        setAction(R.string.button_undo) {\r\n                            viewModel.insert(t.task, t.attachments)\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    override fun <T> onItemArchive(t: T) {\r\n        if (t is TaskPackage) {\r\n            t.task.isTaskArchived = true\r\n            viewModel.update(t.task)\r\n        }\r\n    }\r\n\r\n    private fun onMenuItemClicked(item: MenuItem): Boolean {\r\n        when (item.itemId) {\r\n            R.id.action_name_sort_ascending -> {\r\n                viewModel.sort = TaskViewModel.Sort.NAME\r\n                viewModel.sortDirection = SortDirection.ASCENDING\r\n            }\r\n            R.id.action_name_sort_descending -> {\r\n                viewModel.sort = TaskViewModel.Sort.NAME\r\n                viewModel.sortDirection = SortDirection.DESCENDING\r\n            }\r\n            R.id.action_due_sort_ascending -> {\r\n                viewModel.sort = TaskViewModel.Sort.DUE\r\n                viewModel.sortDirection = SortDirection.ASCENDING\r\n            }\r\n            R.id.action_due_sort_descending -> {\r\n                viewModel.sort = TaskViewModel.Sort.DUE\r\n                viewModel.sortDirection = SortDirection.DESCENDING\r\n            }\r\n            R.id.action_filter_all -> {\r\n                viewModel.filterOption = TaskViewModel.Constraint.ALL\r\n                binding.appBarLayout.toolbar.setTitle(getToolbarTitle())\r\n            }\r\n            R.id.action_filter_pending -> {\r\n                viewModel.filterOption = TaskViewModel.Constraint.PENDING\r\n                binding.appBarLayout.toolbar.setTitle(getToolbarTitle())\r\n            }\r\n            R.id.action_filter_finished -> {\r\n                viewModel.filterOption = TaskViewModel.Constraint.FINISHED\r\n                binding.appBarLayout.toolbar.setTitle(getToolbarTitle())\r\n            }\r\n            R.id.action_archived -> {\r\n                controller?.navigate(R.id.navigation_archived_task)\r\n            }\r\n        }\r\n        return true\r\n    }\r\n\r\n    override fun onDestroy() {\r\n        super.onDestroy()\r\n        _binding = null\r\n    }\r\n\r\n    @StringRes\r\n    private fun getToolbarTitle(): Int {\r\n        return when (viewModel.filterOption) {\r\n            TaskViewModel.Constraint.ALL -> R.string.activity_tasks\r\n            TaskViewModel.Constraint.PENDING -> R.string.activity_tasks_pending\r\n            TaskViewModel.Constraint.FINISHED -> R.string.activity_tasks_finished\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/task/TaskPackage.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.task\n\nimport android.os.Parcelable\nimport androidx.recyclerview.widget.DiffUtil\nimport androidx.room.Embedded\nimport androidx.room.Relation\nimport com.isaiahvonrundstedt.fokus.features.attachments.Attachment\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\nimport kotlinx.android.parcel.Parcelize\n\n/**\n *  Data class used for data representation\n *  of tasks, subjects and its attachments\n *  in the UI\n */\n@Parcelize\ndata class TaskPackage(\n    @Embedded\n    var task: Task,\n    @Embedded\n    var subject: Subject? = null,\n    @Relation(entity = Attachment::class, parentColumn = \"taskID\", entityColumn = \"task\")\n    var attachments: List<Attachment> = emptyList()\n) : Parcelable {\n\n    companion object {\n        val DIFF_CALLBACK = object : DiffUtil.ItemCallback<TaskPackage>() {\n            override fun areItemsTheSame(oldItem: TaskPackage, newItem: TaskPackage): Boolean {\n                return oldItem.task?.taskID == newItem.task?.taskID\n            }\n\n            override fun areContentsTheSame(oldItem: TaskPackage, newItem: TaskPackage): Boolean {\n                return oldItem == newItem\n            }\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/task/TaskViewModel.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.task\r\n\r\nimport androidx.lifecycle.*\r\nimport com.isaiahvonrundstedt.fokus.components.enums.SortDirection\r\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\r\nimport com.isaiahvonrundstedt.fokus.database.repository.TaskRepository\r\nimport com.isaiahvonrundstedt.fokus.features.attachments.Attachment\r\nimport dagger.hilt.android.lifecycle.HiltViewModel\r\nimport kotlinx.coroutines.Dispatchers\r\nimport kotlinx.coroutines.NonCancellable\r\nimport kotlinx.coroutines.launch\r\nimport javax.inject.Inject\r\n\r\n@HiltViewModel\r\nclass TaskViewModel @Inject constructor(\r\n    private val repository: TaskRepository,\r\n    private val preferenceManager: PreferenceManager\r\n) : ViewModel() {\r\n\r\n    val _tasks: LiveData<List<TaskPackage>> = repository.fetchLiveData()\r\n\r\n    val tasks: MediatorLiveData<List<TaskPackage>> = MediatorLiveData()\r\n    val isEmpty: LiveData<Boolean> = Transformations.map(tasks) { it.isNullOrEmpty() }\r\n\r\n    var filterOption = preferenceManager.taskConstraint\r\n        set(value) {\r\n            field = value\r\n            preferenceManager.taskConstraint = value\r\n            rearrange(value, sort, sortDirection)\r\n        }\r\n\r\n    var sort: Sort = preferenceManager.tasksSort\r\n        set(value) {\r\n            field = value\r\n            rearrange(filterOption, value, sortDirection)\r\n        }\r\n\r\n    var sortDirection: SortDirection = preferenceManager.tasksSortDirection\r\n        set(value) {\r\n            field = value\r\n            rearrange(filterOption, sort, value)\r\n        }\r\n\r\n    init {\r\n        tasks.addSource(_tasks) { items ->\r\n            when (filterOption) {\r\n                Constraint.ALL ->\r\n                    tasks.value = items\r\n                Constraint.PENDING ->\r\n                    tasks.value = items.filter { !it.task.isFinished }\r\n                Constraint.FINISHED ->\r\n                    tasks.value = items.filter { it.task.isFinished }\r\n            }\r\n        }\r\n    }\r\n\r\n    fun insert(task: Task, attachmentList: List<Attachment> = emptyList()) =\r\n        viewModelScope.launch(Dispatchers.IO + NonCancellable) {\r\n            repository.insert(task, attachmentList)\r\n        }\r\n\r\n    fun remove(task: Task) = viewModelScope.launch(Dispatchers.IO + NonCancellable) {\r\n        repository.remove(task)\r\n    }\r\n\r\n    fun update(task: Task, attachmentList: List<Attachment> = emptyList()) =\r\n        viewModelScope.launch(Dispatchers.IO + NonCancellable) {\r\n            repository.update(task, attachmentList)\r\n        }\r\n\r\n    private fun rearrange(filter: Constraint, sort: Sort, direction: SortDirection) =\r\n        when (filter) {\r\n            Constraint.ALL -> {\r\n                _tasks.value?.let { items ->\r\n                    tasks.value = when (sort) {\r\n                        Sort.NAME -> {\r\n                            when (direction) {\r\n                                SortDirection.ASCENDING ->\r\n                                    items.sortedBy { it.task.name }\r\n                                SortDirection.DESCENDING ->\r\n                                    items.sortedByDescending { it.task.name }\r\n                            }\r\n                        }\r\n                        Sort.DUE -> {\r\n                            when (direction) {\r\n                                SortDirection.ASCENDING ->\r\n                                    items.sortedBy { it.task.dueDate }\r\n                                SortDirection.DESCENDING ->\r\n                                    items.sortedByDescending { it.task.dueDate }\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n            Constraint.PENDING -> {\r\n                _tasks.value?.let { items ->\r\n                    tasks.value = when (sort) {\r\n                        Sort.NAME -> {\r\n                            when (direction) {\r\n                                SortDirection.ASCENDING ->\r\n                                    items.filter { !it.task.isFinished }\r\n                                        .sortedBy { it.task.name }\r\n                                SortDirection.DESCENDING ->\r\n                                    items.filter { !it.task.isFinished }\r\n                                        .sortedByDescending { it.task.name }\r\n                            }\r\n                        }\r\n                        Sort.DUE -> {\r\n                            when (direction) {\r\n                                SortDirection.ASCENDING ->\r\n                                    items.filter { !it.task.isFinished }\r\n                                        .sortedBy { it.task.dueDate }\r\n                                SortDirection.DESCENDING ->\r\n                                    items.filter { !it.task.isFinished }\r\n                                        .sortedByDescending { it.task.dueDate }\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n            Constraint.FINISHED -> {\r\n                _tasks.value?.let { items ->\r\n                    tasks.value = when (sort) {\r\n                        Sort.NAME -> {\r\n                            when (direction) {\r\n                                SortDirection.ASCENDING ->\r\n                                    items.filter { it.task.isFinished }\r\n                                        .sortedBy { it.task.name }\r\n                                SortDirection.DESCENDING ->\r\n                                    items.filter { it.task.isFinished }\r\n                                        .sortedByDescending { it.task.name }\r\n                            }\r\n                        }\r\n                        Sort.DUE -> {\r\n                            when (direction) {\r\n                                SortDirection.ASCENDING ->\r\n                                    items.filter { it.task.isFinished }\r\n                                        .sortedBy { it.task.dueDate }\r\n                                SortDirection.DESCENDING ->\r\n                                    items.filter { it.task.isFinished }\r\n                                        .sortedByDescending { it.task.dueDate }\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n    enum class Sort {\r\n        NAME, DUE;\r\n\r\n        companion object {\r\n            fun parse(value: String): Sort {\r\n                return when (value) {\r\n                    NAME.toString() -> NAME\r\n                    DUE.toString() -> DUE\r\n                    else -> NAME\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    enum class Constraint {\r\n        ALL, PENDING, FINISHED;\r\n\r\n        companion object {\r\n            fun parse(value: String): Constraint {\r\n                return when (value) {\r\n                    ALL.toString() -> ALL\r\n                    PENDING.toString() -> PENDING\r\n                    FINISHED.toString() -> FINISHED\r\n                    else -> PENDING\r\n                }\r\n            }\r\n        }\r\n    }\r\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/task/archived/ArchivedTaskAdapter.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.task.archived\n\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.view.isVisible\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.getCompoundDrawableAtStart\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.setCompoundDrawableAtStart\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.setStrikeThroughEffect\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.setTextColorFromResource\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutItemArchivedTaskBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseFragment\nimport com.isaiahvonrundstedt.fokus.features.task.TaskPackage\n\nclass ArchivedTaskAdapter(private val listener: SelectListener) :\n    BaseAdapter<TaskPackage, ArchivedTaskAdapter.ArchivedTaskViewHolder>(TaskPackage.DIFF_CALLBACK) {\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArchivedTaskViewHolder {\n        val binding = LayoutItemArchivedTaskBinding.inflate(\n            LayoutInflater.from(parent.context),\n            parent, false\n        )\n        return ArchivedTaskViewHolder(binding.root, listener)\n    }\n\n    override fun onBindViewHolder(holder: ArchivedTaskViewHolder, position: Int) {\n        holder.onBind(getItem(position))\n    }\n\n    class ArchivedTaskViewHolder(itemView: View, private val listener: SelectListener) :\n        BaseViewHolder(itemView) {\n        private val binding = LayoutItemArchivedTaskBinding.bind(itemView)\n\n        override fun <T> onBind(data: T) {\n            if (data is TaskPackage) {\n                with(data.task) {\n                    binding.root.transitionName = BaseFragment.TRANSITION_ELEMENT_ROOT + taskID\n\n                    val textColorRes = if (isFinished)\n                        R.color.color_secondary_text\n                    else R.color.color_primary_text\n\n                    binding.taskNameView.text = name\n                    binding.taskNameView.setTextColorFromResource(textColorRes)\n                    binding.taskNameView.setStrikeThroughEffect(isFinished)\n\n                    if (hasDueDate())\n                        binding.dueDateView.text = formatDueDate(binding.root.context)\n                    else binding.dueDateView.isVisible = false\n                }\n\n                binding.root.setOnClickListener {\n                    listener.onItemSelected(data)\n                }\n\n                if (data.subject != null) {\n                    with(binding.subjectView) {\n                        text = data.subject?.code\n                        setCompoundDrawableAtStart(\n                            data.subject?.tintDrawable(\n                                getCompoundDrawableAtStart()\n                            )\n                        )\n                    }\n                } else binding.subjectView.isVisible = false\n            }\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/task/archived/ArchivedTaskFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.task.archived\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.view.isVisible\nimport androidx.fragment.app.viewModels\nimport androidx.navigation.NavController\nimport androidx.navigation.Navigation\nimport androidx.recyclerview.widget.LinearLayoutManager\nimport com.afollestad.materialdialogs.MaterialDialog\nimport com.afollestad.materialdialogs.lifecycle.lifecycleOwner\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.custom.ItemDecoration\nimport com.isaiahvonrundstedt.fokus.databinding.FragmentArchivedTaskBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseAdapter\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseFragment\nimport com.isaiahvonrundstedt.fokus.features.task.TaskPackage\nimport dagger.hilt.android.AndroidEntryPoint\n\n@AndroidEntryPoint\nclass ArchivedTaskFragment : BaseFragment(), BaseAdapter.SelectListener {\n    private var _binding: FragmentArchivedTaskBinding? = null\n    private var controller: NavController? = null\n\n    private val archivedTaskAdapter = ArchivedTaskAdapter(this)\n    private val viewModel: ArchivedTaskViewModel by viewModels()\n    private val binding get() = _binding!!\n\n    override fun onCreateView(\n        inflater: LayoutInflater, container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        _binding = FragmentArchivedTaskBinding.inflate(layoutInflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        setInsets(binding.root, binding.appBarLayout.toolbar,\n            arrayOf(binding.recyclerView, binding.emptyView))\n        controller = Navigation.findNavController(view)\n\n        with(binding.appBarLayout.toolbar) {\n            setTitle(R.string.activity_archives)\n            setNavigationIcon(R.drawable.ic_outline_arrow_back_24)\n            setNavigationOnClickListener { controller?.navigateUp() }\n        }\n\n        with(binding.recyclerView) {\n            addItemDecoration(ItemDecoration(context))\n            layoutManager = LinearLayoutManager(context)\n            adapter = archivedTaskAdapter\n        }\n    }\n\n    override fun onStart() {\n        super.onStart()\n\n        viewModel.items.observe(viewLifecycleOwner) {\n            archivedTaskAdapter.submitList(it)\n        }\n        viewModel.isEmpty.observe(viewLifecycleOwner) {\n            binding.emptyView.isVisible = it\n        }\n    }\n\n    override fun <T> onItemSelected(t: T) {\n        if (t is TaskPackage) {\n            MaterialDialog(requireContext()).show {\n                lifecycleOwner(viewLifecycleOwner)\n                title(R.string.dialog_confirm_unarchive_title)\n                message(R.string.dialog_confirm_unarchive_summary)\n                positiveButton {\n                    viewModel.removeFromArchive(t)\n                }\n                negativeButton(R.string.button_cancel)\n            }\n        }\n    }\n\n    override fun onDestroy() {\n        super.onDestroy()\n        _binding = null\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/task/archived/ArchivedTaskViewModel.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.task.archived\n\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.Transformations\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.viewModelScope\nimport com.isaiahvonrundstedt.fokus.database.repository.TaskRepository\nimport com.isaiahvonrundstedt.fokus.features.task.TaskPackage\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport kotlinx.coroutines.launch\nimport javax.inject.Inject\n\n@HiltViewModel\nclass ArchivedTaskViewModel @Inject constructor(\n    private val taskRepository: TaskRepository\n) : ViewModel() {\n\n    val items: LiveData<List<TaskPackage>> = taskRepository.fetchArchived()\n    val isEmpty: LiveData<Boolean> = Transformations.map(items) { it.isEmpty() }\n\n    fun removeFromArchive(taskPackage: TaskPackage) = viewModelScope.launch {\n        taskPackage.task.isTaskArchived = false\n        taskRepository.update(taskPackage.task)\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/task/editor/TaskEditorContainer.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.task.editor\n\nimport android.os.Bundle\nimport com.isaiahvonrundstedt.fokus.databinding.ActivityContainerTaskBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseActivity\nimport dagger.hilt.android.AndroidEntryPoint\n\n/**\n * This activity acts as a container\n * for the editor fragment. This is\n * used when needing to show the\n * editor ui without needing a fragment\n * transaction.\n */\n@AndroidEntryPoint\nclass TaskEditorContainer : BaseActivity() {\n    private lateinit var binding: ActivityContainerTaskBinding\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        binding = ActivityContainerTaskBinding.inflate(layoutInflater)\n        setContentView(binding.root)\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/task/editor/TaskEditorFragment.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.task.editor\n\nimport android.Manifest\nimport android.app.Activity\nimport android.content.BroadcastReceiver\nimport android.content.Context\nimport android.content.Intent\nimport android.content.IntentFilter\nimport android.net.Uri\nimport android.os.Bundle\nimport android.text.format.DateFormat.is24HourFormat\nimport android.view.LayoutInflater\nimport android.view.MenuItem\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.activity.result.ActivityResultLauncher\nimport androidx.activity.result.contract.ActivityResultContracts\nimport androidx.browser.customtabs.CustomTabsIntent\nimport androidx.core.app.ShareCompat\nimport androidx.core.content.ContextCompat\nimport androidx.core.view.children\nimport androidx.core.view.isVisible\nimport androidx.fragment.app.FragmentResultListener\nimport androidx.fragment.app.viewModels\nimport androidx.localbroadcastmanager.content.LocalBroadcastManager\nimport androidx.navigation.NavController\nimport androidx.navigation.Navigation\nimport com.afollestad.materialdialogs.MaterialDialog\nimport com.afollestad.materialdialogs.callbacks.onShow\nimport com.afollestad.materialdialogs.checkbox.checkBoxPrompt\nimport com.afollestad.materialdialogs.customview.customView\nimport com.afollestad.materialdialogs.datetime.dateTimePicker\nimport com.afollestad.materialdialogs.lifecycle.lifecycleOwner\nimport com.afollestad.materialdialogs.utils.MDUtil.textChanged\nimport com.google.android.material.chip.Chip\nimport com.google.android.material.snackbar.Snackbar\nimport com.google.android.material.textfield.TextInputEditText\nimport com.isaiahvonrundstedt.fokus.Fokus\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.*\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.toArrayList\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.toCalendar\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.toZonedDateTime\nimport com.isaiahvonrundstedt.fokus.components.interfaces.Streamable\nimport com.isaiahvonrundstedt.fokus.components.service.DataExporterService\nimport com.isaiahvonrundstedt.fokus.components.service.DataImporterService\nimport com.isaiahvonrundstedt.fokus.components.service.FileImporterService\nimport com.isaiahvonrundstedt.fokus.components.utils.PermissionManager\nimport com.isaiahvonrundstedt.fokus.components.utils.PreferenceManager\nimport com.isaiahvonrundstedt.fokus.components.views.RadioButtonCompat\nimport com.isaiahvonrundstedt.fokus.components.views.TwoLineRadioButton\nimport com.isaiahvonrundstedt.fokus.databinding.FragmentEditorTaskBinding\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutDialogInputAttachmentBinding\nimport com.isaiahvonrundstedt.fokus.features.attachments.Attachment\nimport com.isaiahvonrundstedt.fokus.features.attachments.AttachmentOptionSheet\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\nimport com.isaiahvonrundstedt.fokus.features.schedule.picker.SchedulePickerSheet\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseEditorFragment\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseService\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\nimport com.isaiahvonrundstedt.fokus.features.subject.SubjectPackage\nimport com.isaiahvonrundstedt.fokus.features.subject.picker.SubjectPickerFragment\nimport com.isaiahvonrundstedt.fokus.features.task.Task\nimport com.isaiahvonrundstedt.fokus.features.task.TaskPackage\nimport com.isaiahvonrundstedt.fokus.features.viewer.ImageViewer\nimport dagger.hilt.android.AndroidEntryPoint\nimport me.saket.cascade.overrideOverflowMenu\nimport java.io.File\nimport javax.inject.Inject\n\n@AndroidEntryPoint\nclass TaskEditorFragment : BaseEditorFragment(), FragmentResultListener {\n    private var _binding: FragmentEditorTaskBinding? = null\n    private var controller: NavController? = null\n    private var requestKey = REQUEST_KEY_INSERT\n\n    private val viewModel: TaskEditorViewModel by viewModels()\n    private val binding get() = _binding!!\n\n    private lateinit var permissionLauncher: ActivityResultLauncher<String>\n    private lateinit var attachmentLauncher: ActivityResultLauncher<Intent>\n    private lateinit var exportLauncher: ActivityResultLauncher<Intent>\n    private lateinit var importLauncher: ActivityResultLauncher<Intent>\n\n    @Inject\n    lateinit var permissionManager: PermissionManager\n\n    @Inject\n    lateinit var preferenceManager: PreferenceManager\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        sharedElementEnterTransition = buildContainerTransform()\n        sharedElementReturnTransition = buildContainerTransform()\n\n        permissionLauncher =\n            registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->\n                if (isGranted) {\n                    triggerSystemFilePickerForAttachment()\n                } else {\n                    MaterialDialog(requireContext()).show {\n                        lifecycleOwner(viewLifecycleOwner)\n                        title(R.string.dialog_permission_needed_title)\n                        message(R.string.dialog_permission_needed_summary)\n                        positiveButton(R.string.button_continue) {}\n                        negativeButton(R.string.button_cancel)\n                    }\n                }\n            }\n\n        attachmentLauncher =\n            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {\n                if (it.resultCode == Activity.RESULT_OK) {\n                    val attachmentId = Attachment.generateId()\n\n                    context?.startService(Intent(context, FileImporterService::class.java).apply {\n                        action = FileImporterService.ACTION_START\n                        data = it.data?.data\n                        putExtra(FileImporterService.EXTRA_OBJECT_ID, attachmentId)\n                    })\n                }\n            }\n\n        exportLauncher =\n            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {\n                if (it.resultCode == Activity.RESULT_OK) {\n                    context?.startService(Intent(context, DataExporterService::class.java).apply {\n                        this.data = it.data?.data\n                        action = DataExporterService.ACTION_EXPORT_TASK\n                        putExtra(DataExporterService.EXTRA_EXPORT_SOURCE, viewModel.getTask())\n                        putExtra(\n                            DataExporterService.EXTRA_EXPORT_DEPENDENTS,\n                            viewModel.getAttachments()\n                        )\n                    })\n                }\n            }\n\n        importLauncher =\n            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {\n                if (it.resultCode == Activity.RESULT_OK) {\n                    context?.startService(Intent(context, DataImporterService::class.java).apply {\n                        this.data = it.data?.data\n                        action = DataImporterService.ACTION_IMPORT_TASK\n                    })\n                }\n            }\n    }\n\n    override fun onCreateView(\n        inflater: LayoutInflater, container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        _binding = FragmentEditorTaskBinding.inflate(inflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        binding.coordinator.transitionName = TRANSITION_ELEMENT_ROOT\n        controller = Navigation.findNavController(view)\n        setInsets(binding.root, binding.appBarLayout.toolbar, arrayOf(binding.contentView),\n            binding.actionButton)\n\n        arguments?.getBundle(EXTRA_TASK)?.also {\n            requestKey = REQUEST_KEY_UPDATE\n\n            Task.fromBundle(it)?.also { task ->\n                viewModel.setTask(task)\n                binding.root.transitionName = TRANSITION_ELEMENT_ROOT + task.taskID\n                binding.priorityCard.isVisible = task.isFinished\n            }\n        }\n        arguments?.getParcelableArrayList<Attachment>(EXTRA_ATTACHMENTS)?.also {\n            viewModel.setAttachments(it)\n        }\n        arguments?.getBundle(EXTRA_SUBJECT)?.also {\n            viewModel.setSubject(Subject.fromBundle(it))\n        }\n\n        with(binding.appBarLayout.toolbar) {\n            inflateMenu(R.menu.menu_editor)\n            setNavigationOnClickListener {\n                if (controller?.graph?.id == R.id.navigation_container_task)\n                    requireActivity().finish()\n                else controller?.navigateUp()\n            }\n\n            overrideOverflowMenu(::customPopupProvider)\n            setOnMenuItemClickListener(::onMenuItemClicked)\n        }\n\n        registerForFragmentResult(\n            arrayOf(\n                SubjectPickerFragment.REQUEST_KEY_PICK,\n                SchedulePickerSheet.REQUEST_KEY,\n                AttachmentOptionSheet.REQUEST_KEY\n            ), this\n        )\n    }\n\n    private val dialogView: View by lazy {\n        LayoutDialogInputAttachmentBinding.inflate(layoutInflater).root\n    }\n\n    override fun onStart() {\n        super.onStart()\n\n        LocalBroadcastManager.getInstance(requireContext())\n            .registerReceiver(receiver, IntentFilter(BaseService.ACTION_SERVICE_BROADCAST))\n\n        if (requestKey == REQUEST_KEY_UPDATE) {\n            binding.taskNameTextInput.setText(viewModel.getName())\n            binding.notesTextInput.setText(viewModel.getNotes())\n        }\n\n        viewModel.task.observe(this) {\n            if (requestKey == REQUEST_KEY_UPDATE && it != null) {\n                with(it) {\n                    binding.prioritySwitch.isChecked = isImportant\n                    binding.statusSwitch.isChecked = isFinished\n                    binding.removeDueDateButton.isVisible = it.hasDueDate()\n\n                    if (it.hasDueDate()) {\n                        binding.dueDateTextView.text = formatDueDate(requireContext())\n                        binding.dueDateTextView.setTextColorFromResource(R.color.color_primary_text)\n                    } else {\n                        binding.dueDateTextView.setText(R.string.field_due_date)\n                        binding.dueDateTextView.setTextColorFromResource(R.color.color_secondary_text)\n                    }\n                }\n            }\n        }\n\n        viewModel.attachments.observe(this) {\n            binding.attachmentsChipGroup.removeAllViews()\n            it.forEach { attachment ->\n                binding.attachmentsChipGroup.addView(Chip(requireContext()).apply {\n                    text = attachment.name\n                    tag = attachment.attachmentID\n                    isCloseIconVisible = true\n                    setCloseIconResource(R.drawable.ic_outline_close_24)\n                    setOnClickListener {\n                        if (attachment.target != null)\n                            onParseForIntent(attachment)\n                    }\n                    setOnCloseIconClickListener {\n                        val uri = Uri.parse(attachment.target)\n                        MaterialDialog(requireContext()).show {\n                            lifecycleOwner(viewLifecycleOwner)\n                            title(\n                                text = String.format(\n                                    getString(R.string.dialog_confirm_deletion_title),\n                                    attachment.name\n                                )\n                            )\n                            message(R.string.dialog_confirm_deletion_summary)\n                            positiveButton(R.string.button_delete) {\n\n                                viewModel.removeAttachment(attachment)\n                                when (attachment.type) {\n                                    Attachment.TYPE_CONTENT_URI ->\n                                        context.contentResolver.delete(uri, null, null)\n                                    Attachment.TYPE_IMPORTED_FILE ->\n                                        File(attachment.target!!).delete()\n                                }\n                            }\n                            negativeButton(R.string.button_cancel)\n                        }\n                    }\n                })\n            }\n        }\n\n        viewModel.subject.observe(this) {\n            binding.removeButton.isVisible = it != null\n            binding.dateTimeRadioGroup.isVisible = it != null\n            binding.dueDateTextView.isVisible = it == null\n            binding.removeDueDateButton.isVisible = it == null && viewModel.getDueDate() != null\n\n            if (it != null) {\n                with(binding.subjectTextView) {\n                    text = it.code\n                    setTextColorFromResource(R.color.color_primary_text)\n                    setCompoundDrawableAtStart(ContextCompat.getDrawable(\n                        context,\n                        R.drawable.shape_color_holder\n                    )?.let { shape -> it.tintDrawable(shape) })\n                }\n\n                if (viewModel.getDueDate() != null) {\n                    with(binding.customDateTimeRadio) {\n                        isChecked = true\n                        titleTextColor = ContextCompat.getColor(context, R.color.color_primary_text)\n                        subtitle = viewModel.getTask()?.formatDueDate(context)\n                    }\n                }\n            } else {\n                with(binding.subjectTextView) {\n                    setText(R.string.field_subject)\n                    setTextColorFromResource(R.color.color_secondary_text)\n                    removeCompoundDrawableAtStart()\n                }\n\n                if (viewModel.getDueDate() != null) {\n                    with(binding.dueDateTextView) {\n                        text = viewModel.getTask()?.formatDueDate(context)\n                        setTextColorFromResource(R.color.color_primary_text)\n                    }\n                }\n            }\n        }\n\n        viewModel.isNameExists.observe(this) {\n            binding.taskNameTextInputLayout.error =\n                if (it) getString(R.string.feedback_task_name_exists)\n                else null\n        }\n\n        binding.taskNameTextInput.textChanged {\n            viewModel.checkNameUniqueness(it.toString())\n        }\n\n        binding.taskNameTextInput.setOnFocusChangeListener { v, hasFocus ->\n            if (!hasFocus && v is TextInputEditText) {\n                viewModel.setName(v.text.toString())\n            }\n        }\n\n        binding.notesTextInput.setOnFocusChangeListener { v, hasFocus ->\n            if (!hasFocus && v is TextInputEditText) {\n                viewModel.setNotes(v.text.toString())\n            }\n        }\n\n        binding.addActionChip.setOnClickListener {\n            hideKeyboardFromCurrentFocus(requireView())\n            AttachmentOptionSheet.show(childFragmentManager)\n        }\n\n        binding.dueDateTextView.setOnClickListener {\n            MaterialDialog(requireContext()).show {\n                lifecycleOwner(viewLifecycleOwner)\n                dateTimePicker(\n                    requireFutureDateTime = true,\n                    currentDateTime = viewModel.getDueDate()?.toCalendar(),\n                    show24HoursView = is24HourFormat(requireContext())\n                ) { _, datetime ->\n                    viewModel.setDueDate(datetime.toZonedDateTime())\n                    binding.removeDueDateButton.isVisible = true\n                }\n                positiveButton(R.string.button_done) {\n                    with(binding.dueDateTextView) {\n                        text = viewModel.getTask()?.formatDueDate(context)\n                        setTextColorFromResource(R.color.color_primary_text)\n                    }\n                }\n            }\n        }\n\n        binding.removeDueDateButton.setOnClickListener {\n            viewModel.setDueDate(null)\n\n            binding.removeDueDateButton.isVisible = false\n            binding.dueDateTextView.setText(R.string.field_due_date)\n            binding.dueDateTextView.setTextColor(\n                ContextCompat.getColor(\n                    it.context,\n                    R.color.color_secondary_text\n                )\n            )\n        }\n\n        binding.subjectTextView.setOnClickListener {\n            SubjectPickerFragment(childFragmentManager)\n                .show()\n        }\n\n        binding.removeButton.setOnClickListener {\n            binding.dueDateTextView.setText(R.string.field_due_date)\n            binding.dueDateTextView.setTextColor(\n                ContextCompat.getColor(\n                    it.context,\n                    R.color.color_secondary_text\n                )\n            )\n            binding.subjectTextView.startAnimation(animation)\n\n            it.isVisible = false\n            viewModel.setSubject(null)\n        }\n\n        // When a radio button has been checked, set the other\n        // radio buttons text color to colorSecondaryText\n        binding.dateTimeRadioGroup.setOnCheckedChangeListener { radioGroup, _ ->\n            for (v: View in radioGroup.children) {\n                if (v is TwoLineRadioButton && !v.isChecked) {\n                    v.titleTextColor = ContextCompat.getColor(\n                        v.context,\n                        R.color.color_secondary_text\n                    )\n                    v.subtitle = null\n                } else if (v is RadioButtonCompat && !v.isChecked) {\n                    v.setTextColor(\n                        ContextCompat.getColor(\n                            v.context,\n                            R.color.color_secondary_text\n                        )\n                    )\n                }\n            }\n        }\n\n        binding.statusSwitch.setOnCheckedChangeListener { _, isChecked ->\n            viewModel.setFinished(isChecked)\n        }\n\n        binding.prioritySwitch.setOnCheckedChangeListener { _, isChecked ->\n            viewModel.setImportant(isChecked)\n            binding.priorityCard.isVisible = isChecked\n        }\n\n        binding.noDueRadioButton.setOnClickListener {\n            viewModel.setDueDate(null)\n            binding.dueDateTextView.setText(R.string.field_not_set)\n            (it as RadioButtonCompat).setTextColor(\n                ContextCompat.getColor(\n                    it.context,\n                    R.color.color_primary_text\n                )\n            )\n        }\n\n        binding.inNextMeetingRadio.setOnClickListener {\n            viewModel.setNextMeetingForDueDate()\n            with(binding.inNextMeetingRadio) {\n                titleTextColor = ContextCompat.getColor(context, R.color.color_primary_text)\n                subtitle = viewModel.getTask()?.formatDueDate(context)\n            }\n        }\n\n        binding.pickDateTimeRadio.setOnClickListener {\n            hideKeyboardFromCurrentFocus(requireView())\n\n            SchedulePickerSheet\n                .show(viewModel.schedules, childFragmentManager)\n        }\n\n        binding.customDateTimeRadio.setOnClickListener {\n            MaterialDialog(requireContext()).show {\n                lifecycleOwner(viewLifecycleOwner)\n                dateTimePicker(\n                    requireFutureDateTime = true,\n                    currentDateTime = viewModel.getDueDate()?.toCalendar(),\n                    show24HoursView = is24HourFormat(requireContext())\n                ) { _, datetime ->\n                    viewModel.setDueDate(datetime.toZonedDateTime())\n                }\n                positiveButton(R.string.button_done) {\n                    with(binding.customDateTimeRadio) {\n                        titleTextColor = ContextCompat.getColor(\n                            context,\n                            R.color.color_primary_text\n                        )\n                        subtitle = viewModel.getTask()?.formatDueDate(context)\n                    }\n                }\n                negativeButton { binding.customDateTimeRadio.isChecked = false }\n            }\n        }\n\n        binding.actionButton.setOnClickListener {\n            hideKeyboardFromCurrentFocus(requireView())\n\n            viewModel.setName(binding.taskNameTextInput.text.toString())\n            viewModel.setNotes(binding.notesTextInput.text.toString())\n\n            // These if checks if the user have entered the\n            // values on the fields, if we don't have the value required,\n            // show a snackbar feedback then direct the user's\n            // attention to the field. Then return to stop the execution\n            // of the code.\n            if (viewModel.getName()?.isEmpty() == true) {\n                createSnackbar(R.string.feedback_task_empty_name, binding.root)\n                binding.taskNameTextInput.requestFocus()\n                return@setOnClickListener\n            }\n\n            if (requestKey == REQUEST_KEY_INSERT)\n                viewModel.insert()\n            else viewModel.update()\n\n            if (controller?.graph?.id == R.id.navigation_container_task)\n                requireActivity().finish()\n            else controller?.navigateUp()\n        }\n    }\n\n    private fun triggerSystemFilePickerForAttachment() {\n        attachmentLauncher.launch(\n            Intent(Intent.ACTION_OPEN_DOCUMENT)\n                .setType(\"*/*\")\n        )\n    }\n\n    override fun onStop() {\n        super.onStop()\n\n        /**\n         * Check if the soft keyboard is visible\n         * then hide it before the user leaves\n         * the fragment\n         */\n        hideKeyboardFromCurrentFocus(requireView())\n    }\n\n    override fun onDestroy() {\n        _binding = null\n        LocalBroadcastManager.getInstance(requireContext())\n            .unregisterReceiver(receiver)\n\n        // Cancel all current import processes\n        context?.startService(Intent(context, FileImporterService::class.java).apply {\n            action = FileImporterService.ACTION_CANCEL\n        })\n        super.onDestroy()\n    }\n\n    private var receiver = object : BroadcastReceiver() {\n        override fun onReceive(context: Context?, intent: Intent?) {\n            if (intent?.action == BaseService.ACTION_SERVICE_BROADCAST) {\n                when (intent.getStringExtra(BaseService.EXTRA_BROADCAST_STATUS)) {\n                    FileImporterService.BROADCAST_IMPORT_ONGOING -> {\n                        createSnackbar(\n                            R.string.feedback_import_ongoing, binding.root,\n                            Snackbar.LENGTH_INDEFINITE\n                        )\n                    }\n                    FileImporterService.BROADCAST_IMPORT_COMPLETED -> {\n                        createSnackbar(R.string.feedback_import_completed, binding.root)\n\n                        if (intent.hasExtra(BaseService.EXTRA_BROADCAST_DATA) &&\n                            intent.hasExtra(FileImporterService.EXTRA_BROADCAST_EXTRA)\n                        ) {\n\n                            val id = intent.getStringExtra(BaseService.EXTRA_BROADCAST_DATA)\n                            val name =\n                                intent.getStringExtra(FileImporterService.EXTRA_BROADCAST_EXTRA)\n\n                            val extension = File(name!!).extension\n\n                            val attachment = Attachment(\n                                attachmentID = id!!,\n                                name = name,\n                                target = File(\n                                    Attachment.getTargetDirectory(context),\n                                    \"${id}.${extension}\"\n                                ).name,\n                                type = Attachment.TYPE_IMPORTED_FILE,\n                                task = viewModel.getID()!!\n                            )\n\n                            viewModel.addAttachment(attachment)\n\n                            binding.appBarLayout.toolbar\n                                .menu?.findItem(R.id.action_share_options)?.isVisible =\n                                !viewModel.hasFileAttachment()\n                        }\n                    }\n                    FileImporterService.BROADCAST_IMPORT_FAILED -> {\n                        createSnackbar(R.string.feedback_import_failed, binding.root)\n                    }\n                    DataExporterService.BROADCAST_EXPORT_ONGOING -> {\n                        createSnackbar(R.string.feedback_export_ongoing, binding.root)\n                    }\n                    DataExporterService.BROADCAST_EXPORT_COMPLETED -> {\n                        createSnackbar(R.string.feedback_export_completed, binding.root)\n\n                        intent.getStringExtra(BaseService.EXTRA_BROADCAST_DATA)?.also {\n                            val uri = Fokus.obtainUriForFile(requireContext(), File(it))\n\n                            startActivity(\n                                ShareCompat.IntentBuilder.from(requireActivity())\n                                    .addStream(uri)\n                                    .setType(Streamable.MIME_TYPE_ZIP)\n                                    .setChooserTitle(R.string.dialog_send_to)\n                                    .intent\n                            )\n                        }\n                    }\n                    DataExporterService.BROADCAST_EXPORT_FAILED -> {\n                        createSnackbar(R.string.feedback_export_failed, binding.root)\n                    }\n                    DataImporterService.BROADCAST_IMPORT_ONGOING -> {\n                        createSnackbar(R.string.feedback_import_ongoing, binding.root)\n                    }\n                    DataImporterService.BROADCAST_IMPORT_COMPLETED -> {\n                        createSnackbar(R.string.feedback_import_completed, binding.root)\n\n                        intent.getParcelableExtra<TaskPackage>(BaseService.EXTRA_BROADCAST_DATA)\n                            ?.also {\n                                viewModel.setTask(it.task)\n                                viewModel.setAttachments(ArrayList(it.attachments))\n                            }\n                    }\n                    DataImporterService.BROADCAST_IMPORT_FAILED -> {\n                        createSnackbar(R.string.feedback_import_failed, binding.root)\n                    }\n                }\n            }\n        }\n    }\n\n    private fun onMenuItemClicked(item: MenuItem): Boolean {\n        when (item.itemId) {\n            R.id.action_export -> {\n                val fileName = getSharingName()\n                if (fileName == null) {\n                    MaterialDialog(requireContext()).show {\n                        title(R.string.feedback_unable_to_share_title)\n                        message(R.string.feedback_unable_to_share_message)\n                        positiveButton(R.string.button_done) { dismiss() }\n                    }\n                    return false\n                }\n\n                /**\n                 * Make the user specify where to save\n                 * the exported file\n                 */\n                exportLauncher.launch(Intent(Intent.ACTION_CREATE_DOCUMENT).apply {\n                    addCategory(Intent.CATEGORY_OPENABLE)\n                    putExtra(Intent.EXTRA_TITLE, fileName)\n                    type = Streamable.MIME_TYPE_ZIP\n                })\n            }\n            R.id.action_share -> {\n                val fileName = getSharingName()\n                if (fileName == null) {\n                    MaterialDialog(requireContext()).show {\n                        title(R.string.feedback_unable_to_share_title)\n                        message(R.string.feedback_unable_to_share_message)\n                        positiveButton(R.string.button_done) { dismiss() }\n                    }\n                    return false\n                }\n\n                /**\n                 * We need first to export the data as a raw file\n                 * then pass it onto the system sharing component\n                 */\n                context?.startService(Intent(context, DataExporterService::class.java).apply {\n                    action = DataExporterService.ACTION_EXPORT_TASK\n                    putExtra(\n                        DataExporterService.EXTRA_EXPORT_SOURCE,\n                        viewModel.getTask()\n                    )\n                    putExtra(\n                        DataExporterService.EXTRA_EXPORT_DEPENDENTS,\n                        viewModel.getAttachments()\n                    )\n                })\n            }\n            R.id.action_import -> {\n                val chooser = Intent.createChooser(Intent(Intent.ACTION_OPEN_DOCUMENT).apply {\n                    type = Streamable.MIME_TYPE_ZIP\n                }, getString(R.string.dialog_select_file_import))\n\n                importLauncher.launch(chooser)\n            }\n        }\n        return true\n    }\n\n    override fun onFragmentResult(requestKey: String, result: Bundle) {\n        when (requestKey) {\n            SubjectPickerFragment.REQUEST_KEY_PICK -> {\n                result.getParcelable<SubjectPackage>(SubjectPickerFragment.EXTRA_SELECTED_SUBJECT)?.let {\n                    viewModel.setSubject(it.subject)\n                    viewModel.schedules = it.schedules.toArrayList()\n                }\n            }\n            SchedulePickerSheet.REQUEST_KEY -> {\n                result.getParcelable<Schedule>(SchedulePickerSheet.EXTRA_SCHEDULE)?.also {\n                    viewModel.setClassScheduleAsDueDate(it)\n\n                    with(binding.pickDateTimeRadio) {\n                        titleTextColor = ContextCompat.getColor(\n                            context,\n                            R.color.color_primary_text\n                        )\n                        subtitle = viewModel.getTask()?.formatDueDate(context)\n                    }\n                }\n            }\n            AttachmentOptionSheet.REQUEST_KEY -> {\n                result.getInt(AttachmentOptionSheet.EXTRA_OPTION).also {\n                    when (it) {\n                        R.id.action_import_file -> {\n                            // Check if we have read storage permissions then request the permission\n                            // if we have the permission, open up file picker\n                            if (permissionManager.readStorageGranted) {\n                                if (!preferenceManager.noConfirmImport)\n                                    MaterialDialog(requireContext()).show {\n                                        lifecycleOwner(viewLifecycleOwner)\n                                        title(R.string.dialog_import_attachment_title)\n                                        message(R.string.dialog_import_attachment_summary)\n                                        checkBoxPrompt(R.string.dialog_import_attachment_confirm) { isChecked ->\n                                            preferenceManager.noConfirmImport = isChecked\n                                        }\n                                        positiveButton(R.string.button_continue) {\n                                            triggerSystemFilePickerForAttachment()\n                                        }\n                                        negativeButton(R.string.button_cancel)\n                                    }\n                                else triggerSystemFilePickerForAttachment()\n                            } else\n                                permissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)\n                        }\n                        R.id.action_website_url -> {\n                            var attachment: Attachment?\n\n                            MaterialDialog(requireContext()).show {\n                                title(res = R.string.dialog_enter_website_url)\n                                customView(view = dialogView)\n                                positiveButton(R.string.button_done) {\n                                    val binding = LayoutDialogInputAttachmentBinding.bind(it.view)\n\n                                    attachment = Attachment(\n                                        target = binding.editText.text.toString(),\n                                        name = binding.editText.text.toString(),\n                                        type = Attachment.TYPE_WEBSITE_LINK,\n                                        task = viewModel.getID()!!\n                                    )\n\n                                    attachment?.also { item -> viewModel.addAttachment(item) }\n                                }\n                                onShow {\n                                    val webLink = viewModel.fetchRecentItemFromClipboard()\n\n                                    if (webLink.startsWith(\"https://\") ||\n                                        webLink.startsWith(\"http://\") ||\n                                        webLink.startsWith(\"www\")\n                                    ) {\n\n                                        val binding =\n                                            LayoutDialogInputAttachmentBinding.bind(it.view)\n                                        binding.editText.setText(webLink)\n                                    }\n                                }\n                                negativeButton(R.string.button_cancel)\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n\n    // This function invokes the corresponding application that\n    // will open the uri of the attachment if the user clicks\n    // on the attachment item\n    private fun onParseForIntent(attachment: Attachment) {\n        when (attachment.type) {\n            Attachment.TYPE_CONTENT_URI -> {\n                val targetUri: Uri = Uri.parse(attachment.target)\n\n                val intent = Intent(Intent.ACTION_VIEW)\n                    .setDataAndType(targetUri, requireContext().contentResolver?.getType(targetUri))\n                    .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)\n\n                if (intent.resolveActivity(context?.packageManager!!) != null)\n                    startActivity(intent)\n            }\n            Attachment.TYPE_IMPORTED_FILE -> {\n                val file = File(Attachment.getTargetDirectory(context), attachment.target!!)\n\n                when {\n                    Attachment.isImage(file.path) -> {\n                        ImageViewer.show(childFragmentManager, file.path, attachment.name)\n                    }\n                    else -> {\n                        val targetUri = Fokus.obtainUriForFile(\n                            requireContext(),\n                            file\n                        )\n\n                        val intent = Intent(Intent.ACTION_VIEW)\n                            .setDataAndType(\n                                targetUri,\n                                requireContext().contentResolver?.getType(targetUri)\n                            )\n                            .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)\n\n                        if (intent.resolveActivity(context?.packageManager!!) != null)\n                            startActivity(intent)\n                    }\n                }\n            }\n            Attachment.TYPE_WEBSITE_LINK -> {\n                var targetPath: String? = attachment.target\n                if (attachment.target?.startsWith(\"http://\") != true\n                    && attachment.target?.startsWith(\"https://\") != true\n                )\n                    targetPath = \"http://$targetPath\"\n\n                val targetUri: Uri = Uri.parse(targetPath)\n\n                if (PreferenceManager(requireContext()).useExternalBrowser) {\n                    val intent = Intent(Intent.ACTION_VIEW, targetUri)\n\n                    if (intent.resolveActivity(context?.packageManager!!) != null)\n                        startActivity(intent)\n                } else\n                    CustomTabsIntent.Builder().build()\n                        .launchUrl(requireContext(), targetUri)\n            }\n        }\n    }\n\n    private fun getSharingName(): String? {\n        return when (requestKey) {\n            REQUEST_KEY_INSERT -> {\n                if (viewModel.getName()?.isEmpty() == true\n                    || viewModel.getDueDate() == null\n                ) {\n                    return null\n                }\n\n                binding.taskNameTextInput.text.toString()\n            }\n            REQUEST_KEY_UPDATE -> {\n                viewModel.getName() ?: Streamable.ARCHIVE_NAME_GENERIC\n            }\n            else -> null\n        }\n    }\n\n    override fun onSaveInstanceState(outState: Bundle) {\n        with(outState) {\n            putParcelable(EXTRA_TASK, viewModel.getTask())\n            putParcelable(EXTRA_SUBJECT, viewModel.getSubject())\n            putParcelableArrayList(EXTRA_ATTACHMENTS, ArrayList(viewModel.getAttachments()))\n        }\n        super.onSaveInstanceState(outState)\n    }\n\n    override fun onViewStateRestored(savedInstanceState: Bundle?) {\n        super.onViewStateRestored(savedInstanceState)\n        savedInstanceState?.run {\n            viewModel.setTask(getParcelable(EXTRA_TASK))\n            viewModel.setAttachments(getParcelableArrayList(EXTRA_ATTACHMENTS) ?: arrayListOf())\n            viewModel.setSubject(getParcelable(EXTRA_SUBJECT))\n        }\n    }\n\n    companion object {\n        const val REQUEST_KEY_INSERT = \"request:insert\"\n        const val REQUEST_KEY_UPDATE = \"request:update\"\n\n        const val EXTRA_TASK = \"extra:task\"\n        const val EXTRA_SUBJECT = \"extra:subject\"\n        const val EXTRA_ATTACHMENTS = \"extra:attachments\"\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/task/editor/TaskEditorViewModel.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.task.editor\n\nimport android.content.ClipboardManager\nimport androidx.lifecycle.*\nimport com.isaiahvonrundstedt.fokus.components.extensions.jdk.toArrayList\nimport com.isaiahvonrundstedt.fokus.database.dao.ScheduleDAO\nimport com.isaiahvonrundstedt.fokus.database.repository.TaskRepository\nimport com.isaiahvonrundstedt.fokus.features.attachments.Attachment\nimport com.isaiahvonrundstedt.fokus.features.schedule.Schedule\nimport com.isaiahvonrundstedt.fokus.features.subject.Subject\nimport com.isaiahvonrundstedt.fokus.features.task.Task\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.NonCancellable\nimport kotlinx.coroutines.launch\nimport java.time.LocalDate\nimport java.time.ZonedDateTime\nimport javax.inject.Inject\n\n@HiltViewModel\nclass TaskEditorViewModel @Inject constructor(\n    private val clipboardManager: ClipboardManager,\n    private val scheduleDao: ScheduleDAO,\n    private val repository: TaskRepository\n) : ViewModel() {\n\n    private val _task: MutableLiveData<Task> = MutableLiveData(Task())\n    private val _attachments: MutableLiveData<ArrayList<Attachment>> =\n        MutableLiveData(arrayListOf())\n    private val _subject: MutableLiveData<Subject?> = MutableLiveData(null)\n    private val _isNameExists: MutableLiveData<Boolean> = MutableLiveData(false)\n\n    val task: LiveData<Task> = _task\n    val attachments: LiveData<List<Attachment>> = Transformations.map(_attachments) { it.toList() }\n    val subject: LiveData<Subject?> = _subject\n    val isNameExists: LiveData<Boolean> = _isNameExists\n\n    var schedules: ArrayList<Schedule> = arrayListOf()\n\n    fun getTask(): Task? {\n        return task.value\n    }\n\n    fun setTask(task: Task?) {\n        _task.value = task\n    }\n\n    fun getSubject(): Subject? {\n        return subject.value\n    }\n\n    fun setSubject(subject: Subject?) {\n        _subject.value = subject\n\n        if (subject != null) {\n            fetchSchedulesFromDatabase(subject.subjectID)\n            setTaskSubjectID(subject.subjectID)\n        } else {\n            schedules.clear()\n            setTaskSubjectID(null)\n        }\n    }\n\n    fun getAttachments(): List<Attachment> {\n        return attachments.value ?: emptyList()\n    }\n\n    fun setAttachments(items: ArrayList<Attachment>) {\n        _attachments.value = items\n    }\n\n    fun addAttachment(attachment: Attachment) {\n        val items = ArrayList(getAttachments())\n        items.add(attachment)\n        setAttachments(items.distinctBy { it.attachmentID }.toArrayList())\n    }\n\n    fun removeAttachment(attachment: Attachment) {\n        val items = ArrayList(getAttachments())\n        items.remove(attachment)\n        setAttachments(items.distinctBy { it.attachmentID }.toArrayList())\n    }\n\n\n    fun checkNameUniqueness(name: String?) = viewModelScope.launch {\n        val result = repository.checkNameUniqueness(name, getTask()?.taskID)\n        _isNameExists.value = !result.contains(name) && result.isNotEmpty()\n    }\n\n    fun getID(): String? {\n        return getTask()?.taskID\n    }\n\n    fun getName(): String? {\n        return getTask()?.name\n    }\n\n    fun setName(name: String?) {\n        // Check if the same value is being set\n        if (name == getName())\n            return\n\n        val task = getTask()\n        task?.name = name\n        setTask(task)\n    }\n\n    fun getDueDate(): ZonedDateTime? {\n        return getTask()?.dueDate\n    }\n\n    fun setDueDate(dueDate: ZonedDateTime?) {\n        val task = getTask()\n        task?.dueDate = dueDate\n        setTask(task)\n    }\n\n    fun getTaskSubjectID(): String? {\n        return getTask()?.subject\n    }\n\n    fun setTaskSubjectID(id: String?) {\n        val task = getTask()\n        task?.subject = id\n        setTask(task)\n    }\n\n    fun getImportant(): Boolean {\n        return getTask()?.isImportant == true\n    }\n\n    fun setImportant(isImportant: Boolean) {\n        val task = getTask()\n        task?.isImportant = isImportant\n        setTask(task)\n    }\n\n    fun getFinished(): Boolean {\n        return getTask()?.isFinished == true\n    }\n\n    fun setFinished(isFinished: Boolean) {\n        val task = getTask()\n        task?.isFinished = isFinished\n        setTask(task)\n    }\n\n    fun getNotes(): String? {\n        return getTask()?.notes\n    }\n\n    fun setNotes(notes: String?) {\n        // Check if the same value is being set\n        if (notes == getNotes())\n            return\n\n        val task = getTask()\n        task?.notes = notes\n        setTask(task)\n    }\n\n    fun hasFileAttachment(): Boolean {\n        return getAttachments().any {\n            it.type != Attachment.TYPE_WEBSITE_LINK\n        }\n    }\n\n    fun fetchRecentItemFromClipboard(): String =\n        clipboardManager.primaryClip?.getItemAt(0)?.text.toString()\n\n    fun setNextMeetingForDueDate() {\n        setDueDate(getDateTimeForNextMeeting())\n    }\n\n    fun setClassScheduleAsDueDate(schedule: Schedule) {\n        setDueDate(schedule.startTime?.let {\n            Schedule.getNearestDateTime(schedule.daysOfWeek, it)\n        })\n    }\n\n    private fun getDateTimeForNextMeeting(): ZonedDateTime? {\n        val currentDate = LocalDate.now()\n        val individualDates = mutableListOf<Schedule>()\n\n        // Create new instance of schedule with\n        // one day of week each\n        schedules.forEach {\n            it.parseDaysOfWeek().forEach { day ->\n                val newSchedule = Schedule(\n                    startTime = it.startTime,\n                    endTime = it.endTime\n                )\n                newSchedule.daysOfWeek = day\n                individualDates.add(newSchedule)\n            }\n        }\n\n        // Map the schedules to their respective\n        // dateTime instances\n        val dates = individualDates.map {\n            it.startTime?.let { time -> Schedule.getNearestDateTime(it.daysOfWeek, time) }\n        }\n        if (dates.isEmpty())\n            return null\n\n        return dates.singleOrNull {\n            currentDate.isAfter(it?.toLocalDate()) || currentDate.isEqual(it?.toLocalDate())\n        } ?: dates[0]\n    }\n\n    private fun fetchSchedulesFromDatabase(id: String) = viewModelScope.launch {\n        schedules.addAll(scheduleDao.fetchUsingID(id))\n    }\n\n    fun insert() = viewModelScope.launch(Dispatchers.IO + NonCancellable) {\n        getTask()?.let {\n            repository.insert(it, getAttachments())\n        }\n    }\n\n    fun update() = viewModelScope.launch(Dispatchers.IO + NonCancellable) {\n        getTask()?.let {\n            repository.update(it, getAttachments())\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/task/widget/TaskWidgetProvider.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.task.widget\n\nimport android.app.PendingIntent\nimport android.appwidget.AppWidgetManager\nimport android.appwidget.AppWidgetProvider\nimport android.content.ComponentName\nimport android.content.Context\nimport android.content.Intent\nimport android.widget.RemoteViews\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.features.core.activities.MainActivity\nimport com.isaiahvonrundstedt.fokus.features.task.editor.TaskEditorContainer\n\nclass TaskWidgetProvider : AppWidgetProvider() {\n\n    override fun onReceive(context: Context?, intent: Intent?) {\n        super.onReceive(context, intent)\n\n        if (intent?.action == WIDGET_ACTION_UPDATE) {\n            val manager = AppWidgetManager.getInstance(context)\n            val component = ComponentName(context!!, TaskWidgetProvider::class.java)\n\n            manager.notifyAppWidgetViewDataChanged(\n                manager.getAppWidgetIds(component),\n                R.id.listView\n            )\n        }\n    }\n\n    override fun onUpdate(\n        context: Context?, appWidgetManager: AppWidgetManager?,\n        appWidgetIds: IntArray?\n    ) {\n        super.onUpdate(context, appWidgetManager, appWidgetIds)\n\n        appWidgetIds?.forEach {\n            onUpdateWidget(context, appWidgetManager, it)\n        }\n    }\n\n    private fun onUpdateWidget(context: Context?, manager: AppWidgetManager?, id: Int) {\n        val mainIntent = PendingIntent.getActivity(\n            context, 0,\n            Intent(context, MainActivity::class.java).apply {\n                action = MainActivity.ACTION_NAVIGATION_TASK\n            }, PendingIntent.FLAG_IMMUTABLE\n        )\n\n        val itemIntent = PendingIntent.getActivity(\n            context, 0,\n            Intent(context, MainActivity::class.java).apply {\n                action = MainActivity.ACTION_WIDGET_TASK\n            }, PendingIntent.FLAG_IMMUTABLE\n        )\n\n        val addIntent = PendingIntent.getActivity(\n            context, 0,\n            Intent(context, TaskEditorContainer::class.java),\n            PendingIntent.FLAG_IMMUTABLE\n        )\n\n        val views = RemoteViews(context?.packageName, R.layout.layout_widget_tasks)\n        with(views) {\n            setOnClickPendingIntent(R.id.rootView, mainIntent)\n            setRemoteAdapter(R.id.listView, Intent(context, TaskWidgetService::class.java))\n            setPendingIntentTemplate(R.id.listView, itemIntent)\n            setEmptyView(R.id.listView, R.id.emptyView)\n            setOnClickPendingIntent(R.id.actionButton, addIntent)\n        }\n\n        manager?.notifyAppWidgetViewDataChanged(id, R.id.listView)\n        manager?.updateAppWidget(id, views)\n    }\n\n    companion object {\n        private const val WIDGET_ACTION_UPDATE = \"widget:task:update\"\n\n        fun triggerRefresh(context: Context?) {\n            context?.sendBroadcast(Intent(WIDGET_ACTION_UPDATE).apply {\n                component = ComponentName(context, TaskWidgetProvider::class.java)\n            })\n        }\n\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/task/widget/TaskWidgetRemoteViewFactory.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.task.widget\n\nimport android.content.Context\nimport android.content.Intent\nimport android.view.View\nimport android.widget.RemoteViews\nimport android.widget.RemoteViewsService\nimport com.isaiahvonrundstedt.fokus.R\nimport com.isaiahvonrundstedt.fokus.components.extensions.android.putExtra\nimport com.isaiahvonrundstedt.fokus.database.AppDatabase\nimport com.isaiahvonrundstedt.fokus.features.core.activities.MainActivity\nimport com.isaiahvonrundstedt.fokus.features.task.TaskPackage\nimport kotlinx.coroutines.async\nimport kotlinx.coroutines.runBlocking\n\nclass TaskWidgetRemoteViewFactory(private var context: Context) :\n    RemoteViewsService.RemoteViewsFactory {\n\n    private var itemList = mutableListOf<TaskPackage>()\n\n    private fun fetch() {\n        itemList.clear()\n\n        val tasks = AppDatabase.getInstance(context).tasks()\n        var items = emptyList<TaskPackage>()\n        runBlocking {\n            val job = async { tasks.fetchAsPackage() }\n            items = job.await() ?: emptyList()\n            items.forEach { if (it.task.isDueToday() || !it.task.hasDueDate()) itemList.add(it) }\n        }\n    }\n\n    override fun onDataSetChanged() = fetch()\n\n    override fun getLoadingView(): RemoteViews =\n        RemoteViews(context.packageName, R.layout.layout_widget_progress)\n\n    override fun getItemId(position: Int): Long = position.toLong()\n\n    override fun hasStableIds(): Boolean = true\n\n    override fun getViewAt(position: Int): RemoteViews {\n        val task = itemList[position].task\n        val subject = itemList[position].subject\n        val attachments = itemList[position].attachments\n\n        val itemIntent = Intent().apply {\n            putExtra(MainActivity.EXTRA_TASK, task)\n            putExtra(MainActivity.EXTRA_SUBJECT, subject)\n            putExtra(MainActivity.EXTRA_ATTACHMENTS, attachments)\n        }\n\n        val views = RemoteViews(context.packageName, R.layout.layout_item_widget)\n        with(views) {\n            setTextViewText(R.id.titleView, task.name)\n            if (task.hasDueDate())\n                setTextViewText(R.id.summaryView, task.formatDueDate(context))\n            else setViewVisibility(R.id.summaryView, View.GONE)\n            setOnClickFillInIntent(R.id.rootView, itemIntent)\n            if (subject != null)\n                setInt(R.id.imageView, \"setColorFilter\", subject.tag.color)\n            else setViewVisibility(R.id.imageView, View.GONE)\n        }\n        return views\n    }\n\n    override fun getCount(): Int = itemList.size\n\n    override fun getViewTypeCount(): Int = 1\n\n    override fun onCreate() {}\n\n    override fun onDestroy() {}\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/task/widget/TaskWidgetService.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.task.widget\n\nimport android.content.Intent\nimport android.widget.RemoteViewsService\n\nclass TaskWidgetService : RemoteViewsService() {\n\n    override fun onGetViewFactory(intent: Intent?): RemoteViewsFactory {\n        return TaskWidgetRemoteViewFactory(applicationContext)\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/isaiahvonrundstedt/fokus/features/viewer/ImageViewer.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.viewer\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.os.bundleOf\nimport androidx.fragment.app.FragmentManager\nimport coil.load\nimport com.isaiahvonrundstedt.fokus.databinding.LayoutViewerImageBinding\nimport com.isaiahvonrundstedt.fokus.features.shared.abstracts.BaseViewerFragment\nimport java.io.File\n\nclass ImageViewer(manager: FragmentManager) : BaseViewerFragment(manager) {\n    private var _binding: LayoutViewerImageBinding? = null\n\n    private val binding get() = _binding!!\n\n    override fun onCreateView(\n        inflater: LayoutInflater, container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        _binding = LayoutViewerImageBinding.inflate(inflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n\n        with(binding.appBarLayout.toolbar) {\n            setNavigationOnClickListener { dismiss() }\n            title = arguments?.getString(EXTRA_TITLE) ?: arguments?.getString(EXTRA_IMAGE_PATH)\n        }\n\n        arguments?.getString(EXTRA_IMAGE_PATH)?.let {\n            binding.imageContainer.load(File(it))\n        }\n    }\n\n    companion object {\n        private const val EXTRA_TITLE = \"extra:title\"\n        private const val EXTRA_IMAGE_PATH = \"extra:path\"\n\n        fun show(manager: FragmentManager, path: String, title: String? = null) {\n            ImageViewer(manager).apply {\n                arguments = bundleOf(\n                    EXTRA_IMAGE_PATH to path,\n                    EXTRA_TITLE to title\n                )\n            }.show()\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/res/anim/anim_fade_in.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\">\r\n    <alpha\r\n        android:fromAlpha=\"0.0\"\r\n        android:toAlpha=\"1.0\"\r\n        android:interpolator=\"@android:anim/accelerate_interpolator\"\r\n        android:duration=\"400\"\r\n        android:repeatCount=\"0\" />\r\n</set>"
  },
  {
    "path": "app/src/main/res/anim/anim_slide_down.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <translate\n        android:duration=\"@android:integer/config_shortAnimTime\"\n        android:fromYDelta=\"0%p\"\n        android:interpolator=\"@android:anim/accelerate_interpolator\"\n        android:toYDelta=\"100%p\" />\n</set>"
  },
  {
    "path": "app/src/main/res/anim/anim_slide_up.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <translate\n        android:duration=\"@android:integer/config_shortAnimTime\"\n        android:fromYDelta=\"100%\"\n        android:interpolator=\"@android:anim/accelerate_interpolator\"\n        android:toXDelta=\"0\" />\n</set>"
  },
  {
    "path": "app/src/main/res/color/color_text_input_stroke.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:color=\"?attr/colorPrimary\"\n        android:state_hovered=\"true\"/>\n    <item android:color=\"?attr/colorPrimary\"\n        android:state_focused=\"true\"/>\n    <item android:color=\"?attr/colorPrimary\"\n        android:state_selected=\"true\"/>\n    <item android:color=\"?attr/colorSurfaceVariant\"/>\n\n</selector>"
  },
  {
    "path": "app/src/main/res/color/selector_chip_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:color=\"@color/color_chip_background_transparent\"\n        android:state_checked=\"true\"/>\n    <item android:color=\"@color/color_chip_background_transparent\"\n        android:state_selected=\"true\"/>\n    <item android:color=\"?attr/colorPrimaryContainer\"/>\n\n</selector>"
  },
  {
    "path": "app/src/main/res/color/selector_chip_stroke_color.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:color=\"@android:color/transparent\"\n        android:state_checked=\"true\"/>\n    <item android:color=\"@android:color/transparent\"\n        android:state_selected=\"true\"/>\n    <item android:color=\"@color/color_text_input_stroke\"/>\n\n</selector>"
  },
  {
    "path": "app/src/main/res/color/selector_chip_text_color.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:color=\"?attr/colorPrimary\"\n        android:state_checked=\"true\"/>\n    <item android:color=\"?attr/colorPrimary\"\n        android:state_selected=\"true\"/>\n    <item android:color=\"?attr/colorOnPrimary\"/>\n\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/ic_hero_sort_ascending_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorOnSurfaceVariant\">\n  <path\n      android:pathData=\"M3,4H16M3,8H12M3,12H9M13,12L17,8M17,8L21,12M17,8V20\"\n      android:strokeLineJoin=\"round\"\n      android:strokeWidth=\"2\"\n      android:fillColor=\"#00000000\"\n      android:strokeColor=\"#4A5568\"\n      android:strokeLineCap=\"round\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_hero_sort_descending_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorOnSurfaceVariant\">\n  <path\n      android:pathData=\"M3,4H16M3,8H12M3,12H12M17,8V20M17,20L13,16M17,20L21,16\"\n      android:strokeLineJoin=\"round\"\n      android:strokeWidth=\"2\"\n      android:fillColor=\"#00000000\"\n      android:strokeColor=\"#4A5568\"\n      android:strokeLineCap=\"round\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_launcher_foreground.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    android:width=\"108dp\"\r\n    android:height=\"108dp\"\r\n    android:viewportWidth=\"108\"\r\n    android:viewportHeight=\"108\">\r\n  <group android:scaleX=\"0.09492187\"\r\n      android:scaleY=\"0.09492187\"\r\n      android:translateX=\"29.7\"\r\n      android:translateY=\"29.7\">\r\n    <path\r\n        android:pathData=\"m512,154.352 l-49.532,-49.532 -49.532,49.531 -203.292,104.237 -61.05,-61.05 -49.532,49.532 51.046,61.047 59.535,49.534 49.529,49.529z\"\r\n        android:fillColor=\"#00b0ff\"/>\r\n    <path\r\n        android:pathData=\"m412.938,154.352 l-49.532,-49.532 -203.296,203.295 -110.577,-110.577 -49.533,49.532 160.11,160.11z\"\r\n        android:fillColor=\"#69e2ff\"/>\r\n  </group>\r\n</vector>\r\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_launcher_monochrome.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    android:width=\"108dp\"\r\n    android:height=\"108dp\"\r\n    android:viewportWidth=\"108\"\r\n    android:viewportHeight=\"108\">\r\n  <group android:scaleX=\"0.09492187\"\r\n      android:scaleY=\"0.09492187\"\r\n      android:translateX=\"29.7\"\r\n      android:translateY=\"29.7\">\r\n    <path\r\n        android:pathData=\"m512,154.352 l-49.532,-49.532 -49.532,49.531 -203.292,104.237 -61.05,-61.05 -49.532,49.532 51.046,61.047 59.535,49.534 49.529,49.529z\"\r\n        android:fillColor=\"#000000\"\r\n        android:fillAlpha=\"0.7\"/>\r\n    <path\r\n        android:pathData=\"m412.938,154.352 l-49.532,-49.532 -203.296,203.295 -110.577,-110.577 -49.533,49.532 160.11,160.11z\"\r\n        android:fillColor=\"#000000\"\r\n        android:fillAlpha=\"0.9\"/>\r\n  </group>\r\n</vector>\r\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_access_time_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM12.5,7L11,7v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_add_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_archive_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M20.54,5.23l-1.39,-1.68C18.88,3.21 18.47,3 18,3L6,3c-0.47,0 -0.88,0.21 -1.16,0.55L3.46,5.23C3.17,5.57 3,6.02 3,6.5L3,19c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,6.5c0,-0.48 -0.17,-0.93 -0.46,-1.27zM6.24,5h11.52l0.81,0.97L5.44,5.97l0.8,-0.97zM5,19L5,8h14v11L5,19zM13.45,10h-2.9v3L8,13l4,4 4,-4h-2.55z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_arrow_back_24.xml",
    "content": "<vector android:autoMirrored=\"true\" android:height=\"24dp\"\n    android:tint=\"?attr/colorOnSurfaceVariant\" android:viewportHeight=\"24\"\n    android:viewportWidth=\"24\" android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_attach_file_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M16.5,6v11.5c0,2.21 -1.79,4 -4,4s-4,-1.79 -4,-4V5c0,-1.38 1.12,-2.5 2.5,-2.5s2.5,1.12 2.5,2.5v10.5c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1V6H10v9.5c0,1.38 1.12,2.5 2.5,2.5s2.5,-1.12 2.5,-2.5V5c0,-2.21 -1.79,-4 -4,-4S7,2.79 7,5v12.5c0,3.04 2.46,5.5 5.5,5.5s5.5,-2.46 5.5,-5.5V6h-1.5z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_balance_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M13,7.83c0.85,-0.3 1.53,-0.98 1.83,-1.83H18l-3,7c0,1.66 1.57,3 3.5,3s3.5,-1.34 3.5,-3l-3,-7h2V4h-6.17C14.42,2.83 13.31,2 12,2S9.58,2.83 9.17,4L3,4v2h2l-3,7c0,1.66 1.57,3 3.5,3S9,14.66 9,13L6,6h3.17c0.3,0.85 0.98,1.53 1.83,1.83V19H2v2h20v-2h-9V7.83zM20.37,13h-3.74l1.87,-4.36L20.37,13zM7.37,13H3.63L5.5,8.64L7.37,13zM12,6c-0.55,0 -1,-0.45 -1,-1c0,-0.55 0.45,-1 1,-1s1,0.45 1,1C13,5.55 12.55,6 12,6z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_calendar_month_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M19,4h-1V2h-2v2H8V2H6v2H5C3.89,4 3.01,4.9 3.01,6L3,20c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2V6C21,4.9 20.1,4 19,4zM19,20H5V10h14V20zM19,8H5V6h14V8zM9,14H7v-2h2V14zM13,14h-2v-2h2V14zM17,14h-2v-2h2V14zM9,18H7v-2h2V18zM13,18h-2v-2h2V18zM17,18h-2v-2h2V18z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_celebration_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M2,22l14,-5L7,8L2,22zM12.35,16.18L5.3,18.7l2.52,-7.05L12.35,16.18z\"/>\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M14.53,12.53l5.59,-5.59c0.49,-0.49 1.28,-0.49 1.77,0l0.59,0.59l1.06,-1.06l-0.59,-0.59c-1.07,-1.07 -2.82,-1.07 -3.89,0l-5.59,5.59L14.53,12.53z\"/>\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M10.06,6.88L9.47,7.47l1.06,1.06l0.59,-0.59c1.07,-1.07 1.07,-2.82 0,-3.89l-0.59,-0.59L9.47,4.53l0.59,0.59C10.54,5.6 10.54,6.4 10.06,6.88z\"/>\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M17.06,11.88l-1.59,1.59l1.06,1.06l1.59,-1.59c0.49,-0.49 1.28,-0.49 1.77,0l1.61,1.61l1.06,-1.06l-1.61,-1.61C19.87,10.81 18.13,10.81 17.06,11.88z\"/>\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M15.06,5.88l-3.59,3.59l1.06,1.06l3.59,-3.59c1.07,-1.07 1.07,-2.82 0,-3.89l-1.59,-1.59l-1.06,1.06l1.59,1.59C15.54,4.6 15.54,5.4 15.06,5.88z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_check_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41L9,16.17z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_checklist_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M22,7h-9v2h9V7zM22,15h-9v2h9V15zM5.54,11L2,7.46l1.41,-1.41l2.12,2.12l4.24,-4.24l1.41,1.41L5.54,11zM5.54,19L2,15.46l1.41,-1.41l2.12,2.12l4.24,-4.24l1.41,1.41L5.54,19z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_close_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12 19,6.41z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_code_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M9.4,16.6L4.8,12l4.6,-4.6L8,6l-6,6 6,6 1.4,-1.4zM14.6,16.6l4.6,-4.6 -4.6,-4.6L16,6l6,6 -6,6 -1.4,-1.4z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_color_lens_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M12,22C6.49,22 2,17.51 2,12S6.49,2 12,2s10,4.04 10,9c0,3.31 -2.69,6 -6,6h-1.77c-0.28,0 -0.5,0.22 -0.5,0.5 0,0.12 0.05,0.23 0.13,0.33 0.41,0.47 0.64,1.06 0.64,1.67 0,1.38 -1.12,2.5 -2.5,2.5zM12,4c-4.41,0 -8,3.59 -8,8s3.59,8 8,8c0.28,0 0.5,-0.22 0.5,-0.5 0,-0.16 -0.08,-0.28 -0.14,-0.35 -0.41,-0.46 -0.63,-1.05 -0.63,-1.65 0,-1.38 1.12,-2.5 2.5,-2.5L16,15c2.21,0 4,-1.79 4,-4 0,-3.86 -3.59,-7 -8,-7z\"/>\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M6.5,11.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0\"/>\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M9.5,7.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0\"/>\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M14.5,7.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0\"/>\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M17.5,11.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_confirmation_number_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M22,10L22,6c0,-1.11 -0.9,-2 -2,-2L4,4c-1.1,0 -1.99,0.89 -1.99,2v4c1.1,0 1.99,0.9 1.99,2s-0.89,2 -2,2v4c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2v-4c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2zM20,8.54c-1.19,0.69 -2,1.99 -2,3.46s0.81,2.77 2,3.46L20,18L4,18v-2.54c1.19,-0.69 2,-1.99 2,-3.46 0,-1.48 -0.8,-2.77 -1.99,-3.46L4,6h16v2.54zM11,15h2v2h-2zM11,11h2v2h-2zM11,7h2v2h-2z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_date_range_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M7,11h2v2L7,13v-2zM21,6v14c0,1.1 -0.9,2 -2,2L5,22c-1.11,0 -2,-0.9 -2,-2l0.01,-14c0,-1.1 0.88,-2 1.99,-2h1L6,2h2v2h8L16,2h2v2h1c1.1,0 2,0.9 2,2zM5,8h14L19,6L5,6v2zM19,20L19,10L5,10v10h14zM15,13h2v-2h-2v2zM11,13h2v-2h-2v2z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_delete_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M16,9v10H8V9h8m-1.5,-6h-5l-1,1H5v2h14V4h-3.5l-1,-1zM18,7H6v12c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_edit_note_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M3,10h11v2H3V10zM3,8h11V6H3V8zM3,16h7v-2H3V16zM18.01,12.87l0.71,-0.71c0.39,-0.39 1.02,-0.39 1.41,0l0.71,0.71c0.39,0.39 0.39,1.02 0,1.41l-0.71,0.71L18.01,12.87zM17.3,13.58l-5.3,5.3V21h2.12l5.3,-5.3L17.3,13.58z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_event_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M19,4h-1L18,2h-2v2L8,4L8,2L6,2v2L5,4c-1.11,0 -1.99,0.9 -1.99,2L3,20c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,6c0,-1.1 -0.9,-2 -2,-2zM19,20L5,20L5,10h14v10zM19,8L5,8L5,6h14v2zM12,13h5v5h-5z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_event_busy_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M19,3h-1L18,1h-2v2L8,3L8,1L6,1v2L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM19,19L5,19L5,9h14v10zM5,7L5,5h14v2L5,7zM8.23,16.41l1.06,1.06 2.44,-2.44 2.44,2.44 1.06,-1.06 -2.44,-2.44 2.44,-2.44 -1.06,-1.06 -2.44,2.44 -2.44,-2.44 -1.06,1.06 2.44,2.44z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_event_repeat_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M21,12V6c0,-1.1 -0.9,-2 -2,-2h-1V2h-2v2H8V2H6v2H5C3.9,4 3,4.9 3,6v14c0,1.1 0.9,2 2,2h7v-2H5V10h14v2H21zM19,8H5V6h14V8zM15.64,20c0.43,1.45 1.77,2.5 3.36,2.5c1.93,0 3.5,-1.57 3.5,-3.5s-1.57,-3.5 -3.5,-3.5c-0.95,0 -1.82,0.38 -2.45,1l1.45,0V18h-4v-4h1.5l0,1.43C16.4,14.55 17.64,14 19,14c2.76,0 5,2.24 5,5s-2.24,5 -5,5c-2.42,0 -4.44,-1.72 -4.9,-4L15.64,20z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_file_download_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M18,15v3H6v-3H4v3c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2v-3H18zM17,11l-1.41,-1.41L13,12.17V4h-2v8.17L8.41,9.59L7,11l5,5L17,11z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_file_open_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M15,22H6c-1.1,0 -2,-0.9 -2,-2V4c0,-1.1 0.9,-2 2,-2h8l6,6v6h-2V9h-5V4H6v16h9V22zM19,21.66l0,-2.24l2.95,2.95l1.41,-1.41L20.41,18h2.24v-2H17v5.66H19z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_file_upload_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M18,15v3H6v-3H4v3c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2v-3H18zM7,9l1.41,1.41L11,7.83V16h2V7.83l2.59,2.58L17,9l-5,-5L7,9z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_filter_alt_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M7,6h10l-5.01,6.3L7,6zM4.25,5.61C6.27,8.2 10,13 10,13v6c0,0.55 0.45,1 1,1h2c0.55,0 1,-0.45 1,-1v-6c0,0 3.72,-4.8 5.74,-7.39C20.25,4.95 19.78,4 18.95,4H5.04C4.21,4 3.74,4.95 4.25,5.61z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_info_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M11,7h2v2h-2zM11,11h2v6h-2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_lightbulb_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M9,21c0,0.55 0.45,1 1,1h4c0.55,0 1,-0.45 1,-1v-1L9,20v1zM12,2C8.14,2 5,5.14 5,9c0,2.38 1.19,4.47 3,5.74L8,17c0,0.55 0.45,1 1,1h6c0.55,0 1,-0.45 1,-1v-2.26c1.81,-1.27 3,-3.36 3,-5.74 0,-3.86 -3.14,-7 -7,-7zM14.85,13.1l-0.85,0.6L14,16h-4v-2.3l-0.85,-0.6C7.8,12.16 7,10.63 7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,1.63 -0.8,3.16 -2.15,4.1z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_link_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M17,7h-4v2h4c1.65,0 3,1.35 3,3s-1.35,3 -3,3h-4v2h4c2.76,0 5,-2.24 5,-5s-2.24,-5 -5,-5zM11,15L7,15c-1.65,0 -3,-1.35 -3,-3s1.35,-3 3,-3h4L11,7L7,7c-2.76,0 -5,2.24 -5,5s2.24,5 5,5h4v-2zM8,11h8v2L8,13z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_location_on_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,2.88 -2.88,7.19 -5,9.88C9.92,16.21 7,11.85 7,9z\"/>\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M12,9m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_menu_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M3,18h18v-2L3,16v2zM3,13h18v-2L3,11v2zM3,6v2h18L21,6L3,6z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_more_vert_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_music_note_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M12,3l0.01,10.55c-0.59,-0.34 -1.27,-0.55 -2,-0.55C7.79,13 6,14.79 6,17s1.79,4 4.01,4S14,19.21 14,17L14,7h4L18,3h-6zM10.01,19c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_notes_24.xml",
    "content": "<vector android:autoMirrored=\"true\" android:height=\"24dp\"\n    android:tint=\"?attr/colorOnSurfaceVariant\" android:viewportHeight=\"24\"\n    android:viewportWidth=\"24\" android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M21,11.01L3,11v2h18zM3,16h12v2H3zM21,6H3v2.01L21,8z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_notifications_active_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.9,2 2,2zM18,16v-5c0,-3.07 -1.63,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.64,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2zM16,17L8,17v-6c0,-2.48 1.51,-4.5 4,-4.5s4,2.02 4,4.5v6zM7.58,4.08L6.15,2.65C3.75,4.48 2.17,7.3 2.03,10.5h2c0.15,-2.65 1.51,-4.97 3.55,-6.42zM19.97,10.5h2c-0.15,-3.2 -1.73,-6.02 -4.12,-7.85l-1.42,1.43c2.02,1.45 3.39,3.77 3.54,6.42z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_numbers_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M20.5,10L21,8h-4l1,-4h-2l-1,4h-4l1,-4h-2L9,8H5l-0.5,2h4l-1,4h-4L3,16h4l-1,4h2l1,-4h4l-1,4h2l1,-4h4l0.5,-2h-4l1,-4H20.5zM13.5,14h-4l1,-4h4L13.5,14z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_open_in_new_24.xml",
    "content": "<vector android:autoMirrored=\"true\" android:height=\"24dp\"\n    android:tint=\"?attr/colorOnSurfaceVariant\" android:viewportHeight=\"24\"\n    android:viewportWidth=\"24\" android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M19,19H5V5h7V3H5c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2v-7h-2v7zM14,3v2h3.59l-9.83,9.83 1.41,1.41L19,6.41V10h2V3h-7z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_person_2_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M18.39,14.56C16.71,13.7 14.53,13 12,13c-2.53,0 -4.71,0.7 -6.39,1.56C4.61,15.07 4,16.1 4,17.22V20h16v-2.78C20,16.1 19.39,15.07 18.39,14.56zM18,18H6v-0.78c0,-0.38 0.2,-0.72 0.52,-0.88C7.71,15.73 9.63,15 12,15c2.37,0 4.29,0.73 5.48,1.34C17.8,16.5 18,16.84 18,17.22V18z\"/>\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M9.78,12h4.44c1.21,0 2.14,-1.06 1.98,-2.26l-0.32,-2.45C15.57,5.39 13.92,4 12,4S8.43,5.39 8.12,7.29L7.8,9.74C7.64,10.94 8.57,12 9.78,12zM10.1,7.59C10.26,6.67 11.06,6 12,6s1.74,0.67 1.9,1.59L14.22,10H9.78L10.1,7.59z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_priority_high_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M12,19m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0\"/>\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M10,3h4v12h-4z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_query_stats_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M19.88,18.47c0.44,-0.7 0.7,-1.51 0.7,-2.39c0,-2.49 -2.01,-4.5 -4.5,-4.5s-4.5,2.01 -4.5,4.5s2.01,4.5 4.49,4.5c0.88,0 1.7,-0.26 2.39,-0.7L21.58,23L23,21.58L19.88,18.47zM16.08,18.58c-1.38,0 -2.5,-1.12 -2.5,-2.5c0,-1.38 1.12,-2.5 2.5,-2.5s2.5,1.12 2.5,2.5C18.58,17.46 17.46,18.58 16.08,18.58zM15.72,10.08c-0.74,0.02 -1.45,0.18 -2.1,0.45l-0.55,-0.83l-3.8,6.18l-3.01,-3.52l-3.63,5.81L1,17l5,-8l3,3.5L13,6C13,6 15.72,10.08 15.72,10.08zM18.31,10.58c-0.64,-0.28 -1.33,-0.45 -2.05,-0.49c0,0 5.12,-8.09 5.12,-8.09L23,3.18L18.31,10.58z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_save_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM19,19L5,19L5,5h11.17L19,7.83L19,19zM12,12c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3zM6,6h9v4L6,10z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_science_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M13,11.33L18,18H6l5,-6.67V6h2M15.96,4H8.04C7.62,4 7.39,4.48 7.65,4.81L9,6.5v4.17L3.2,18.4C2.71,19.06 3.18,20 4,20h16c0.82,0 1.29,-0.94 0.8,-1.6L15,10.67V6.5l1.35,-1.69C16.61,4.48 16.38,4 15.96,4L15.96,4z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_sensor_door_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M18,4v16H6V4H18M18,2H6C4.9,2 4,2.9 4,4v18h16V4C20,2.9 19.1,2 18,2L18,2zM15.5,10.5c-0.83,0 -1.5,0.67 -1.5,1.5s0.67,1.5 1.5,1.5c0.83,0 1.5,-0.67 1.5,-1.5S16.33,10.5 15.5,10.5z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_settings_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98 0,-0.34 -0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.09,-0.16 -0.26,-0.25 -0.44,-0.25 -0.06,0 -0.12,0.01 -0.17,0.03l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.06,-0.02 -0.12,-0.03 -0.18,-0.03 -0.17,0 -0.34,0.09 -0.43,0.25l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98 0,0.33 0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.09,0.16 0.26,0.25 0.44,0.25 0.06,0 0.12,-0.01 0.17,-0.03l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.06,0.02 0.12,0.03 0.18,0.03 0.17,0 0.34,-0.09 0.43,-0.25l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM17.45,11.27c0.04,0.31 0.05,0.52 0.05,0.73 0,0.21 -0.02,0.43 -0.05,0.73l-0.14,1.13 0.89,0.7 1.08,0.84 -0.7,1.21 -1.27,-0.51 -1.04,-0.42 -0.9,0.68c-0.43,0.32 -0.84,0.56 -1.25,0.73l-1.06,0.43 -0.16,1.13 -0.2,1.35h-1.4l-0.19,-1.35 -0.16,-1.13 -1.06,-0.43c-0.43,-0.18 -0.83,-0.41 -1.23,-0.71l-0.91,-0.7 -1.06,0.43 -1.27,0.51 -0.7,-1.21 1.08,-0.84 0.89,-0.7 -0.14,-1.13c-0.03,-0.31 -0.05,-0.54 -0.05,-0.74s0.02,-0.43 0.05,-0.73l0.14,-1.13 -0.89,-0.7 -1.08,-0.84 0.7,-1.21 1.27,0.51 1.04,0.42 0.9,-0.68c0.43,-0.32 0.84,-0.56 1.25,-0.73l1.06,-0.43 0.16,-1.13 0.2,-1.35h1.39l0.19,1.35 0.16,1.13 1.06,0.43c0.43,0.18 0.83,0.41 1.23,0.71l0.91,0.7 1.06,-0.43 1.27,-0.51 0.7,1.21 -1.07,0.85 -0.89,0.7 0.14,1.13zM12,8c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zM12,14c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_share_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92s2.92,-1.31 2.92,-2.92c0,-1.61 -1.31,-2.92 -2.92,-2.92zM18,4c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM6,13c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1zM18,20.02c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_translate_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M12.87,15.07l-2.54,-2.51 0.03,-0.03c1.74,-1.94 2.98,-4.17 3.71,-6.53L17,6L17,4h-7L10,2L8,2v2L1,4v1.99h11.17C11.5,7.92 10.44,9.75 9,11.35 8.07,10.32 7.3,9.19 6.69,8h-2c0.73,1.63 1.73,3.17 2.98,4.56l-5.09,5.02L4,19l5,-5 3.11,3.11 0.76,-2.04zM18.5,10h-2L12,22h2l1.12,-3h4.75L21,22h2l-4.5,-12zM15.88,17l1.62,-4.33L19.12,17h-3.24z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_verified_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M23,11.99l-2.44,-2.79l0.34,-3.69l-3.61,-0.82L15.4,1.5L12,2.96L8.6,1.5L6.71,4.69L3.1,5.5L3.44,9.2L1,11.99l2.44,2.79l-0.34,3.7l3.61,0.82L8.6,22.5l3.4,-1.47l3.4,1.46l1.89,-3.19l3.61,-0.82l-0.34,-3.69L23,11.99zM19.05,13.47l-0.56,0.65l0.08,0.85l0.18,1.95l-1.9,0.43l-0.84,0.19l-0.44,0.74l-0.99,1.68l-1.78,-0.77L12,18.85l-0.79,0.34l-1.78,0.77l-0.99,-1.67l-0.44,-0.74l-0.84,-0.19l-1.9,-0.43l0.18,-1.96l0.08,-0.85l-0.56,-0.65l-1.29,-1.47l1.29,-1.48l0.56,-0.65L5.43,9.01L5.25,7.07l1.9,-0.43l0.84,-0.19l0.44,-0.74l0.99,-1.68l1.78,0.77L12,5.14l0.79,-0.34l1.78,-0.77l0.99,1.68l0.44,0.74l0.84,0.19l1.9,0.43l-0.18,1.95l-0.08,0.85l0.56,0.65l1.29,1.47L19.05,13.47z\"/>\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M10.09,13.75l-2.32,-2.33l-1.48,1.49l3.8,3.81l7.34,-7.36l-1.48,-1.49z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_wb_sunny_24.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"?attr/colorOnSurfaceVariant\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M6.76,4.84l-1.8,-1.79 -1.41,1.41 1.79,1.79zM1,10.5h3v2L1,12.5zM11,0.55h2L13,3.5h-2zM19.04,3.045l1.408,1.407 -1.79,1.79 -1.407,-1.408zM17.24,18.16l1.79,1.8 1.41,-1.41 -1.8,-1.79zM20,10.5h3v2h-3zM12,5.5c-3.31,0 -6,2.69 -6,6s2.69,6 6,6 6,-2.69 6,-6 -2.69,-6 -6,-6zM12,15.5c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4 4,1.79 4,4 -1.79,4 -4,4zM11,19.5h2v2.95h-2zM3.55,18.54l1.41,1.41 1.79,-1.8 -1.41,-1.41z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/selector_checkbox.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<animated-selector\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\">\r\n    <item\r\n        android:id=\"@+id/state_checked\"\r\n        android:drawable=\"@drawable/vector_checked\"\r\n        android:state_checked=\"true\" />\r\n    <item\r\n        android:id=\"@+id/state_unchecked\"\r\n        android:drawable=\"@drawable/vector_unchecked\" />\r\n\r\n    <transition\r\n        android:drawable=\"@drawable/toggle_unchecked_to_checked\"\r\n        android:fromId=\"@id/state_unchecked\"\r\n        android:toId=\"@id/state_checked\"/>\r\n\r\n    <transition\r\n        android:drawable=\"@drawable/toggle_checked_to_unchecked\"\r\n        android:fromId=\"@id/state_checked\"\r\n        android:toId=\"@id/state_unchecked\"/>\r\n\r\n</animated-selector>"
  },
  {
    "path": "app/src/main/res/drawable/shape_bottom_sheet.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    android:shape=\"rectangle\">\r\n    <solid android:color=\"?attr/colorSurface\"/>\r\n    <corners android:topLeftRadius=\"@dimen/surface_corner_radius\"\r\n        android:topRightRadius=\"@dimen/surface_corner_radius\"/>\r\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_calendar_current_day.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"oval\">\n    <solid android:color=\"?attr/colorPrimaryContainer\"/>\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_calendar_selected_day.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"oval\">\n\n    <stroke android:color=\"?attr/colorPrimary\"\n        android:width=\"2dp\"/>\n\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_cascade_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <corners android:radius=\"@dimen/surface_corner_radius\"/>\n    <solid android:color=\"?attr/colorSurface\"/>\n    <padding android:top=\"@dimen/item_padding_small\"\n        android:bottom=\"@dimen/item_padding_small\"/>\n\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_color_holder.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    android:shape=\"oval\">\r\n\r\n    <solid\r\n        android:color=\"#2196f3\"/>\r\n\r\n    <size\r\n        android:width=\"24dp\"\r\n        android:height=\"24dp\"/>\r\n\r\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_color_holder_chip.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    android:shape=\"oval\">\r\n\r\n    <size android:width=\"12dp\" android:height=\"12dp\"/>\r\n\r\n    <solid android:color=\"?attr/colorSurface\"/>\r\n\r\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_color_holder_vertical.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<shape\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    android:shape=\"rectangle\">\r\n\r\n    <corners android:radius=\"4dp\"/>\r\n    <size android:width=\"8dp\"/>\r\n    <solid android:color=\"?attr/colorSurface\"/>\r\n\r\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_icon_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\">\n\n    <corners android:radius=\"@dimen/surface_corner_radius\"/>\n    <solid android:color=\"?attr/colorPrimaryContainer\"/>\n    <size android:width=\"@dimen/icon_width\"\n        android:height=\"@dimen/icon_height\"/>\n\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_widget_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    android:shape=\"rectangle\">\r\n\r\n    <corners android:radius=\"@dimen/surface_corner_radius\"/>\r\n    <solid android:color=\"?android:attr/colorBackground\"/>\r\n\r\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shortcut_icon_base_event.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"@color/theme_on_primary_container\">\n  <path\n      android:pathData=\"M8,7V3M16,7V3M7,11H17M5,21H19C20.1046,21 21,20.1046 21,19V7C21,5.8954 20.1046,5 19,5H5C3.8954,5 3,5.8954 3,7V19C3,20.1046 3.8954,21 5,21Z\"\n      android:strokeLineJoin=\"round\"\n      android:strokeWidth=\"2\"\n      android:fillColor=\"#00000000\"\n      android:strokeColor=\"#4A5568\"\n      android:strokeLineCap=\"round\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/shortcut_icon_base_subject.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"@color/theme_on_primary_container\">\n  <path\n      android:pathData=\"M19.428,15.4282C19.1488,15.149 18.7932,14.9587 18.406,14.8812L16.0185,14.4037C14.7101,14.1421 13.3519,14.324 12.1585,14.9207L11.8411,15.0793C10.6477,15.676 9.2895,15.8579 7.9811,15.5963L6.0494,15.2099C5.3937,15.0788 4.7158,15.284 4.2429,15.7569M7.9998,4H15.9998L14.9998,5V10.1716C14.9998,10.702 15.2105,11.2107 15.5856,11.5858L20.5856,16.5858C21.8455,17.8457 20.9532,20 19.1714,20H4.8282C3.0464,20 2.1541,17.8457 3.414,16.5858L8.414,11.5858C8.7891,11.2107 8.9998,10.702 8.9998,10.1716V5L7.9998,4Z\"\n      android:strokeLineJoin=\"round\"\n      android:strokeWidth=\"2\"\n      android:fillColor=\"#00000000\"\n      android:strokeColor=\"#374151\"\n      android:strokeLineCap=\"round\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/shortcut_icon_base_task.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"@color/theme_on_primary_container\">\n  <path\n      android:pathData=\"M5,13L9,17L19,7\"\n      android:strokeLineJoin=\"round\"\n      android:strokeWidth=\"2\"\n      android:fillColor=\"#00000000\"\n      android:strokeColor=\"#4A5568\"\n      android:strokeLineCap=\"round\"/>\n</vector>\n\n"
  },
  {
    "path": "app/src/main/res/drawable/shortcut_icon_event.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\r\n\r\n    <item>\r\n        <shape android:shape=\"oval\">\r\n            <solid android:color=\"@color/theme_primary_container\"/>\r\n        </shape>\r\n    </item>\r\n\r\n    <item\r\n        android:drawable=\"@drawable/shortcut_icon_base_event\"\r\n        android:top=\"@dimen/drawable_icon_padding\"\r\n        android:bottom=\"@dimen/drawable_icon_padding\"\r\n        android:left=\"@dimen/drawable_icon_padding\"\r\n        android:right=\"@dimen/drawable_icon_padding\"/>\r\n\r\n</layer-list>"
  },
  {
    "path": "app/src/main/res/drawable/shortcut_icon_subject.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\r\n\r\n    <item>\r\n        <shape android:shape=\"oval\">\r\n            <solid android:color=\"@color/theme_primary_container\"/>\r\n        </shape>\r\n    </item>\r\n\r\n    <item\r\n        android:drawable=\"@drawable/shortcut_icon_base_subject\"\r\n        android:top=\"@dimen/drawable_icon_padding\"\r\n        android:bottom=\"@dimen/drawable_icon_padding\"\r\n        android:left=\"@dimen/drawable_icon_padding\"\r\n        android:right=\"@dimen/drawable_icon_padding\"/>\r\n\r\n</layer-list>"
  },
  {
    "path": "app/src/main/res/drawable/shortcut_icon_task.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\r\n\r\n    <item>\r\n        <shape android:shape=\"oval\">\r\n            <solid android:color=\"@color/theme_primary_container\"/>\r\n        </shape>\r\n    </item>\r\n\r\n    <item\r\n        android:drawable=\"@drawable/shortcut_icon_base_task\"\r\n        android:top=\"@dimen/drawable_icon_padding\"\r\n        android:bottom=\"@dimen/drawable_icon_padding\"\r\n        android:left=\"@dimen/drawable_icon_padding\"\r\n        android:right=\"@dimen/drawable_icon_padding\"/>\r\n\r\n</layer-list>"
  },
  {
    "path": "app/src/main/res/drawable/toggle_checked_to_unchecked.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<animated-vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\r\n    android:drawable=\"@drawable/vector_checked\">\r\n\r\n    <target android:name=\"tick\">\r\n        <aapt:attr name=\"android:animation\">\r\n            <objectAnimator\r\n                android:duration=\"@android:integer/config_shortAnimTime\"\r\n                android:interpolator=\"@android:interpolator/decelerate_cubic\"\r\n                android:propertyName=\"trimPathEnd\"\r\n                android:valueFrom=\"1\"\r\n                android:valueTo=\"0\"\r\n                android:valueType=\"floatType\" />\r\n        </aapt:attr>\r\n    </target>\r\n\r\n    <target android:name=\"circle\">\r\n        <aapt:attr name=\"android:animation\">\r\n            <objectAnimator\r\n                android:duration=\"@android:integer/config_shortAnimTime\"\r\n                android:interpolator=\"@android:interpolator/accelerate_decelerate\"\r\n                android:propertyName=\"strokeColor\"\r\n                android:valueFrom=\"@color/theme_primary\"\r\n                android:valueTo=\"@color/color_secondary_text\"\r\n                android:valueType=\"intType\" />\r\n        </aapt:attr>\r\n    </target>\r\n</animated-vector>"
  },
  {
    "path": "app/src/main/res/drawable/toggle_unchecked_to_checked.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<animated-vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\r\n    android:drawable=\"@drawable/vector_checked\">\r\n\r\n    <target android:name=\"tick\">\r\n        <aapt:attr name=\"android:animation\">\r\n            <objectAnimator\r\n                android:duration=\"@android:integer/config_shortAnimTime\"\r\n                android:interpolator=\"@android:interpolator/accelerate_cubic\"\r\n                android:propertyName=\"trimPathEnd\"\r\n                android:valueFrom=\"0\"\r\n                android:valueTo=\"1\"\r\n                android:valueType=\"floatType\"/>\r\n        </aapt:attr>\r\n    </target>\r\n\r\n    <target android:name=\"circle\">\r\n        <aapt:attr name=\"android:animation\">\r\n            <objectAnimator\r\n                android:duration=\"@android:integer/config_shortAnimTime\"\r\n                android:interpolator=\"@android:interpolator/accelerate_decelerate\"\r\n                android:propertyName=\"strokeColor\"\r\n                android:valueFrom=\"@color/color_secondary_text\"\r\n                android:valueTo=\"@color/theme_primary\"\r\n                android:valueType=\"intType\" />\r\n        </aapt:attr>\r\n    </target>\r\n\r\n</animated-vector>"
  },
  {
    "path": "app/src/main/res/drawable/vector_checked.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    android:width=\"32dp\"\r\n    android:height=\"32dp\"\r\n    android:viewportHeight=\"24\"\r\n    android:viewportWidth=\"24\">\r\n\r\n    <path\r\n        android:name=\"tick\"\r\n        android:pathData=\"M7,12.448 L10.254,15.348 L17.265,9\"\r\n        android:strokeColor=\"@color/theme_primary\"\r\n        android:strokeLineCap=\"round\"\r\n        android:strokeLineJoin=\"round\"\r\n        android:strokeWidth=\"1.5\" />\r\n\r\n    <path\r\n        android:name=\"circle\"\r\n        android:pathData=\"M12,2 C17.5228,2,22,6.47715,22,12 C22,17.5228,17.5228,22,12,22 C6.47715,22,2,17.5228,2,12 C2,6.47715,6.47715,2,12,2 Z\"\r\n        android:strokeColor=\"@color/theme_primary\"\r\n        android:strokeWidth=\"1.5\" />\r\n</vector>"
  },
  {
    "path": "app/src/main/res/drawable/vector_unchecked.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    android:width=\"32dp\"\r\n    android:height=\"32dp\"\r\n    android:viewportHeight=\"24\"\r\n    android:viewportWidth=\"24\">\r\n\r\n    <path\r\n        android:name=\"circle\"\r\n        android:pathData=\"M12,2 C17.5228,2,22,6.47715,22,12 C22,17.5228,17.5228,22,12,22 C6.47715,22,2,17.5228,2,12 C2,6.47715,6.47715,2,12,2 Z\"\r\n        android:strokeColor=\"@color/color_secondary_text\"\r\n        android:strokeWidth=\"1.5\" />\r\n</vector>"
  },
  {
    "path": "app/src/main/res/layout/activity_attach_to_task.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <include\n        android:id=\"@+id/appBarLayout\"\n        layout=\"@layout/layout_appbar\"/>\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:orientation=\"vertical\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\n\n        <com.google.android.material.card.MaterialCardView\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_margin=\"@dimen/item_padding\">\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:padding=\"@dimen/item_padding\"\n                android:orientation=\"vertical\">\n\n                <TextView\n                    android:id=\"@+id/titleView\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:textAppearance=\"@style/Fokus.TextAppearance.Title.Large\"\n                    tools:text=\"mdpf.pdf\"/>\n\n                <TextView\n                    android:id=\"@+id/summaryView\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:maxLines=\"3\"\n                    android:ellipsize=\"end\"\n                    android:textAppearance=\"@style/Fokus.TextAppearance.Body.Medium\"\n                    tools:text=\"anything\"/>\n\n            </LinearLayout>\n\n        </com.google.android.material.card.MaterialCardView>\n\n        <androidx.recyclerview.widget.RecyclerView\n            android:id=\"@+id/recyclerView\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"/>\n\n    </LinearLayout>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_container_event.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <fragment\n        android:id=\"@+id/containerNavHost\"\n        android:name=\"androidx.navigation.fragment.NavHostFragment\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:navGraph=\"@navigation/navigation_container_event\"\n        tools:ignore=\"FragmentTagUsage\"/>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_container_subject.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <fragment\n        android:id=\"@+id/containerNavHost\"\n        android:name=\"androidx.navigation.fragment.NavHostFragment\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:navGraph=\"@navigation/navigation_container_subject\"\n        tools:ignore=\"FragmentTagUsage\"/>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_container_task.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <fragment\n        android:id=\"@+id/containerNavHost\"\n        android:name=\"androidx.navigation.fragment.NavHostFragment\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:navGraph=\"@navigation/navigation_container_task\"\n        tools:ignore=\"FragmentTagUsage\"/>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <fragment\n        android:id=\"@+id/navigationHostFragment\"\n        android:name=\"androidx.navigation.fragment.NavHostFragment\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:defaultNavHost=\"true\"\n        app:navGraph=\"@navigation/navigation_main\"\n        tools:ignore=\"FragmentTagUsage\" />\n\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_about.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <include\n        android:id=\"@+id/appBarLayout\"\n        layout=\"@layout/layout_appbar\"/>\n\n    <fragment\n        android:id=\"@+id/container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.about.AboutFragment$Companion$AboutFragment\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"\n        tools:ignore=\"FragmentTagUsage\"/>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_archived_event.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <include\n        android:id=\"@+id/appBarLayout\"\n        layout=\"@layout/layout_appbar\"/>\n\n    <androidx.recyclerview.widget.RecyclerView\n        android:id=\"@+id/recyclerView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"/>\n\n    <LinearLayout\n        android:id=\"@+id/emptyView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:orientation=\"vertical\"\n        android:gravity=\"center\"\n        android:padding=\"@dimen/activity_padding_medium\"\n        android:visibility=\"gone\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\n\n        <TextView\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"8dp\"\n            android:gravity=\"center\"\n            android:text=\"@string/empty_view_no_archived_events\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Headline.Small\"/>\n\n    </LinearLayout>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_archived_subject.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <include\n        android:id=\"@+id/appBarLayout\"\n        layout=\"@layout/layout_appbar\"/>\n\n    <androidx.recyclerview.widget.RecyclerView\n        android:id=\"@+id/recyclerView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"/>\n\n    <LinearLayout\n        android:id=\"@+id/emptyView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:orientation=\"vertical\"\n        android:gravity=\"center\"\n        android:padding=\"@dimen/activity_padding_medium\"\n        android:visibility=\"gone\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\n\n        <TextView\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"8dp\"\n            android:gravity=\"center\"\n            android:text=\"@string/empty_view_no_archived_subjects\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Headline.Small\"/>\n\n    </LinearLayout>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_archived_task.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <include\n        android:id=\"@+id/appBarLayout\"\n        layout=\"@layout/layout_appbar\"/>\n\n    <androidx.recyclerview.widget.RecyclerView\n        android:id=\"@+id/recyclerView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"/>\n\n    <LinearLayout\n        android:id=\"@+id/emptyView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:orientation=\"vertical\"\n        android:gravity=\"center\"\n        android:padding=\"@dimen/activity_padding_medium\"\n        android:visibility=\"gone\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\n\n        <TextView\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"8dp\"\n            android:gravity=\"center\"\n            android:text=\"@string/empty_view_no_archived_tasks\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Headline.Small\"/>\n\n    </LinearLayout>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_backup.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <include\n        android:id=\"@+id/appBarLayout\"\n        layout=\"@layout/layout_appbar\"/>\n\n    <fragment\n        android:id=\"@+id/container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.settings.BackupFragment$Companion$BackupPreference\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"\n        tools:ignore=\"FragmentTagUsage\"/>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_editor_event.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:animateLayoutChanges=\"true\">\n\n    <include\n        android:id=\"@+id/appBarLayout\"\n        layout=\"@layout/layout_appbar_editor\"/>\n\n    <androidx.core.widget.NestedScrollView\n        android:id=\"@+id/contentView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\"\n            android:paddingBottom=\"@dimen/activity_padding\"\n            android:animateLayoutChanges=\"true\">\n\n            <com.google.android.material.textfield.TextInputLayout\n                android:id=\"@+id/eventNameTextInputLayout\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginHorizontal=\"@dimen/activity_padding\"\n                android:hint=\"@string/field_event_name\"\n                app:errorEnabled=\"true\"\n                style=\"@style/Fokus.Widget.TextInput.Layout\">\n\n                <com.google.android.material.textfield.TextInputEditText\n                    android:id=\"@+id/eventNameTextInput\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:inputType=\"textCapWords\"\n                    android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\">\n\n                    <requestFocus/>\n\n                </com.google.android.material.textfield.TextInputEditText>\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"horizontal\">\n\n                <androidx.appcompat.widget.AppCompatImageView\n                    android:layout_width=\"@dimen/icon_dimen\"\n                    android:layout_height=\"@dimen/icon_dimen\"\n                    android:layout_margin=\"@dimen/container_padding_regular\"\n                    app:srcCompat=\"@drawable/ic_outline_calendar_month_24\"/>\n\n                <RelativeLayout\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:animateLayoutChanges=\"true\">\n\n                    <TextView\n                        android:id=\"@+id/scheduleTextView\"\n                        android:layout_width=\"match_parent\"\n                        android:layout_height=\"@dimen/editor_item_height\"\n                        android:background=\"?attr/selectableItemBackground\"\n                        android:clickable=\"true\"\n                        android:focusable=\"true\"\n                        android:gravity=\"center_vertical\"\n                        android:text=\"@string/field_schedule\"\n                        android:textAppearance=\"@style/Fokus.TextAppearance.Label.Large\" />\n\n                    <RadioGroup\n                        android:id=\"@+id/dateTimeRadioGroup\"\n                        android:layout_width=\"match_parent\"\n                        android:layout_height=\"wrap_content\"\n                        android:visibility=\"gone\">\n\n                        <com.isaiahvonrundstedt.fokus.components.views.TwoLineRadioButton\n                            android:id=\"@+id/inNextMeetingRadio\"\n                            android:layout_width=\"match_parent\"\n                            android:layout_height=\"wrap_content\"\n                            app:titleText=\"@string/field_due_in_the_next_meeting\"\n                            app:titleTextAppearance=\"@style/Fokus.TextAppearance.Label.Large\" />\n\n                        <com.isaiahvonrundstedt.fokus.components.views.TwoLineRadioButton\n                            android:id=\"@+id/pickDateTimeRadio\"\n                            android:layout_width=\"match_parent\"\n                            android:layout_height=\"wrap_content\"\n                            app:titleText=\"@string/field_due_pick_from_schedule\"\n                            app:titleTextAppearance=\"@style/Fokus.TextAppearance.Label.Large\"/>\n\n                        <com.isaiahvonrundstedt.fokus.components.views.TwoLineRadioButton\n                            android:id=\"@+id/customDateTimeRadio\"\n                            android:layout_width=\"match_parent\"\n                            android:layout_height=\"wrap_content\"\n                            app:titleText=\"@string/field_due_custom\"\n                            app:titleTextAppearance=\"@style/Fokus.TextAppearance.Label.Large\"/>\n\n                    </RadioGroup>\n\n                </RelativeLayout>\n\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"horizontal\">\n\n                <androidx.appcompat.widget.AppCompatImageView\n                    android:layout_width=\"@dimen/icon_dimen\"\n                    android:layout_height=\"@dimen/icon_dimen\"\n                    android:layout_margin=\"@dimen/container_padding_regular\"\n                    app:srcCompat=\"@drawable/ic_outline_location_on_24\"/>\n\n                <androidx.appcompat.widget.AppCompatEditText\n                    android:id=\"@+id/locationTextInput\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"match_parent\"\n                    android:layout_marginEnd=\"@dimen/container_padding_regular\"\n                    android:hint=\"@string/hint_event_location\"\n                    android:inputType=\"textCapWords\"\n                    android:textAppearance=\"@style/Fokus.TextAppearance.Label.Large\"\n                    android:background=\"@android:color/transparent\"/>\n\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:gravity=\"center\"\n                android:orientation=\"horizontal\">\n\n                <androidx.appcompat.widget.AppCompatImageView\n                    android:layout_width=\"@dimen/icon_dimen\"\n                    android:layout_height=\"@dimen/icon_dimen\"\n                    android:layout_margin=\"@dimen/container_padding_regular\"\n                    app:srcCompat=\"@drawable/ic_outline_science_24\"/>\n\n                <TextView\n                    android:id=\"@+id/subjectTextView\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"match_parent\"\n                    android:layout_weight=\"1\"\n                    android:clickable=\"true\"\n                    android:focusable=\"true\"\n                    android:gravity=\"center_vertical\"\n                    android:text=\"@string/field_subject\"\n                    android:textAppearance=\"@style/Fokus.TextAppearance.Label.Large\"\n                    android:drawablePadding=\"16dp\"\n                    android:background=\"?attr/selectableItemBackground\"/>\n\n                <com.google.android.material.chip.Chip\n                    android:id=\"@+id/removeButton\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_marginEnd=\"@dimen/activity_padding\"\n                    android:text=\"@string/button_remove\"\n                    android:visibility=\"invisible\"\n                    tools:visibility=\"visible\"/>\n\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"vertical\">\n\n                <LinearLayout\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_marginEnd=\"@dimen/container_padding_regular\"\n                    android:orientation=\"horizontal\">\n\n                    <androidx.appcompat.widget.AppCompatImageView\n                        android:layout_width=\"@dimen/icon_dimen\"\n                        android:layout_height=\"@dimen/icon_dimen\"\n                        android:layout_margin=\"@dimen/container_padding_regular\"\n                        app:srcCompat=\"@drawable/ic_outline_priority_high_24\"/>\n\n                    <com.isaiahvonrundstedt.fokus.components.views.ReactiveTextColorSwitch\n                        android:id=\"@+id/prioritySwitch\"\n                        android:layout_width=\"0dp\"\n                        android:layout_height=\"match_parent\"\n                        android:layout_weight=\"1\"\n                        android:gravity=\"center_vertical\"\n                        android:text=\"@string/button_mark_as_important\"\n                        android:textColor=\"@color/color_secondary_text\"\n                        android:textAppearance=\"@style/Fokus.TextAppearance.Label.Large\" />\n\n                </LinearLayout>\n\n                <com.google.android.material.card.MaterialCardView\n                    android:id=\"@+id/priorityCard\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_marginHorizontal=\"@dimen/container_padding_regular\"\n                    android:layout_marginBottom=\"@dimen/container_padding_regular\"\n                    android:visibility=\"gone\"\n                    style=\"@style/Widget.Material3.CardView.Filled\">\n\n                    <androidx.appcompat.widget.AppCompatTextView\n                        android:layout_width=\"match_parent\"\n                        android:layout_height=\"wrap_content\"\n                        android:padding=\"@dimen/container_padding_small\"\n                        android:text=\"@string/helper_this_is_important\"\n                        android:textColor=\"?attr/colorOnSurfaceVariant\"\n                        android:drawableStart=\"@drawable/ic_outline_info_24\"\n                        android:drawablePadding=\"@dimen/container_padding_regular\"/>\n\n                </com.google.android.material.card.MaterialCardView>\n\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"horizontal\">\n\n                <androidx.appcompat.widget.AppCompatImageView\n                    android:layout_width=\"@dimen/icon_dimen\"\n                    android:layout_height=\"@dimen/icon_dimen\"\n                    android:layout_margin=\"@dimen/container_padding_regular\"\n                    app:srcCompat=\"@drawable/ic_outline_notes_24\"/>\n\n                <androidx.appcompat.widget.AppCompatEditText\n                    android:id=\"@+id/notesTextInput\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"match_parent\"\n                    android:layout_marginEnd=\"@dimen/editor_container_padding\"\n                    android:hint=\"@string/hint_task_notes\"\n                    android:inputType=\"textMultiLine\"\n                    android:lines=\"4\"\n                    android:maxLines=\"6\"\n                    android:minLines=\"2\"\n                    android:scrollbars=\"vertical\"\n                    android:textAppearance=\"@style/Fokus.TextAppearance.Label.Large\"\n                    android:background=\"@android:color/transparent\"/>\n\n            </LinearLayout>\n\n        </LinearLayout>\n\n    </androidx.core.widget.NestedScrollView>\n\n    <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton\n        android:id=\"@+id/actionButton\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_margin=\"@dimen/activity_padding\"\n        android:layout_gravity=\"bottom|end\"\n        android:text=\"@string/button_save\"\n        app:icon=\"@drawable/ic_outline_save_24\"/>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>\n\n"
  },
  {
    "path": "app/src/main/res/layout/fragment_editor_subject.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:animateLayoutChanges=\"true\">\n\n    <include\n        android:id=\"@+id/appBarLayout\"\n        layout=\"@layout/layout_appbar_editor\"/>\n\n    <androidx.core.widget.NestedScrollView\n        android:id=\"@+id/contentView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\">\n\n            <com.google.android.material.textfield.TextInputLayout\n                android:id=\"@+id/codeTextInputLayout\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginHorizontal=\"@dimen/container_padding_regular\"\n                android:hint=\"@string/field_subject_code\"\n                app:errorEnabled=\"true\"\n                style=\"@style/Fokus.Widget.TextInput.Layout\">\n\n                <com.google.android.material.textfield.TextInputEditText\n                    android:id=\"@+id/codeTextInput\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:inputType=\"textCapWords\"\n                    android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\">\n\n                    <requestFocus/>\n\n                </com.google.android.material.textfield.TextInputEditText>\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:gravity=\"center\"\n                android:orientation=\"horizontal\">\n\n                <androidx.appcompat.widget.AppCompatImageView\n                    android:layout_width=\"@dimen/icon_dimen\"\n                    android:layout_height=\"@dimen/icon_dimen\"\n                    android:layout_marginHorizontal=\"16dp\"\n                    app:srcCompat=\"@drawable/ic_outline_edit_note_24\"/>\n\n                <androidx.appcompat.widget.AppCompatEditText\n                    android:id=\"@+id/descriptionTextInput\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"?attr/listPreferredItemHeightSmall\"\n                    android:layout_weight=\"1\"\n                    android:layout_marginEnd=\"@dimen/container_padding_regular\"\n                    android:hint=\"@string/field_description\"\n                    android:inputType=\"textCapWords\"\n                    android:textAppearance=\"@style/Fokus.TextAppearance.Label.Large\"\n                    android:background=\"@android:color/transparent\"/>\n\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:gravity=\"center\"\n                android:orientation=\"horizontal\">\n\n                <androidx.appcompat.widget.AppCompatImageView\n                    android:layout_width=\"@dimen/icon_dimen\"\n                    android:layout_height=\"@dimen/icon_dimen\"\n                    android:layout_marginHorizontal=\"16dp\"\n                    app:srcCompat=\"@drawable/ic_outline_person_2_24\"/>\n\n                <androidx.appcompat.widget.AppCompatEditText\n                    android:id=\"@+id/instructorTextInput\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"?attr/listPreferredItemHeightSmall\"\n                    android:layout_weight=\"1\"\n                    android:layout_marginEnd=\"@dimen/container_padding_regular\"\n                    android:hint=\"@string/field_instructor\"\n                    android:inputType=\"textCapWords\"\n                    android:textAppearance=\"@style/Fokus.TextAppearance.Label.Large\"\n                    android:background=\"@android:color/transparent\"/>\n\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"horizontal\">\n\n                <TextView\n                    android:id=\"@+id/tagView\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"?attr/listPreferredItemHeightSmall\"\n                    android:gravity=\"center_vertical\"\n                    android:paddingStart=\"16dp\"\n                    android:paddingEnd=\"16dp\"\n                    android:background=\"?attr/selectableItemBackground\"\n                    android:text=\"@string/color_sky\"\n                    android:textColor=\"@color/color_primary_text\"\n                    android:textAppearance=\"@style/Fokus.TextAppearance.Label.Large\"\n                    android:clickable=\"true\"\n                    android:focusable=\"true\"\n                    android:drawablePadding=\"16dp\"\n                    app:drawableStartCompat=\"@drawable/shape_color_holder\" />\n\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"vertical\"\n                android:animateLayoutChanges=\"true\">\n\n                <LinearLayout\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_gravity=\"center\"\n                    android:orientation=\"horizontal\">\n\n                    <androidx.appcompat.widget.AppCompatImageView\n                        android:layout_width=\"@dimen/icon_dimen\"\n                        android:layout_height=\"@dimen/icon_dimen\"\n                        android:layout_margin=\"16dp\"\n                        app:srcCompat=\"@drawable/ic_outline_event_repeat_24\"/>\n\n                    <LinearLayout\n                        android:layout_width=\"0dp\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_weight=\"1\"\n                        android:layout_marginEnd=\"@dimen/container_padding_regular\"\n                        android:gravity=\"center_vertical\"\n                        android:minHeight=\"@dimen/editor_item_height\"\n                        android:orientation=\"vertical\">\n\n                        <com.google.android.material.chip.ChipGroup\n                            android:id=\"@+id/schedulesChipGroup\"\n                            android:layout_width=\"match_parent\"\n                            android:layout_height=\"wrap_content\"\n                            app:chipSpacingVertical=\"0dp\"/>\n\n                        <com.google.android.material.chip.Chip\n                            android:id=\"@+id/addActionChip\"\n                            android:layout_width=\"wrap_content\"\n                            android:layout_height=\"wrap_content\"\n                            android:text=\"@string/button_add\"\n                            app:chipIcon=\"@drawable/ic_outline_add_24\"/>\n\n                    </LinearLayout>\n\n                </LinearLayout>\n\n                <com.google.android.material.card.MaterialCardView\n                    android:id=\"@+id/errorScheduleConflict\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_marginHorizontal=\"@dimen/container_padding_regular\"\n                    android:layout_marginBottom=\"@dimen/container_padding_regular\"\n                    android:visibility=\"gone\"\n                    tools:visibility=\"visible\"\n                    style=\"@style/Widget.Material3.CardView.Filled\">\n\n                    <androidx.appcompat.widget.AppCompatTextView\n                        android:layout_width=\"match_parent\"\n                        android:layout_height=\"wrap_content\"\n                        android:padding=\"@dimen/container_padding_small\"\n                        android:text=\"@string/feedback_schedule_exists\"\n                        android:textColor=\"?attr/colorOnSurfaceVariant\"\n                        android:drawableStart=\"@drawable/ic_outline_event_busy_24\"\n                        android:drawablePadding=\"@dimen/container_padding_regular\"\n                        android:gravity=\"center_vertical\"/>\n\n                </com.google.android.material.card.MaterialCardView>\n\n            </LinearLayout>\n\n        </LinearLayout>\n\n    </androidx.core.widget.NestedScrollView>\n\n    <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton\n        android:id=\"@+id/actionButton\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_margin=\"@dimen/activity_padding\"\n        android:layout_gravity=\"bottom|end\"\n        android:text=\"@string/button_save\"\n        app:icon=\"@drawable/ic_outline_save_24\"/>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_editor_task.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/coordinator\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <include\n        android:id=\"@+id/appBarLayout\"\n        layout=\"@layout/layout_appbar_editor\" />\n\n    <androidx.core.widget.NestedScrollView\n        android:id=\"@+id/contentView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\"\n            android:paddingBottom=\"@dimen/activity_padding\"\n            android:animateLayoutChanges=\"true\">\n\n            <com.google.android.material.textfield.TextInputLayout\n                android:id=\"@+id/taskNameTextInputLayout\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginHorizontal=\"@dimen/activity_padding\"\n                android:hint=\"@string/field_task_name\"\n                app:errorEnabled=\"true\"\n                style=\"@style/Fokus.Widget.TextInput.Layout\">\n\n                <com.google.android.material.textfield.TextInputEditText\n                    android:id=\"@+id/taskNameTextInput\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:inputType=\"textCapWords\"\n                    android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\">\n\n                    <requestFocus/>\n\n                </com.google.android.material.textfield.TextInputEditText>\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"horizontal\">\n\n                <androidx.appcompat.widget.AppCompatImageView\n                    android:layout_width=\"@dimen/icon_dimen\"\n                    android:layout_height=\"@dimen/icon_dimen\"\n                    android:layout_margin=\"@dimen/container_padding_regular\"\n                    app:srcCompat=\"@drawable/ic_outline_verified_24\"/>\n\n                <com.isaiahvonrundstedt.fokus.components.views.ReactiveTextColorSwitch\n                    android:id=\"@+id/statusSwitch\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"match_parent\"\n                    android:layout_marginEnd=\"@dimen/container_padding_regular\"\n                    android:gravity=\"center_vertical\"\n                    android:text=\"@string/button_mark_as_finished\"\n                    android:textColor=\"@color/color_secondary_text\"\n                    android:textAppearance=\"@style/Fokus.TextAppearance.Label.Large\"/>\n\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"horizontal\">\n\n                <androidx.appcompat.widget.AppCompatImageView\n                    android:layout_width=\"@dimen/icon_dimen\"\n                    android:layout_height=\"@dimen/icon_dimen\"\n                    android:layout_margin=\"@dimen/container_padding_regular\"\n                    app:srcCompat=\"@drawable/ic_outline_access_time_24\"/>\n\n                <androidx.constraintlayout.widget.ConstraintLayout\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:layout_marginEnd=\"@dimen/container_padding_regular\"\n                    android:layout_gravity=\"center\"\n                    android:animateLayoutChanges=\"true\">\n\n                    <TextView\n                        android:id=\"@+id/dueDateTextView\"\n                        android:layout_width=\"0dp\"\n                        android:layout_height=\"56dp\"\n                        android:clickable=\"true\"\n                        android:focusable=\"true\"\n                        android:gravity=\"center_vertical\"\n                        android:background=\"?attr/selectableItemBackground\"\n                        android:text=\"@string/field_due_date\"\n                        android:textAppearance=\"@style/Fokus.TextAppearance.Label.Large\"\n                        app:layout_constraintTop_toTopOf=\"parent\"\n                        app:layout_constraintBottom_toBottomOf=\"parent\"\n                        app:layout_constraintStart_toStartOf=\"parent\"\n                        app:layout_constraintEnd_toStartOf=\"@id/removeDueDateButton\"/>\n\n                    <com.google.android.material.chip.Chip\n                        android:id=\"@+id/removeDueDateButton\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_marginEnd=\"@dimen/activity_padding\"\n                        android:text=\"@string/button_remove\"\n                        android:visibility=\"gone\"\n                        app:layout_constraintTop_toTopOf=\"parent\"\n                        app:layout_constraintBottom_toBottomOf=\"parent\"\n                        app:layout_constraintEnd_toEndOf=\"parent\" />\n\n                    <RadioGroup\n                        android:id=\"@+id/dateTimeRadioGroup\"\n                        android:layout_width=\"match_parent\"\n                        android:layout_height=\"match_parent\"\n                        android:visibility=\"gone\"\n                        app:layout_constraintTop_toTopOf=\"parent\"\n                        app:layout_constraintBottom_toBottomOf=\"parent\">\n\n                        <com.isaiahvonrundstedt.fokus.components.views.RadioButtonCompat\n                            android:id=\"@+id/noDueRadioButton\"\n                            android:layout_width=\"match_parent\"\n                            android:layout_height=\"wrap_content\"\n                            android:paddingStart=\"@dimen/editor_container_padding\"\n                            android:paddingEnd=\"@dimen/editor_container_padding\"\n                            android:checked=\"true\"\n                            android:text=\"@string/field_not_set\"\n                            app:textAppearanceCompat=\"@style/Fokus.TextAppearance.Label.Large\"/>\n\n                        <com.isaiahvonrundstedt.fokus.components.views.TwoLineRadioButton\n                            android:id=\"@+id/inNextMeetingRadio\"\n                            android:layout_width=\"match_parent\"\n                            android:layout_height=\"wrap_content\"\n                            android:paddingStart=\"@dimen/editor_container_padding\"\n                            android:paddingEnd=\"@dimen/editor_container_padding\"\n                            app:titleText=\"@string/field_due_in_the_next_meeting\"\n                            app:titleTextAppearance=\"@style/Fokus.TextAppearance.Label.Large\" />\n\n                        <com.isaiahvonrundstedt.fokus.components.views.TwoLineRadioButton\n                            android:id=\"@+id/pickDateTimeRadio\"\n                            android:layout_width=\"match_parent\"\n                            android:layout_height=\"wrap_content\"\n                            android:paddingStart=\"@dimen/editor_container_padding\"\n                            android:paddingEnd=\"@dimen/editor_container_padding\"\n                            app:titleText=\"@string/field_due_pick_from_schedule\"\n                            app:titleTextAppearance=\"@style/Fokus.TextAppearance.Label.Large\"/>\n\n                        <com.isaiahvonrundstedt.fokus.components.views.TwoLineRadioButton\n                            android:id=\"@+id/customDateTimeRadio\"\n                            android:layout_width=\"match_parent\"\n                            android:layout_height=\"wrap_content\"\n                            android:paddingStart=\"@dimen/editor_container_padding\"\n                            android:paddingEnd=\"@dimen/editor_container_padding\"\n                            app:titleText=\"@string/field_due_custom\"\n                            app:titleTextAppearance=\"@style/Fokus.TextAppearance.Label.Large\"/>\n\n                    </RadioGroup>\n\n                </androidx.constraintlayout.widget.ConstraintLayout>\n\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:gravity=\"center\"\n                android:orientation=\"horizontal\">\n\n                <androidx.appcompat.widget.AppCompatImageView\n                    android:layout_width=\"@dimen/icon_dimen\"\n                    android:layout_height=\"@dimen/icon_dimen\"\n                    android:layout_margin=\"@dimen/container_padding_regular\"\n                    app:srcCompat=\"@drawable/ic_outline_science_24\"/>\n\n                <TextView\n                    android:id=\"@+id/subjectTextView\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"match_parent\"\n                    android:layout_weight=\"1\"\n                    android:clickable=\"true\"\n                    android:focusable=\"true\"\n                    android:gravity=\"center_vertical\"\n                    android:text=\"@string/field_subject\"\n                    android:textAppearance=\"@style/Fokus.TextAppearance.Label.Large\"\n                    android:drawablePadding=\"16dp\"\n                    android:background=\"?attr/selectableItemBackground\"/>\n\n                <com.google.android.material.chip.Chip\n                    android:id=\"@+id/removeButton\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_marginEnd=\"@dimen/activity_padding\"\n                    android:text=\"@string/button_remove\"\n                    android:visibility=\"invisible\"\n                    tools:visibility=\"visible\"/>\n\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"vertical\"\n                android:animateLayoutChanges=\"true\">\n\n                <LinearLayout\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_marginEnd=\"@dimen/container_padding_regular\"\n                    android:orientation=\"horizontal\">\n\n                    <androidx.appcompat.widget.AppCompatImageView\n                        android:layout_width=\"@dimen/icon_dimen\"\n                        android:layout_height=\"@dimen/icon_dimen\"\n                        android:layout_margin=\"@dimen/container_padding_regular\"\n                        app:srcCompat=\"@drawable/ic_outline_priority_high_24\"/>\n\n                    <com.isaiahvonrundstedt.fokus.components.views.ReactiveTextColorSwitch\n                        android:id=\"@+id/prioritySwitch\"\n                        android:layout_width=\"0dp\"\n                        android:layout_height=\"match_parent\"\n                        android:layout_weight=\"1\"\n                        android:gravity=\"center_vertical\"\n                        android:text=\"@string/button_mark_as_important\"\n                        android:textColor=\"@color/color_secondary_text\"\n                        android:textAppearance=\"@style/Fokus.TextAppearance.Label.Large\" />\n\n                </LinearLayout>\n\n                <com.google.android.material.card.MaterialCardView\n                    android:id=\"@+id/priorityCard\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_marginHorizontal=\"@dimen/container_padding_regular\"\n                    android:layout_marginBottom=\"@dimen/container_padding_regular\"\n                    android:visibility=\"gone\"\n                    style=\"@style/Widget.Material3.CardView.Filled\">\n\n                    <androidx.appcompat.widget.AppCompatTextView\n                        android:layout_width=\"match_parent\"\n                        android:layout_height=\"wrap_content\"\n                        android:padding=\"@dimen/container_padding_small\"\n                        android:text=\"@string/helper_this_is_important\"\n                        android:textColor=\"?attr/colorOnSurfaceVariant\"\n                        android:drawableStart=\"@drawable/ic_outline_info_24\"\n                        android:drawablePadding=\"@dimen/container_padding_regular\"/>\n\n                </com.google.android.material.card.MaterialCardView>\n\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"horizontal\">\n\n                <androidx.appcompat.widget.AppCompatImageView\n                    android:layout_width=\"@dimen/icon_dimen\"\n                    android:layout_height=\"@dimen/icon_dimen\"\n                    android:layout_margin=\"@dimen/container_padding_regular\"\n                    app:srcCompat=\"@drawable/ic_outline_notes_24\"/>\n\n                <androidx.appcompat.widget.AppCompatEditText\n                    android:id=\"@+id/notesTextInput\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"match_parent\"\n                    android:layout_marginEnd=\"@dimen/editor_container_padding\"\n                    android:hint=\"@string/hint_task_notes\"\n                    android:inputType=\"textMultiLine\"\n                    android:lines=\"4\"\n                    android:maxLines=\"6\"\n                    android:minLines=\"2\"\n                    android:scrollbars=\"vertical\"\n                    android:textAppearance=\"@style/Fokus.TextAppearance.Label.Large\"\n                    android:background=\"@android:color/transparent\"/>\n\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"horizontal\">\n\n                <androidx.appcompat.widget.AppCompatImageView\n                    android:layout_width=\"@dimen/icon_dimen\"\n                    android:layout_height=\"@dimen/icon_dimen\"\n                    android:layout_margin=\"@dimen/container_padding_regular\"\n                    app:srcCompat=\"@drawable/ic_outline_attach_file_24\"/>\n\n                <LinearLayout\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:layout_marginEnd=\"@dimen/container_padding_regular\"\n                    android:layout_gravity=\"center\"\n                    android:padding=\"4dp\"\n                    android:minHeight=\"@dimen/editor_item_height\"\n                    android:orientation=\"vertical\">\n\n                    <com.google.android.material.chip.ChipGroup\n                        android:id=\"@+id/attachmentsChipGroup\"\n                        android:layout_width=\"match_parent\"\n                        android:layout_height=\"wrap_content\"\n                        app:chipSpacingVertical=\"0dp\"/>\n\n                    <com.google.android.material.chip.Chip\n                        android:id=\"@+id/addActionChip\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"@string/button_add\"\n                        app:chipIcon=\"@drawable/ic_outline_add_24\"/>\n\n                </LinearLayout>\n\n            </LinearLayout>\n\n        </LinearLayout>\n\n    </androidx.core.widget.NestedScrollView>\n\n    <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton\n        android:id=\"@+id/actionButton\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_margin=\"@dimen/activity_padding\"\n        android:layout_gravity=\"bottom|end\"\n        android:text=\"@string/button_save\"\n        app:icon=\"@drawable/ic_outline_save_24\"/>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_event.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<androidx.coordinatorlayout.widget.CoordinatorLayout\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"wrap_content\"\r\n    android:animateLayoutChanges=\"true\">\r\n\r\n    <include\r\n        android:id=\"@+id/appBarLayout\"\r\n        layout=\"@layout/layout_appbar\"/>\r\n\r\n    <androidx.core.widget.NestedScrollView\r\n        android:id=\"@+id/containerLayout\"\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"match_parent\"\r\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\r\n\r\n        <LinearLayout\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"match_parent\"\r\n            android:orientation=\"vertical\">\r\n\r\n            <com.kizitonwose.calendarview.CalendarView\r\n                android:id=\"@+id/calendarView\"\r\n                android:layout_width=\"match_parent\"\r\n                android:layout_height=\"wrap_content\"\r\n                app:cv_dayViewResource=\"@layout/layout_calendar_day\"\r\n                app:cv_monthHeaderResource=\"@layout/layout_calendar_week_days\"\r\n                app:cv_orientation=\"horizontal\"\r\n                app:cv_scrollMode=\"paged\"\r\n                app:cv_outDateStyle=\"endOfRow\"/>\r\n\r\n            <TextView\r\n                android:id=\"@+id/currentDateTextView\"\r\n                android:layout_width=\"match_parent\"\r\n                android:layout_height=\"wrap_content\"\r\n                android:layout_marginTop=\"8dp\"\r\n                android:background=\"?attr/colorSurfaceVariant\"\r\n                android:fontFamily=\"sans-serif-medium\"\r\n                android:paddingStart=\"20dp\"\r\n                android:paddingTop=\"12dp\"\r\n                android:paddingEnd=\"20dp\"\r\n                android:paddingBottom=\"12dp\"\r\n                android:textAllCaps=\"true\"\r\n                android:textColor=\"?attr/colorOnSurfaceVariant\"\r\n                android:textSize=\"14sp\" />\r\n\r\n            <FrameLayout\r\n                android:layout_width=\"match_parent\"\r\n                android:layout_height=\"match_parent\">\r\n\r\n                <androidx.recyclerview.widget.RecyclerView\r\n                    android:id=\"@+id/recyclerView\"\r\n                    android:layout_width=\"match_parent\"\r\n                    android:layout_height=\"wrap_content\"\r\n                    android:clipChildren=\"false\"\r\n                    android:nestedScrollingEnabled=\"true\"\r\n                    android:transitionGroup=\"true\"/>\r\n\r\n                <LinearLayout\r\n                    android:id=\"@+id/emptyView\"\r\n                    android:layout_width=\"match_parent\"\r\n                    android:layout_height=\"match_parent\"\r\n                    android:orientation=\"vertical\"\r\n                    android:gravity=\"center\"\r\n                    android:padding=\"@dimen/activity_padding_medium\"\r\n                    android:visibility=\"gone\">\r\n\r\n                    <TextView\r\n                        android:layout_width=\"match_parent\"\r\n                        android:layout_height=\"wrap_content\"\r\n                        android:layout_marginBottom=\"8dp\"\r\n                        android:gravity=\"center\"\r\n                        android:text=\"@string/empty_view_no_events_title\"\r\n                        android:textColor=\"?attr/colorPrimary\"\r\n                        android:textAppearance=\"@style/Fokus.TextAppearance.Headline.Small\"/>\r\n\r\n                    <TextView\r\n                        android:layout_width=\"match_parent\"\r\n                        android:layout_height=\"wrap_content\"\r\n                        android:gravity=\"center\"\r\n                        android:text=\"@string/empty_view_no_events_summary\"\r\n                        android:textAppearance=\"@style/Fokus.TextAppearance.Body.Medium\"/>\r\n\r\n                </LinearLayout>\r\n\r\n            </FrameLayout>\r\n\r\n        </LinearLayout>\r\n\r\n    </androidx.core.widget.NestedScrollView>\r\n\r\n    <com.google.android.material.floatingactionbutton.FloatingActionButton\r\n        android:id=\"@+id/actionButton\"\r\n        android:layout_width=\"wrap_content\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:layout_gravity=\"bottom|end\"\r\n        android:layout_margin=\"@dimen/activity_padding\"\r\n        android:contentDescription=\"@string/button_add\"\r\n        app:srcCompat=\"@drawable/ic_outline_add_24\" />\r\n\r\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_libraries.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <include\n        android:id=\"@+id/appBarLayout\"\n        layout=\"@layout/layout_appbar\"/>\n\n    <androidx.recyclerview.widget.RecyclerView\n        android:id=\"@+id/recyclerView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"/>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_logs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <include\n        android:id=\"@+id/appBarLayout\"\n        layout=\"@layout/layout_appbar\"/>\n\n    <androidx.recyclerview.widget.RecyclerView\n        android:id=\"@+id/recyclerView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:transitionGroup=\"true\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"/>\n\n    <LinearLayout\n        android:id=\"@+id/emptyView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:orientation=\"vertical\"\n        android:gravity=\"center\"\n        android:padding=\"@dimen/activity_padding_medium\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\n\n        <androidx.appcompat.widget.AppCompatTextView\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"8dp\"\n            android:gravity=\"center\"\n            android:text=\"@string/empty_view_no_logs_title\"\n            android:textColor=\"?attr/colorPrimary\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Headline.Small\"/>\n\n        <androidx.appcompat.widget.AppCompatTextView\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:gravity=\"center\"\n            android:text=\"@string/empty_view_no_logs_summary\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Body.Medium\"/>\n\n    </LinearLayout>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_notices.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <include\n        android:id=\"@+id/appBarLayout\"\n        layout=\"@layout/layout_appbar\"/>\n\n    <fragment\n        android:id=\"@+id/container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.about.NoticesFragment$Companion$NoticesFragment\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"\n        tools:ignore=\"FragmentTagUsage\"/>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_picker_subject.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <include\n        android:id=\"@+id/appBarLayout\"\n        layout=\"@layout/layout_appbar\"/>\n\n    <androidx.recyclerview.widget.RecyclerView\n        android:id=\"@+id/recyclerView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:clipChildren=\"false\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"/>\n\n    <LinearLayout\n        android:id=\"@+id/emptyView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:orientation=\"vertical\"\n        android:gravity=\"center\"\n        android:padding=\"@dimen/activity_padding_medium\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\n\n        <androidx.appcompat.widget.AppCompatTextView\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"8dp\"\n            android:gravity=\"center\"\n            android:text=\"@string/empty_view_no_subjects_title\"\n            android:textColor=\"?attr/colorPrimary\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Headline.Small\"/>\n\n        <TextView\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:gravity=\"center\"\n            android:text=\"@string/empty_view_no_subjects_summary\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Body.Medium\"/>\n\n    </LinearLayout>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_root.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.drawerlayout.widget.DrawerLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/drawerLayout\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:openDrawer=\"start\">\n\n    <androidx.fragment.app.FragmentContainerView\n        android:id=\"@+id/fragmentContainerView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:name=\"androidx.navigation.fragment.NavHostFragment\"\n        app:defaultNavHost=\"true\"\n        app:navGraph=\"@navigation/navigation_root\"/>\n\n    <com.google.android.material.navigation.NavigationView\n        android:id=\"@+id/navigationView\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"match_parent\"\n        android:layout_gravity=\"start\"\n        app:headerLayout=\"@layout/layout_navigation_header\"\n        app:menu=\"@menu/navigation_main\"/>\n\n</androidx.drawerlayout.widget.DrawerLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_settings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <include\n        android:id=\"@+id/appBarLayout\"\n        layout=\"@layout/layout_appbar\"/>\n\n    <fragment\n        android:id=\"@+id/container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.settings.SettingsFragment$Companion$SettingsFragment\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"\n        tools:ignore=\"FragmentTagUsage\"/>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_subject.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<androidx.coordinatorlayout.widget.CoordinatorLayout\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"match_parent\"\r\n    android:animateLayoutChanges=\"true\">\r\n\r\n    <include\r\n        android:id=\"@+id/appBarLayout\"\r\n        layout=\"@layout/layout_appbar\"/>\r\n\r\n    <androidx.recyclerview.widget.RecyclerView\r\n        android:id=\"@+id/recyclerView\"\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"match_parent\"\r\n        android:transitionGroup=\"true\"\r\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"/>\r\n\r\n    <LinearLayout\r\n        android:id=\"@+id/emptyViewSubjectsAll\"\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"match_parent\"\r\n        android:orientation=\"vertical\"\r\n        android:gravity=\"center\"\r\n        android:padding=\"@dimen/activity_padding_medium\"\r\n        android:visibility=\"gone\">\r\n\r\n        <TextView\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:layout_marginBottom=\"8dp\"\r\n            android:gravity=\"center\"\r\n            android:text=\"@string/empty_view_no_subjects_title\"\r\n            android:textColor=\"?attr/colorPrimary\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Headline.Small\"/>\r\n\r\n        <TextView\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:gravity=\"center\"\r\n            android:text=\"@string/empty_view_no_subjects_summary\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Body.Medium\"/>\r\n\r\n    </LinearLayout>\r\n\r\n    <LinearLayout\r\n        android:id=\"@+id/emptyViewSubjectsToday\"\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"match_parent\"\r\n        android:orientation=\"vertical\"\r\n        android:gravity=\"center\"\r\n        android:padding=\"@dimen/activity_padding_medium\"\r\n        android:visibility=\"gone\">\r\n\r\n        <TextView\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:layout_marginBottom=\"8dp\"\r\n            android:gravity=\"center\"\r\n            android:text=\"@string/empty_view_no_classes_today_title\"\r\n            android:textColor=\"?attr/colorPrimary\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Headline.Small\"/>\r\n\r\n        <TextView\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:gravity=\"center\"\r\n            android:text=\"@string/empty_view_no_classes_today_summary\"\r\n            style=\"@style/Fokus.TextAppearance.Body.Medium\"/>\r\n\r\n    </LinearLayout>\r\n\r\n    <LinearLayout\r\n        android:id=\"@+id/emptyViewSubjectsTomorrow\"\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"match_parent\"\r\n        android:orientation=\"vertical\"\r\n        android:gravity=\"center\"\r\n        android:padding=\"@dimen/activity_padding_medium\"\r\n        android:visibility=\"gone\">\r\n\r\n        <TextView\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:layout_marginBottom=\"8dp\"\r\n            android:gravity=\"center\"\r\n            android:text=\"@string/empty_view_no_classes_tomorrow_title\"\r\n            android:textColor=\"?attr/colorPrimary\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Headline.Small\"/>\r\n\r\n        <TextView\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:gravity=\"center\"\r\n            android:text=\"@string/empty_view_no_classes_tomorrow_summary\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Body.Medium\"/>\r\n\r\n    </LinearLayout>\r\n\r\n    <com.google.android.material.floatingactionbutton.FloatingActionButton\r\n        android:id=\"@+id/actionButton\"\r\n        android:layout_width=\"wrap_content\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:layout_gravity=\"bottom|end\"\r\n        android:layout_margin=\"@dimen/activity_padding\"\r\n        android:contentDescription=\"@string/button_add\"\r\n        app:srcCompat=\"@drawable/ic_outline_add_24\"/>\r\n\r\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_task.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<androidx.coordinatorlayout.widget.CoordinatorLayout\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"match_parent\"\r\n    android:animateLayoutChanges=\"true\">\r\n\r\n    <include\r\n        android:id=\"@+id/appBarLayout\"\r\n        layout=\"@layout/layout_appbar\"/>\r\n\r\n    <androidx.recyclerview.widget.RecyclerView\r\n        android:id=\"@+id/recyclerView\"\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"match_parent\"\r\n        android:transitionGroup=\"true\"\r\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"/>\r\n\r\n    <nl.dionsegijn.konfetti.xml.KonfettiView\r\n        android:id=\"@+id/confettiView\"\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"wrap_content\"/>\r\n\r\n    <LinearLayout\r\n        android:id=\"@+id/emptyViewPendingTasks\"\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"match_parent\"\r\n        android:orientation=\"vertical\"\r\n        android:gravity=\"center\"\r\n        android:padding=\"@dimen/activity_padding_medium\"\r\n        android:visibility=\"gone\"\r\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\r\n\r\n        <TextView\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:layout_marginBottom=\"8dp\"\r\n            android:gravity=\"center\"\r\n            android:text=\"@string/empty_view_no_tasks_title\"\r\n            android:textColor=\"?attr/colorPrimary\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Headline.Small\"/>\r\n\r\n        <TextView\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:layout_marginBottom=\"16dp\"\r\n            android:gravity=\"center\"\r\n            android:text=\"@string/empty_view_no_tasks_summary\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Body.Medium\"/>\r\n\r\n    </LinearLayout>\r\n\r\n    <LinearLayout\r\n        android:id=\"@+id/emptyViewFinishedTasks\"\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"match_parent\"\r\n        android:orientation=\"vertical\"\r\n        android:gravity=\"center\"\r\n        android:padding=\"@dimen/activity_padding_medium\"\r\n        android:visibility=\"gone\"\r\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\r\n\r\n        <TextView\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:layout_marginBottom=\"8dp\"\r\n            android:gravity=\"center\"\r\n            android:text=\"@string/empty_view_no_finished_title\"\r\n            android:textColor=\"?attr/colorPrimary\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Headline.Small\"/>\r\n\r\n        <TextView\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:layout_marginBottom=\"16dp\"\r\n            android:gravity=\"center\"\r\n            android:text=\"@string/empty_view_no_finished_summary\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Body.Medium\"/>\r\n\r\n    </LinearLayout>\r\n\r\n    <com.google.android.material.floatingactionbutton.FloatingActionButton\r\n        android:id=\"@+id/actionButton\"\r\n        android:layout_width=\"wrap_content\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:layout_gravity=\"bottom|end\"\r\n        android:layout_margin=\"@dimen/activity_padding\"\r\n        android:contentDescription=\"@string/button_add\"\r\n        app:srcCompat=\"@drawable/ic_outline_add_24\"/>\r\n\r\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_appbar.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<com.google.android.material.appbar.AppBarLayout\r\n    android:id=\"@+id/appBarLayout\"\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\r\n    xmlns:tools=\"http://schemas.android.com/tools\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"wrap_content\">\r\n\r\n    <com.google.android.material.appbar.MaterialToolbar\r\n        android:id=\"@+id/toolbar\"\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"?attr/actionBarSize\"\r\n        app:layout_scrollFlags=\"snap\"\r\n        tools:title=\"@string/activity_tasks\" />\r\n\r\n</com.google.android.material.appbar.AppBarLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_appbar_editor.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<com.google.android.material.appbar.AppBarLayout\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"wrap_content\">\r\n\r\n    <com.google.android.material.appbar.MaterialToolbar\r\n        android:id=\"@+id/toolbar\"\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"?attr/actionBarSize\"\r\n        app:navigationIcon=\"@drawable/ic_outline_close_24\"/>\r\n\r\n</com.google.android.material.appbar.AppBarLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_appbar_viewer.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.google.android.material.appbar.AppBarLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\">\n\n    <com.google.android.material.appbar.MaterialToolbar\n        android:id=\"@+id/toolbar\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"?attr/actionBarSize\"\n        app:navigationIcon=\"@drawable/ic_outline_close_24\"\n        tools:title=\"@string/activity_tasks\" />\n\n</com.google.android.material.appbar.AppBarLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_calendar_day.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:layout_margin=\"4dp\"\n    android:padding=\"8dp\">\n\n    <TextView\n        android:id=\"@+id/calendarDayView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_gravity=\"center\"\n        android:layout_margin=\"2dp\"\n        android:gravity=\"center\"\n        android:textColor=\"@color/color_primary_text\"\n        android:textSize=\"14sp\"\n        tools:text=\"22\" />\n\n    <View\n        android:id=\"@+id/calendarDotView\"\n        android:layout_width=\"4dp\"\n        android:layout_height=\"4dp\"\n        android:layout_marginBottom=\"4dp\"\n        android:layout_gravity=\"bottom|center_horizontal\"\n        android:background=\"@drawable/shape_calendar_current_day\" />\n\n</FrameLayout>\n\n"
  },
  {
    "path": "app/src/main/res/layout/layout_calendar_week_days.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:orientation=\"vertical\">\n\n    <LinearLayout\n        android:id=\"@+id/headerLayout\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:paddingVertical=\"8dp\"\n        android:orientation=\"horizontal\"\n        android:gravity=\"center\">\n\n        <TextView\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_weight=\"1\"\n            android:gravity=\"center\"\n            android:text=\"@string/days_of_week_item_sunday_short\"\n            android:textColor=\"@color/color_secondary_text\"\n            android:textSize=\"14sp\" />\n\n        <TextView\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_weight=\"1\"\n            android:gravity=\"center\"\n            android:text=\"@string/days_of_week_item_monday_short\"\n            android:textColor=\"@color/color_secondary_text\"\n            android:textSize=\"14sp\" />\n\n        <TextView\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_weight=\"1\"\n            android:gravity=\"center\"\n            android:text=\"@string/days_of_week_item_tuesday_short\"\n            android:textColor=\"@color/color_secondary_text\"\n            android:textSize=\"14sp\" />\n\n        <TextView\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_weight=\"1\"\n            android:gravity=\"center\"\n            android:text=\"@string/days_of_week_item_wednesday_short\"\n            android:textColor=\"@color/color_secondary_text\"\n            android:textSize=\"14sp\" />\n\n        <TextView\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_weight=\"1\"\n            android:gravity=\"center\"\n            android:text=\"@string/days_of_week_item_thursday_short\"\n            android:textColor=\"@color/color_secondary_text\"\n            android:textSize=\"14sp\" />\n\n        <TextView\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_weight=\"1\"\n            android:gravity=\"center\"\n            android:text=\"@string/days_of_week_item_friday_short\"\n            android:textColor=\"@color/color_secondary_text\"\n            android:textSize=\"14sp\" />\n\n        <TextView\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_weight=\"1\"\n            android:gravity=\"center\"\n            android:text=\"@string/days_of_week_item_saturday_short\"\n            android:textColor=\"@color/color_secondary_text\"\n            android:textSize=\"14sp\" />\n\n    </LinearLayout>\n\n    <View\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"1dp\"\n        android:background=\"@color/theme_surface_variant\"/>\n\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/layout_dialog_input_attachment.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:padding=\"@dimen/activity_padding\">\n\n    <EditText\n        android:id=\"@+id/editText\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:hint=\"@string/attachment_type_website_url\"\n        android:inputType=\"textWebEmailAddress\"\n        android:autofillHints=\"@null\"/>\n\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_item_add.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<com.google.android.material.button.MaterialButton\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\r\n    android:id=\"@+id/addItemButton\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"wrap_content\"\r\n    android:layout_gravity=\"center_horizontal\"\r\n    android:text=\"@string/button_add\"\r\n    app:icon=\"@drawable/ic_outline_add_24\"\r\n    app:iconGravity=\"textStart\"\r\n    style=\"@style/Widget.MaterialComponents.Button.TextButton\"/>\r\n\r\n\r\n"
  },
  {
    "path": "app/src/main/res/layout/layout_item_archived_event.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:foreground=\"?attr/selectableItemBackground\">\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n\n        <TextView\n            android:id=\"@+id/timeView\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"match_parent\"\n            android:maxLines=\"1\"\n            android:ellipsize=\"end\"\n            android:textAlignment=\"center\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\"\n            tools:text=\"10:00AM\"\n            app:layout_constraintWidth_percent=\"0.3\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"/>\n\n        <LinearLayout\n            android:id=\"@+id/detailsLayout\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"match_parent\"\n            android:orientation=\"vertical\"\n            android:padding=\"@dimen/item_padding\"\n            app:layout_constraintWidth_percent=\"0.7\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintStart_toEndOf=\"@id/timeView\">\n\n            <TextView\n                android:id=\"@+id/nameView\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginBottom=\"@dimen/item_spacing_small\"\n                android:lines=\"1\"\n                android:ellipsize=\"end\"\n                android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\"\n                app:layout_constraintTop_toTopOf=\"parent\"\n                app:layout_constraintBottom_toTopOf=\"@id/locationView\"\n                tools:text=\"Academic Seminar\"/>\n\n            <TextView\n                android:id=\"@+id/locationView\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:lines=\"1\"\n                android:ellipsize=\"end\"\n                android:textAppearance=\"@style/Fokus.TextAppearance.Body.Small\"\n                app:layout_constraintTop_toBottomOf=\"@id/nameView\"\n                app:layout_constraintBottom_toBottomOf=\"parent\"\n                tools:text=\"CLSU Auditorium\"/>\n\n            <TextView\n                android:id=\"@+id/subjectView\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginTop=\"@dimen/item_spacing_large\"\n                android:textAppearance=\"@style/Fokus.TextAppearance.Label.Medium\"\n                android:drawablePadding=\"@dimen/item_spacing_large\"\n                app:drawableStartCompat=\"@drawable/shape_color_holder_chip\"\n                tools:text=\"Intech 1100\"/>\n\n        </LinearLayout>\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_item_archived_subject.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:foreground=\"?attr/selectableItemBackground\">\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:padding=\"@dimen/item_padding\">\n\n        <ImageView\n            android:id=\"@+id/tagView\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:contentDescription=\"@null\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:srcCompat=\"@drawable/shape_color_holder\"/>\n\n        <TextView\n            android:id=\"@+id/titleView\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"4dp\"\n            android:layout_marginStart=\"@dimen/item_spacing_huge\"\n            android:ellipsize=\"end\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:layout_constraintBottom_toTopOf=\"@id/summaryView\"\n            app:layout_constraintStart_toEndOf=\"@id/tagView\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintHorizontal_bias=\"0.0\"\n            tools:text=\"COMSCI 2101\"/>\n\n        <TextView\n            android:id=\"@+id/summaryView\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"@dimen/item_spacing_small\"\n            android:layout_marginStart=\"@dimen/item_spacing_huge\"\n            android:ellipsize=\"end\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Body.Small\"\n            app:layout_constraintTop_toBottomOf=\"@id/titleView\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintStart_toEndOf=\"@id/tagView\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintHorizontal_bias=\"0.0\"\n            tools:text=\"Web Design and Development\"/>\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_item_archived_task.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:foreground=\"?attr/selectableItemBackground\">\n\n    <LinearLayout\n        android:id=\"@+id/detailsLayout\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"vertical\"\n        android:paddingVertical=\"@dimen/item_padding\">\n\n        <TextView\n            android:id=\"@+id/taskNameView\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"@dimen/item_spacing_small\"\n            android:layout_marginStart=\"@dimen/item_padding\"\n            android:layout_marginEnd=\"@dimen/item_padding\"\n            android:lines=\"1\"\n            android:ellipsize=\"end\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\"\n            tools:text=\"Draw the Flowchart\"/>\n\n        <TextView\n            android:id=\"@+id/dueDateView\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"@dimen/item_padding\"\n            android:layout_marginEnd=\"@dimen/item_padding\"\n            android:lines=\"1\"\n            android:ellipsize=\"end\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Body.Medium\"\n            tools:text=\"Tomorrow at 1:00PM\"/>\n\n        <TextView\n            android:id=\"@+id/subjectView\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"@dimen/item_spacing_large\"\n            android:layout_marginStart=\"@dimen/item_padding\"\n            android:layout_marginEnd=\"@dimen/item_padding\"\n            android:lines=\"1\"\n            android:ellipsize=\"end\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Title.Small\"\n            android:drawablePadding=\"@dimen/item_spacing_large\"\n            app:drawableStartCompat=\"@drawable/shape_color_holder_chip\"\n            tools:text=\"COMSCI 2101\"/>\n\n    </LinearLayout>\n\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_item_event.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<FrameLayout\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\r\n    xmlns:tools=\"http://schemas.android.com/tools\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"wrap_content\"\r\n    android:foreground=\"?attr/selectableItemBackground\">\r\n\r\n    <androidx.constraintlayout.widget.ConstraintLayout\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"wrap_content\">\r\n\r\n        <TextView\r\n            android:id=\"@+id/timeView\"\r\n            android:layout_width=\"0dp\"\r\n            android:layout_height=\"match_parent\"\r\n            android:maxLines=\"1\"\r\n            android:ellipsize=\"end\"\r\n            android:textAlignment=\"center\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\"\r\n            tools:text=\"10:00AM\"\r\n            app:layout_constraintWidth_percent=\"0.3\"\r\n            app:layout_constraintTop_toTopOf=\"parent\"\r\n            app:layout_constraintBottom_toBottomOf=\"parent\"\r\n            app:layout_constraintStart_toStartOf=\"parent\"/>\r\n\r\n        <LinearLayout\r\n            android:id=\"@+id/detailsLayout\"\r\n            android:layout_width=\"0dp\"\r\n            android:layout_height=\"match_parent\"\r\n            android:orientation=\"vertical\"\r\n            android:padding=\"@dimen/item_padding\"\r\n            app:layout_constraintWidth_percent=\"0.7\"\r\n            app:layout_constraintTop_toTopOf=\"parent\"\r\n            app:layout_constraintBottom_toBottomOf=\"parent\"\r\n            app:layout_constraintStart_toEndOf=\"@id/timeView\">\r\n\r\n            <TextView\r\n                android:id=\"@+id/nameView\"\r\n                android:layout_width=\"wrap_content\"\r\n                android:layout_height=\"wrap_content\"\r\n                android:layout_marginBottom=\"@dimen/item_spacing_small\"\r\n                android:lines=\"1\"\r\n                android:ellipsize=\"end\"\r\n                android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\"\r\n                app:layout_constraintTop_toTopOf=\"parent\"\r\n                app:layout_constraintBottom_toTopOf=\"@id/locationView\"\r\n                tools:text=\"Academic Seminar\"/>\r\n\r\n            <TextView\r\n                android:id=\"@+id/locationView\"\r\n                android:layout_width=\"wrap_content\"\r\n                android:layout_height=\"wrap_content\"\r\n                android:lines=\"1\"\r\n                android:ellipsize=\"end\"\r\n                android:textAppearance=\"@style/Fokus.TextAppearance.Body.Small\"\r\n                app:layout_constraintTop_toBottomOf=\"@id/nameView\"\r\n                app:layout_constraintBottom_toBottomOf=\"parent\"\r\n                tools:text=\"CLSU Auditorium\"/>\r\n\r\n            <TextView\r\n                android:id=\"@+id/subjectView\"\r\n                android:layout_width=\"wrap_content\"\r\n                android:layout_height=\"wrap_content\"\r\n                android:layout_marginTop=\"@dimen/item_spacing_large\"\r\n                android:textAppearance=\"@style/Fokus.TextAppearance.Label.Medium\"\r\n                android:drawablePadding=\"@dimen/item_spacing_large\"\r\n                app:drawableStartCompat=\"@drawable/shape_color_holder_chip\"\r\n                tools:text=\"Intech 1100\"/>\r\n\r\n        </LinearLayout>\r\n\r\n    </androidx.constraintlayout.widget.ConstraintLayout>\r\n\r\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_item_library.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:foreground=\"?attr/selectableItemBackground\">\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:padding=\"@dimen/item_padding\">\n\n        <TextView\n            android:id=\"@+id/nameTextView\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:ellipsize=\"end\"\n            android:maxLines=\"1\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:layout_constraintBottom_toTopOf=\"@id/authorTextView\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintEnd_toStartOf=\"@id/versionTextView\"\n            tools:text=\"Library\"/>\n\n        <TextView\n            android:id=\"@+id/authorTextView\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"@dimen/item_spacing_large\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Body.Small\"\n            app:layout_constraintTop_toBottomOf=\"@id/nameTextView\"\n            app:layout_constraintBottom_toTopOf=\"@id/licenseNameTextView\"\n            tools:text=\"Author\"/>\n\n        <TextView\n            android:id=\"@+id/versionTextView\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Body.Small\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintHorizontal_bias=\"1.0\"\n            tools:text=\"1.0.0\"/>\n\n        <TextView\n            android:id=\"@+id/licenseNameTextView\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"@dimen/item_spacing_small\"\n            app:layout_constraintTop_toBottomOf=\"@id/authorTextView\"\n            app:layout_constraintBottom_toTopOf=\"@id/licenseDescriptionTextView\"/>\n\n        <TextView\n            android:id=\"@+id/licenseDescriptionTextView\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            app:layout_constraintTop_toBottomOf=\"@id/licenseNameTextView\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"/>\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_item_log.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<FrameLayout\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\r\n    xmlns:tools=\"http://schemas.android.com/tools\"\r\n    android:id=\"@+id/rootView\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"wrap_content\"\r\n    android:foreground=\"?attr/selectableItemBackground\">\r\n\r\n    <androidx.constraintlayout.widget.ConstraintLayout\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:padding=\"16dp\">\r\n\r\n        <androidx.appcompat.widget.AppCompatImageView\r\n            android:id=\"@+id/iconView\"\r\n            android:layout_width=\"@dimen/icon_width\"\r\n            android:layout_height=\"@dimen/icon_height\"\r\n            android:padding=\"4dp\"\r\n            android:background=\"@drawable/shape_icon_background\"\r\n            app:tint=\"@color/theme_on_primary_container\"\r\n            app:layout_constraintTop_toTopOf=\"parent\"\r\n            app:layout_constraintBottom_toBottomOf=\"parent\"\r\n            app:layout_constraintStart_toStartOf=\"parent\"\r\n            tools:src=\"@drawable/ic_outline_settings_24\"/>\r\n\r\n        <TextView\r\n            android:id=\"@+id/titleView\"\r\n            android:layout_width=\"wrap_content\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:layout_marginStart=\"@dimen/icon_to_text_padding\"\r\n            android:ellipsize=\"end\"\r\n            android:lines=\"1\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\"\r\n            app:layout_constraintTop_toTopOf=\"parent\"\r\n            app:layout_constraintBottom_toTopOf=\"@id/summaryView\"\r\n            app:layout_constraintStart_toEndOf=\"@id/iconView\"\r\n            app:layout_constraintEnd_toEndOf=\"parent\"\r\n            app:layout_constraintHorizontal_bias=\"0.0\"\r\n            tools:text=\"COMSCI 210\"/>\r\n\r\n        <TextView\r\n            android:id=\"@+id/summaryView\"\r\n            android:layout_width=\"0dp\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:layout_marginStart=\"@dimen/icon_to_text_padding\"\r\n            android:layout_marginEnd=\"16dp\"\r\n            android:ellipsize=\"end\"\r\n            android:maxLines=\"1\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Body.Small\"\r\n            app:layout_constraintTop_toBottomOf=\"@id/titleView\"\r\n            app:layout_constraintBottom_toBottomOf=\"parent\"\r\n            app:layout_constraintStart_toEndOf=\"@id/iconView\"\r\n            app:layout_constraintEnd_toStartOf=\"@id/dateTimeView\"\r\n            app:layout_constraintHorizontal_bias=\"0.0\"\r\n            tools:text=\"Mathematics, English, Science and History are the\"/>\r\n\r\n        <TextView\r\n            android:id=\"@+id/dateTimeView\"\r\n            android:layout_width=\"wrap_content\"\r\n            android:layout_height=\"wrap_content\"\r\n            app:layout_constraintTop_toTopOf=\"parent\"\r\n            app:layout_constraintBottom_toBottomOf=\"parent\"\r\n            app:layout_constraintEnd_toEndOf=\"parent\"\r\n            app:layout_constraintVertical_bias=\"1.0\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Body.Small\"\r\n            tools:text=\"h:mm\"/>\r\n\r\n    </androidx.constraintlayout.widget.ConstraintLayout>\r\n\r\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_item_menu.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:orientation=\"vertical\"\n    android:padding=\"@dimen/activity_padding\"\n    android:background=\"?attr/selectableItemBackground\">\n\n    <ImageView\n        android:id=\"@+id/iconView\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginStart=\"@dimen/activity_padding\"\n        android:contentDescription=\"@null\"\n        app:tint=\"@color/theme_on_surface\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintEnd_toStartOf=\"@id/titleView\"/>\n\n    <TextView\n        android:id=\"@+id/titleView\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginStart=\"32dp\"\n        android:layout_marginEnd=\"@dimen/activity_padding\"\n        android:textColor=\"@color/theme_on_surface\"\n        android:textAppearance=\"@style/Fokus.TextAppearance.Body.Medium\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintStart_toEndOf=\"@id/iconView\"\n        tools:text=\"Item Name\"/>\n\n</androidx.constraintlayout.widget.ConstraintLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_item_schedule.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<FrameLayout\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\r\n    xmlns:tools=\"http://schemas.android.com/tools\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"wrap_content\"\r\n    android:background=\"?attr/selectableItemBackground\">\r\n\r\n    <androidx.constraintlayout.widget.ConstraintLayout\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:paddingVertical=\"@dimen/editor_container_padding\"\r\n        android:paddingHorizontal=\"24dp\">\r\n\r\n        <TextView\r\n            android:id=\"@+id/titleView\"\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:ellipsize=\"end\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\"\r\n            app:layout_constraintTop_toTopOf=\"parent\"\r\n            tools:text=\"Sunday\"/>\r\n\r\n        <TextView\r\n            android:id=\"@+id/summaryView\"\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:ellipsize=\"end\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Body.Small\"\r\n            app:layout_constraintTop_toBottomOf=\"@id/titleView\"\r\n            app:layout_constraintBottom_toBottomOf=\"parent\"\r\n            tools:text=\"8:00AM to 2:00PM\"/>\r\n\r\n    </androidx.constraintlayout.widget.ConstraintLayout>\r\n\r\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_item_subject.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<FrameLayout\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\r\n    xmlns:tools=\"http://schemas.android.com/tools\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"wrap_content\"\r\n    android:foreground=\"?attr/selectableItemBackground\">\r\n\r\n    <androidx.constraintlayout.widget.ConstraintLayout\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:padding=\"@dimen/item_padding\">\r\n\r\n        <androidx.appcompat.widget.AppCompatImageView\r\n            android:id=\"@+id/tagView\"\r\n            android:layout_width=\"wrap_content\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:layout_marginStart=\"@dimen/item_spacing_medium\"\r\n            app:layout_constraintTop_toTopOf=\"parent\"\r\n            app:layout_constraintBottom_toBottomOf=\"parent\"\r\n            app:layout_constraintStart_toStartOf=\"parent\"\r\n            app:srcCompat=\"@drawable/shape_color_holder\"/>\r\n\r\n        <TextView\r\n            android:id=\"@+id/nameView\"\r\n            android:layout_width=\"wrap_content\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:layout_marginStart=\"24dp\"\r\n            android:ellipsize=\"end\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Label.Medium\"\r\n            app:layout_constraintTop_toTopOf=\"parent\"\r\n            app:layout_constraintBottom_toTopOf=\"@id/descriptionView\"\r\n            app:layout_constraintStart_toEndOf=\"@id/tagView\"\r\n            tools:text=\"INTECH 2100\"/>\r\n\r\n        <TextView\r\n            android:id=\"@+id/descriptionView\"\r\n            android:layout_width=\"wrap_content\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:layout_marginBottom=\"@dimen/item_spacing_medium\"\r\n            android:layout_marginStart=\"24dp\"\r\n            android:ellipsize=\"end\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\"\r\n            app:layout_constraintTop_toBottomOf=\"@id/nameView\"\r\n            app:layout_constraintBottom_toTopOf=\"@id/scheduleView\"\r\n            app:layout_constraintStart_toEndOf=\"@id/tagView\"\r\n            tools:text=\"Introduction to Web Design\"/>\r\n\r\n        <com.google.android.material.chip.Chip\r\n            android:id=\"@+id/scheduleView\"\r\n            android:layout_width=\"wrap_content\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:layout_marginStart=\"24dp\"\r\n            android:text=\"@string/button_view_schedules\"\r\n            app:layout_constraintTop_toBottomOf=\"@id/descriptionView\"\r\n            app:layout_constraintBottom_toBottomOf=\"parent\"\r\n            app:layout_constraintStart_toEndOf=\"@id/tagView\" />\r\n\r\n    </androidx.constraintlayout.widget.ConstraintLayout>\r\n\r\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_item_subject_picker.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:foreground=\"?attr/selectableItemBackground\">\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:padding=\"@dimen/item_padding\">\n\n        <ImageView\n            android:id=\"@+id/tagView\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:contentDescription=\"@null\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:srcCompat=\"@drawable/shape_color_holder\"/>\n\n        <TextView\n            android:id=\"@+id/titleView\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"4dp\"\n            android:layout_marginStart=\"@dimen/item_spacing_huge\"\n            android:ellipsize=\"end\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:layout_constraintBottom_toTopOf=\"@id/summaryView\"\n            app:layout_constraintStart_toEndOf=\"@id/tagView\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintHorizontal_bias=\"0.0\"\n            tools:text=\"COMSCI 2101\"/>\n\n        <TextView\n            android:id=\"@+id/summaryView\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"@dimen/item_spacing_small\"\n            android:layout_marginStart=\"@dimen/item_spacing_huge\"\n            android:ellipsize=\"end\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Body.Small\"\n            app:layout_constraintTop_toBottomOf=\"@id/titleView\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintStart_toEndOf=\"@id/tagView\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintHorizontal_bias=\"0.0\"\n            tools:text=\"Web Design and Development\"/>\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_item_subject_single.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:foreground=\"?attr/selectableItemBackground\">\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:padding=\"@dimen/item_padding\">\n\n        <androidx.appcompat.widget.AppCompatImageView\n            android:id=\"@+id/tagView\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"@dimen/item_spacing_medium\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:srcCompat=\"@drawable/shape_color_holder\"/>\n\n        <TextView\n            android:id=\"@+id/nameView\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"24dp\"\n            android:ellipsize=\"end\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Label.Medium\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:layout_constraintBottom_toTopOf=\"@id/descriptionView\"\n            app:layout_constraintStart_toEndOf=\"@id/tagView\"\n            tools:text=\"INTECH 2100\"/>\n\n        <TextView\n            android:id=\"@+id/descriptionView\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"@dimen/item_spacing_medium\"\n            android:layout_marginStart=\"24dp\"\n            android:ellipsize=\"end\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\"\n            app:layout_constraintTop_toBottomOf=\"@id/nameView\"\n            app:layout_constraintBottom_toTopOf=\"@id/scheduleView\"\n            app:layout_constraintStart_toEndOf=\"@id/tagView\"\n            tools:text=\"Introduction to Web Design\"/>\n\n        <TextView\n            android:id=\"@+id/scheduleView\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"24dp\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Body.Small\"\n            app:layout_constraintTop_toBottomOf=\"@id/descriptionView\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintStart_toEndOf=\"@id/tagView\"\n            tools:text=\"Wednesdays at 7:00am\"/>\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_item_task.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<FrameLayout\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\r\n    xmlns:tools=\"http://schemas.android.com/tools\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"wrap_content\"\r\n    android:foreground=\"?attr/selectableItemBackground\">\r\n\r\n    <androidx.constraintlayout.widget.ConstraintLayout\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"wrap_content\">\r\n\r\n        <androidx.appcompat.widget.AppCompatCheckBox\r\n            android:id=\"@+id/checkBox\"\r\n            android:layout_width=\"wrap_content\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:layout_marginStart=\"@dimen/item_spacing_huge\"\r\n            android:button=\"@drawable/selector_checkbox\"\r\n            app:layout_constraintTop_toTopOf=\"parent\"\r\n            app:layout_constraintBottom_toBottomOf=\"parent\"\r\n            app:layout_constraintStart_toStartOf=\"parent\"\r\n            app:layout_constraintEnd_toStartOf=\"@id/detailsLayout\"/>\r\n\r\n        <LinearLayout\r\n            android:id=\"@+id/detailsLayout\"\r\n            android:layout_width=\"0dp\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:orientation=\"vertical\"\r\n            android:paddingVertical=\"@dimen/item_padding\"\r\n            app:layout_constraintTop_toTopOf=\"parent\"\r\n            app:layout_constraintBottom_toBottomOf=\"parent\"\r\n            app:layout_constraintStart_toEndOf=\"@id/checkBox\"\r\n            app:layout_constraintEnd_toEndOf=\"parent\">\r\n\r\n            <TextView\r\n                android:id=\"@+id/taskNameView\"\r\n                android:layout_width=\"match_parent\"\r\n                android:layout_height=\"wrap_content\"\r\n                android:layout_marginBottom=\"@dimen/item_spacing_small\"\r\n                android:layout_marginStart=\"@dimen/item_padding\"\r\n                android:layout_marginEnd=\"@dimen/item_padding\"\r\n                android:lines=\"1\"\r\n                android:ellipsize=\"end\"\r\n                android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\"\r\n                tools:text=\"Draw the Flowchart\"/>\r\n\r\n            <TextView\r\n                android:id=\"@+id/dueDateView\"\r\n                android:layout_width=\"match_parent\"\r\n                android:layout_height=\"wrap_content\"\r\n                android:layout_marginStart=\"@dimen/item_padding\"\r\n                android:layout_marginEnd=\"@dimen/item_padding\"\r\n                android:lines=\"1\"\r\n                android:ellipsize=\"end\"\r\n                android:textAppearance=\"@style/Fokus.TextAppearance.Body.Small\"\r\n                tools:text=\"Tomorrow at 1:00PM\"/>\r\n\r\n            <TextView\r\n                android:id=\"@+id/subjectView\"\r\n                android:layout_width=\"match_parent\"\r\n                android:layout_height=\"wrap_content\"\r\n                android:layout_marginTop=\"@dimen/item_spacing_large\"\r\n                android:layout_marginStart=\"@dimen/item_padding\"\r\n                android:layout_marginEnd=\"@dimen/item_padding\"\r\n                android:lines=\"1\"\r\n                android:ellipsize=\"end\"\r\n                android:textAppearance=\"@style/Fokus.TextAppearance.Label.Medium\"\r\n                android:drawablePadding=\"@dimen/item_spacing_large\"\r\n                app:drawableStartCompat=\"@drawable/shape_color_holder_chip\"\r\n                tools:text=\"COMSCI 2101\"/>\r\n\r\n        </LinearLayout>\r\n\r\n    </androidx.constraintlayout.widget.ConstraintLayout>\r\n\r\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_item_task_send.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:background=\"?attr/selectableItemBackground\">\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:padding=\"@dimen/item_padding\">\n\n        <TextView\n            android:id=\"@+id/titleView\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginEnd=\"@dimen/activity_padding\"\n            android:ellipsize=\"end\"\n            android:maxLines=\"1\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintEnd_toStartOf=\"@id/addButton\"\n            tools:text=\"Task\"/>\n\n        <TextView\n            android:id=\"@+id/summaryView\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginEnd=\"@dimen/activity_padding\"\n            android:ellipsize=\"end\"\n            android:maxLines=\"1\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Body.Small\"\n            app:layout_constraintTop_toBottomOf=\"@id/titleView\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintEnd_toStartOf=\"@id/addButton\"\n            tools:text=\"8:00AM to 2:00PM\"/>\n\n        <com.google.android.material.chip.Chip\n            android:id=\"@+id/addButton\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/button_add\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"/>\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_item_widget.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<LinearLayout\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:tools=\"http://schemas.android.com/tools\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"wrap_content\"\r\n    android:orientation=\"horizontal\"\r\n    android:padding=\"@dimen/item_padding_small\">\r\n\r\n    <ImageView\r\n        android:id=\"@+id/imageView\"\r\n        android:layout_width=\"4dp\"\r\n        android:layout_height=\"match_parent\"\r\n        android:layout_marginEnd=\"@dimen/item_spacing_medium\"\r\n        android:contentDescription=\"@null\"\r\n        android:src=\"@drawable/shape_color_holder_vertical\"/>\r\n\r\n    <LinearLayout\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:orientation=\"vertical\">\r\n\r\n        <TextView\r\n            android:id=\"@+id/titleView\"\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:maxLines=\"1\"\r\n            android:ellipsize=\"end\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\"\r\n            tools:text=\"Make Dinner\"/>\r\n\r\n        <TextView\r\n            android:id=\"@+id/summaryView\"\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:layout_marginTop=\"2dp\"\r\n            android:lines=\"1\"\r\n            android:ellipsize=\"end\"\r\n            android:textAppearance=\"@style/Fokus.TextAppearance.Body.Small\"\r\n            tools:text=\"7:30PM\"/>\r\n\r\n    </LinearLayout>\r\n\r\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_navigation_header.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<TextView\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/menuTitleView\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:layout_marginTop=\"@dimen/container_padding_large\"\n    android:layout_marginStart=\"@dimen/container_padding_medium\"\n    android:layout_marginEnd=\"@dimen/container_padding_medium\"\n    android:layout_marginBottom=\"@dimen/container_padding_regular\"\n    android:text=\"@string/app_name\"\n    android:textColor=\"?attr/colorOnSurfaceVariant\"\n    android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\" />"
  },
  {
    "path": "app/src/main/res/layout/layout_preference_info.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<LinearLayout\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\r\n    xmlns:tools=\"http://schemas.android.com/tools\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"wrap_content\"\r\n    android:orientation=\"vertical\"\r\n    android:padding=\"@dimen/activity_padding\"\r\n    android:background=\"@android:color/transparent\">\r\n\r\n    <TextView\r\n        android:id=\"@android:id/title\"\r\n        android:layout_width=\"wrap_content\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:visibility=\"gone\"\r\n        tools:text=\"text\"/>\r\n\r\n    <androidx.appcompat.widget.AppCompatTextView\r\n        android:id=\"@android:id/summary\"\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:drawableStart=\"@drawable/ic_outline_info_24\"\r\n        android:drawablePadding=\"32dp\"\r\n        app:drawableTint=\"?attr/colorControlNormal\"\r\n        tools:text=\"text\"/>\r\n\r\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_sheet_options.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n\n    <TextView\n        android:id=\"@+id/menuTitleView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"@dimen/bottom_sheet_padding\"\n        android:layout_marginStart=\"@dimen/bottom_sheet_padding\"\n        android:layout_marginEnd=\"@dimen/bottom_sheet_padding\"\n        android:layout_marginBottom=\"16dp\"\n        android:text=\"@string/app_name\"\n        android:textAppearance=\"@style/Fokus.TextAppearance.Title.Large\" />\n\n    <androidx.recyclerview.widget.RecyclerView\n        android:id=\"@+id/recyclerView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"/>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_sheet_schedule.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<LinearLayout\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"match_parent\"\r\n    android:minHeight=\"@dimen/bottom_sheet_min_height\"\r\n    android:orientation=\"vertical\">\r\n\r\n    <TextView\r\n        android:id=\"@+id/menuTitleView\"\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:layout_marginTop=\"@dimen/bottom_sheet_padding\"\r\n        android:layout_marginStart=\"@dimen/bottom_sheet_padding\"\r\n        android:layout_marginEnd=\"@dimen/bottom_sheet_padding\"\r\n        android:layout_marginBottom=\"16dp\"\r\n        android:text=\"@string/dialog_class_schedules\"\r\n        android:textAppearance=\"@style/Fokus.TextAppearance.Title.Large\" />\r\n\r\n    <androidx.recyclerview.widget.RecyclerView\r\n        android:id=\"@+id/recyclerView\"\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"wrap_content\"/>\r\n\r\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_sheet_schedule_editor.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:orientation=\"vertical\">\n\n    <TextView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_margin=\"16dp\"\n        android:text=\"@string/dialog_schedule_details\"\n        android:textAppearance=\"@style/Fokus.TextAppearance.Title.Large\"/>\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"horizontal\">\n\n        <androidx.appcompat.widget.AppCompatImageView\n            android:layout_width=\"@dimen/icon_dimen\"\n            android:layout_height=\"@dimen/icon_dimen\"\n            android:layout_margin=\"@dimen/container_padding_regular\"\n            app:srcCompat=\"@drawable/ic_outline_sensor_door_24\"/>\n\n        <androidx.appcompat.widget.AppCompatEditText\n            android:id=\"@+id/classroomTextInput\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:hint=\"@string/field_classroom\"\n            android:inputType=\"text\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Label.Large\"\n            android:background=\"@android:color/transparent\"/>\n\n    </LinearLayout>\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"horizontal\">\n\n        <androidx.appcompat.widget.AppCompatImageView\n            android:layout_width=\"@dimen/icon_dimen\"\n            android:layout_height=\"@dimen/icon_dimen\"\n            android:layout_margin=\"@dimen/container_padding_regular\"\n            app:srcCompat=\"@drawable/ic_outline_date_range_24\"/>\n\n        <com.google.android.material.chip.ChipGroup\n            android:id=\"@+id/daysOfWeekGroup\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_weight=\"1\"\n            android:layout_marginEnd=\"@dimen/container_padding_regular\"\n            app:chipSpacingVertical=\"0dp\">\n\n            <com.google.android.material.chip.Chip\n                android:id=\"@+id/sundayChip\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"@string/days_of_week_item_sunday\"\n                style=\"@style/Fokus.Widget.Chip\"/>\n\n            <com.google.android.material.chip.Chip\n                android:id=\"@+id/mondayChip\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"@string/days_of_week_item_monday\"\n                style=\"@style/Fokus.Widget.Chip\"/>\n\n            <com.google.android.material.chip.Chip\n                android:id=\"@+id/tuesdayChip\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"@string/days_of_week_item_tuesday\"\n                style=\"@style/Fokus.Widget.Chip\"/>\n\n            <com.google.android.material.chip.Chip\n                android:id=\"@+id/wednesdayChip\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"@string/days_of_week_item_wednesday\"\n                style=\"@style/Fokus.Widget.Chip\"/>\n\n            <com.google.android.material.chip.Chip\n                android:id=\"@+id/thursdayChip\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"@string/days_of_week_item_thursday\"\n                style=\"@style/Fokus.Widget.Chip\"/>\n\n            <com.google.android.material.chip.Chip\n                android:id=\"@+id/fridayChip\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"@string/days_of_week_item_friday\"\n                style=\"@style/Fokus.Widget.Chip\"/>\n\n            <com.google.android.material.chip.Chip\n                android:id=\"@+id/saturdayChip\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"@string/days_of_week_item_saturday\"\n                style=\"@style/Fokus.Widget.Chip\"/>\n\n        </com.google.android.material.chip.ChipGroup>\n\n    </LinearLayout>\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"horizontal\">\n\n        <androidx.appcompat.widget.AppCompatImageView\n            android:layout_width=\"@dimen/icon_dimen\"\n            android:layout_height=\"@dimen/icon_dimen\"\n            android:layout_margin=\"@dimen/container_padding_regular\"\n            app:srcCompat=\"@drawable/ic_outline_access_time_24\"/>\n\n        <TextView\n            android:id=\"@+id/startTimeTextView\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_weight=\"1\"\n            android:gravity=\"center_vertical\"\n            android:text=\"@string/field_start_time\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Label.Large\"\n            android:clickable=\"true\"\n            android:focusable=\"true\"/>\n\n        <TextView\n            android:id=\"@+id/endTimeTextView\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_weight=\"1\"\n            android:gravity=\"center_vertical\"\n            android:layout_marginEnd=\"@dimen/container_padding_regular\"\n            android:text=\"@string/field_end_time\"\n            android:textAppearance=\"@style/Fokus.TextAppearance.Label.Large\"\n            android:clickable=\"true\"\n            android:focusable=\"true\"/>\n\n    </LinearLayout>\n\n    <LinearLayout\n        android:id=\"@+id/weekNumbersHeader\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"horizontal\">\n\n        <androidx.appcompat.widget.AppCompatImageView\n            android:layout_width=\"@dimen/icon_dimen\"\n            android:layout_height=\"@dimen/icon_dimen\"\n            android:layout_margin=\"@dimen/container_padding_regular\"\n            app:srcCompat=\"@drawable/ic_outline_calendar_month_24\"/>\n\n        <com.google.android.material.chip.ChipGroup\n            android:id=\"@+id/weekOfMonthGroup\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_weight=\"1\"\n            app:chipSpacingVertical=\"0dp\">\n\n            <com.google.android.material.chip.Chip\n                android:id=\"@+id/weekOneChip\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:checked=\"true\"\n                android:text=\"@string/weeks_of_month_item_week_1\"\n                style=\"@style/Fokus.Widget.Chip\"/>\n\n            <com.google.android.material.chip.Chip\n                android:id=\"@+id/weekTwoChip\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:checked=\"true\"\n                android:text=\"@string/weeks_of_month_item_week_2\"\n                style=\"@style/Fokus.Widget.Chip\"/>\n\n            <com.google.android.material.chip.Chip\n                android:id=\"@+id/weekThreeChip\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:checked=\"true\"\n                android:text=\"@string/weeks_of_month_item_week_3\"\n                style=\"@style/Fokus.Widget.Chip\"/>\n\n            <com.google.android.material.chip.Chip\n                android:id=\"@+id/weekFourChip\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:checked=\"true\"\n                android:text=\"@string/weeks_of_month_item_week_4\"\n                style=\"@style/Fokus.Widget.Chip\"/>\n\n        </com.google.android.material.chip.ChipGroup>\n\n    </LinearLayout>\n\n    <com.google.android.material.button.MaterialButton\n        android:id=\"@+id/actionButton\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_margin=\"@dimen/container_padding_regular\"\n        android:layout_gravity=\"end\"\n        android:text=\"@string/button_save\"\n        app:icon=\"@drawable/ic_outline_save_24\"\n        app:iconGravity=\"textStart\"\n        app:iconPadding=\"@dimen/container_padding_regular\"\n        style=\"@style/Fokus.Widget.Button\"/>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_viewer_image.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <include\n        android:id=\"@+id/appBarLayout\"\n        layout=\"@layout/layout_appbar_viewer\"/>\n\n    <com.github.chrisbanes.photoview.PhotoView\n        android:id=\"@+id/imageContainer\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"/>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_widget_events.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<RelativeLayout\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:tools=\"http://schemas.android.com/tools\"\r\n    android:id=\"@+id/rootView\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"match_parent\"\r\n    android:background=\"?android:attr/colorBackground\"\r\n    android:theme=\"@style/Theme.Material3.DynamicColors.DayNight\">\r\n\r\n    <TextView\r\n        android:id=\"@+id/emptyView\"\r\n        android:layout_width=\"wrap_content\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:layout_marginHorizontal=\"@dimen/widget_empty_text_padding\"\r\n        android:layout_centerInParent=\"true\"\r\n        android:gravity=\"center\"\r\n        android:text=\"@string/widget_event_empty\"\r\n        android:textColor=\"?attr/colorPrimary\"\r\n        android:textAppearance=\"@style/Fokus.TextAppearance.Label.Medium\"/>\r\n\r\n    <LinearLayout\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:orientation=\"vertical\">\r\n\r\n        <RelativeLayout\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:padding=\"@dimen/widget_title_padding\">\r\n\r\n            <TextView\r\n                android:layout_width=\"match_parent\"\r\n                android:layout_height=\"wrap_content\"\r\n                android:text=\"@string/widget_event_title\"\r\n                android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\"\r\n                android:textColor=\"?attr/colorPrimary\" />\r\n\r\n            <ImageButton\r\n                android:id=\"@+id/actionButton\"\r\n                android:layout_width=\"wrap_content\"\r\n                android:layout_height=\"wrap_content\"\r\n                android:layout_alignParentEnd=\"true\"\r\n                android:background=\"@android:color/transparent\"\r\n                android:contentDescription=\"@string/button_add\"\r\n                android:src=\"@drawable/ic_outline_add_24\"\r\n                android:tint=\"?attr/colorPrimary\"\r\n                tools:ignore=\"UseAppTint\" />\r\n\r\n        </RelativeLayout>\r\n        <ListView\r\n            android:id=\"@+id/listView\"\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"match_parent\"\r\n            android:divider=\"@null\"/>\r\n\r\n    </LinearLayout>\r\n\r\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_widget_progress.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<ProgressBar\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    android:id=\"@+id/progressBar\"\r\n    android:layout_width=\"wrap_content\"\r\n    android:layout_height=\"wrap_content\"/>"
  },
  {
    "path": "app/src/main/res/layout/layout_widget_subjects.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<RelativeLayout\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:tools=\"http://schemas.android.com/tools\"\r\n    android:id=\"@+id/rootView\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"match_parent\"\r\n    android:background=\"?android:attr/colorBackground\"\r\n    android:theme=\"@style/Theme.Material3.DynamicColors.DayNight\">\r\n\r\n    <TextView\r\n        android:id=\"@+id/emptyView\"\r\n        android:layout_width=\"wrap_content\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:layout_marginHorizontal=\"@dimen/widget_empty_text_padding\"\r\n        android:layout_centerInParent=\"true\"\r\n        android:gravity=\"center\"\r\n        android:text=\"@string/widget_class_empty\"\r\n        android:textColor=\"?attr/colorPrimary\"\r\n        android:textAppearance=\"@style/Fokus.TextAppearance.Label.Medium\"/>\r\n\r\n    <LinearLayout\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"match_parent\"\r\n        android:orientation=\"vertical\">\r\n\r\n        <RelativeLayout\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:padding=\"@dimen/widget_title_padding\">\r\n\r\n            <TextView\r\n                android:layout_width=\"match_parent\"\r\n                android:layout_height=\"wrap_content\"\r\n                android:text=\"@string/widget_class_title\"\r\n                android:textColor=\"?attr/colorPrimary\"\r\n                android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\"/>\r\n\r\n            <ImageButton\r\n                android:id=\"@+id/actionButton\"\r\n                android:layout_width=\"wrap_content\"\r\n                android:layout_height=\"wrap_content\"\r\n                android:layout_alignParentEnd=\"true\"\r\n                android:background=\"@android:color/transparent\"\r\n                android:contentDescription=\"@string/button_add\"\r\n                android:src=\"@drawable/ic_outline_add_24\"\r\n                android:tint=\"?attr/colorPrimary\"\r\n                tools:ignore=\"UseAppTint\" />\r\n\r\n        </RelativeLayout>\r\n        <ListView\r\n            android:id=\"@+id/listView\"\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"match_parent\"\r\n            android:divider=\"@null\"/>\r\n\r\n    </LinearLayout>\r\n\r\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_widget_tasks.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<RelativeLayout\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:tools=\"http://schemas.android.com/tools\"\r\n    android:id=\"@+id/rootView\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"match_parent\"\r\n    android:background=\"?android:attr/colorBackground\"\r\n    android:theme=\"@style/Theme.Material3.DynamicColors.DayNight\">\r\n\r\n    <TextView\r\n        android:id=\"@+id/emptyView\"\r\n        android:layout_width=\"wrap_content\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:layout_marginHorizontal=\"@dimen/widget_empty_text_padding\"\r\n        android:layout_centerInParent=\"true\"\r\n        android:gravity=\"center\"\r\n        android:text=\"@string/widget_task_empty\"\r\n        android:textColor=\"?attr/colorPrimary\"\r\n        android:textAppearance=\"@style/Fokus.TextAppearance.Label.Medium\" />\r\n\r\n    <LinearLayout\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"match_parent\"\r\n        android:orientation=\"vertical\">\r\n\r\n        <RelativeLayout\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:padding=\"@dimen/widget_title_padding\">\r\n\r\n            <TextView\r\n                android:layout_width=\"match_parent\"\r\n                android:layout_height=\"wrap_content\"\r\n                android:text=\"@string/widget_task_title\"\r\n                android:textColor=\"?attr/colorPrimary\"\r\n                android:textAppearance=\"@style/Fokus.TextAppearance.Title.Medium\"/>\r\n\r\n            <ImageButton\r\n                android:id=\"@+id/actionButton\"\r\n                android:layout_width=\"wrap_content\"\r\n                android:layout_height=\"wrap_content\"\r\n                android:layout_alignParentEnd=\"true\"\r\n                android:contentDescription=\"@string/button_add\"\r\n                android:background=\"@android:color/transparent\"\r\n                android:src=\"@drawable/ic_outline_add_24\"\r\n                android:tint=\"?attr/colorPrimary\"\r\n                tools:ignore=\"UseAppTint\" />\r\n\r\n        </RelativeLayout>\r\n\r\n        <ListView\r\n            android:id=\"@+id/listView\"\r\n            android:layout_width=\"match_parent\"\r\n            android:layout_height=\"match_parent\"\r\n            android:divider=\"@null\"/>\r\n\r\n    </LinearLayout>\r\n\r\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/menu/menu_add.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <item\n        android:id=\"@+id/action_add\"\n        android:title=\"@string/menu_add\"\n        android:icon=\"@drawable/ic_outline_add_24\"\n        app:iconTint=\"?attr/colorOnSurface\"\n        app:showAsAction=\"ifRoom\"/>\n\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/menu_attachment.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item\n        android:id=\"@+id/action_import_file\"\n        android:title=\"@string/attachment_type_import_file\"\n        android:icon=\"@drawable/ic_outline_file_open_24\"/>\n\n    <item\n        android:id=\"@+id/action_website_url\"\n        android:title=\"@string/attachment_type_website_url\"\n        android:icon=\"@drawable/ic_outline_link_24\"/>\n\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/menu_editor.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <item\n        android:id=\"@+id/action_share_options\"\n        android:title=\"@string/menu_share\"\n        android:icon=\"@drawable/ic_outline_share_24\"\n        app:iconTint=\"@color/theme_on_surface\">\n\n        <menu>\n            <item\n                android:id=\"@+id/action_share\"\n                android:title=\"@string/menu_share_directly\"\n                android:icon=\"@drawable/ic_outline_share_24\"/>\n\n            <item\n                android:id=\"@+id/action_export\"\n                android:title=\"@string/menu_export_to_file\"\n                android:icon=\"@drawable/ic_outline_file_open_24\"/>\n        </menu>\n\n    </item>\n\n    <item\n        android:id=\"@+id/action_import\"\n        android:title=\"@string/menu_import\"\n        android:icon=\"@drawable/ic_outline_file_upload_24\"\n        app:showAsAction=\"never\"/>\n\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/menu_events.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item\n        android:id=\"@+id/action_archived\"\n        android:title=\"@string/menu_archived\"\n        android:icon=\"@drawable/ic_outline_archive_24\"/>\n\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/menu_logs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <item\n        android:id=\"@+id/action_clear_items\"\n        android:title=\"@string/menu_clear_items\"\n        android:icon=\"@drawable/ic_outline_delete_24\"\n        app:showAsAction=\"never\"/>\n\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/menu_share.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <item\n        android:id=\"@+id/action_export\"\n        android:title=\"@string/menu_export_to_file\"\n        android:icon=\"@drawable/ic_outline_file_upload_24\"\n        app:iconTint=\"@color/theme_on_surface\"/>\n\n    <item\n        android:id=\"@+id/action_share\"\n        android:title=\"@string/menu_share_directly\"\n        android:icon=\"@drawable/ic_outline_share_24\"\n        app:iconTint=\"@color/theme_on_surface\"/>\n\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/menu_subjects.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <item\n        android:title=\"@string/menu_sort\"\n        android:icon=\"@drawable/ic_hero_sort_ascending_24\"\n        app:showAsAction=\"never\">\n\n        <menu>\n            <item\n                android:title=\"@string/field_subject_code\"\n                android:icon=\"@drawable/ic_outline_numbers_24\">\n                <menu>\n                    <item\n                        android:id=\"@+id/action_code_sort_ascending\"\n                        android:title=\"@string/sorting_directions_ascending\"\n                        android:icon=\"@drawable/ic_hero_sort_ascending_24\"/>\n\n                    <item\n                        android:id=\"@+id/action_code_sort_descending\"\n                        android:title=\"@string/sorting_directions_descending\"\n                        android:icon=\"@drawable/ic_hero_sort_descending_24\"/>\n                </menu>\n            </item>\n            <item\n                android:title=\"@string/field_description\"\n                android:icon=\"@drawable/ic_outline_edit_note_24\">\n                <menu>\n                    <item\n                        android:id=\"@+id/action_description_sort_ascending\"\n                        android:title=\"@string/sorting_directions_ascending\"\n                        android:icon=\"@drawable/ic_hero_sort_ascending_24\"/>\n\n                    <item\n                        android:id=\"@+id/action_description_sort_descending\"\n                        android:title=\"@string/sorting_directions_descending\"\n                        android:icon=\"@drawable/ic_hero_sort_descending_24\"/>\n                </menu>\n            </item>\n            <item\n                android:id=\"@+id/action_sort_schedule\"\n                android:title=\"@string/field_schedule\"\n                android:icon=\"@drawable/ic_outline_event_24\">\n                <menu>\n                    <item\n                        android:id=\"@+id/action_schedule_sort_ascending\"\n                        android:title=\"@string/sorting_directions_ascending\"\n                        android:icon=\"@drawable/ic_hero_sort_ascending_24\"/>\n\n                    <item\n                        android:id=\"@+id/action_schedule_sort_descending\"\n                        android:title=\"@string/sorting_directions_descending\"\n                        android:icon=\"@drawable/ic_hero_sort_descending_24\"/>\n                </menu>\n            </item>\n        </menu>\n\n    </item>\n\n    <item\n        android:title=\"@string/menu_filter\"\n        android:icon=\"@drawable/ic_outline_filter_alt_24\"\n        app:showAsAction=\"never\">\n\n        <menu>\n            <item\n                android:id=\"@+id/action_filter_all\"\n                android:title=\"@string/filter_options_all\"\n                android:icon=\"@drawable/ic_outline_checklist_24\"/>\n            <item\n                android:id=\"@+id/action_filter_today\"\n                android:title=\"@string/filter_options_today_classes\"\n                android:icon=\"@drawable/ic_outline_priority_high_24\" />\n            <item\n                android:id=\"@+id/action_filter_tomorrow\"\n                android:title=\"@string/filter_options_tomorrow_classes\"\n                android:icon=\"@drawable/ic_outline_event_24\"/>\n        </menu>\n    </item>\n\n    <item\n        android:id=\"@+id/action_archived\"\n        android:title=\"@string/menu_archived\"\n        android:icon=\"@drawable/ic_outline_archive_24\"/>\n\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/menu_tasks.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <item\n        android:title=\"@string/menu_sort\"\n        android:icon=\"@drawable/ic_hero_sort_ascending_24\"\n        app:showAsAction=\"never\">\n\n        <menu>\n            <item\n                android:title=\"@string/field_task_name\"\n                android:icon=\"@drawable/ic_outline_edit_note_24\">\n                <menu>\n                    <item\n                        android:id=\"@+id/action_name_sort_ascending\"\n                        android:title=\"@string/sorting_directions_ascending\"\n                        android:icon=\"@drawable/ic_hero_sort_ascending_24\"/>\n\n                    <item\n                        android:id=\"@+id/action_name_sort_descending\"\n                        android:title=\"@string/sorting_directions_descending\"\n                        android:icon=\"@drawable/ic_hero_sort_descending_24\"/>\n                </menu>\n            </item>\n            <item\n                android:title=\"@string/field_due_date\"\n                android:icon=\"@drawable/ic_outline_access_time_24\">\n                <menu>\n                    <item\n                        android:id=\"@+id/action_due_sort_ascending\"\n                        android:title=\"@string/sorting_directions_ascending\"\n                        android:icon=\"@drawable/ic_hero_sort_ascending_24\"/>\n\n                    <item\n                        android:id=\"@+id/action_due_sort_descending\"\n                        android:title=\"@string/sorting_directions_descending\"\n                        android:icon=\"@drawable/ic_hero_sort_descending_24\"/>\n                </menu>\n            </item>\n        </menu>\n\n    </item>\n\n    <item\n        android:title=\"@string/menu_filter\"\n        android:icon=\"@drawable/ic_outline_filter_alt_24\"\n        app:showAsAction=\"never\">\n\n        <menu>\n            <item\n                android:id=\"@+id/action_filter_all\"\n                android:title=\"@string/filter_options_all\"\n                android:icon=\"@drawable/ic_outline_checklist_24\"/>\n            <item\n                android:id=\"@+id/action_filter_pending\"\n                android:title=\"@string/filter_options_pending_tasks\"\n                android:icon=\"@drawable/ic_outline_priority_high_24\" />\n            <item\n                android:id=\"@+id/action_filter_finished\"\n                android:title=\"@string/filter_options_finished_tasks\"\n                android:icon=\"@drawable/ic_outline_check_24\"/>\n        </menu>\n    </item>\n\n    <item\n        android:id=\"@+id/action_archived\"\n        android:title=\"@string/menu_archived\"\n        android:icon=\"@drawable/ic_outline_archive_24\"/>\n\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/navigation_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <group android:id=\"@+id/groupFragments\" android:checkableBehavior=\"single\">\n\n        <item\n            android:id=\"@+id/navigation_tasks\"\n            android:title=\"@string/navigation_tasks\"\n            android:icon=\"@drawable/ic_outline_check_24\"\n            android:checked=\"true\"/>\n        <item\n            android:id=\"@+id/navigation_events\"\n            android:title=\"@string/navigation_events\"\n            android:icon=\"@drawable/ic_outline_event_24\"/>\n        <item\n            android:id=\"@+id/navigation_subjects\"\n            android:title=\"@string/navigation_subjects\"\n            android:icon=\"@drawable/ic_outline_science_24\"/>\n\n    </group>\n\n    <group android:id=\"@+id/groupActivities\" android:checkableBehavior=\"none\">\n\n        <item\n            android:id=\"@+id/navigation_logs\"\n            android:title=\"@string/navigation_logs\"\n            android:icon=\"@drawable/ic_outline_query_stats_24\"/>\n        <item\n            android:id=\"@+id/navigation_settings\"\n            android:title=\"@string/navigation_settings\"\n            android:icon=\"@drawable/ic_outline_settings_24\"/>\n        <item\n            android:id=\"@+id/navigation_about\"\n            android:title=\"@string/navigation_about\"\n            android:icon=\"@drawable/ic_outline_info_24\"/>\n    </group>\n\n</menu>"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\r\n    <background android:drawable=\"@color/ic_launcher_background\"/>\r\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\"/>\r\n    <monochrome android:drawable=\"@drawable/ic_launcher_monochrome\"/>\r\n</adaptive-icon>"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\r\n    <background android:drawable=\"@color/ic_launcher_background\"/>\r\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\"/>\r\n    <monochrome android:drawable=\"@drawable/ic_launcher_monochrome\"/>\r\n</adaptive-icon>"
  },
  {
    "path": "app/src/main/res/navigation/navigation_container_event.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<navigation\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/navigation_container_event\"\n    app:startDestination=\"@id/navigation_editor_event\">\n\n    <fragment\n        android:id=\"@+id/navigation_editor_event\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.event.editor.EventEditorFragment\"\n        tools:layout=\"@layout/fragment_editor_task\"/>\n\n</navigation>"
  },
  {
    "path": "app/src/main/res/navigation/navigation_container_subject.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<navigation\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/navigation_container_subject\"\n    app:startDestination=\"@id/navigation_editor_subject\">\n\n    <fragment\n        android:id=\"@+id/navigation_editor_subject\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.subject.editor.SubjectEditorFragment\"\n        tools:layout=\"@layout/fragment_editor_task\"/>\n\n</navigation>"
  },
  {
    "path": "app/src/main/res/navigation/navigation_container_task.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<navigation\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/navigation_container_task\"\n    app:startDestination=\"@id/navigation_editor_task\">\n\n    <fragment\n        android:id=\"@+id/navigation_editor_task\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.task.editor.TaskEditorFragment\"\n        tools:layout=\"@layout/fragment_editor_task\"/>\n\n</navigation>"
  },
  {
    "path": "app/src/main/res/navigation/navigation_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<navigation xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/navigation_main\"\n    app:startDestination=\"@id/navigation_root\">\n\n    <fragment\n        android:id=\"@+id/navigation_root\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.core.fragment.RootFragment\"\n        tools:layout=\"@layout/fragment_root\"/>\n    <fragment\n        android:id=\"@+id/navigation_backup\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.settings.BackupFragment\"\n        tools:layout=\"@layout/fragment_root\"/>\n    <fragment\n        android:id=\"@+id/navigation_notices\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.about.NoticesFragment\"\n        tools:layout=\"@layout/fragment_notices\"/>\n    <fragment\n        android:id=\"@+id/navigation_libraries\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.about.LibrariesFragment\"\n        tools:layout=\"@layout/fragment_libraries\"/>\n\n    <!-- EditorUI -->\n    <fragment\n        android:id=\"@+id/navigation_editor_task\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.task.editor.TaskEditorFragment\"\n        tools:layout=\"@layout/fragment_editor_task\"/>\n    <fragment\n        android:id=\"@+id/navigation_editor_event\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.event.editor.EventEditorFragment\"\n        tools:layout=\"@layout/fragment_editor_event\"/>\n    <fragment\n        android:id=\"@+id/navigation_editor_subject\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.subject.editor.SubjectEditorFragment\"\n        tools:layout=\"@layout/fragment_editor_subject\"/>\n    <!-- Archived -->\n\n    <fragment\n        android:id=\"@+id/navigation_archived_event\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.event.archived.ArchivedEventFragment\"\n        android:label=\"@string/activity_archives\"\n        tools:layout=\"@layout/fragment_archived_event\"/>\n    <fragment\n        android:id=\"@+id/navigation_archived_subject\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.subject.archived.ArchivedSubjectFragment\"\n        android:label=\"@string/activity_archives\"\n        tools:layout=\"@layout/fragment_archived_subject\"/>\n    <fragment\n        android:id=\"@+id/navigation_archived_task\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.task.archived.ArchivedTaskFragment\"\n        android:label=\"@string/activity_archives\"\n        tools:layout=\"@layout/fragment_archived_task\"/>\n\n</navigation>"
  },
  {
    "path": "app/src/main/res/navigation/navigation_root.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<navigation xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/navigation_root\"\n    app:startDestination=\"@id/navigation_tasks\">\n\n    <fragment\n        android:id=\"@+id/navigation_tasks\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.task.TaskFragment\"\n        android:label=\"@string/navigation_tasks\"\n        tools:layout=\"@layout/fragment_task\"/>\n    <fragment\n        android:id=\"@+id/navigation_events\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.event.EventFragment\"\n        android:label=\"@string/navigation_events\"\n        tools:layout=\"@layout/fragment_event\"/>\n    <fragment\n        android:id=\"@+id/navigation_subjects\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.subject.SubjectFragment\"\n        android:label=\"@string/activity_subjects\"\n        tools:layout=\"@layout/fragment_subject\"/>\n    <fragment\n        android:id=\"@+id/navigation_logs\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.log.LogFragment\"\n        android:label=\"@string/activity_logs\"\n        tools:layout=\"@layout/fragment_logs\"/>\n    <fragment\n        android:id=\"@+id/navigation_settings\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.settings.SettingsFragment\"\n        tools:layout=\"@layout/fragment_settings\"/>\n    <fragment\n        android:id=\"@+id/navigation_about\"\n        android:name=\"com.isaiahvonrundstedt.fokus.features.about.AboutFragment\"\n        tools:layout=\"@layout/fragment_about\"/>\n\n</navigation>"
  },
  {
    "path": "app/src/main/res/values/array.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n\r\n    <string-array name=\"oem_battery_optimization\">\r\n        <item>oneplus</item>\r\n        <item>samsung</item>\r\n        <item>huawei</item>\r\n        <item>meizu</item>\r\n        <item>xiaomi</item>\r\n        <item>wiko</item>\r\n        <item>asus</item>\r\n        <item>lenovo</item>\r\n        <item>oppo</item>\r\n        <item>nokia</item>\r\n        <item>sony</item>\r\n        <item>google</item>\r\n        <item>htc</item>\r\n    </string-array>\r\n\r\n    <string-array name=\"settings_dark_theme_items\">\r\n        <item>@string/settings_theme_item_system</item>\r\n        <item>@string/settings_theme_item_dark</item>\r\n        <item>@string/settings_theme_item_light</item>\r\n    </string-array>\r\n\r\n    <string-array name=\"settings_dark_theme_values\">\r\n        <item>SYSTEM</item>\r\n        <item>DARK</item>\r\n        <item>LIGHT</item>\r\n    </string-array>\r\n\r\n    <string-array name=\"settings_task_reminder_frequency_items\">\r\n        <item>@string/settings_reminder_frequency_item_everyday</item>\r\n        <item>@string/settings_reminder_frequency_item_weekends</item>\r\n    </string-array>\r\n\r\n    <string-array name=\"settings_task_reminder_frequency_values\">\r\n        <item>EVERYDAY</item>\r\n        <item>WEEKENDS</item>\r\n    </string-array>\r\n\r\n    <string-array name=\"settings_task_reminder_interval_items\">\r\n        <item>@string/settings_task_reminders_item_hour</item>\r\n        <item>@string/settings_task_reminders_item_three_hours</item>\r\n        <item>@string/settings_task_reminders_item_day</item>\r\n    </string-array>\r\n\r\n    <string-array name=\"settings_task_reminder_interval_values\">\r\n        <item>1</item>\r\n        <item>3</item>\r\n        <item>24</item>\r\n    </string-array>\r\n\r\n    <string-array name=\"settings_event_reminder_interval_items\">\r\n        <item>@string/settings_event_reminders_item_quarter_hour</item>\r\n        <item>@string/settings_event_reminders_item_half_hour</item>\r\n        <item>@string/settings_event_reminders_item_hour</item>\r\n    </string-array>\r\n\r\n    <string-array name=\"settings_event_reminder_interval_values\">\r\n        <item>15</item>\r\n        <item>30</item>\r\n        <item>60</item>\r\n    </string-array>\r\n\r\n    <string-array name=\"settings_subject_reminder_interval_items\">\r\n        <item>@string/settings_class_reminders_item_5_minutes</item>\r\n        <item>@string/settings_class_reminders_item_15_minutes</item>\r\n        <item>@string/settings_class_reminders_item_30_minutes</item>\r\n    </string-array>\r\n\r\n    <string-array name=\"settings_subject_reminder_interval_values\">\r\n        <item>5</item>\r\n        <item>15</item>\r\n        <item>30</item>\r\n    </string-array>\r\n\r\n</resources>"
  },
  {
    "path": "app/src/main/res/values/attrs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <declare-styleable name=\"RadioButtonCompat\">\n        <attr name=\"textAppearanceCompat\" format=\"reference\"/>\n    </declare-styleable>\n\n    <declare-styleable name=\"TwoLineRadioButton\">\n        <attr name=\"titleText\" format=\"string\"/>\n        <attr name=\"subtitleText\" format=\"string\"/>\n        <attr name=\"titleTextColor\" format=\"color\"/>\n        <attr name=\"subtitleTextColor\" format=\"color\"/>\n        <attr name=\"titleTextAppearance\" format=\"reference\"/>\n        <attr name=\"subtitleTextAppearance\" format=\"reference\"/>\n    </declare-styleable>\n\n</resources>"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n    <color name=\"theme_primary\">#006591</color>\r\n    <color name=\"theme_on_primary\">#ffffff</color>\r\n    <color name=\"theme_primary_container\">#c9e6ff</color>\r\n    <color name=\"theme_on_primary_container\">#001e2f</color>\r\n    <color name=\"theme_secondary\">#1160a4</color>\r\n    <color name=\"theme_on_secondary\">#ffffff</color>\r\n    <color name=\"theme_secondary_container\">#d2e4ff</color>\r\n    <color name=\"theme_on_secondary_container\">#001c38</color>\r\n    <color name=\"theme_tertiary\">#494bd6</color>\r\n    <color name=\"theme_on_tertiary\">#ffffff</color>\r\n    <color name=\"theme_tertiary_container\">#e1e0ff</color>\r\n    <color name=\"theme_on_tertiary_container\">#07006c</color>\r\n    <color name=\"theme_error\">#ba1a1a</color>\r\n    <color name=\"theme_on_error\">#ffffff</color>\r\n    <color name=\"theme_error_container\">#ffdad6</color>\r\n    <color name=\"theme_on_error_container\">#410002</color>\r\n    <color name=\"theme_background\">#fcfcff</color>\r\n    <color name=\"theme_on_background\">#191c1e</color>\r\n    <color name=\"theme_surface\">#fcfcff</color>\r\n    <color name=\"theme_on_surface\">#191c1e</color>\r\n    <color name=\"theme_surface_variant\">#dde3ea</color>\r\n    <color name=\"theme_on_surface_variant\">#41474d</color>\r\n    <color name=\"theme_outline\">#71787e</color>\r\n    <color name=\"theme_inverse_on_surface\">#f0f0f3</color>\r\n    <color name=\"theme_inverse_surface\">#2e3133</color>\r\n    <color name=\"theme_inverse_primary\">#89ceff</color>\r\n    <color name=\"theme_shadow\">#000000</color>\r\n    <color name=\"theme_surface_tint\">#006591</color>\r\n    <color name=\"theme_surface_tint_color\">#006591</color>\r\n\r\n    <color name=\"color_primary_text\">@color/theme_on_surface</color>\r\n    <color name=\"color_secondary_text\">#808080</color>\r\n\r\n    <color name=\"color_chip_background_transparent\">#392197fe</color>\r\n\r\n    <color name=\"color_fokus_blue_50\">#e3f2ff</color>\r\n    <color name=\"color_fokus_blue_100\">#bcdeff</color>\r\n    <color name=\"color_fokus_blue_500\">#2197fe</color>\r\n    <color name=\"color_fokus_blue_700\">#2076dc</color>\r\n    <color name=\"color_fokus_blue_900\">#1a46aa</color>\r\n</resources>\r\n"
  },
  {
    "path": "app/src/main/res/values/dimen.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n    <dimen name=\"container_padding_large\">32dp</dimen>\r\n    <dimen name=\"container_padding_medium\">24dp</dimen>\r\n    <dimen name=\"container_padding_regular\">16dp</dimen>\r\n    <dimen name=\"container_padding_small\">8dp</dimen>\r\n\r\n    <!-- Legacy -->\r\n    <dimen name=\"activity_padding\">16dp</dimen>\r\n    <dimen name=\"activity_padding_medium\">32dp</dimen>\r\n\r\n    <dimen name=\"button_icon_padding\">32dp</dimen>\r\n\r\n    <dimen name=\"bottom_sheet_margin_horizontal\">0dp</dimen>\r\n    <dimen name=\"bottom_sheet_padding\">24dp</dimen>\r\n    <dimen name=\"bottom_sheet_min_height\">256dp</dimen>\r\n\r\n    <dimen name=\"surface_corner_radius\">12dp</dimen>\r\n\r\n    <dimen name=\"editor_container_padding\">12dp</dimen>\r\n    <dimen name=\"editor_item_height\">56dp</dimen>\r\n\r\n    <!-- RecyclerView -->\r\n    <dimen name=\"item_padding\">16dp</dimen>\r\n    <dimen name=\"item_padding_small\">8dp</dimen>\r\n    <dimen name=\"item_spacing_small\">4dp</dimen>\r\n    <dimen name=\"item_spacing_medium\">8dp</dimen>\r\n    <dimen name=\"item_spacing_large\">16dp</dimen>\r\n    <dimen name=\"item_spacing_huge\">32dp</dimen>\r\n\r\n    <dimen name=\"icon_width\">40dp</dimen>\r\n    <dimen name=\"icon_height\">40dp</dimen>\r\n    <dimen name=\"icon_to_text_padding\">@dimen/item_padding</dimen>\r\n\r\n    <!-- Widget -->\r\n    <dimen name=\"widget_title\">16sp</dimen>\r\n    <dimen name=\"widget_title_padding\">12sp</dimen>\r\n    <dimen name=\"widget_item_text_title\">16sp</dimen>\r\n    <dimen name=\"widget_item_tag_padding_end\">8dp</dimen>\r\n    <dimen name=\"widget_empty_text_padding\">8dp</dimen>\r\n\r\n    <dimen name=\"drawable_icon_padding\">8dp</dimen>\r\n\r\n    <!-- Switch -->\r\n    <dimen name=\"switch_thumb_size\">20dp</dimen>\r\n    <dimen name=\"switch_thumb_stroke_size\">1dp</dimen>\r\n    <dimen name=\"switch_track_radius\">20dp</dimen>\r\n    <dimen name=\"switch_track_stroke_size\">1dp</dimen>\r\n\r\n    <!-- Radio -->\r\n    <dimen name=\"radio_button_width\">48dp</dimen>\r\n    <dimen name=\"radio_button_height\">48dp</dimen>\r\n\r\n    <!-- Icon -->\r\n    <dimen name=\"icon_dimen\">24dp</dimen>\r\n\r\n</resources>"
  },
  {
    "path": "app/src/main/res/values/integer.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!-- Animations -->\n    <integer name=\"animation_duration_medium\">300</integer>\n    <integer name=\"animation_duration_long\">400</integer>\n\n</resources>"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\r\n    <string translatable=\"false\" name=\"app_name\">Fokus</string>\r\n\r\n    <string name=\"shortcut_add_task\">@string/button_add_task</string>\r\n    <string name=\"shortcut_add_event\">@string/button_add_event</string>\r\n    <string name=\"shortcut_add_subject\">@string/button_add_subject</string>\r\n\r\n    <string name=\"activity_tasks\">Your Tasks</string>\r\n    <string name=\"activity_tasks_pending\">Your Pending Tasks</string>\r\n    <string name=\"activity_tasks_finished\">Your Finished Tasks</string>\r\n    <string name=\"activity_subjects\">Your Subjects</string>\r\n    <string name=\"activity_subjects_today\">Your Subjects Today</string>\r\n    <string name=\"activity_subjects_tomorrow\">Your Subjects Tomorrow</string>\r\n    <string name=\"activity_archives\">Your Archived Items</string>\r\n    <string name=\"activity_logs\">Notification Logs</string>\r\n    <string name=\"activity_settings\">Settings</string>\r\n    <string name=\"activity_backup\">Backup and Restore</string>\r\n    <string name=\"activity_notices\">Third Party Notices</string>\r\n    <string name=\"activity_open_source_licenses\">Open Source Licenses</string>\r\n    <string name=\"activity_about\">About</string>\r\n\r\n    <string name=\"menu_add\">@string/button_add</string>\r\n    <string name=\"menu_more\">More</string>\r\n    <string name=\"menu_sort\">Sort</string>\r\n    <string name=\"menu_filter\">Filter</string>\r\n    <string name=\"menu_share\">Share</string>\r\n    <string name=\"menu_import\">Import</string>\r\n    <string name=\"menu_clear_items\">Clear Logs</string>\r\n    <string name=\"menu_export_to_file\">Export to file</string>\r\n    <string name=\"menu_share_directly\">Share directly</string>\r\n    <string name=\"menu_archived\">Archived</string>\r\n\r\n    <string name=\"navigation_tasks\">Tasks</string>\r\n    <string name=\"navigation_events\">Events</string>\r\n    <string name=\"navigation_subjects\">Subjects</string>\r\n    <string name=\"navigation_home\">Home</string>\r\n\r\n    <string name=\"navigation_logs\">Logs</string>\r\n    <string name=\"navigation_settings\">@string/activity_settings</string>\r\n    <string name=\"navigation_about\">@string/activity_about</string>\r\n\r\n    <string name=\"button_add_task\">Add Task</string>\r\n    <string name=\"button_add_event\">Add Event</string>\r\n    <string name=\"button_add_subject\">Add Subject</string>\r\n    <string name=\"button_add\">Add</string>\r\n    <string name=\"button_new\">New</string>\r\n    <string name=\"button_save\">Save</string>\r\n    <string name=\"button_done\">Done</string>\r\n    <string name=\"button_undo\">Undo</string>\r\n    <string name=\"button_remove\">Remove</string>\r\n    <string name=\"button_continue\">Continue</string>\r\n    <string name=\"button_mark_as_finished\">Mark as Finished</string>\r\n    <string name=\"button_mark_as_important\">Mark as Important</string>\r\n    <string name=\"button_delete\">Delete</string>\r\n    <string name=\"button_cancel\">Cancel</string>\r\n    <string name=\"button_discard\">Discard</string>\r\n    <string name=\"button_dismiss\">Dismiss</string>\r\n    <string name=\"button_learn_more\">Learn More</string>\r\n    <string name=\"button_view_schedules\">View Schedules</string>\r\n\r\n    <string name=\"empty_view_no_subjects_title\">No Added Subjects</string>\r\n    <string name=\"empty_view_no_subjects_summary\">Subjects help sort your tasks and events, If you have one, add it using the button below.</string>\r\n    <string name=\"empty_view_no_classes_today_title\">No Classes for Today</string>\r\n    <string name=\"empty_view_no_classes_today_summary\">You have no class scheduled for today.</string>\r\n    <string name=\"empty_view_no_classes_tomorrow_title\">No Classes for Tomorrow</string>\r\n    <string name=\"empty_view_no_classes_tomorrow_summary\">You have no class schedules for tomorrow.</string>\r\n    <string name=\"empty_view_no_tasks_title\">No Pending Tasks</string>\r\n    <string name=\"empty_view_no_tasks_summary\">You currently have no pending tasks. If you have one, add it using the button below.</string>\r\n    <string name=\"empty_view_no_finished_title\">No Finished Tasks</string>\r\n    <string name=\"empty_view_no_finished_summary\">You currently have no finished tasks. Every task you marked as finished will show here.</string>\r\n    <string name=\"empty_view_no_logs_title\">No Recorded Logs</string>\r\n    <string name=\"empty_view_no_logs_summary\">Once a task, event or any reminder appear at your notification shade, it will also appear here.</string>\r\n    <string name=\"empty_view_no_events_title\">No Scheduled Events</string>\r\n    <string name=\"empty_view_no_events_summary\">You currently have no scheduled events. If you have one, add it using the button below.</string>\r\n    <string name=\"empty_view_no_previous_title\">No Previous Events</string>\r\n    <string name=\"empty_view_no_previous_summary\">You currently have no previous events. Every event that is past its schedule will appear here</string>\r\n    <string name=\"empty_view_no_archived_tasks\">No Archived Tasks</string>\r\n    <string name=\"empty_view_no_archived_events\">No Archived Events</string>\r\n    <string name=\"empty_view_no_archived_subjects\">No Archived Subjects</string>\r\n\r\n    <string name=\"days_of_week_item_sunday\">Sunday</string>\r\n    <string name=\"days_of_week_item_monday\">Monday</string>\r\n    <string name=\"days_of_week_item_tuesday\">Tuesday</string>\r\n    <string name=\"days_of_week_item_wednesday\">Wednesday</string>\r\n    <string name=\"days_of_week_item_thursday\">Thursday</string>\r\n    <string name=\"days_of_week_item_friday\">Friday</string>\r\n    <string name=\"days_of_week_item_saturday\">Saturday</string>\r\n\r\n    <string name=\"days_of_week_item_sunday_short\">Sun</string>\r\n    <string name=\"days_of_week_item_monday_short\">Mon</string>\r\n    <string name=\"days_of_week_item_tuesday_short\">Tue</string>\r\n    <string name=\"days_of_week_item_wednesday_short\">Wed</string>\r\n    <string name=\"days_of_week_item_thursday_short\">Thu</string>\r\n    <string name=\"days_of_week_item_friday_short\">Fri</string>\r\n    <string name=\"days_of_week_item_saturday_short\">Sat</string>\r\n\r\n    <string name=\"weeks_of_month_item_week_1\">Week 1</string>\r\n    <string name=\"weeks_of_month_item_week_2\">Week 2</string>\r\n    <string name=\"weeks_of_month_item_week_3\">Week 3</string>\r\n    <string name=\"weeks_of_month_item_week_4\">Week 4</string>\r\n\r\n    <string name=\"dialog_assign_subject\">Assign Subject</string>\r\n    <string name=\"dialog_pick_start_time\">Pick a Start Time</string>\r\n    <string name=\"dialog_pick_end_time\">Pick an End Time</string>\r\n    <string name=\"dialog_pick_color_tag\">Pick a color tag</string>\r\n    <string name=\"dialog_select_notification_interval\">Select notification interval</string>\r\n    <string name=\"dialog_choose_theme\">Choose theme</string>\r\n    <string name=\"dialog_choose_backup\">Choose a backup file</string>\r\n    <string name=\"dialog_confirm_deletion_title\">Do you want to remove \\\"%1$s\\\"?</string>\r\n    <string name=\"dialog_confirm_deletion_summary\">Once this item has been deleted, it cannot be recovered.</string>\r\n    <string name=\"dialog_confirm_unarchive_title\">Remove from archives?</string>\r\n    <string name=\"dialog_confirm_unarchive_summary\">You can always swipe left to archive this item again.</string>\r\n    <string name=\"dialog_import_attachment_title\">Import attachment?</string>\r\n    <string name=\"dialog_import_attachment_summary\">Due to the recent restrictions imposed by the Android system, the app will have to copy the file onto its own data folder. Continue?</string>\r\n    <string name=\"dialog_import_attachment_confirm\">Never ask again</string>\r\n    <string name=\"dialog_schedule_details\">Schedule Details</string>\r\n    <string name=\"dialog_discard_changes\">Discard changes?</string>\r\n    <string name=\"dialog_select_file_import\">Select file to import</string>\r\n    <string name=\"dialog_send_to\">Send to</string>\r\n    <string name=\"dialog_sharing_options\">Sharing options</string>\r\n    <string name=\"dialog_class_schedules\">Class Schedules</string>\r\n    <string name=\"dialog_filter_options\">Filter Options</string>\r\n    <string name=\"dialog_new_attachment\">New Attachment</string>\r\n    <string name=\"dialog_attachment_name\">@string/field_attachment_name</string>\r\n    <string name=\"dialog_enter_website_url\">Enter Website URL</string>\r\n    <string name=\"dialog_sorting\">Sorting</string>\r\n    <string name=\"dialog_permission_needed_title\">Storage Permission needed</string>\r\n    <string name=\"dialog_permission_needed_summary\">To attach a file from your device, the application needs the storage permission to be granted.</string>\r\n\r\n    <string name=\"attachment_type_import_file\">Import file</string>\r\n    <string name=\"attachment_type_website_url\">Website URL</string>\r\n\r\n    <string name=\"sorting_directions_ascending\">Ascending</string>\r\n    <string name=\"sorting_directions_descending\">Descending</string>\r\n\r\n    <string name=\"filter_options_all\">All</string>\r\n    <string name=\"filter_options_pending_tasks\">Pending only</string>\r\n    <string name=\"filter_options_finished_tasks\">Finished only</string>\r\n    <string name=\"filter_options_today_classes\">Today only</string>\r\n    <string name=\"filter_options_tomorrow_classes\">Tomorrow only</string>\r\n\r\n    <string name=\"field_subject_code\">Subject Code</string>\r\n    <string name=\"field_description\">Description</string>\r\n    <string name=\"field_days_of_week\">Days of Week</string>\r\n    <string name=\"field_weeks_of_month\">Weeks of Month</string>\r\n    <string name=\"field_start_time\">Start Time</string>\r\n    <string name=\"field_end_time\">End Time</string>\r\n    <string name=\"field_task_name\">Task Name</string>\r\n    <string name=\"field_notes\">Notes</string>\r\n    <string name=\"field_subject\">Subject</string>\r\n    <string name=\"field_due_date\">Due Date</string>\r\n    <string name=\"field_event_name\">Event Name</string>\r\n    <string name=\"field_schedule\">Schedule</string>\r\n    <string name=\"field_location\">Location</string>\r\n    <string name=\"field_attachments\">Attachments</string>\r\n    <string name=\"field_class_time\">Class Time</string>\r\n    <string name=\"field_color\">Color Tag</string>\r\n    <string name=\"field_priority\">Priority</string>\r\n    <string name=\"field_status\">Status</string>\r\n    <string name=\"field_not_set\">Not Set</string>\r\n    <string name=\"field_due_in_the_next_meeting\">In the next meeting</string>\r\n    <string name=\"field_due_pick_from_schedule\">Pick from class schedule</string>\r\n    <string name=\"field_due_custom\">Custom</string>\r\n    <string name=\"field_attachment_name\">Attachment name</string>\r\n    <string name=\"field_instructor\">Instructor</string>\r\n    <string name=\"field_classroom\">Classroom</string>\r\n\r\n    <string name=\"hint_subject_description\">The name of the subject</string>\r\n    <string name=\"hint_task_notes\">Some ideas or minor details about the task</string>\r\n    <string name=\"hint_event_location\">Enter a room, a building or any place</string>\r\n    <string name=\"hint_event_notes\">Some ideas or minor details about the event</string>\r\n\r\n    <string name=\"feedback_subject_removed\">Subject removed</string>\r\n    <string name=\"feedback_log_removed\">Log removed</string>\r\n    <string name=\"feedback_task_removed\">Task removed</string>\r\n    <string name=\"feedback_schedule_removed\">Schedule removed</string>\r\n    <string name=\"feedback_attachment_added\">Attachment added</string>\r\n    <string name=\"feedback_attachment_removed\">Attachment removed</string>\r\n    <string name=\"feedback_event_removed\">Event removed</string>\r\n    <string name=\"feedback_task_marked_as_finished\">Task marked as finished</string>\r\n    <string name=\"feedback_task_marked_as_pending\">Task marked as pending</string>\r\n    <string name=\"feedback_subject_empty_name\">You forgot to enter the subject code</string>\r\n    <string name=\"feedback_subject_empty_description\">You forgot to enter the description</string>\r\n    <string name=\"feedback_subject_no_schedule\">You forgot to add a schedule</string>\r\n    <string name=\"feedback_schedule_empty_days\">You forgot to specify the days</string>\r\n    <string name=\"feedback_schedule_empty_start_time\">You forgot to enter the start time</string>\r\n    <string name=\"feedback_schedule_empty_end_time\">You forgot to enter the end time</string>\r\n    <string name=\"feedback_task_empty_name\">You forgot to enter the task name</string>\r\n    <string name=\"feedback_task_empty_due_date\">You forgot to specify its due date</string>\r\n    <string name=\"feedback_event_empty_name\">You forgot to enter the event name</string>\r\n    <string name=\"feedback_event_empty_location\">You forgot to enter the location</string>\r\n    <string name=\"feedback_event_empty_schedule\">You forgot to enter the schedule</string>\r\n    <string name=\"feedback_restore_invalid\">Backup file is invalid</string>\r\n    <string name=\"feedback_restore_corrupted\">Backup file is corrupted or unreadable</string>\r\n    <string name=\"feedback_backup_empty\">There are no items to backup</string>\r\n    <string name=\"feedback_backup_failed\">Backup process encountered an error</string>\r\n    <string name=\"feedback_import_ongoing\">Import in progress</string>\r\n    <string name=\"feedback_import_completed\">Import completed</string>\r\n    <string name=\"feedback_import_failed\">Import failed</string>\r\n    <string name=\"feedback_export_ongoing\">Export in progress</string>\r\n    <string name=\"feedback_export_completed\">Export completed</string>\r\n    <string name=\"feedback_export_failed\">Export failed</string>\r\n    <string name=\"feedback_unable_to_share_title\">Unable to share</string>\r\n    <string name=\"feedback_unable_to_share_message\">There are no valid information that can be shared</string>\r\n    <string name=\"feedback_subject_code_exists\">A subject with this code already exists.</string>\r\n    <string name=\"feedback_schedule_exists\">A schedule conflicts with another schedule.</string>\r\n    <string name=\"feedback_task_name_exists\">A task with this name already exists.</string>\r\n    <string name=\"feedback_event_name_exists\">An event with this name already exists.</string>\r\n    <string name=\"feedback_event_schedule_exists\">An event with the same schedule already exists.</string>\r\n\r\n    <string name=\"settings_group_interface\">Interface</string>\r\n    <string name=\"settings_group_sound\">Sound</string>\r\n    <string name=\"settings_group_notification\">Notifications</string>\r\n    <string name=\"settings_group_advanced\">Advanced</string>\r\n    <string name=\"settings_group_debugging\">Debugging</string>\r\n    <string name=\"settings_group_contribute\">Contribute</string>\r\n\r\n    <string name=\"settings_theme\">Theme</string>\r\n    <string name=\"settings_theme_item_system\">System default</string>\r\n    <string name=\"settings_theme_item_dark\">Dark</string>\r\n    <string name=\"settings_theme_item_light\">Light</string>\r\n    <string name=\"settings_confetti_title\">Confetti</string>\r\n    <string name=\"settings_confetti_summary\">Show confetti when tasks are marked as finished</string>\r\n\r\n    <string name=\"settings_completion_sounds_title\">Completion Sounds</string>\r\n    <string name=\"settings_completion_sounds_summary\">Play a sound when you mark a task as completed</string>\r\n\r\n    <string name=\"settings_reminder_frequency_title\">Reminder frequency</string>\r\n    <string name=\"settings_reminder_frequency_item_everyday\">Everyday</string>\r\n    <string name=\"settings_reminder_frequency_item_weekends\">Weekends</string>\r\n    <string name=\"settings_remind_me_in_time_of_day\">Remind me at this time</string>\r\n    <string name=\"settings_when_nearing_due_title\">When a task is nearing due</string>\r\n    <string name=\"settings_when_nearing_due_summary\">Show notifications for tasks that are nearing its deadline</string>\r\n    <string name=\"settings_task_reminders\">Task reminder interval</string>\r\n    <string name=\"settings_task_reminders_item_hour\">1 hour before</string>\r\n    <string name=\"settings_task_reminders_item_three_hours\">3 hours before</string>\r\n    <string name=\"settings_task_reminders_item_day\">1 day before</string>\r\n    <string name=\"settings_incoming_events_title\">Incoming events</string>\r\n    <string name=\"settings_incoming_events_summary\">Show notifications about incoming events this day</string>\r\n    <string name=\"settings_event_reminders\">Event reminder interval</string>\r\n    <string name=\"settings_event_reminders_item_quarter_hour\">15 minutes before</string>\r\n    <string name=\"settings_event_reminders_item_half_hour\">30 minutes before</string>\r\n    <string name=\"settings_event_reminders_item_hour\">@string/settings_task_reminders_item_hour</string>\r\n    <string name=\"settings_classes_for_this_day_title\">Classes for this day</string>\r\n    <string name=\"settings_classes_for_this_day_summary\">Show notifications about classes for my subjects this day</string>\r\n    <string name=\"settings_class_reminders\">Class reminder interval</string>\r\n    <string name=\"settings_class_reminders_item_5_minutes\">5 minutes before</string>\r\n    <string name=\"settings_class_reminders_item_15_minutes\">@string/settings_event_reminders_item_quarter_hour</string>\r\n    <string name=\"settings_class_reminders_item_30_minutes\">@string/settings_event_reminders_item_half_hour</string>\r\n    <string name=\"settings_more_notification_settings\">More Settings</string>\r\n\r\n    <string name=\"settings_allow_week_numbers_title\">Enable Week Numbers</string>\r\n    <string name=\"settings_allow_week_numbers_summary\">Show week numbers when configuring schedules.</string>\r\n    <string name=\"settings_backup_and_restore\">@string/activity_backup</string>\r\n    <string name=\"settings_backup\">Backup</string>\r\n    <string name=\"settings_backup_summary_no_previous\">No Previous Backups</string>\r\n    <string name=\"settings_restore\">Restore</string>\r\n    <string name=\"settings_use_external_browser_title\">Open links in external browser</string>\r\n    <string name=\"settings_use_external_browser_summary\">Use the system default browser to handle hyperlinks</string>\r\n\r\n    <string name=\"settings_not_working_notifications\">@string/button_learn_more</string>\r\n    <string name=\"settings_not_working_notifications_info\">Sometimes, your notification might not trigger due to the aggressive battery optimization by your phone manufacturer.</string>\r\n\r\n    <string name=\"settings_translate\">Translate</string>\r\n    <string name=\"settings_report_an_issue\">Report an issue</string>\r\n    <string name=\"settings_third_party_notices\">@string/activity_notices</string>\r\n    <string name=\"settings_build_version\">Build Version</string>\r\n\r\n    <string name=\"color_sky\">Sky</string>\r\n    <string name=\"color_grass\">Grass</string>\r\n    <string name=\"color_sunset\">Sunset</string>\r\n    <string name=\"color_lemon\">Lemon</string>\r\n    <string name=\"color_sea\">Sea</string>\r\n    <string name=\"color_grape\">Grape</string>\r\n    <string name=\"color_cherry\">Cherry</string>\r\n    <string name=\"color_coral\">Coral</string>\r\n    <string name=\"color_midnight\">Midnight</string>\r\n    <string name=\"color_mint\">Mint</string>\r\n    <string name=\"color_lavender\">Lavender</string>\r\n    <string name=\"color_graphite\">Graphite</string>\r\n\r\n    <string name=\"widget_task_name\">Task Widget</string>\r\n    <string name=\"widget_task_title\">Tasks</string>\r\n    <string name=\"widget_task_empty\">You have no tasks for today</string>\r\n    <string name=\"widget_event_name\">Event Widget</string>\r\n    <string name=\"widget_event_title\">Events</string>\r\n    <string name=\"widget_event_empty\">You have no events for today</string>\r\n    <string name=\"widget_class_name\">Class Widget</string>\r\n    <string name=\"widget_class_title\">Classes</string>\r\n    <string name=\"widget_class_empty\">You have no classes for today</string>\r\n\r\n    <!-- Helper Text -->\r\n    <string name=\"helper_this_is_important\">Marking this as important means that it will show a persistent notification at your notification shade.</string>\r\n\r\n    <!-- Notifications -->\r\n    <string name=\"notification_channel_group_reminders\">Reminders</string>\r\n\r\n    <string name=\"notification_channel_general\">General</string>\r\n    <string name=\"notification_channel_task_reminders\">Task Reminders</string>\r\n    <string name=\"notification_channel_event_reminders\">Event Reminders</string>\r\n    <string name=\"notification_channel_class_reminders\">Class Reminders</string>\r\n\r\n    <string name=\"notification_pending_tasks_title\">You have %1$d tasks pending</string>\r\n    <string name=\"notification_pending_tasks_summary\">It might be worth to take a look</string>\r\n\r\n    <string name=\"notification_backup_ongoing\">Performing Backup</string>\r\n    <string name=\"notification_backup_error\">Backup Failed</string>\r\n    <string name=\"notification_backup_success\">Backup Completed</string>\r\n\r\n    <string name=\"notification_restore_ongoing\">Restoring Backup</string>\r\n    <string name=\"notification_restore_error\">Restore Failed</string>\r\n    <string name=\"notification_restore_success\">Restore Completed</string>\r\n\r\n    <!-- Sharing -->\r\n    <string name=\"sharing_attach_to_task\">Attach to Task</string>\r\n\r\n    <!-- Greetings -->\r\n    <string name=\"greeting_default\">Good day!</string>\r\n    <string name=\"greeting_morning\">Good morning!</string>\r\n    <string name=\"greeting_afternoon\">Good afternoon!</string>\r\n    <string name=\"greeting_evening\">Good evening!</string>\r\n\r\n    <!-- used for concat and formatting -->\r\n    <string name=\"and\">&#160;and&#160;</string>\r\n    <string name=\"yesterday_at\">Yesterday at %1$s</string>\r\n    <string name=\"yesterday\">Yesterday</string>\r\n    <string name=\"tomorrow_at\">Tomorrow at %1$s</string>\r\n    <string name=\"tomorrow\">Tomorrow</string>\r\n    <string name=\"today_at\">Today at %1$s</string>\r\n    <string name=\"today\">Today</string>\r\n    <string name=\"due_today_at\">Due today at %1$s</string>\r\n    <string name=\"due_tomorrow_at\">Due tomorrow at %1$s</string>\r\n    <string name=\"due_at\">Due at %1$s</string>\r\n\r\n    <string name=\"open_source_libraries\">Open Source Libraries</string>\r\n    <string name=\"credit_other_resources\">Other Resources</string>\r\n    <string name=\"credit_notification_sound_title\" translatable=\"false\">Zapsplat</string>\r\n    <string name=\"credit_notification_sound_summary\">Notification Sound</string>\r\n    <string name=\"credit_launcher_icon_title\" translatable=\"false\">Freepik</string>\r\n    <string name=\"credit_launcher_icon_summary\">Launcher Icon</string>\r\n    <string name=\"credit_user_interface_icons_title\" translatable=\"false\">Tailwind Labs</string>\r\n    <string name=\"credit_user_interface_icons_summary\">User Interface Icons</string>\r\n\r\n    <string name=\"notifications_are_now_enabled_for_this_app\">Notifications are now enabled for this app!</string>\r\n    <string name=\"notifications_are_not_enabled_for_this_app\">Notifications are NOT enabled for this app!</string>\r\n</resources>\r\n"
  },
  {
    "path": "app/src/main/res/values/themes.xml",
    "content": "<resources>\n\n    <style name=\"Fokus.Theme.Base\" parent=\"Fokus.Theme\">\n        <item name=\"android:statusBarColor\">@android:color/black</item>\n        <item name=\"android:navigationBarColor\">@android:color/black</item>\n    </style>\n\n    <style name=\"Fokus.Theme.Core\" parent=\"Fokus.Theme.Base\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n    </style>\n\n    <style name=\"Fokus.Theme.Core.Navigation\"/>\n\n    <!-- Components -->\n    <style name=\"Fokus.Component.Viewer\" parent=\"Fokus.Component.Viewer.Bridge\">\n        <item name=\"android:statusBarColor\">@android:color/black</item>\n    </style>\n    <style name=\"Fokus.Component.BottomSheet\" parent=\"Fokus.Component.BottomSheet.Bridge\">\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/values.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n\r\n    <style name=\"Fokus\"/>\r\n    <!-- Base application theme -->\r\n    <style name=\"Fokus.Theme\" parent=\"Theme.Material3.DynamicColors.DayNight\">\r\n        <item name=\"android:windowDrawsSystemBarBackgrounds\">true</item>\r\n\r\n        <item name=\"colorPrimary\">@color/theme_primary</item>\r\n        <item name=\"colorOnPrimary\">@color/theme_on_primary</item>\r\n        <item name=\"colorPrimaryContainer\">@color/theme_primary_container</item>\r\n        <item name=\"colorOnPrimaryContainer\">@color/theme_on_primary_container</item>\r\n        <item name=\"colorSecondary\">@color/theme_secondary</item>\r\n        <item name=\"colorOnSecondary\">@color/theme_on_secondary</item>\r\n        <item name=\"colorSecondaryContainer\">@color/theme_secondary_container</item>\r\n        <item name=\"colorOnSecondaryContainer\">@color/theme_on_secondary_container</item>\r\n        <item name=\"colorTertiary\">@color/theme_tertiary</item>\r\n        <item name=\"colorOnTertiary\">@color/theme_on_tertiary</item>\r\n        <item name=\"colorTertiaryContainer\">@color/theme_tertiary_container</item>\r\n        <item name=\"colorOnTertiaryContainer\">@color/theme_on_tertiary_container</item>\r\n        <item name=\"colorError\">@color/theme_error</item>\r\n        <item name=\"colorOnError\">@color/theme_on_error</item>\r\n        <item name=\"colorErrorContainer\">@color/theme_error_container</item>\r\n        <item name=\"colorOnErrorContainer\">@color/theme_on_error_container</item>\r\n        <item name=\"android:colorBackground\">@color/theme_background</item>\r\n        <item name=\"colorOnBackground\">@color/theme_on_background</item>\r\n        <item name=\"colorSurface\">@color/theme_surface</item>\r\n        <item name=\"colorOnSurface\">@color/theme_on_surface</item>\r\n        <item name=\"colorSurfaceVariant\">@color/theme_surface_variant</item>\r\n        <item name=\"colorOnSurfaceVariant\">@color/theme_on_surface_variant</item>\r\n        <item name=\"colorOutline\">@color/theme_outline</item>\r\n        <item name=\"colorOnSurfaceInverse\">@color/theme_inverse_on_surface</item>\r\n        <item name=\"colorSurfaceInverse\">@color/theme_inverse_surface</item>\r\n        <item name=\"colorPrimaryInverse\">@color/theme_inverse_primary</item>\r\n\r\n        <item name=\"preferenceTheme\">@style/Fokus.Component.Preference</item>\r\n        <item name=\"bottomSheetDialogTheme\">@style/Fokus.Component.BottomSheet</item>\r\n        <item name=\"alertDialogTheme\">@style/Fokus.Component.Dialog</item>\r\n\r\n        <item name=\"appBarLayoutStyle\">@style/Fokus.Widget.AppBar</item>\r\n        <item name=\"toolbarStyle\">@style/Fokus.Widget.Toolbar</item>\r\n        <item name=\"switchStyle\">@style/Fokus.Widget.Switch</item>\r\n        <item name=\"floatingActionButtonStyle\">@style/Fokus.Widget.FAB</item>\r\n        <item name=\"extendedFloatingActionButtonStyle\">@style/Fokus.Widget.FAB.Extended</item>\r\n        <item name=\"snackbarStyle\">@style/Fokus.Widget.Snackbar</item>\r\n\r\n        <item name=\"md_background_color\">?attr/colorSurface</item>\r\n        <item name=\"md_corner_radius\">@dimen/surface_corner_radius</item>\r\n    </style>\r\n\r\n    <style name=\"Fokus.Component.Preference\" parent=\"PreferenceThemeOverlay.v14.Material\">\r\n        <item name=\"preferenceCategoryTitleTextAppearance\">@style/Fokus.TextAppearance.Label.Large</item>\r\n    </style>\r\n    <style name=\"Fokus.Component.Dialog\" parent=\"ThemeOverlay.Material3.MaterialAlertDialog\">\r\n        <item name=\"cornerFamily\">rounded</item>\r\n        <item name=\"dialogCornerRadius\">@dimen/surface_corner_radius</item>\r\n        <item name=\"android:colorBackground\">?attr/colorSurface</item>\r\n        <item name=\"buttonBarPositiveButtonStyle\">@style/Fokus.Widget.Button.Text.Dialog</item>\r\n        <item name=\"buttonBarNegativeButtonStyle\">@style/Fokus.Widget.Button.Text.Dialog</item>\r\n    </style>\r\n    <style name=\"Fokus.Component.Viewer.Bridge\" parent=\"ThemeOverlay.Material3.Dialog.Alert\">\r\n        <item name=\"android:windowDrawsSystemBarBackgrounds\">true</item>\r\n        <item name=\"android:windowIsFloating\">false</item>\r\n        <item name=\"android:windowBackground\">?attr/colorSurface</item>\r\n    </style>\r\n    <style name=\"Fokus.Component.BottomSheet.Bridge\" parent=\"ThemeOverlay.Material3.BottomSheetDialog\">\r\n        <item name=\"bottomSheetStyle\">@style/Fokus.Component.BottomSheet.Base</item>\r\n        <item name=\"android:windowIsFloating\">false</item>\r\n        <item name=\"android:windowSoftInputMode\">adjustResize</item>\r\n    </style>\r\n    <style name=\"Fokus.Component.BottomSheet.Base\" parent=\"Widget.Design.BottomSheet.Modal\">\r\n        <item name=\"android:background\">@drawable/shape_bottom_sheet</item>\r\n        <item name=\"android:layout_marginStart\">@dimen/bottom_sheet_margin_horizontal</item>\r\n        <item name=\"android:layout_marginEnd\">@dimen/bottom_sheet_margin_horizontal</item>\r\n    </style>\r\n\r\n    <style name=\"Fokus.Widget.AppBar\" parent=\"Widget.Material3.AppBarLayout\"/>\r\n    <style name=\"Fokus.Widget.Toolbar\" parent=\"Widget.Material3.Toolbar\">\r\n        <item name=\"titleCentered\">true</item>\r\n        <item name=\"titleTextColor\">?attr/colorOnSurfaceVariant</item>\r\n        <item name=\"titleTextAppearance\">@style/Fokus.TextAppearance.Title.Large</item>\r\n    </style>\r\n    <style name=\"Fokus.Widget.Button\" parent=\"Widget.Material3.Button\">\r\n        <item name=\"iconTint\">?attr/colorOnPrimary</item>\r\n        <item name=\"iconGravity\">end</item>\r\n        <item name=\"iconPadding\">@dimen/button_icon_padding</item>\r\n        <item name=\"android:textColor\">?attr/colorOnPrimary</item>\r\n    </style>\r\n    <style name=\"Fokus.Widget.Button.Outlined\" parent=\"Widget.Material3.Button.OutlinedButton\">\r\n        <item name=\"iconTint\">@color/theme_primary</item>\r\n        <item name=\"iconGravity\">end</item>\r\n        <item name=\"iconPadding\">@dimen/button_icon_padding</item>\r\n        <item name=\"android:textColor\">?attr/colorOnPrimary</item>\r\n    </style>\r\n    <style name=\"Fokus.Widget.Button.Text\" parent=\"Widget.Material3.Button.TextButton\"/>\r\n    <style name=\"Fokus.Widget.Button.Text.Dialog\" parent=\"Widget.Material3.Button.TextButton.Dialog\"/>\r\n    <style name=\"Fokus.Widget.Chip\" parent=\"Widget.Material3.Chip.Filter\"/>\r\n    <style name=\"Fokus.Widget.Switch\" parent=\"Widget.AppCompat.CompoundButton.Switch\"/>\r\n    <style name=\"Fokus.Widget.FAB\" parent=\"Widget.Material3.FloatingActionButton.Primary\"/>\r\n    <style name=\"Fokus.Widget.FAB.Extended\" parent=\"Widget.Material3.ExtendedFloatingActionButton.Primary\"/>\r\n    <style name=\"Fokus.Widget.TextInput.Layout\" parent=\"Widget.Material3.TextInputLayout.OutlinedBox.Dense\">\r\n        <item name=\"boxStrokeColor\">@color/color_text_input_stroke</item>\r\n        <item name=\"boxStrokeWidth\">2dp</item>\r\n    </style>\r\n    <style name=\"Fokus.Widget.Snackbar\" parent=\"Widget.Material3.Snackbar\"/>\r\n\r\n    <!-- TextAppearance -->\r\n    <style name=\"Fokus.TextAppearance.Display.Large\" parent=\"TextAppearance.Material3.DisplayLarge\"/>\r\n    <style name=\"Fokus.TextAppearance.Display.Medium\" parent=\"TextAppearance.Material3.DisplayMedium\"/>\r\n    <style name=\"Fokus.TextAppearance.Display.Small\" parent=\"TextAppearance.Material3.DisplaySmall\"/>\r\n    <style name=\"Fokus.TextAppearance.Headline.Large\" parent=\"TextAppearance.Material3.HeadlineLarge\"/>\r\n    <style name=\"Fokus.TextAppearance.Headline.Medium\" parent=\"TextAppearance.Material3.HeadlineMedium\"/>\r\n    <style name=\"Fokus.TextAppearance.Headline.Small\" parent=\"TextAppearance.Material3.HeadlineSmall\"/>\r\n    <style name=\"Fokus.TextAppearance.Title.Large\" parent=\"TextAppearance.Material3.TitleLarge\"/>\r\n    <style name=\"Fokus.TextAppearance.Title.Medium\" parent=\"TextAppearance.Material3.TitleMedium\"/>\r\n    <style name=\"Fokus.TextAppearance.Title.Small\" parent=\"TextAppearance.Material3.TitleSmall\"/>\r\n    <style name=\"Fokus.TextAppearance.Body.Large\" parent=\"TextAppearance.Material3.BodyLarge\"/>\r\n    <style name=\"Fokus.TextAppearance.Body.Medium\" parent=\"TextAppearance.Material3.BodyMedium\"/>\r\n    <style name=\"Fokus.TextAppearance.Body.Small\" parent=\"TextAppearance.Material3.BodySmall\"/>\r\n    <style name=\"Fokus.TextAppearance.Label.Large\" parent=\"TextAppearance.Material3.LabelLarge\"/>\r\n    <style name=\"Fokus.TextAppearance.Label.Medium\" parent=\"TextAppearance.Material3.LabelMedium\"/>\r\n    <style name=\"Fokus.TextAppearance.Label.Small\" parent=\"TextAppearance.Material3.LabelSmall\"/>\r\n\r\n    <!-- Animations -->\r\n    <style name=\"Fokus.Animations\"/>\r\n    <style name=\"Fokus.Animations.Slide\">\r\n        <item name=\"android:windowEnterAnimation\">@anim/anim_slide_up</item>\r\n        <item name=\"android:windowExitAnimation\">@anim/anim_slide_down</item>\r\n    </style>\r\n\r\n    <!-- Used for Adaptive Launcher Icon Background -->\r\n    <color name=\"ic_launcher_background\">#000051</color>\r\n</resources>"
  },
  {
    "path": "app/src/main/res/values-ar/strings.xml",
    "content": "<resources>\n    <string translatable=\"false\" name=\"app_name\">Fokus</string>\n\n    <string name=\"shortcut_add_task\">@string/button_add_task</string>\n    <string name=\"shortcut_add_event\">@string/button_add_event</string>\n    <string name=\"shortcut_add_subject\">@string/button_add_subject</string>\n\n    <string name=\"activity_tasks\">مهامك</string>\n    <string name=\"activity_tasks_pending\">المهام المؤجلة</string>\n    <string name=\"activity_tasks_finished\">المهام المنتهية</string>\n    <string name=\"activity_subjects\">الموضوع</string>\n    <string name=\"activity_subjects_today\">مواضيعك لهذا اليوم</string>\n    <string name=\"activity_subjects_tomorrow\">مواضيعك ليوم غد</string>\n    <string name=\"activity_archives\">الأشياء المؤرشفة</string>\n    <string name=\"activity_logs\">سجل الأشعارات</string>\n    <string name=\"activity_settings\">الأعدادات</string>\n    <string name=\"activity_backup\">النسخ الأحتياطي والأستعادة</string>\n    <string name=\"activity_notices\">أشعرات الطرف الثالث</string>\n    <string name=\"activity_open_source_licenses\">تراخيص مفتوحة المصدر</string>\n    <string name=\"activity_about\">عن</string>\n\n    <string name=\"menu_add\">@string/button_add</string>\n    <string name=\"menu_more\">المزيد</string>\n    <string name=\"menu_sort\">فرز</string>\n    <string name=\"menu_filter\">فلتره</string>\n    <string name=\"menu_share\">مشاركة</string>\n    <string name=\"menu_import\">أستيراد</string>\n    <string name=\"menu_clear_items\">تنظيف السجل</string>\n    <string name=\"menu_export_to_file\">تصدير الى ملف</string>\n    <string name=\"menu_share_directly\">مشاركة مباشرة</string>\n    <string name=\"menu_archived\">مؤرشف</string>\n\n    <string name=\"navigation_tasks\">المهام</string>\n    <string name=\"navigation_events\">الأحداث</string>\n    <string name=\"navigation_subjects\">المواضيع</string>\n    <string name=\"navigation_home\">منزل</string>\n    <string name=\"navigation_logs\">السجلات</string>\n    <string name=\"navigation_settings\">@string/activity_settings</string>\n    <string name=\"navigation_about\">@string/activity_about</string>\n\n    <string name=\"button_add_task\">أضافة مهام</string>\n    <string name=\"button_add_event\">أضافة حدث</string>\n    <string name=\"button_add_subject\">أضافة موضوع</string>\n    <string name=\"button_add\">أضف</string>\n    <string name=\"button_new\">جديد</string>\n    <string name=\"button_save\">حفظ</string>\n    <string name=\"button_done\">تم</string>\n    <string name=\"button_undo\">تراجع</string>\n    <string name=\"button_remove\">مسح</string>\n    <string name=\"button_continue\">أستمرار</string>\n    <string name=\"button_mark_as_finished\">علم كمنتهية</string>\n    <string name=\"button_mark_as_important\">علم كمهمة</string>\n    <string name=\"button_delete\">مسح</string>\n    <string name=\"button_cancel\">ألغاء</string>\n    <string name=\"button_discard\">تجاهل</string>\n    <string name=\"button_dismiss\">صرف النظر</string>\n    <string name=\"button_learn_more\">أعرف أكثر</string>\n    <string name=\"button_view_schedules\">عرض جدول االمواضيع</string>\n\n    <string name=\"empty_view_no_subjects_title\">لاتوجد مواضيع مضافة</string>\n    <string name=\"empty_view_no_subjects_summary\">تساعد المواضيع في فرز المهام والأحداث الخاصة بك ، إذا كان لديك واحد ، قم بإضافته باستخدام الزر أدناه.</string>\n    <string name=\"empty_view_no_classes_today_title\">لاتوجد حصص لهذا اليوم</string>\n    <string name=\"empty_view_no_classes_today_summary\">ليس لديك فصل دراسي لهذا اليوم</string>\n    <string name=\"empty_view_no_classes_tomorrow_title\">ليس لديك فصل دراسي ليوم غد</string>\n    <string name=\"empty_view_no_classes_tomorrow_summary\">ليس لديك مواعيد حصص ليوم غد</string>\n    <string name=\"empty_view_no_tasks_title\">لاتوجد مهام معلقة</string>\n    <string name=\"empty_view_no_tasks_summary\">ليس لديك حاليا أي مهام معلقة.إذا كان لديك واحد ، قم بإضافته باستخدام الزر أدناه</string>\n    <string name=\"empty_view_no_finished_title\">لاتوجد مهام منتهية</string>\n    <string name=\"empty_view_no_finished_summary\">ليس لديك حاليا أي مهام منتهية. ستظهر هنا كل مهمة حددتها على أنها منتهية.</string>\n    <string name=\"empty_view_no_logs_title\">لايوجد قيد للسجلات</string>\n    <string name=\"empty_view_no_logs_summary\">بمجرد ظهور مهمة أو حدث أو أي تذكير في مركز الإشعارات ، سيظهر هنا أيضًا</string>\n    <string name=\"empty_view_no_events_title\">لاتوجد احداث مجدولة</string>\n    <string name=\"empty_view_no_events_summary\">ليس لديك حاليا أي أحداث مجدولة. إذا كان لديك واحد ، قم بإضافته باستخدام الزر أدناه</string>\n    <string name=\"empty_view_no_previous_title\">لاتوجد أحداث سابقة</string>\n    <string name=\"empty_view_no_previous_summary\">ليس لديك حاليا أي أحداث سابقة. سيظهر هنا كل حدث تجاوز جدوله الزمني</string>\n    <string name=\"empty_view_no_archived_tasks\">لا توجد مهام مؤرشفة</string>\n    <string name=\"empty_view_no_archived_events\">لا توجد أحداث مؤرشفة</string>\n    <string name=\"empty_view_no_archived_subjects\">لا توجد مواضيع مؤرشفة</string>\n\n    <string name=\"days_of_week_item_sunday\">الأحد</string>\n    <string name=\"days_of_week_item_monday\">الأثنين</string>\n    <string name=\"days_of_week_item_tuesday\">الثلاثاء</string>\n    <string name=\"days_of_week_item_wednesday\">الأربعاء</string>\n    <string name=\"days_of_week_item_thursday\">الخميس</string>\n    <string name=\"days_of_week_item_friday\">الجمعة</string>\n    <string name=\"days_of_week_item_saturday\">السبت</string>\n\n    <string name=\"days_of_week_item_sunday_short\">أحد</string>\n    <string name=\"days_of_week_item_monday_short\">أثن</string>\n    <string name=\"days_of_week_item_tuesday_short\">ثلا</string>\n    <string name=\"days_of_week_item_wednesday_short\">أرب</string>\n    <string name=\"days_of_week_item_thursday_short\">خمي</string>\n    <string name=\"days_of_week_item_friday_short\">جمع</string>\n    <string name=\"days_of_week_item_saturday_short\">سبت</string>\n\n    <string name=\"weeks_of_month_item_week_1\">الأسبوع 1</string>\n    <string name=\"weeks_of_month_item_week_2\">الأسبوع 2</string>\n    <string name=\"weeks_of_month_item_week_3\">الأسبوع 3</string>\n    <string name=\"weeks_of_month_item_week_4\">الأسبوع 4</string>\n\n    <string name=\"dialog_assign_subject\">أختر الموضوع</string>\n    <string name=\"dialog_pick_start_time\">أختر وقت البدأ</string>\n    <string name=\"dialog_pick_end_time\">أختر وقت الأنتهاء</string>\n    <string name=\"dialog_pick_color_tag\">أختر لون</string>\n    <string name=\"dialog_select_notification_interval\">أختر فترة الأخطار</string>\n    <string name=\"dialog_choose_theme\">أختر ثيم</string>\n    <string name=\"dialog_choose_backup\">اختر ملف النسخ الاحتياطي</string>\n    <string name=\"dialog_confirm_deletion_title\">هل تريد الأزالة \\\"%1$s\\\"?</string>\n    <string name=\"dialog_confirm_deletion_summary\">بمجرد حذف هذا العنصر ، لا يمكن استعادته</string>\n    <string name=\"dialog_confirm_unarchive_title\">حذف من الارشيف؟</string>\n    <string name=\"dialog_confirm_unarchive_summary\">يمكنك السحب الى اليسار لأرشفة هذا العنصر مرة اخرى</string>\n    <string name=\"dialog_import_attachment_title\">استيراد المرفقات؟</string>\n    <string name=\"dialog_import_attachment_summary\">نظرًا للقيود الأخيرة التي يفرضها نظام أندرويد سيتعين على التطبيق نسخ الملف إلى مجلد البيانات الخاص به. أستمرار؟</string>\n    <string name=\"dialog_import_attachment_confirm\">لا تسأل مرة أخرى</string>\n    <string name=\"dialog_schedule_details\">تفاصيل الجدول</string>\n    <string name=\"dialog_discard_changes\">تجاهل التغييرات؟</string>\n    <string name=\"dialog_select_file_import\">حدد ملفًا للاستيراد</string>\n    <string name=\"dialog_send_to\">أرسال الى</string>\n    <string name=\"dialog_sharing_options\">خيارات المشاركة</string>\n    <string name=\"dialog_class_schedules\">جداول الحصص</string>\n    <string name=\"dialog_filter_options\">خيارات الفلترة</string>\n    <string name=\"dialog_new_attachment\">مرفق جديد</string>\n    <string name=\"dialog_attachment_name\">@string/field_attachment_name</string>\n    <string name=\"dialog_enter_website_url\">أدخل عنوان لموقع الويب</string>\n    <string name=\"dialog_sorting\">ترتيب</string>\n    <string name=\"dialog_permission_needed_title\">يحتاج الى اذن التخزين</string>\n    <string name=\"dialog_permission_needed_summary\">لإرفاق ملف من جهازك ، يحتاج التطبيق إلى منح إذن التخزين.</string>\n\n    <string name=\"attachment_type_import_file\">استيراد ملف</string>\n    <string name=\"attachment_type_website_url\">رابط الموقع</string>\n\n    <string name=\"sorting_directions_ascending\">تصاعدي</string>\n    <string name=\"sorting_directions_descending\">تنازلي</string>\n\n    <string name=\"filter_options_all\">الكل</string>\n    <string name=\"filter_options_pending_tasks\">المعلقة فقط</string>\n    <string name=\"filter_options_finished_tasks\">المنتهية فقط</string>\n    <string name=\"filter_options_today_classes\">اليوم فقط</string>\n    <string name=\"filter_options_tomorrow_classes\">غدا فقط</string>\n\n    <string name=\"field_subject_code\">كود الموضوع</string>\n    <string name=\"field_description\">وصف</string>\n    <string name=\"field_days_of_week\">ايام الاسبوع</string>\n    <string name=\"field_weeks_of_month\">أسابيع من الشهر</string>\n    <string name=\"field_start_time\">وقت البدء</string>\n    <string name=\"field_end_time\">وقت النهاية</string>\n    <string name=\"field_task_name\">اسم المهمة</string>\n    <string name=\"field_notes\">ملاحظات</string>\n    <string name=\"field_subject\">موضوع</string>\n    <string name=\"field_due_date\">تاريخ الاستحقاق</string>\n    <string name=\"field_event_name\">اسم الحدث</string>\n    <string name=\"field_schedule\">جدول</string>\n    <string name=\"field_location\">موقعك</string>\n    <string name=\"field_attachments\">المرفقات</string>\n    <string name=\"field_class_time\">وقت الفصل</string>\n    <string name=\"field_color\">علامة اللون</string>\n    <string name=\"field_priority\">أولولية</string>\n    <string name=\"field_status\">الحالة</string>\n    <string name=\"field_not_set\">غير مضبوط</string>\n    <string name=\"field_due_in_the_next_meeting\">في الاجتماع القادم</string>\n    <string name=\"field_due_pick_from_schedule\">اختر من جدول الحصص</string>\n    <string name=\"field_due_custom\">مخصص</string>\n    <string name=\"field_attachment_name\">أسم المرفق</string>\n    <string name=\"field_instructor\">معلم</string>\n    <string name=\"field_classroom\">قاعة الدراسة</string>\n\n    <string name=\"hint_subject_description\">اسم الموضوع</string>\n    <string name=\"hint_task_notes\">بعض الأفكار أو التفاصيل الصغيرة حول المهمة</string>\n    <string name=\"hint_event_location\">أدخل غرفة أو مبنى أو أي مكان</string>\n    <string name=\"hint_event_notes\">بعض الأفكار أو التفاصيل البسيطة حول الحدث</string>\n\n    <string name=\"feedback_subject_removed\">تمت إزالة الموضوع</string>\n    <string name=\"feedback_log_removed\">تمت إزالة السجل</string>\n    <string name=\"feedback_task_removed\">تمت إزالة المهمة</string>\n    <string name=\"feedback_schedule_removed\">تمت إزالة الجدول </string>\n    <string name=\"feedback_attachment_added\">تمت إضافة المرفق</string>\n    <string name=\"feedback_attachment_removed\">تمت إزالة المرفق</string>\n    <string name=\"feedback_event_removed\">تمت إزالة الحدث</string>\n    <string name=\"feedback_task_marked_as_finished\">تم وضع علامة على المهمة على أنها منتهية</string>\n    <string name=\"feedback_task_marked_as_pending\">تم وضع علامة على المهمة على أنها معلقة</string>\n    <string name=\"feedback_subject_empty_name\">لقد نسيت إدخال رمز الموضوع</string>\n    <string name=\"feedback_subject_empty_description\">لقد نسيت إدخال الوصف</string>\n    <string name=\"feedback_subject_no_schedule\">لقد نسيت إضافة جدول</string>\n    <string name=\"feedback_schedule_empty_days\">لقد نسيت تحديد الأيام</string>\n    <string name=\"feedback_schedule_empty_start_time\">لقد نسيت إدخال وقت البدء</string>\n    <string name=\"feedback_schedule_empty_end_time\">لقد نسيت إدخال وقت الانتهاء</string>\n    <string name=\"feedback_task_empty_name\">لقد نسيت إدخال اسم المهمة</string>\n    <string name=\"feedback_task_empty_due_date\">لقد نسيت تحديد تاريخ استحقاقه</string>\n    <string name=\"feedback_event_empty_name\">لقد نسيت إدخال اسم الحدث</string>\n    <string name=\"feedback_event_empty_location\">لقد نسيت أدخال الموقع</string>\n    <string name=\"feedback_event_empty_schedule\">لقد نسيت إدخال الجدول</string>\n    <string name=\"feedback_restore_invalid\">ملف النسخ الاحتياطي غير صالح</string>\n    <string name=\"feedback_restore_corrupted\">ملف النسخ الاحتياطي تالف أو غير قابل للقراءة</string>\n    <string name=\"feedback_backup_empty\">لا توجد عناصر للنسخ الاحتياطي</string>\n    <string name=\"feedback_backup_failed\">واجهت عملية النسخ الاحتياطي خطأ</string>\n    <string name=\"feedback_import_ongoing\">الاستيراد قيد التقدم</string>\n    <string name=\"feedback_import_completed\">اكتمل الاستيراد</string>\n    <string name=\"feedback_import_failed\">فشل الاستيراد</string>\n    <string name=\"feedback_export_ongoing\">التصدير قيد التقدم</string>\n    <string name=\"feedback_export_completed\">اكتمل التصدير</string>\n    <string name=\"feedback_export_failed\">فشل التصدير</string>\n    <string name=\"feedback_unable_to_share_title\">غير قادر على المشاركة</string>\n    <string name=\"feedback_unable_to_share_message\">لا توجد معلومات صالحة يمكن مشاركتها</string>\n    <string name=\"feedback_subject_code_exists\">موضوع بهذا الرمز موجود بالفعل.</string>\n    <string name=\"feedback_schedule_exists\">جدول يتعارض مع جدول آخر.</string>\n    <string name=\"feedback_task_name_exists\">توجد بالفعل مهمة بهذا الاسم.</string>\n    <string name=\"feedback_event_name_exists\">يوجد بالفعل حدث بهذا الاسم.</string>\n    <string name=\"feedback_event_schedule_exists\">حدث بالفعل بنفس الجدول الزمني موجود بالفعل.</string>\n\n    <string name=\"settings_group_interface\">واجهه المستخدم</string>\n    <string name=\"settings_group_sound\">صوت</string>\n    <string name=\"settings_group_notification\">إشعارات</string>\n    <string name=\"settings_group_advanced\">المتقدمة</string>\n    <string name=\"settings_group_debugging\">تصحيح</string>\n    <string name=\"settings_group_contribute\">مساهمة</string>\n\n    <string name=\"settings_theme\">ثيم</string>\n    <string name=\"settings_theme_item_system\">النظام الافتراضي</string>\n    <string name=\"settings_theme_item_dark\">داكن</string>\n    <string name=\"settings_theme_item_light\">فاتح</string>\n    <string name=\"settings_confetti_title\">قصاصات ورق ملون</string>\n    <string name=\"settings_confetti_summary\">إظهار القصاصات عند وضع علامة على المهام كمنتهية</string>\n\n    <string name=\"settings_completion_sounds_title\">أصوات الإنجاز</string>\n    <string name=\"settings_completion_sounds_summary\">قم بتشغيل صوت عند وضع علامة على مهمة كمكتملة</string>\n\n    <string name=\"settings_reminder_frequency_title\">معدل التذكير</string>\n    <string name=\"settings_reminder_frequency_item_everyday\">كل يوم</string>\n    <string name=\"settings_reminder_frequency_item_weekends\">أيام العطل</string>\n    <string name=\"settings_remind_me_in_time_of_day\">ذكرني في هذا الوقت</string>\n    <string name=\"settings_when_nearing_due_title\">عندما تكون المهمة على وشك الاستحقاق</string>\n    <string name=\"settings_when_nearing_due_summary\">إظهار إعلامات للمهام التي اقتربت من موعدها النهائي</string>\n    <string name=\"settings_task_reminders\">الفاصل الزمني لتذكير المهام</string>\n    <string name=\"settings_task_reminders_item_hour\">قبل ساعة</string>\n    <string name=\"settings_task_reminders_item_three_hours\">قبل 3 ساعات</string>\n    <string name=\"settings_task_reminders_item_day\">قبل يوم واحد</string>\n    <string name=\"settings_incoming_events_title\">الأحداث القادمة</string>\n    <string name=\"settings_incoming_events_summary\">إظهار الإخطارات حول الأحداث الواردة هذا اليوم</string>\n    <string name=\"settings_event_reminders\">الفاصل الزمني لتذكير الحدث</string>\n    <string name=\"settings_event_reminders_item_quarter_hour\">قبل 15 دقيقة</string>\n    <string name=\"settings_event_reminders_item_half_hour\">قبل 30 دقيقة</string>\n    <string name=\"settings_event_reminders_item_hour\">@string/settings_task_reminders_item_hour</string>\n    <string name=\"settings_classes_for_this_day_title\">فصول لهذا اليوم</string>\n    <string name=\"settings_classes_for_this_day_summary\">إظهار الإخطارات حول الفصول الدراسية لموضوعاتي هذا اليوم</string>\n    <string name=\"settings_class_reminders\">الفاصل الزمني لتذكير الفصل</string>\n    <string name=\"settings_class_reminders_item_5_minutes\">قبل 5 دقائق</string>\n    <string name=\"settings_class_reminders_item_15_minutes\">@string/settings_event_reminders_item_quarter_hour</string>\n    <string name=\"settings_class_reminders_item_30_minutes\">@string/settings_event_reminders_item_half_hour</string>\n    <string name=\"settings_more_notification_settings\">المزيد من الإعدادات</string>\n\n    <string name=\"settings_allow_week_numbers_title\">تمكين أرقام الأسبوع</string>\n    <string name=\"settings_allow_week_numbers_summary\">إظهار أرقام الأسبوع عند تكوين الجداول.</string>\n    <string name=\"settings_backup_and_restore\">@string/activity_backup</string>\n    <string name=\"settings_backup\">نسخ أحتياطي</string>\n    <string name=\"settings_backup_summary_no_previous\">لا توجد نسخ احتياطية سابقة</string>\n    <string name=\"settings_restore\">استعادة</string>\n    <string name=\"settings_use_external_browser_title\">افتح الروابط في متصفح خارجي</string>\n    <string name=\"settings_use_external_browser_summary\">استخدم متصفح النظام الافتراضي للتعامل مع الارتباطات التشعبية</string>\n\n    <string name=\"settings_not_working_notifications\">@string/button_learn_more</string>\n    <string name=\"settings_not_working_notifications_info\">في بعض الأحيان ، قد لا يتم تشغيل إخطارك بسبب التحسين القوي للبطارية من قبل الشركة المصنعة للهاتف.</string>\n\n    <string name=\"settings_translate\">ترجمة</string>\n    <string name=\"settings_report_an_issue\">بلغ عن خطأ</string>\n    <string name=\"settings_third_party_notices\">@string/activity_notices</string>\n    <string name=\"settings_build_version\">نسخة الإصدار</string>\n\n    <string name=\"color_sky\">سماء</string>\n    <string name=\"color_grass\">عشب</string>\n    <string name=\"color_sunset\">غروب</string>\n    <string name=\"color_lemon\">ليمون</string>\n    <string name=\"color_sea\">بحر</string>\n    <string name=\"color_grape\">عنب</string>\n    <string name=\"color_cherry\">كرز</string>\n    <string name=\"color_coral\">المرجان</string>\n    <string name=\"color_midnight\">منتصف الليل</string>\n    <string name=\"color_mint\">نعناع</string>\n    <string name=\"color_lavender\">لافندر</string>\n    <string name=\"color_graphite\">الجرافيت</string>\n\n    <string name=\"widget_task_name\">وجت المهمة</string>\n    <string name=\"widget_task_title\">مهام</string>\n    <string name=\"widget_task_empty\">ليس لديك مهام لهذا اليوم</string>\n    <string name=\"widget_event_name\">وجت الحدث</string>\n    <string name=\"widget_event_title\">الأحداث</string>\n    <string name=\"widget_event_empty\">ليس لديك أحداث لهذا اليوم</string>\n    <string name=\"widget_class_name\">وجت الحصة</string>\n    <string name=\"widget_class_title\">الحصص</string>\n    <string name=\"widget_class_empty\">ليس لديك دروس لهذا اليوم</string>\n\n    <!-- Helper Text -->\n    <string name=\"helper_this_is_important\">يعني وضع علامة على هذا باعتباره مهمًا بأنه سيعرض إشعارًا دائمًا في مركز الإشعارات.</string>\n\n    <!-- Notifications -->\n    <string name=\"notification_channel_group_reminders\">تذكير</string>\n\n    <string name=\"notification_channel_general\">عام</string>\n    <string name=\"notification_channel_task_reminders\">تذكير المهام</string>\n    <string name=\"notification_channel_event_reminders\">تذكير الحدث</string>\n    <string name=\"notification_channel_class_reminders\">تذكير الفصل</string>\n\n    <string name=\"notification_pending_tasks_title\"> لديك %1$d مهمة معلقة</string>\n    <string name=\"notification_pending_tasks_summary\">قد يكون من المفيد إلقاء نظرة</string>\n\n    <string name=\"notification_backup_ongoing\">أداء النسخ الاحتياطي</string>\n    <string name=\"notification_backup_error\">فشل النسخ الاحتياطي</string>\n    <string name=\"notification_backup_success\">اكتمل النسخ الاحتياطي</string>\n\n    <string name=\"notification_restore_ongoing\">استعادة النسخة الاحتياطية</string>\n    <string name=\"notification_restore_error\">فشلت الاستعادة</string>\n    <string name=\"notification_restore_success\">اكتملت الاستعادة</string>\n\n    <!-- System -->\n    <string name=\"sharing_attach_to_task\">أضف كمرفق</string>\n\n    <!-- Greetings -->\n    <string name=\"greeting_default\">يوم جيد</string>\n    <string name=\"greeting_morning\">صباح الخير</string>\n    <string name=\"greeting_afternoon\">طاب مسائك</string>\n    <string name=\"greeting_evening\">مساء الخير</string>\n\n    <!-- used for concat and formatting -->\n    <string name=\"and\">&#160;and&#160;</string>\n    <string name=\"yesterday_at\"> %1$s البارحة في</string>\n    <string name=\"yesterday\">البارحة</string>\n    <string name=\"tomorrow_at\"> %1$s البارحة في</string>\n    <string name=\"tomorrow\">غدا</string>\n    <string name=\"today_at\">%1$s غدا في</string>\n    <string name=\"today\">اليوم</string>\n    <string name=\"due_today_at\"> %1$s اليوم في</string>\n    <string name=\"due_tomorrow_at\"> %1$s موعد التسليم غدًا في</string>\n    <string name=\"due_at\">موعد التسليم %1$s</string>\n\n    <string name=\"open_source_libraries\">مكتبات مفتوحة المصدر</string>\n    <string name=\"credit_other_resources\">مصادر أخرى</string>\n    <string name=\"credit_notification_sound_title\" translatable=\"false\">Zapsplat</string>\n    <string name=\"credit_notification_sound_summary\">صوت الإشعار</string>\n    <string name=\"credit_launcher_icon_title\" translatable=\"false\">Freepik</string>\n    <string name=\"credit_launcher_icon_summary\">Launcher Icon</string>\n    <string name=\"credit_user_interface_icons_title\" translatable=\"false\">Tailwind Labs</string>\n    <string name=\"credit_user_interface_icons_summary\">أيكونه واجهة المستخدم</string>\n\n    <string name=\"notifications_are_now_enabled_for_this_app\">تم تمكين الإخطارات الآن لهذا التطبيق!</string>\n    <string name=\"notifications_are_not_enabled_for_this_app\">لم يتم تمكين الإخطارات لهذا التطبيق!</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-de/strings.xml",
    "content": "<resources xmlns:tools=\"http://schemas.android.com/tools\" tools:ignore=\"MissingTranslation\">\n    <string name=\"shortcut_add_task\">@string/button_add_task</string>\n    <string name=\"shortcut_add_event\">@string/button_add_event</string>\n    <string name=\"shortcut_add_subject\">@string/button_add_subject</string>\n    <string name=\"activity_tasks\">Deine Aufgaben</string>\n    <string name=\"activity_tasks_pending\">Deine Anstehenden Aufgaben</string>\n    <string name=\"activity_tasks_finished\">Deine Erledigten Aufgaben</string>\n    <string name=\"activity_subjects\">Deine Fächer</string>\n    <string name=\"activity_subjects_today\">Deine Fächer Heute</string>\n    <string name=\"activity_subjects_tomorrow\">Deine Fächer Morgen</string>\n    <string name=\"activity_archives\">Deine Archivierten Einträge</string>\n    <string name=\"activity_logs\">Benachrichtigungsprotokolle</string>\n    <string name=\"activity_settings\">Einstellungen</string>\n    <string name=\"activity_backup\">Sichern und Wiederherstellen</string>\n    <string name=\"activity_notices\">Hinweise zu Dritten</string>\n    <string name=\"activity_open_source_licenses\">Open Source Lizenzen</string>\n    <string name=\"activity_about\">Über</string>\n    <string name=\"menu_add\">@string/button_add</string>\n    <string name=\"menu_more\">Mehr</string>\n    <string name=\"menu_sort\">Sortieren</string>\n    <string name=\"menu_filter\">Filtern</string>\n    <string name=\"menu_share\">Teilen</string>\n    <string name=\"menu_import\">Importieren</string>\n    <string name=\"menu_clear_items\">Protokolle Löschen</string>\n    <string name=\"menu_export_to_file\">Als Datei Exportieren</string>\n    <string name=\"menu_share_directly\">Direkt Teilen</string>\n    <string name=\"menu_archived\">Archiviert</string>\n    <string name=\"navigation_tasks\">Aufgaben</string>\n    <string name=\"navigation_events\">Termine</string>\n    <string name=\"navigation_subjects\">Fächer</string>\n    <string name=\"navigation_home\">Home</string>\n    <string name=\"navigation_logs\">Protokolle</string>\n    <string name=\"navigation_settings\">@string/activity_settings</string>\n    <string name=\"navigation_about\">@string/activity_about</string>\n    <string name=\"button_add_task\">Aufgabe Hinzufügen</string>\n    <string name=\"button_add_event\">Neuer Termin</string>\n    <string name=\"button_add_subject\">Fach Hinzufügen</string>\n    <string name=\"button_add\">Hinzufügen</string>\n    <string name=\"button_new\">Neu</string>\n    <string name=\"button_save\">Speichern</string>\n    <string name=\"button_done\">Fertig</string>\n    <string name=\"button_undo\">Rückgängig</string>\n    <string name=\"button_remove\">Entfernen</string>\n    <string name=\"button_continue\">Weiter</string>\n    <string name=\"button_mark_as_finished\">Als Erledigt Markieren</string>\n    <string name=\"button_mark_as_important\">Als Wichtig Markieren</string>\n    <string name=\"button_delete\">Löschen</string>\n    <string name=\"button_cancel\">Abbrechen</string>\n    <string name=\"button_discard\">Verwerfen</string>\n    <string name=\"button_dismiss\">Schließen</string>\n    <string name=\"button_learn_more\">Mehr Erfahren</string>\n    <string name=\"empty_view_no_subjects_title\">Keine Hinzugefügten Fächer</string>\n    <string name=\"empty_view_no_subjects_summary\">Fächer helfen bei der Sortierung Ihrer Aufgaben und Termine. Über den Button unten können Sie welche hinzufügen.</string>\n    <string name=\"empty_view_no_classes_today_title\">Kein Unterricht Heute</string>\n    <string name=\"empty_view_no_classes_today_summary\">Sie haben heute keinen Unterricht.</string>\n    <string name=\"empty_view_no_classes_tomorrow_title\">Kein Unterricht Morgen</string>\n    <string name=\"empty_view_no_classes_tomorrow_summary\">Sie haben morgen keinen Unterricht.</string>\n    <string name=\"empty_view_no_tasks_title\">Keine Anstehenden Aufgaben</string>\n    <string name=\"empty_view_no_tasks_summary\">Sie haben aktuell keine anstehenden Aufgaben. Mit dem Button unten können Sie welche hinzufügen.</string>\n    <string name=\"empty_view_no_finished_title\">Keine Erledigten Aufgaben</string>\n    <string name=\"empty_view_no_finished_summary\">Sie haben aktuell keine erledigten Aufgaben. Jede Aufgabe, die Sie als erledigt markieren wird hier erscheinen.</string>\n    <string name=\"empty_view_no_logs_title\">Keine Aufgezeichneten Protokolle</string>\n    <string name=\"empty_view_no_logs_summary\">Sobald eine Aufgabe, ein Termin oder eine Erinnerung in Ihrer Benachrichtigungsleiste auftaucht, wird sie auch hier angezeigt.</string>\n    <string name=\"empty_view_no_events_title\">Keine Geplanten Termine</string>\n    <string name=\"empty_view_no_events_summary\">Sie haben aktuell keine geplanten Termine. Mit dem Button unten können Sie welche hinzufügen.</string>\n    <string name=\"empty_view_no_previous_title\">Keine Vergangenen Termine</string>\n    <string name=\"empty_view_no_previous_summary\">Sie haben aktuell keine vergangenen Termine. Jeder Termin, der in der Vegangenheit liegt, wird hier erscheinen.</string>\n    <string name=\"empty_view_no_archived_tasks\">Keine Archivierten Aufgaben</string>\n    <string name=\"empty_view_no_archived_events\">Keine Archivierten Termine</string>\n    <string name=\"empty_view_no_archived_subjects\">Keine Archivierten Fächer</string>\n    <string name=\"days_of_week_item_sunday\">Sonntag</string>\n    <string name=\"days_of_week_item_monday\">Montag</string>\n    <string name=\"days_of_week_item_tuesday\">Dienstag</string>\n    <string name=\"days_of_week_item_wednesday\">Mittwoch</string>\n    <string name=\"days_of_week_item_thursday\">Donnerstag</string>\n    <string name=\"days_of_week_item_friday\">Freitag</string>\n    <string name=\"days_of_week_item_saturday\">Samstag</string>\n    <string name=\"days_of_week_item_sunday_short\">Son</string>\n    <string name=\"days_of_week_item_monday_short\">Mon</string>\n    <string name=\"days_of_week_item_tuesday_short\">Die</string>\n    <string name=\"days_of_week_item_wednesday_short\">Mit</string>\n    <string name=\"days_of_week_item_thursday_short\">Don</string>\n    <string name=\"days_of_week_item_friday_short\">Fre</string>\n    <string name=\"days_of_week_item_saturday_short\">Sam</string>\n    <string name=\"weeks_of_month_item_week_1\">Woche 1</string>\n    <string name=\"weeks_of_month_item_week_2\">Woche 2</string>\n    <string name=\"weeks_of_month_item_week_3\">Woche 3</string>\n    <string name=\"weeks_of_month_item_week_4\">Woche 4</string>\n    <string name=\"dialog_assign_subject\">Fach Zuordnen</string>\n    <string name=\"dialog_pick_start_time\">Wähle einen Startzeitpunkt</string>\n    <string name=\"dialog_pick_end_time\">Wähle einen Endzeitpunk</string>\n    <string name=\"dialog_pick_color_tag\">Wähle ein Farbtag</string>\n    <string name=\"dialog_select_notification_interval\">Benachrichtigungsintervall wählen</string>\n    <string name=\"dialog_choose_theme\">Theme wählen</string>\n    <string name=\"dialog_choose_backup\">Wähle eine Sicherungsdatei</string>\n    <string name=\"dialog_confirm_deletion_title\">Wollen Sie \\\"%1$s\\\" löschen?</string>\n    <string name=\"dialog_confirm_deletion_summary\">Sobald dieses Element gelöscht wurde, kann es nicht wiederhergestellt werden.</string>\n    <string name=\"dialog_confirm_unarchive_title\">Aus dem Archiv entfernen?</string>\n    <string name=\"dialog_confirm_unarchive_summary\">Sie können jederzeit nach links wischen, um dieses Element erneut zu archivieren.</string>\n    <string name=\"dialog_import_attachment_title\">Anhang importieren?</string>\n    <string name=\"dialog_import_attachment_summary\">Aufgrund der neuen Einschränkungen des Android-Systems muss die App die Datei in einen eigenen Dateiordner kopieren. Weiter?</string>\n    <string name=\"dialog_import_attachment_confirm\">Nie wieder fragen</string>\n    <string name=\"dialog_schedule_details\">Zeitplan Details</string>\n    <string name=\"dialog_discard_changes\">Änderungen verwerfen?</string>\n    <string name=\"dialog_select_file_import\">Zu importierende Datei wählen</string>\n    <string name=\"dialog_send_to\">Senden an</string>\n    <string name=\"dialog_sharing_options\">Optionen zum Teilen</string>\n    <string name=\"dialog_class_schedules\">Stundenpläne</string>\n    <string name=\"dialog_filter_options\">Filter Optionen</string>\n    <string name=\"dialog_new_attachment\">Neuer Anhang</string>\n    <string name=\"dialog_attachment_name\">@string/field_attachment_name</string>\n    <string name=\"dialog_enter_website_url\">Website-URL Eingeben</string>\n    <string name=\"dialog_sorting\">Sortierung</string>\n    <string name=\"dialog_permission_needed_title\">Speicher-Berechtigung erforderlich</string>\n    <string name=\"dialog_permission_needed_summary\">Um eine Datei von Ihrem Gerät anzuhängen muss die App die Speicher-Berechtigung erhalten.</string>\n    <string name=\"attachment_type_import_file\">Datei importieren</string>\n    <string name=\"attachment_type_website_url\">Website URL</string>\n    <string name=\"sorting_directions_ascending\">Aufsteigend</string>\n    <string name=\"sorting_directions_descending\">Absteigend</string>\n    <string name=\"filter_options_all\">Alles</string>\n    <string name=\"filter_options_pending_tasks\">Nur Anstehendes</string>\n    <string name=\"filter_options_finished_tasks\">Nur Erledigtes</string>\n    <string name=\"filter_options_today_classes\">Nur Heute</string>\n    <string name=\"filter_options_tomorrow_classes\">Nur Morgen</string>\n    <string name=\"field_subject_code\">Fachabkürzung</string>\n    <string name=\"field_description\">Beschreibung</string>\n    <string name=\"field_days_of_week\">Wochentage</string>\n    <string name=\"field_weeks_of_month\">Wochen des Monats</string>\n    <string name=\"field_start_time\">Startzeit</string>\n    <string name=\"field_end_time\">Endzeit</string>\n    <string name=\"field_task_name\">Aufgabenname</string>\n    <string name=\"field_notes\">Notizen</string>\n    <string name=\"field_subject\">Fach</string>\n    <string name=\"field_due_date\">Fälligkeitsdatum</string>\n    <string name=\"field_event_name\">Terminname</string>\n    <string name=\"field_schedule\">Zeitplan</string>\n    <string name=\"field_location\">Ort</string>\n    <string name=\"field_attachments\">Anhänge</string>\n    <string name=\"field_class_time\">Unterrichtszeit</string>\n    <string name=\"field_color\">Farbtag</string>\n    <string name=\"field_priority\">Priorität</string>\n    <string name=\"field_status\">Status</string>\n    <string name=\"field_not_set\">Nicht Festgelegt</string>\n    <string name=\"field_due_in_the_next_meeting\">Im Nächsten Treffen</string>\n    <string name=\"field_due_pick_from_schedule\">Aus dem Stundenplan auswählen</string>\n    <string name=\"field_due_custom\">Benutzerdefiniert</string>\n    <string name=\"field_attachment_name\">Name des Anhangs</string>\n    <string name=\"field_instructor\">Ausbilder</string>\n    <string name=\"field_classroom\">Klassenzimmer</string>\n\n    <string name=\"hint_task_notes\">Ein paar Ideen oder Details zur der Aufgabe</string>\n    <string name=\"hint_event_location\">Geben Sie einen Raum, ein Gebäude oder einen Platz ein</string>\n    <string name=\"hint_event_notes\">Ein paar Ideen oder Details zu dem Termin</string>\n    <string name=\"feedback_subject_removed\">Fach entfernt</string>\n    <string name=\"feedback_log_removed\">Protokoll entfernt</string>\n    <string name=\"feedback_task_removed\">Aufgabe entfernt</string>\n    <string name=\"feedback_attachment_added\">Anhang hinzugefügt</string>\n    <string name=\"feedback_attachment_removed\">Anhang entfernt</string>\n    <string name=\"feedback_event_removed\">Termin entfernt</string>\n    <string name=\"feedback_task_marked_as_finished\">Aufgabe als erledigt markiert</string>\n    <string name=\"feedback_task_marked_as_pending\">Aufgabe als anstehend markiert</string>\n    <string name=\"feedback_subject_empty_name\">Sie haben vergessen, die Fachabkürzung einzugeben</string>\n    <string name=\"feedback_subject_empty_description\">Sie haben vergessen, die Beschreibung einzugeben</string>\n    <string name=\"feedback_subject_no_schedule\">Sie haben vergessen, einen Zeitplan hinzuzufügen</string>\n    <string name=\"feedback_schedule_empty_days\">Sie haben vergessen, die Tage festzulegen</string>\n    <string name=\"feedback_schedule_empty_start_time\">Sie haben vergessen, den Startzeitpunkt einzugeben</string>\n    <string name=\"feedback_schedule_empty_end_time\">Sie haben vergessen, den Endzeitpunkt einzugeben</string>\n    <string name=\"feedback_task_empty_name\">Sie haben vergessen, den Aufgabennamen einzugeben</string>\n    <string name=\"feedback_task_empty_due_date\">Sie haben vergessen, das Fälligkeitsdatum festzulegen</string>\n    <string name=\"feedback_event_empty_name\">Sie haben vergessen, den Terminnamen einzugeben</string>\n    <string name=\"feedback_event_empty_location\">Sie haben vergessen, den Ort einzugeben</string>\n    <string name=\"feedback_event_empty_schedule\">Sie haben vergessen, den Zeitplan einzugeben</string>\n    <string name=\"feedback_restore_invalid\">Sicherungsdatei ist ungültig</string>\n    <string name=\"feedback_restore_corrupted\">Sicherungsdatei ist beschädigt oder unlesbar</string>\n    <string name=\"feedback_backup_empty\">Es gibt keine zu sichernden Daten</string>\n    <string name=\"feedback_backup_failed\">Fehler beim Sicherungsprozess</string>\n    <string name=\"feedback_import_ongoing\">Import läuft</string>\n    <string name=\"feedback_import_completed\">Import abgeschlossen</string>\n    <string name=\"feedback_import_failed\">Import fehlgeschlagen</string>\n    <string name=\"feedback_export_ongoing\">Export läuft</string>\n    <string name=\"feedback_export_completed\">Export abgeschlossen</string>\n    <string name=\"feedback_export_failed\">Export fehlgeschlagen</string>\n    <string name=\"feedback_unable_to_share_title\">Teilen ist nicht möglich</string>\n    <string name=\"feedback_unable_to_share_message\">Es gibt keine gültige Information, die geteilt werden kann</string>\n    <string name=\"feedback_subject_code_exists\">Ein Fach mit dieser Abkürzung existiert bereits.</string>\n    <string name=\"feedback_schedule_exists\">Ein Zeitplan kollidiert mit einem anderen Zeitplan.</string>\n    <string name=\"feedback_task_name_exists\">Eine Aufgabe mit diesem Namen existiert bereits.</string>\n    <string name=\"feedback_event_name_exists\">Ein Termin mit diesem Namen existiert bereits.</string>\n    <string name=\"feedback_event_schedule_exists\">Ein Termin mit dem gleichen Zeitplan existiert bereits.</string>\n    <string name=\"settings_group_interface\">Benutzeroberfläche</string>\n    <string name=\"settings_group_sound\">Töne</string>\n    <string name=\"settings_group_notification\">Benachrichtigungen</string>\n    <string name=\"settings_group_advanced\">Fortgeschritten</string>\n    <string name=\"settings_group_debugging\">Debugging</string>\n    <string name=\"settings_group_contribute\">Beitragen</string>\n    <string name=\"settings_theme\">Theme</string>\n    <string name=\"settings_theme_item_system\">System-Standard</string>\n    <string name=\"settings_theme_item_dark\">Dunkel</string>\n    <string name=\"settings_theme_item_light\">Hell</string>\n    <string name=\"settings_confetti_title\">Konfetti</string>\n    <string name=\"settings_confetti_summary\">Konfetti anzeigen, wenn Aufgaben\n        als erledigt markiert werden</string>\n    <string name=\"settings_completion_sounds_title\">Fertigstellungs-Ton</string>\n    <string name=\"settings_completion_sounds_summary\">Einen Ton abspielen, wenn eine Aufgabe als erledigt markiert wird</string>\n    <string name=\"settings_reminder_frequency_title\">Häufigkeit der Erinnerung</string>\n    <string name=\"settings_reminder_frequency_item_everyday\">Täglich</string>\n    <string name=\"settings_remind_me_in_time_of_day\">Erinnere mich zu dieser Zeit</string>\n    <string name=\"settings_when_nearing_due_title\">Wenn eine Aufgabe bald fällig ist</string>\n    <string name=\"settings_when_nearing_due_summary\">Zeige Benachrichtigungen für Aufgaben, die kurz vor der Fälligkeit stehen</string>\n    <string name=\"settings_task_reminders\">Erinnerungszeitpunkt für Aufgaben</string>\n    <string name=\"settings_task_reminders_item_hour\">1 Stunde vorher</string>\n    <string name=\"settings_task_reminders_item_three_hours\">3 Stunden vorher</string>\n    <string name=\"settings_task_reminders_item_day\">1 Tag vorher</string>\n    <string name=\"settings_incoming_events_title\">Kommende Termine</string>\n    <string name=\"settings_incoming_events_summary\">Benachrichtigungen für anstehende Termine an diesem Tag anzeigen</string>\n    <string name=\"settings_event_reminders\">Erinnerungszeitpunkt für Termine</string>\n    <string name=\"settings_event_reminders_item_quarter_hour\">15 Minuten vorher</string>\n    <string name=\"settings_event_reminders_item_half_hour\">30 Minuten vorher</string>\n    <string name=\"settings_event_reminders_item_hour\">@string/settings_task_reminders_item_hour</string>\n    <string name=\"settings_classes_for_this_day_title\">Unterricht an diesem Tag</string>\n    <string name=\"settings_classes_for_this_day_summary\">Zeige Benachrichtigungen für den Unterricht meiner Fächer an diesem Tag</string>\n    <string name=\"settings_class_reminders\">Erinnerungszeitpunkt für Unterricht</string>\n    <string name=\"settings_class_reminders_item_5_minutes\">5 Minuten vorher</string>\n    <string name=\"settings_class_reminders_item_15_minutes\">@string/settings_event_reminders_item_quarter_hour</string>\n    <string name=\"settings_class_reminders_item_30_minutes\">@string/settings_event_reminders_item_half_hour</string>\n    <string name=\"settings_more_notification_settings\">Mehr Einstellungen</string>\n    <string name=\"settings_allow_week_numbers_title\">Wochennummern aktivieren</string>\n    <string name=\"settings_allow_week_numbers_summary\">Zeige Wochennummern beim Festlegen von Zeitplänen.</string>\n    <string name=\"settings_backup_and_restore\">@string/activity_backup</string>\n    <string name=\"settings_backup\">Sicherung</string>\n    <string name=\"settings_backup_summary_no_previous\">Keine Bisherigen Sicherungen</string>\n    <string name=\"settings_restore\">Wiederherstellen</string>\n    <string name=\"settings_use_external_browser_title\">Links in externem Browser öffnen</string>\n    <string name=\"settings_use_external_browser_summary\">Nutze den Standardbrowser des Systems, um Hyperlinks zu öffnen</string>\n    <string name=\"settings_not_working_notifications\">@string/button_learn_more</string>\n    <string name=\"settings_translate\">Übersetzen</string>\n    <string name=\"settings_report_an_issue\">Problem melden</string>\n    <string name=\"settings_third_party_notices\">@string/activity_notices</string>\n    <string name=\"settings_build_version\">Build Version</string>\n    <string name=\"color_sky\">Himmel</string>\n    <string name=\"color_grass\">Gras</string>\n    <string name=\"color_sunset\">Sonnenuntergang</string>\n    <string name=\"color_lemon\">Zitrone</string>\n    <string name=\"color_sea\">Meer</string>\n    <string name=\"color_grape\">Weintraube</string>\n    <string name=\"color_cherry\">Kirsche</string>\n    <string name=\"color_coral\">Koralle</string>\n    <string name=\"color_midnight\">Mitternacht</string>\n    <string name=\"color_mint\">Minze</string>\n    <string name=\"color_lavender\">Lavendel</string>\n    <string name=\"color_graphite\">Graphit</string>\n    <string name=\"widget_task_name\">Aufgaben-Widget</string>\n    <string name=\"widget_task_title\">Aufgaben</string>\n    <string name=\"widget_task_empty\">Sie haben keine Aufgaben für heute</string>\n    <string name=\"widget_event_name\">Termin-Widget</string>\n    <string name=\"widget_event_title\">Termine</string>\n    <string name=\"widget_event_empty\">Sie haben keine Termine für heute</string>\n    <string name=\"widget_class_name\">Unterrichts-Widget</string>\n    <string name=\"widget_class_title\">Unterrichtsstunden</string>\n    <string name=\"widget_class_empty\">Sie haben keinen Unterricht für heute</string>\n    <string name=\"helper_this_is_important\">Wenn Sie dies als wichtig markieren, wird eine dauerhafte Benachrichtigung in der Benachrichtigungsleiste angezeigt.</string>\n    <string name=\"notification_channel_group_reminders\">Erinnerungen</string>\n    <string name=\"notification_channel_general\">Allgemein</string>\n    <string name=\"notification_channel_task_reminders\">Aufgabenerinnerungen</string>\n    <string name=\"notification_channel_event_reminders\">Terminerinnerungen</string>\n    <string name=\"notification_channel_class_reminders\">Unterrichtserinnerungen</string>\n    <string name=\"notification_pending_tasks_title\">Sie haben %1$d anstehende Aufgaben</string>\n    <string name=\"notification_pending_tasks_summary\">Es könnte sich lohnen, einen Blick darauf zu werfen</string>\n    <string name=\"notification_backup_ongoing\">Sicherung läuft</string>\n    <string name=\"notification_backup_error\">Sicherung fehlgeschlagen</string>\n    <string name=\"notification_backup_success\">Sicherung abgeschlossen</string>\n    <string name=\"notification_restore_ongoing\">Sicherung wiederherstellen</string>\n    <string name=\"notification_restore_error\">Wiederherstellung fehlgeschlagen</string>\n    <string name=\"notification_restore_success\">Wiederherstellung abgeschlossen</string>\n    <string name=\"sharing_attach_to_task\">An Aufgabe anhängen</string>\n    <string name=\"greeting_default\">Guten Tag!</string>\n    <string name=\"greeting_morning\">Guten Morgen!</string>\n    <string name=\"greeting_afternoon\">Guten Tag!</string>\n    <string name=\"greeting_evening\">Guten Abend!</string>\n    <string name=\"and\">&#160;und&#160;</string>\n    <string name=\"yesterday_at\">Gestern, %1$s</string>\n    <string name=\"yesterday\">Gestern</string>\n    <string name=\"tomorrow_at\">Morgen, %1$s</string>\n    <string name=\"tomorrow\">Morgen</string>\n    <string name=\"today_at\">Heute, %1$s</string>\n    <string name=\"today\">Heute</string>\n    <string name=\"due_today_at\">Fällig heute, %1$s</string>\n    <string name=\"due_tomorrow_at\">Fällig morgen, %1$s</string>\n    <string name=\"due_at\">Fällig am %1$s</string>\n    <string name=\"open_source_libraries\">Open-Source-Bibliotheken</string>\n    <string name=\"credit_other_resources\">Andere Ressourcen</string>\n    <string name=\"credit_notification_sound_summary\">Benachrichtigungs-Ton</string>\n    <string name=\"credit_launcher_icon_summary\">Launcher Icon</string>\n    <string name=\"credit_user_interface_icons_summary\">Icons der Benutzeroberfläche</string>\n    <string name=\"button_view_schedules\">Termine Anzeigen</string>\n    <string name=\"hint_subject_description\">Der Name des Fachs</string>\n    <string name=\"feedback_schedule_removed\">Zeitplan entfernt</string>\n    <string name=\"settings_reminder_frequency_item_weekends\">Wochenenden</string>\n    <string name=\"settings_not_working_notifications_info\">Manchmal kann es vorkommen, dass Benachrichtigungen aufgrund von aggressiver Akku-Optimierung durch den Hersteller des Telefons nicht gesendet wird.</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-es/strings.xml",
    "content": "<resources>\n    <string translatable=\"false\" name=\"app_name\">Fokus</string>\n\n    <string name=\"shortcut_add_task\">@string/button_add_task</string>\n    <string name=\"shortcut_add_event\">@string/button_add_event</string>\n    <string name=\"shortcut_add_subject\">@string/button_add_subject</string>\n\n    <string name=\"activity_tasks\">Tus Tareas</string>\n    <string name=\"activity_tasks_pending\">Tus tareas pendientes</string>\n    <string name=\"activity_tasks_finished\">Tus tareas finalizadas</string>\n    <string name=\"activity_subjects\">Tus Asignaturas</string>\n    <string name=\"activity_subjects_today\">Tus asignaturas de hoy</string>\n    <string name=\"activity_subjects_tomorrow\">Tus asignaturas de mañana</string>\n    <string name=\"activity_archives\">Sus artículos archivados</string>\n    <string name=\"activity_logs\">Registro de notificaciones</string>\n    <string name=\"activity_settings\">Configuracion</string>\n    <string name=\"activity_backup\">Backup y Restauración</string>\n    <string name=\"activity_notices\">Avisos de terceros</string>\n    <string name=\"activity_open_source_licenses\">Licencias Open Source</string>\n    <string name=\"activity_about\">Acerca de</string>\n\n    <string name=\"menu_add\">@string/button_add</string>\n    <string name=\"menu_more\">Más</string>\n    <string name=\"menu_sort\">Ordenar</string>\n    <string name=\"menu_filter\">Filtro</string>\n    <string name=\"menu_share\">Compartir</string>\n    <string name=\"menu_import\">Importar</string>\n    <string name=\"menu_clear_items\">Eliminar registros</string>\n    <string name=\"menu_export_to_file\">Exportar a archivo</string>\n    <string name=\"menu_share_directly\">Compartir directamente</string>\n    <string name=\"menu_archived\">Archivado</string>\n\n    <string name=\"navigation_tasks\">Tareas</string>\n    <string name=\"navigation_events\">Eventos</string>\n    <string name=\"navigation_subjects\">Asignaturas</string>\n    <string name=\"navigation_home\">Inicio</string>\n\n    <string name=\"navigation_logs\">Registro</string>\n    <string name=\"navigation_settings\">@string/activity_settings</string>\n    <string name=\"navigation_about\">@string/activity_about</string>\n\n    <string name=\"button_add_task\">Añadir tarea</string>\n    <string name=\"button_add_event\">Añadir Evento</string>\n    <string name=\"button_add_subject\">Añadir Asignatura</string>\n    <string name=\"button_add\">Agregar</string>\n    <string name=\"button_new\">Nuevo</string>\n    <string name=\"button_save\">Guardar</string>\n    <string name=\"button_done\">Listo</string>\n    <string name=\"button_undo\">Deshacer</string>\n    <string name=\"button_remove\">Remover</string>\n    <string name=\"button_continue\">Continuar</string>\n    <string name=\"button_mark_as_finished\">Marcar como Terminado</string>\n    <string name=\"button_mark_as_important\">Marcar como Importante</string>\n    <string name=\"button_delete\">Eliminar</string>\n    <string name=\"button_cancel\">Cancelar</string>\n    <string name=\"button_discard\">Descartar</string>\n    <string name=\"button_dismiss\">Descartar</string>\n    <string name=\"button_learn_more\">Más información</string>\n    <string name=\"button_view_schedules\">Ver Programas</string>\n\n    <string name=\"empty_view_no_subjects_title\">Sin asignaturas añadidas</string>\n    <string name=\"empty_view_no_subjects_summary\">Las asignaturas te ayudan a ordenar tus tareas y eventos, Si tienes una, añadela con el boton de abajo.</string>\n    <string name=\"empty_view_no_classes_today_title\">No hay clases hoy</string>\n    <string name=\"empty_view_no_classes_today_summary\">No tienes clases programadas para hoy.</string>\n    <string name=\"empty_view_no_classes_tomorrow_title\">No hay clases mañana</string>\n    <string name=\"empty_view_no_classes_tomorrow_summary\">No tiene clases programadas para mañana.</string>\n    <string name=\"empty_view_no_tasks_title\">No hay tareas pendientes</string>\n    <string name=\"empty_view_no_tasks_summary\">Por el momento no tienes tareas pendientes. Si tienes una, añadela con el boton de abajo.</string>\n    <string name=\"empty_view_no_finished_title\">Sin tareas finalizadas</string>\n    <string name=\"empty_view_no_finished_summary\">Por el momento no tienes tareas finalizadas. Cada tarea marcada como finalizada se mostrará aquí.</string>\n    <string name=\"empty_view_no_logs_title\">No hay registros</string>\n    <string name=\"empty_view_no_logs_summary\">Una vez que una tarea, evento o cualquier recordatorio aparezca en tus notificaciones, también aparecerá aquí.</string>\n    <string name=\"empty_view_no_events_title\">No hay eventos programados</string>\n    <string name=\"empty_view_no_events_summary\">Por el momento no tienes eventos programados. Si tienes uno, añadela con el boton de abajo.</string>\n    <string name=\"empty_view_no_previous_title\">No hay eventos previos</string>\n    <string name=\"empty_view_no_previous_summary\">Por el momento no tienes eventos previos. Cada evento que haya pasado su fecha de programación, aparecerá aquí.</string>\n    <string name=\"empty_view_no_archived_tasks\">No hay tareas archivadas</string>\n    <string name=\"empty_view_no_archived_events\">No hay eventos archivados</string>\n    <string name=\"empty_view_no_archived_subjects\">No hay temas archivados</string>\n\n    <string name=\"days_of_week_item_sunday\">Domingo</string>\n    <string name=\"days_of_week_item_monday\">Lunes</string>\n    <string name=\"days_of_week_item_tuesday\">Martes</string>\n    <string name=\"days_of_week_item_wednesday\">Miercoles</string>\n    <string name=\"days_of_week_item_thursday\">Jueves</string>\n    <string name=\"days_of_week_item_friday\">Viernes</string>\n    <string name=\"days_of_week_item_saturday\">Sabado</string>\n\n    <string name=\"days_of_week_item_sunday_short\">Dom</string>\n    <string name=\"days_of_week_item_monday_short\">Lun</string>\n    <string name=\"days_of_week_item_tuesday_short\">Mar</string>\n    <string name=\"days_of_week_item_wednesday_short\">Mie</string>\n    <string name=\"days_of_week_item_thursday_short\">Jue</string>\n    <string name=\"days_of_week_item_friday_short\">Vie</string>\n    <string name=\"days_of_week_item_saturday_short\">Sab</string>\n\n    <string name=\"weeks_of_month_item_week_1\">Semana 1</string>\n    <string name=\"weeks_of_month_item_week_2\">Semana 2</string>\n    <string name=\"weeks_of_month_item_week_3\">Semana 3</string>\n    <string name=\"weeks_of_month_item_week_4\">Semana 4</string>\n\n    <string name=\"dialog_assign_subject\">Asignar Asignatura</string>\n    <string name=\"dialog_pick_start_time\">Escoge una Hora de inicio</string>\n    <string name=\"dialog_pick_end_time\">Escoge una Hora de finalización</string>\n    <string name=\"dialog_pick_color_tag\">Escoge un color para la etiqueta</string>\n    <string name=\"dialog_select_notification_interval\">Seleccionar intervalo de notificacion</string>\n    <string name=\"dialog_choose_theme\">Seleccionar tema</string>\n    <string name=\"dialog_choose_backup\">Seleccionar archivo de backup</string>\n    <string name=\"dialog_confirm_deletion_title\">Quieres remover \\\"%1$s\\\"?</string>\n    <string name=\"dialog_confirm_deletion_summary\">Una vez que este item sea borrado, no se puede recuperar.</string>\n    <string name=\"dialog_confirm_unarchive_title\">¿Sacar de los archivos?</string>\n    <string name=\"dialog_confirm_unarchive_summary\">Siempre puedes deslizar el dedo hacia la izquierda para volver a archivar este elemento.</string>\n    <string name=\"dialog_import_attachment_title\">¿Importar el archivo adjunto?</string>\n    <string name=\"dialog_import_attachment_summary\">Debido a las recientes restricciones impuestas por el sistema Android, la aplicación tendrá que copiar el archivo en su propia carpeta de datos. ¿Continuar?</string>\n    <string name=\"dialog_import_attachment_confirm\">No vuelvas a preguntar</string>\n    <string name=\"dialog_schedule_details\">Detalles del programa</string>\n    <string name=\"dialog_discard_changes\">Descartar cambios?</string>\n    <string name=\"dialog_select_file_import\">Seleccionar archivo para importar</string>\n    <string name=\"dialog_send_to\">Enviar a</string>\n    <string name=\"dialog_sharing_options\">Opciones para compartir</string>\n    <string name=\"dialog_class_schedules\">Programas de clase</string>\n    <string name=\"dialog_filter_options\">Opciones de filtro</string>\n    <string name=\"dialog_new_attachment\">Nuevo Adjunto</string>\n    <string name=\"dialog_attachment_name\">@string/field_attachment_name</string>\n    <string name=\"dialog_enter_website_url\">Ingresa la URL del sitio web</string>\n    <string name=\"dialog_sorting\">Ordenar</string>\n    <string name=\"dialog_permission_needed_title\">Permiso de almacenamiento necesario</string>\n    <string name=\"dialog_permission_needed_summary\">Para adjuntar un archivo desde su dispositivo, la aplicación necesita que se conceda el permiso de almacenamiento.</string>\n\n    <string name=\"attachment_type_import_file\">Importar archivo</string>\n    <string name=\"attachment_type_website_url\">URL del sitio web</string>\n\n    <string name=\"sorting_directions_ascending\">Ascendente</string>\n    <string name=\"sorting_directions_descending\">Descendente</string>\n\n    <string name=\"filter_options_all\">Todos</string>\n    <string name=\"filter_options_pending_tasks\">Solo pendientes</string>\n    <string name=\"filter_options_finished_tasks\">Solo finalizados</string>\n    <string name=\"filter_options_today_classes\">Solo de hoy</string>\n    <string name=\"filter_options_tomorrow_classes\">Solo de mañana</string>\n\n    <string name=\"field_subject_code\">Codigo de asignacion</string>\n    <string name=\"field_description\">Descripcion</string>\n    <string name=\"field_days_of_week\">Dias de la semana</string>\n    <string name=\"field_weeks_of_month\">Semanas del mes</string>\n    <string name=\"field_start_time\">Hora de inicio</string>\n    <string name=\"field_end_time\">Hora de finalización</string>\n    <string name=\"field_task_name\">Nombre de la tarea</string>\n    <string name=\"field_notes\">Notas</string>\n    <string name=\"field_subject\">Asignatura</string>\n    <string name=\"field_due_date\">Fecha limite</string>\n    <string name=\"field_event_name\">Nombre del evento</string>\n    <string name=\"field_schedule\">Programa</string>\n    <string name=\"field_location\">Lugar</string>\n    <string name=\"field_attachments\">Archivos adjuntos</string>\n    <string name=\"field_class_time\">Hora de clase</string>\n    <string name=\"field_color\">Color de etiqueta</string>\n    <string name=\"field_priority\">Prioridad</string>\n    <string name=\"field_status\">Estado</string>\n    <string name=\"field_not_set\">No establecido</string>\n    <string name=\"field_due_in_the_next_meeting\">En la proxima reunion</string>\n    <string name=\"field_due_pick_from_schedule\">Elegir del programa de clases</string>\n    <string name=\"field_due_custom\">Personalizado</string>\n    <string name=\"field_attachment_name\">Nombre del archivo adjunto</string>\n    <string name=\"field_instructor\">Instructor</string>\n    <string name=\"field_classroom\">Aula</string>\n\n    <string name=\"hint_subject_description\">El nombre de la asignatura</string>\n    <string name=\"hint_task_notes\">Algunas ideas o detalles menores sobre la tarea</string>\n    <string name=\"hint_event_location\">Entrar a una habitación, edificio o cualquier lugar</string>\n    <string name=\"hint_event_notes\">Algunas ideas o detalles menores sobre el evento</string>\n\n    <string name=\"feedback_subject_removed\">Asignatura removida</string>\n    <string name=\"feedback_log_removed\">Registro removido</string>\n    <string name=\"feedback_task_removed\">Tarea removida</string>\n    <string name=\"feedback_schedule_removed\">Programa removido</string>\n    <string name=\"feedback_attachment_added\">Adjunto añadido</string>\n    <string name=\"feedback_attachment_removed\">Adjunto removido</string>\n    <string name=\"feedback_event_removed\">Evento removido</string>\n    <string name=\"feedback_task_marked_as_finished\">Tarea marcada como finalizada</string>\n    <string name=\"feedback_task_marked_as_pending\">Tarea marcada como pendiente</string>\n    <string name=\"feedback_subject_empty_name\">Olvidaste agregar el codigo de la asignacion</string>\n    <string name=\"feedback_subject_empty_description\">Olvidaste agregar una descripcion</string>\n    <string name=\"feedback_subject_no_schedule\">Olvidaste agregar un programa</string>\n    <string name=\"feedback_schedule_empty_days\">Olvidaste especificar los dias</string>\n    <string name=\"feedback_schedule_empty_start_time\">Olvidaste agregar el horario de inicio</string>\n    <string name=\"feedback_schedule_empty_end_time\">Olvidaste agregar el horario de finalización</string>\n    <string name=\"feedback_task_empty_name\">Olvidaste agregar el nombre de la tarea</string>\n    <string name=\"feedback_task_empty_due_date\">Olvidaste especificar la fecha limite</string>\n    <string name=\"feedback_event_empty_name\">Olvidaste agregar el nombre del evento</string>\n    <string name=\"feedback_event_empty_location\">Olvidaste agregar el lugar</string>\n    <string name=\"feedback_event_empty_schedule\">Olvidaste agregar el programa</string>\n    <string name=\"feedback_restore_invalid\">El archivo de backup es invalido</string>\n    <string name=\"feedback_restore_corrupted\">El archivo de backup esta corrupto</string>\n    <string name=\"feedback_backup_empty\">No hay items para el backup</string>\n    <string name=\"feedback_backup_failed\">El proceso de backup tuvo un error</string>\n    <string name=\"feedback_import_ongoing\">Importacion en progreso</string>\n    <string name=\"feedback_import_completed\">Importacion completada</string>\n    <string name=\"feedback_import_failed\">Importacion fallida</string>\n    <string name=\"feedback_export_ongoing\">Exportacion en progreso</string>\n    <string name=\"feedback_export_completed\">Exportacion completada</string>\n    <string name=\"feedback_export_failed\">Exportacion fallida</string>\n    <string name=\"feedback_unable_to_share_title\">No es posible compartir</string>\n    <string name=\"feedback_unable_to_share_message\">No hay inforamción valida para ser compartida</string>\n    <string name=\"feedback_subject_code_exists\">Ya existe un asignacion con este código.</string>\n    <string name=\"feedback_schedule_exists\">Un horario entra en conflicto con otro horario.</string>\n    <string name=\"feedback_task_name_exists\">Ya existe una tarea con este nombre.</string>\n    <string name=\"feedback_event_name_exists\">Ya existe un evento con este nombre.</string>\n    <string name=\"feedback_event_schedule_exists\">Ya existe un evento con el mismo horario.</string>\n\n    <string name=\"settings_group_interface\">Interface</string>\n    <string name=\"settings_group_sound\">Sonido</string>\n    <string name=\"settings_group_notification\">Notificaciones</string>\n    <string name=\"settings_group_advanced\">Avanzado</string>\n    <string name=\"settings_group_debugging\">Debugging</string>\n    <string name=\"settings_group_contribute\">Contribuir</string>\n\n    <string name=\"settings_theme\">Tema</string>\n    <string name=\"settings_theme_item_system\">Default del sistema</string>\n    <string name=\"settings_theme_item_dark\">Oscuro</string>\n    <string name=\"settings_theme_item_light\">Claro</string>\n    <string name=\"settings_confetti_title\">Confetti</string>\n    <string name=\"settings_confetti_summary\">Mostrar confetti cuando las tareas se marquen como finalizadas</string>\n\n    <string name=\"settings_completion_sounds_title\">Sonidos de finalizacion</string>\n    <string name=\"settings_completion_sounds_summary\">Reproducir un sonido cuando las tareas se marquen como finalizadas</string>\n\n    <string name=\"settings_reminder_frequency_title\">Frecuencia de recordatorio</string>\n    <string name=\"settings_reminder_frequency_item_everyday\">Todos los dias</string>\n    <string name=\"settings_reminder_frequency_item_weekends\">Fines de semana</string>\n    <string name=\"settings_remind_me_in_time_of_day\">Recordame a esta hora</string>\n    <string name=\"settings_when_nearing_due_title\">Cuando la tarea este cerca de la fecha limite</string>\n    <string name=\"settings_when_nearing_due_summary\">Mostrar notificaciones para tareas que esten cerca de su fecha limite</string>\n    <string name=\"settings_task_reminders\">Intervalo de recordatorio para las tareas</string>\n    <string name=\"settings_task_reminders_item_hour\">1 hora antes</string>\n    <string name=\"settings_task_reminders_item_three_hours\">3 horas antes</string>\n    <string name=\"settings_task_reminders_item_day\">1 dia antes</string>\n    <string name=\"settings_incoming_events_title\">Eventos entrantes</string>\n    <string name=\"settings_incoming_events_summary\">Mostrar notificaciones acerca de eventos entrantes para este dia</string>\n    <string name=\"settings_event_reminders\">Intervalo de recordatorio para los eventos</string>\n    <string name=\"settings_event_reminders_item_quarter_hour\">15 minutos antes</string>\n    <string name=\"settings_event_reminders_item_half_hour\">30 minutos antes</string>\n    <string name=\"settings_event_reminders_item_hour\">@string/settings_task_reminders_item_hour</string>\n    <string name=\"settings_classes_for_this_day_title\">Clases para este dia</string>\n    <string name=\"settings_classes_for_this_day_summary\">Mostrar notificaciones de clases para este dia</string>\n    <string name=\"settings_class_reminders\">Intervalo de recordatorio para las clases</string>\n    <string name=\"settings_class_reminders_item_5_minutes\">5 minutos antes</string>\n    <string name=\"settings_class_reminders_item_15_minutes\">@string/settings_event_reminders_item_quarter_hour</string>\n    <string name=\"settings_class_reminders_item_30_minutes\">@string/settings_event_reminders_item_half_hour</string>\n    <string name=\"settings_more_notification_settings\">Mas opciones</string>\n\n    <string name=\"settings_allow_week_numbers_title\">Activar los números de la semana</string>\n    <string name=\"settings_allow_week_numbers_summary\">Mostrar los números de semana al configurar los horarios.</string>\n    <string name=\"settings_backup_and_restore\">@string/activity_backup</string>\n    <string name=\"settings_backup\">Backup</string>\n    <string name=\"settings_backup_summary_no_previous\">No hay Backups previos</string>\n    <string name=\"settings_restore\">Restaurar</string>\n    <string name=\"settings_use_external_browser_title\">Abrir links en navegador externo</string>\n    <string name=\"settings_use_external_browser_summary\">Usar el navegador default del sistema para abrir hyperlinks</string>\n\n    <string name=\"settings_not_working_notifications\">@string/button_learn_more</string>\n    <string name=\"settings_not_working_notifications_info\">A veces no te llegarán notificaciones debido a la agresiva optimizacion de bateria del fabricante.</string>\n\n    <string name=\"settings_translate\">Traducir</string>\n    <string name=\"settings_report_an_issue\">Reportar un problema</string>\n    <string name=\"settings_third_party_notices\">@string/activity_notices</string>\n    <string name=\"settings_build_version\">Build Version</string>\n\n    <string name=\"color_sky\">Cielo</string>\n    <string name=\"color_grass\">Cesped</string>\n    <string name=\"color_sunset\">Ocaso</string>\n    <string name=\"color_lemon\">Limon</string>\n    <string name=\"color_sea\">Mar</string>\n    <string name=\"color_grape\">Uva</string>\n    <string name=\"color_cherry\">Cereza</string>\n    <string name=\"color_coral\">Coral</string>\n    <string name=\"color_midnight\">Medianoche</string>\n    <string name=\"color_mint\">Menta</string>\n    <string name=\"color_lavender\">Lavanda</string>\n    <string name=\"color_graphite\">Grafito</string>\n\n    <string name=\"widget_task_name\">Widget de tareas</string>\n    <string name=\"widget_task_title\">Tareas</string>\n    <string name=\"widget_task_empty\">No tienes tareas por hoy</string>\n    <string name=\"widget_event_name\">Widget de eventos</string>\n    <string name=\"widget_event_title\">Eventoss</string>\n    <string name=\"widget_event_empty\">No tienes eventos por hoy</string>\n    <string name=\"widget_class_name\">Widget de clases</string>\n    <string name=\"widget_class_title\">Clases</string>\n    <string name=\"widget_class_empty\">No tienes clases por hoy</string>\n\n    <!-- Helper Text -->\n    <string name=\"helper_this_is_important\">Marcar esto como importante significa que mostrará una notificacion permanente en tu barra de notificaciones.</string>\n\n    <!-- Notifications -->\n    <string name=\"notification_channel_group_reminders\">Recordatorios</string>\n\n    <string name=\"notification_channel_general\">General</string>\n    <string name=\"notification_channel_task_reminders\">Recordatorios de tareas</string>\n    <string name=\"notification_channel_event_reminders\">Recordatorios de eventos</string>\n    <string name=\"notification_channel_class_reminders\">Recordatorios de clases</string>\n\n    <string name=\"notification_pending_tasks_title\">Tienes %1$d tareas pendientes</string>\n    <string name=\"notification_pending_tasks_summary\">Quizás quieras echarle un vistazo</string>\n\n    <string name=\"notification_backup_ongoing\">Realizando backup</string>\n    <string name=\"notification_backup_error\">Backup Fallido</string>\n    <string name=\"notification_backup_success\">Backup Completado</string>\n\n    <string name=\"notification_restore_ongoing\">Restaurando backup</string>\n    <string name=\"notification_restore_error\">Restauracion fallida</string>\n    <string name=\"notification_restore_success\">Restauracion completada</string>\n\n    <!-- System -->\n    <string name=\"sharing_attach_to_task\">Agregar como adjunto</string>\n\n    <!-- Greetings -->\n    <string name=\"greeting_default\">Buen dia!</string>\n    <string name=\"greeting_morning\">Buenos días!</string>\n    <string name=\"greeting_afternoon\">Buenas tardes!</string>\n    <string name=\"greeting_evening\">Buenas noches!</string>\n\n    <!-- used for concat and formatting -->\n    <string name=\"and\">&#160;and&#160;</string>\n    <string name=\"yesterday_at\">Ayer a las %1$s</string>\n    <string name=\"yesterday\">Ayer</string>\n    <string name=\"tomorrow_at\">Mañana a las %1$s</string>\n    <string name=\"tomorrow\">Mañana</string>\n    <string name=\"today_at\">Hoy a las %1$s</string>\n    <string name=\"today\">Hoy</string>\n    <string name=\"due_today_at\">Fecha limite hoy a las %1$s</string>\n    <string name=\"due_tomorrow_at\">Fecha limite hoy a las %1$s</string>\n    <string name=\"due_at\">Con fecha de vencimiento en %1$s</string>\n\n    <string name=\"open_source_libraries\">Open Source Libraries</string>\n    <string name=\"credit_other_resources\">Otros recursos</string>\n    <string name=\"credit_notification_sound_title\" translatable=\"false\">Zapsplat</string>\n    <string name=\"credit_notification_sound_summary\">Sonido de notificacion</string>\n    <string name=\"credit_launcher_icon_title\" translatable=\"false\">Freepik</string>\n    <string name=\"credit_launcher_icon_summary\">Icono del launcher</string>\n    <string name=\"credit_user_interface_icons_title\" translatable=\"false\">Tailwind Labs</string>\n    <string name=\"credit_user_interface_icons_summary\">Iconos de la interfaz del usuario</string>\n\n</resources>"
  },
  {
    "path": "app/src/main/res/values-fr/strings.xml",
    "content": "<resources>\r\n    <string name=\"shortcut_add_task\">@string/button_add_task</string>\r\n    <string name=\"shortcut_add_event\">@string/button_add_event</string>\r\n    <string name=\"shortcut_add_subject\">@string/button_add_subject</string>\r\n\r\n    <string name=\"activity_tasks\">Vos tâches</string>\r\n    <string name=\"activity_tasks_pending\">Vos tâches en cours</string>\r\n    <string name=\"activity_tasks_finished\">Vos tâches terminées</string>\r\n    <string name=\"activity_subjects\">Vos matières</string>\r\n    <string name=\"activity_subjects_today\">Vos matières d’aujourd’hui</string>\r\n    <string name=\"activity_subjects_tomorrow\">Vos matières de demain</string>\r\n    <string name=\"activity_archives\">Vos archives</string>\r\n    <string name=\"activity_logs\">Journaux de notification</string>\r\n    <string name=\"activity_settings\">Paramètres</string>\r\n    <string name=\"activity_backup\">Sauvegarde et restauration</string>\r\n    <string name=\"activity_notices\">Mentions tierces</string>\r\n    <string name=\"activity_open_source_licenses\">Licences open source</string>\r\n    <string name=\"activity_about\">À propos</string>\r\n\r\n    <string name=\"menu_add\">@string/button_add</string>\r\n    <string name=\"menu_more\">Plus</string>\r\n    <string name=\"menu_sort\">Trier</string>\r\n    <string name=\"menu_filter\">Filtrer</string>\r\n    <string name=\"menu_share\">Partager</string>\r\n    <string name=\"menu_import\">Importer</string>\r\n    <string name=\"menu_clear_items\">Effacer les journaux</string>\r\n    <string name=\"menu_export_to_file\">Exporter dans un fichier</string>\r\n    <string name=\"menu_share_directly\">Partager directement</string>\r\n    <string name=\"menu_archived\">Archivé</string>\r\n\r\n    <string name=\"navigation_tasks\">Tâches</string>\r\n    <string name=\"navigation_events\">Événements</string>\r\n    <string name=\"navigation_subjects\">Matières</string>\r\n    <string name=\"navigation_home\">Accueil</string>\r\n    <string name=\"navigation_logs\">Journaux</string>\r\n    <string name=\"navigation_settings\">@string/activity_settings</string>\r\n    <string name=\"navigation_about\">@string/activity_about</string>\r\n\r\n    <string name=\"button_add_task\">Ajouter une tâche</string>\r\n    <string name=\"button_add_event\">Ajouter un événement</string>\r\n    <string name=\"button_add_subject\">Ajouter une matière</string>\r\n    <string name=\"button_add\">Ajouter</string>\r\n    <string name=\"button_new\">Nouveau</string>\r\n    <string name=\"button_save\">Enregistrer</string>\r\n    <string name=\"button_done\">Terminé</string>\r\n    <string name=\"button_undo\">Annuler</string>\r\n    <string name=\"button_remove\">Supprimer</string>\r\n    <string name=\"button_continue\">Continuer</string>\r\n    <string name=\"button_mark_as_finished\">Marquer comme terminé</string>\r\n    <string name=\"button_mark_as_important\">Marquer comme important</string>\r\n    <string name=\"button_delete\">Supprimer</string>\r\n    <string name=\"button_cancel\">Annuler</string>\r\n    <string name=\"button_discard\">Annuler</string>\r\n    <string name=\"button_dismiss\">Fermer</string>\r\n    <string name=\"button_learn_more\">En savoir plus</string>\r\n    <string name=\"button_view_schedules\">Voir les horaires</string>\r\n\r\n    <string name=\"empty_view_no_subjects_title\">Aucune matière ajoutée</string>\r\n    <string name=\"empty_view_no_subjects_summary\">Les matières vous aident à classer vos tâches et événements. Ajoutez-en un en utilisant le bouton ci-dessous.</string>\r\n    <string name=\"empty_view_no_classes_today_title\">Pas de classes aujourd’hui</string>\r\n    <string name=\"empty_view_no_classes_today_summary\">Vous n’avez pas de classe planifiée aujourd\\'hui.</string>\r\n    <string name=\"empty_view_no_classes_tomorrow_title\">Pas de classes demain</string>\r\n    <string name=\"empty_view_no_classes_tomorrow_summary\">Vous n’avez pas de classe planifiée demain.</string>\r\n    <string name=\"empty_view_no_tasks_title\">Aucune tâche en cours</string>\r\n    <string name=\"empty_view_no_tasks_summary\">Vous n’avez aucune tâche en cours. Si vous en avez une, ajoutez-la en utilisant le bouton ci-dessus.</string>\r\n    <string name=\"empty_view_no_finished_title\">Aucune tâche terminée</string>\r\n    <string name=\"empty_view_no_finished_summary\">Vous n’avez actuellement aucune tâche terminée. Vous retrouverez toutes les tâches marquées comme terminées ici.</string>\r\n    <string name=\"empty_view_no_logs_title\">Aucun journal enregistré</string>\r\n    <string name=\"empty_view_no_logs_summary\">Dès qu’une tâche, un événement ou un rappel est affiché dans votre volet de notifications, il apparaîtra également ici.</string>\r\n    <string name=\"empty_view_no_events_title\">Aucun événement planifié</string>\r\n    <string name=\"empty_view_no_events_summary\">Vous n’avez actuellement aucun événement planifié. Vous pouvez en ajouter un en utilisant le bouton ci-dessous.</string>\r\n    <string name=\"empty_view_no_previous_title\">Aucun événement antérieur</string>\r\n    <string name=\"empty_view_no_previous_summary\">Vous n’avez actuellement aucun événement antérieur. Vous retrouverez ici tous les éléments dont la date est dépassée.</string>\r\n    <string name=\"empty_view_no_archived_tasks\">Aucune tâche archivée</string>\r\n    <string name=\"empty_view_no_archived_events\">Aucun événement archivé</string>\r\n    <string name=\"empty_view_no_archived_subjects\">Aucune matière archivée</string>\r\n\r\n    <string name=\"days_of_week_item_sunday\">Dimanche</string>\r\n    <string name=\"days_of_week_item_monday\">Lundi</string>\r\n    <string name=\"days_of_week_item_tuesday\">Mardi</string>\r\n    <string name=\"days_of_week_item_wednesday\">Mercredi</string>\r\n    <string name=\"days_of_week_item_thursday\">Jeudi</string>\r\n    <string name=\"days_of_week_item_friday\">Vendredi</string>\r\n    <string name=\"days_of_week_item_saturday\">Samedi</string>\r\n\r\n    <string name=\"days_of_week_item_sunday_short\">Dim</string>\r\n    <string name=\"days_of_week_item_monday_short\">Lun</string>\r\n    <string name=\"days_of_week_item_tuesday_short\">Mar</string>\r\n    <string name=\"days_of_week_item_wednesday_short\">Mer</string>\r\n    <string name=\"days_of_week_item_thursday_short\">Jeu</string>\r\n    <string name=\"days_of_week_item_friday_short\">Ven</string>\r\n    <string name=\"days_of_week_item_saturday_short\">Sam</string>\r\n\r\n    <string name=\"weeks_of_month_item_week_1\">Semaine 1</string>\r\n    <string name=\"weeks_of_month_item_week_2\">Semaine 2</string>\r\n    <string name=\"weeks_of_month_item_week_3\">Semaine 3</string>\r\n    <string name=\"weeks_of_month_item_week_4\">Semaine 4</string>\r\n\r\n    <string name=\"dialog_assign_subject\">Attribuer une matière</string>\r\n    <string name=\"dialog_pick_start_time\">Choisir une heure de début</string>\r\n    <string name=\"dialog_pick_end_time\">Choisir une heure de fin</string>\r\n    <string name=\"dialog_pick_color_tag\">Choisir une couleur pour l’indicateur</string>\r\n    <string name=\"dialog_select_notification_interval\">Sélectionner un intervalle de notification</string>\r\n    <string name=\"dialog_choose_theme\">Choisir un thème</string>\r\n    <string name=\"dialog_choose_backup\">Choisir un fichier de sauvegarde</string>\r\n    <string name=\"dialog_confirm_deletion_title\">Voulez-vous supprimer \\\"%1$s\\\" ?</string>\r\n    <string name=\"dialog_confirm_deletion_summary\">Une fois supprimé, il ne pourra plus être récupéré.</string>\r\n    <string name=\"dialog_confirm_unarchive_title\">Supprimer des archives ?</string>\r\n    <string name=\"dialog_confirm_unarchive_summary\">Vous pouvez toujours glisser vers la gauche pour l\\'archiver à nouveau.</string>\r\n    <string name=\"dialog_import_attachment_title\">Importer la pièce jointe ?</string>\r\n    <string name=\"dialog_import_attachment_summary\">De nouvelles restrictions imposées par le système Android obligent l\\'application à copier le fichier dans son propre répertoire de données. Continuer ?</string>\r\n    <string name=\"dialog_import_attachment_confirm\">Ne plus demander</string>\r\n    <string name=\"dialog_schedule_details\">Détails des horaires</string>\r\n    <string name=\"dialog_discard_changes\">Annuler les modifications ?</string>\r\n    <string name=\"dialog_select_file_import\">Sélectionner un fichier à importer</string>\r\n    <string name=\"dialog_send_to\">Envoyer à</string>\r\n    <string name=\"dialog_sharing_options\">Paramètres de partage</string>\r\n    <string name=\"dialog_class_schedules\">Horaires des classes</string>\r\n    <string name=\"dialog_filter_options\">Paramètres de filtre</string>\r\n    <string name=\"dialog_new_attachment\">Nouvelle pièce jointe</string>\r\n    <string name=\"dialog_attachment_name\">@string/field_attachment_name</string>\r\n    <string name=\"dialog_enter_website_url\">Saisissez l’URL du site Web</string>\r\n    <string name=\"dialog_sorting\">Tri</string>\r\n    <string name=\"dialog_permission_needed_title\">Permission de stockage requise</string>\r\n    <string name=\"dialog_permission_needed_summary\">Pour joindre un fichier depuis votre appareil, vous devez accorder la permission de stockage à l\\'application.</string>\r\n\r\n    <string name=\"attachment_type_import_file\">Importer le fichier</string>\r\n    <string name=\"attachment_type_website_url\">URL du site Web</string>\r\n\r\n    <string name=\"sorting_directions_ascending\">Croissant</string>\r\n    <string name=\"sorting_directions_descending\">Décroissant</string>\r\n\r\n    <string name=\"filter_options_all\">Tous</string>\r\n    <string name=\"filter_options_pending_tasks\">En cours uniquement</string>\r\n    <string name=\"filter_options_finished_tasks\">Terminé uniquement</string>\r\n    m\r\n    <string name=\"filter_options_today_classes\">Aujourd\\'hui uniquement</string>\r\n    <string name=\"filter_options_tomorrow_classes\">Hier uniquement</string>\r\n\r\n    <string name=\"field_subject_code\">Code de la matière</string>\r\n    <string name=\"field_description\">Description</string>\r\n    <string name=\"field_days_of_week\">Jours de la semaine</string>\r\n    <string name=\"field_weeks_of_month\">Semaines du mois</string>\r\n    <string name=\"field_start_time\">Heure de début</string>\r\n    <string name=\"field_end_time\">Heure de fin</string>\r\n    <string name=\"field_task_name\">Nom de la tâche</string>\r\n    <string name=\"field_notes\">Notes</string>\r\n    <string name=\"field_subject\">Matière</string>\r\n    <string name=\"field_due_date\">Date d\\'échéance</string>\r\n    <string name=\"field_event_name\">Nom de l’événement</string>\r\n    <string name=\"field_schedule\">Planning</string>\r\n    <string name=\"field_location\">Lieu</string>\r\n    <string name=\"field_attachments\">Pièces jointes</string>\r\n    <string name=\"field_class_time\">Horaire de la classe</string>\r\n    <string name=\"field_color\">Couleur de l’indicateur</string>\r\n    <string name=\"field_priority\">Priorité</string>\r\n    <string name=\"field_status\">Statut</string>\r\n    <string name=\"field_not_set\">Non configuré</string>\r\n    <string name=\"field_due_in_the_next_meeting\">Lors du prochain rendez-vous</string>\r\n    <string name=\"field_due_pick_from_schedule\">Choisir dans les horaires des classes</string>\r\n    <string name=\"field_due_custom\">Personnalisé</string>\r\n    <string name=\"field_attachment_name\">Nom de la pièce jointe</string>\r\n    <string name=\"field_instructor\">Instructeur</string>\r\n    <string name=\"field_classroom\">Salle de classe</string>\r\n\r\n    <string name=\"hint_subject_description\">Le nom de la matière</string>\r\n    <string name=\"hint_task_notes\">Quelques idées ou détails mineurs concernant la dernière tâche</string>\r\n    <string name=\"hint_event_location\">Saisir une salle, un bâtiment ou un lieu</string>\r\n    <string name=\"hint_event_notes\">Quelques idées ou détails mineurs concernant le dernier événement</string>\r\n\r\n    <string name=\"feedback_subject_removed\">Matière supprimée</string>\r\n    <string name=\"feedback_log_removed\">Journal supprimé</string>\r\n    <string name=\"feedback_task_removed\">Tâche supprimée</string>\r\n    <string name=\"feedback_schedule_removed\">Horaire supprimé</string>\r\n    <string name=\"feedback_attachment_added\">Pièce jointe ajoutée</string>\r\n    <string name=\"feedback_attachment_removed\">Pièce jointe supprimée</string>\r\n    <string name=\"feedback_event_removed\">Événement supprimé</string>\r\n    <string name=\"feedback_task_marked_as_finished\">Tâche marquée comme terminée</string>\r\n    <string name=\"feedback_task_marked_as_pending\">Tâche marquée comme en cours</string>\r\n    <string name=\"feedback_subject_empty_name\">Vous avez oublié de saisir le code de la matière</string>\r\n    <string name=\"feedback_subject_empty_description\">Vous avez oublié de saisir la description</string>\r\n    <string name=\"feedback_subject_no_schedule\">Vous avez oublié d’ajouter un horaire</string>\r\n    <string name=\"feedback_schedule_empty_days\">Vous n’avez pas précisé les jours</string>\r\n    <string name=\"feedback_schedule_empty_start_time\">Vous n’avez pas précisé l’heure de début</string>\r\n    <string name=\"feedback_schedule_empty_end_time\">Vous n’avez pas précisé l’heure de fin</string>\r\n    <string name=\"feedback_task_empty_name\">Vous avez oublié de saisir le nom de la tâche</string>\r\n    <string name=\"feedback_task_empty_due_date\">Vous avez oublié de saisir la date d’échéance</string>\r\n    <string name=\"feedback_event_empty_name\">Vous avez oublié de saisir le nom de l’événement</string>\r\n    <string name=\"feedback_event_empty_location\">Vous avez oublié de saisir le lieu</string>\r\n    <string name=\"feedback_event_empty_schedule\">Vous avez oublié de saisir l’horaire</string>\r\n    <string name=\"feedback_restore_invalid\">Le fichier de sauvegarde n’est pas valide.</string>\r\n    <string name=\"feedback_restore_corrupted\">Le fichier de sauvegarde est corrompu ou ne peut pas être lu.</string>\r\n    <string name=\"feedback_backup_empty\">Il n’y a rien à sauvegarder.</string>\r\n    <string name=\"feedback_backup_failed\">Le processus de sauvegarde a rencontré une erreur.</string>\r\n    <string name=\"feedback_import_ongoing\">Importation en cours</string>\r\n    <string name=\"feedback_import_completed\">Importation terminée</string>\r\n    <string name=\"feedback_import_failed\">Échec de l’importation</string>\r\n    <string name=\"feedback_export_ongoing\">Exportation en cours</string>\r\n    <string name=\"feedback_export_completed\">Exportation terminée</string>\r\n    <string name=\"feedback_export_failed\">Échec de l’exportation</string>\r\n    <string name=\"feedback_unable_to_share_title\">Impossible de partager</string>\r\n    <string name=\"feedback_unable_to_share_message\">Aucune information valide ne peut être partagée</string>\r\n    <string name=\"feedback_subject_code_exists\">Un événement avec le même horaire existe déjà.</string>\r\n    <string name=\"feedback_schedule_exists\">Un horaire entre en conflit avec un autre horaire.</string>\r\n    <string name=\"feedback_task_name_exists\">Une tâche portant ce nom existe déjà.</string>\r\n    <string name=\"feedback_event_name_exists\">Un événement portant ce nom existe déjà.</string>\r\n    <string name=\"feedback_event_schedule_exists\">Un événement avec le même horaire existe déjà.</string>\r\n\r\n    <string name=\"settings_group_interface\">Interface</string>\r\n    <string name=\"settings_group_sound\">Son</string>\r\n    <string name=\"settings_group_notification\">Notifications</string>\r\n    <string name=\"settings_group_advanced\">Avancé</string>\r\n    <string name=\"settings_group_debugging\">Débogage</string>\r\n    <string name=\"settings_group_contribute\">Contribuer</string>\r\n\r\n    <string name=\"settings_theme\">Thème</string>\r\n    <string name=\"settings_theme_item_system\">Valeur par défaut du système</string>\r\n    <string name=\"settings_theme_item_dark\">Sombre</string>\r\n    <string name=\"settings_theme_item_light\">Clair</string>\r\n    <string name=\"settings_confetti_title\">Confetti</string>\r\n    <string name=\"settings_confetti_summary\">Afficher des confettis lorsque des tâches passent à l\\'état terminé.</string>\r\n\r\n    <string name=\"settings_completion_sounds_title\">Effets sonores de félicitations</string>\r\n    <string name=\"settings_completion_sounds_summary\">Jouer un son lorsqu’une tâche passe à l\\'état terminé.</string>\r\n\r\n    <string name=\"settings_reminder_frequency_title\">Fréquence des rappels</string>\r\n    <string name=\"settings_reminder_frequency_item_everyday\">Quotidienne</string>\r\n    <string name=\"settings_reminder_frequency_item_weekends\">Weekend</string>\r\n    <string name=\"settings_remind_me_in_time_of_day\">Rappelez-moi à ce moment</string>\r\n    <string name=\"settings_when_nearing_due_title\">Lorsqu’une tâche approche son échéance</string>\r\n    <string name=\"settings_when_nearing_due_summary\">Afficher les notifications pour les tâches approchant leur échéance</string>\r\n    <string name=\"settings_task_reminders\">Intervalle de rappel pour les tâches</string>\r\n    <string name=\"settings_task_reminders_item_hour\">1 heure avant</string>\r\n    <string name=\"settings_task_reminders_item_three_hours\">3 heures avant</string>\r\n    <string name=\"settings_task_reminders_item_day\">1 jour avant</string>\r\n    <string name=\"settings_incoming_events_title\">Événements à venir</string>\r\n    <string name=\"settings_incoming_events_summary\">Afficher les notifications pour les événements du jour à venir</string>\r\n    <string name=\"settings_event_reminders\">Intervalle de rappel pour les événements</string>\r\n    <string name=\"settings_event_reminders_item_quarter_hour\">15 minutes avant</string>\r\n    <string name=\"settings_event_reminders_item_half_hour\">30 minutes avant</string>\r\n    <string name=\"settings_event_reminders_item_hour\">@string/settings_task_reminders_item_hour</string>\r\n    <string name=\"settings_classes_for_this_day_title\">Classes aujourd\\'hui</string>\r\n    <string name=\"settings_classes_for_this_day_summary\">Afficher les notifications pour mes matières du jour</string>\r\n    <string name=\"settings_class_reminders\">Intervalle de rappel pour les classes</string>\r\n    <string name=\"settings_class_reminders_item_5_minutes\">5 minutes avant</string>\r\n    <string name=\"settings_class_reminders_item_15_minutes\">@string/settings_event_reminders_item_quarter_hour</string>\r\n    <string name=\"settings_class_reminders_item_30_minutes\">@string/settings_event_reminders_item_half_hour</string>\r\n    <string name=\"settings_more_notification_settings\">Plus de paramètres</string>\r\n\r\n    <string name=\"settings_allow_week_numbers_title\">Activer les numéros de semaine</string>\r\n    <string name=\"settings_allow_week_numbers_summary\">Afficher les numéros de semaine lors de la configuration des horaires.</string>\r\n    <string name=\"settings_backup_and_restore\">@string/activity_backup</string>\r\n    <string name=\"settings_backup\">Sauvegarde</string>\r\n    <string name=\"settings_backup_summary_no_previous\">Pas de sauvegarde antérieure</string>\r\n    <string name=\"settings_restore\">Restaurer</string>\r\n    <string name=\"settings_use_external_browser_title\">Ouvrir les liens dans un navigateur externe</string>\r\n    <string name=\"settings_use_external_browser_summary\">Utiliser la valeur par défaut du système pour gérer les liens</string>\r\n\r\n    <string name=\"settings_not_working_notifications\">@string/button_learn_more</string>\r\n    <string name=\"settings_not_working_notifications_info\">Les notifications pourraient ne pas s’afficher à cause de l’optimisation de l’utilisation de la batterie du fabricant de votre téléphone.</string>\r\n\r\n    <string name=\"settings_translate\">Traduire</string>\r\n    <string name=\"settings_report_an_issue\">Signaler un problème</string>\r\n    <string name=\"settings_third_party_notices\">@string/activity_notices</string>\r\n    <string name=\"settings_build_version\">Construire une version</string>\r\n\r\n    <string name=\"color_sky\">Ciel</string>\r\n    <string name=\"color_grass\">Gazon</string>\r\n    <string name=\"color_sunset\">Coucher de soleil</string>\r\n    <string name=\"color_lemon\">Citron</string>\r\n    <string name=\"color_sea\">Mer</string>\r\n    <string name=\"color_grape\">Raisin</string>\r\n    <string name=\"color_cherry\">Cerise</string>\r\n    <string name=\"color_coral\">Corail</string>\r\n    <string name=\"color_midnight\">Minuit</string>\r\n    <string name=\"color_mint\">Menthe</string>\r\n    <string name=\"color_lavender\">Lavande</string>\r\n    <string name=\"color_graphite\">Graphite</string>\r\n\r\n    <string name=\"widget_task_name\">Widget des tâches</string>\r\n    <string name=\"widget_task_title\">Tâches</string>\r\n    <string name=\"widget_task_empty\">Vous n’avez aucune tâche aujourd\\'hui</string>\r\n    <string name=\"widget_event_name\">Widget des événements</string>\r\n    <string name=\"widget_event_title\">Événements</string>\r\n    <string name=\"widget_event_empty\">Vous n’avez aucun événement aujourd\\'hui</string>\r\n    <string name=\"widget_class_name\">Widget des classes</string>\r\n    <string name=\"widget_class_title\">Classes</string>\r\n    <string name=\"widget_class_empty\">Vous n’avez aucune classe aujourd\\'hui</string>\r\n\r\n    <!-- Helper Text -->\r\n    <string name=\"helper_this_is_important\">Marquer ceci comme important permettra d’afficher une notification persistante dans votre volet de notifications.</string><!-- Notifications --><string name=\"notification_channel_group_reminders\">Rappels</string>\r\n\r\n    <string name=\"notification_channel_general\">Général</string>\r\n    <string name=\"notification_channel_task_reminders\">Rappels pour les tâches</string>\r\n    <string name=\"notification_channel_event_reminders\">Rappels pour les événements</string>\r\n    <string name=\"notification_channel_class_reminders\">Rappels pour les classes</string>\r\n\r\n    <string name=\"notification_pending_tasks_title\">Vous avez %1$d tâches en cours</string>\r\n    <string name=\"notification_pending_tasks_summary\">Jetez-y donc un œil !</string>\r\n\r\n    <string name=\"notification_backup_ongoing\">Sauvegarde en cours</string>\r\n    <string name=\"notification_backup_error\">Échec de la sauvegarde</string>\r\n    <string name=\"notification_backup_success\">Sauvegarde terminée</string>\r\n\r\n    <string name=\"notification_restore_ongoing\">Restauration de la sauvegarde</string>\r\n    <string name=\"notification_restore_error\">Échec de la restauration</string>\r\n    <string name=\"notification_restore_success\">Restauration terminée</string>\r\n\r\n    <!-- System -->\r\n    <string name=\"sharing_attach_to_task\">Ajouter comme pièce jointe</string>\r\n\r\n    <!-- Greetings -->\r\n    <string name=\"greeting_default\">Bonne journée !</string>\r\n    <string name=\"greeting_morning\">Bonjour !</string>\r\n    <string name=\"greeting_afternoon\">Bonjour !</string>\r\n    <string name=\"greeting_evening\">Bonsoir !</string>\r\n\r\n    <!-- used for concat and formatting -->\r\n    <string name=\"and\"> et </string>\r\n    <string name=\"yesterday_at\">Hier à %1$s</string>\r\n    <string name=\"yesterday\">Hier</string>\r\n    <string name=\"tomorrow_at\">Demain à %1$s</string>\r\n    <string name=\"tomorrow\">Demain</string>\r\n    <string name=\"today_at\">Aujourd’hui à %1$s</string>\r\n    <string name=\"today\">Aujourd’hui</string>\r\n    <string name=\"due_today_at\">Prévu aujourd’hui à %1$s</string>\r\n    <string name=\"due_tomorrow_at\">Prévu demain à %1$s</string>\r\n    <string name=\"due_at\">Due à %1$s</string>\r\n\r\n    <string name=\"open_source_libraries\">Bibliothèques open source</string>\r\n    <string name=\"credit_other_resources\">Autres ressources</string>\r\n    <string name=\"credit_notification_sound_title\" translatable=\"false\">Zapsplat</string>\r\n    <string name=\"credit_notification_sound_summary\">Son de notification</string>\r\n    <string name=\"credit_launcher_icon_title\" translatable=\"false\">Freepik</string>\r\n    <string name=\"credit_launcher_icon_summary\">Icône de lancement</string>\r\n    <string name=\"credit_user_interface_icons_title\" translatable=\"false\">Tailwind Labs</string>\r\n    <string name=\"credit_user_interface_icons_summary\">Icônes de l’interface utilisateur</string>\r\n\r\n</resources>"
  },
  {
    "path": "app/src/main/res/values-hdpi/dimen.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n\r\n    <!-- Widget -->\r\n    <dimen name=\"widget_title\">20sp</dimen>\r\n    <dimen name=\"widget_title_padding\">16sp</dimen>\r\n    <dimen name=\"widget_item_text_title\">18sp</dimen>\r\n    <dimen name=\"widget_item_tag_padding_end\">16dp</dimen>\r\n    <dimen name=\"widget_empty_text_padding\">16dp</dimen>\r\n\r\n</resources>"
  },
  {
    "path": "app/src/main/res/values-id/strings.xml",
    "content": "<resources>\n    <string translatable=\"false\" name=\"app_name\">Fokus</string>\n\n    <string name=\"shortcut_add_task\">@string/button_add_task</string>\n    <string name=\"shortcut_add_event\">@string/button_add_event</string>\n    <string name=\"shortcut_add_subject\">@string/button_add_subject</string>\n\n    <string name=\"activity_tasks\">Tugas Anda</string>\n    <string name=\"activity_tasks_pending\">Tugas Tertunda</string>\n    <string name=\"activity_tasks_finished\">Tugas Selesai</string>\n    <string name=\"activity_subjects\">Subjek Anda</string>\n    <string name=\"activity_subjects_today\">Subjek Anda Hari Ini</string>\n    <string name=\"activity_subjects_tomorrow\">Subjek Anda Besok</string>\n    <string name=\"activity_archives\">Item Anda yang Diarsipkan</string>\n    <string name=\"activity_logs\">Log Pemberitahuan</string>\n    <string name=\"activity_settings\">Pengaturan</string>\n    <string name=\"activity_backup\">Cadangkan dan Pulihkan</string>\n    <string name=\"activity_notices\">Pemberitahuan Pihak Ketiga</string>\n    <string name=\"activity_open_source_licenses\">Lisensi Sumber Terbuka</string>\n    <string name=\"activity_about\">Tentang</string>\n\n    <string name=\"menu_add\">@string/button_add</string>\n    <string name=\"menu_more\">Lainnya</string>\n    <string name=\"menu_sort\">Menyortir</string>\n    <string name=\"menu_filter\">Saring</string>\n    <string name=\"menu_share\">Bagikan</string>\n    <string name=\"menu_import\">Impor</string>\n    <string name=\"menu_clear_items\">Hapus Log</string>\n    <string name=\"menu_export_to_file\">Ekspor ke file</string>\n    <string name=\"menu_share_directly\">Bagikan langsung</string>\n    <string name=\"menu_archived\">Arsip</string>\n\n    <string name=\"navigation_tasks\">Tugas</string>\n    <string name=\"navigation_events\">Acara</string>\n    <string name=\"navigation_subjects\">Subjek</string>\n    <string name=\"navigation_home\">Beranda</string>\n    <string name=\"navigation_logs\">Log</string>\n    <string name=\"navigation_settings\">@string/activity_settings</string>\n    <string name=\"navigation_about\">@string/activity_about</string>\n\n    <string name=\"button_add_task\">Tambah tugas</string>\n    <string name=\"button_add_event\">Tambah acara</string>\n    <string name=\"button_add_subject\">Tambah subjek</string>\n    <string name=\"button_add\">Tambah</string>\n    <string name=\"button_new\">Baru</string>\n    <string name=\"button_save\">Simpan</string>\n    <string name=\"button_done\">Selesai</string>\n    <string name=\"button_undo\">Undo</string>\n    <string name=\"button_remove\">Hapus</string>\n    <string name=\"button_continue\">Lanjut</string>\n    <string name=\"button_mark_as_finished\">Tandai selesai</string>\n    <string name=\"button_mark_as_important\">Tandai penting</string>\n    <string name=\"button_delete\">Hapus</string>\n    <string name=\"button_cancel\">Batal</string>\n    <string name=\"button_discard\">Batal</string>\n    <string name=\"button_dismiss\">Batal</string>\n    <string name=\"button_learn_more\">Pelajari lebih lanjut</string>\n    <string name=\"button_view_schedules\">Lihat Jadwal</string>\n\n    <string name=\"empty_view_no_subjects_title\">Tidak Ada Subjek yang Ditambahkan</string>\n    <string name=\"empty_view_no_subjects_summary\">Subjek membantu mengurutkan tugas dan acara Anda, Jika ada, tambahkan menggunakan tombol di bawah ini.</string>\n    <string name=\"empty_view_no_classes_today_title\">Tidak Ada Kelas untuk Hari Ini</string>\n    <string name=\"empty_view_no_classes_today_summary\">Anda tidak memiliki kelas yang dijadwalkan untuk hari ini.</string>\n    <string name=\"empty_view_no_classes_tomorrow_title\">Tidak Ada Kelas untuk Besok</string>\n    <string name=\"empty_view_no_classes_tomorrow_summary\">Anda tidak memiliki jadwal kelas untuk besok.</string>\n    <string name=\"empty_view_no_tasks_title\">Tidak Ada Tugas yang Menunggu Keputusan</string>\n    <string name=\"empty_view_no_tasks_summary\">Saat ini Anda tidak memiliki tugas yang menunggu keputusan. Jika Anda punya, tambahkan menggunakan tombol di bawah.</string>\n    <string name=\"empty_view_no_finished_title\">Tidak Ada Tugas yang Selesai</string>\n    <string name=\"empty_view_no_finished_summary\">Saat ini Anda tidak memiliki tugas yang sudah selesai. Setiap tugas yang Anda tandai sebagai selesai akan ditampilkan di sini.</string>\n    <string name=\"empty_view_no_logs_title\">Tidak Ada Log Terekam</string>\n    <string name=\"empty_view_no_logs_summary\">Setelah tugas, acara, atau pengingat apa pun muncul di bayangan pemberitahuan Anda, itu juga akan muncul di sini.</string>\n    <string name=\"empty_view_no_events_title\">Tidak Ada Acara Terjadwal</string>\n    <string name=\"empty_view_no_events_summary\">Saat ini Anda tidak memiliki acara terjadwal. Jika Anda punya, tambahkan menggunakan tombol di bawah.</string>\n    <string name=\"empty_view_no_previous_title\">Tidak Ada Acara Sebelumnya</string>\n    <string name=\"empty_view_no_previous_summary\">Saat ini Anda tidak memiliki acara sebelumnya. Setiap acara yang melewati jadwalnya akan muncul di sini</string>\n    <string name=\"empty_view_no_archived_tasks\">Tidak Ada Tugas yang Diarsipkan</string>\n    <string name=\"empty_view_no_archived_events\">Tidak Ada Acara yang Diarsipkan</string>\n    <string name=\"empty_view_no_archived_subjects\">Tidak Ada Subjek yang Diarsipkan</string>\n\n    <string name=\"days_of_week_item_sunday\">Minggu</string>\n    <string name=\"days_of_week_item_monday\">Senin</string>\n    <string name=\"days_of_week_item_tuesday\">Selasa</string>\n    <string name=\"days_of_week_item_wednesday\">Rabu</string>\n    <string name=\"days_of_week_item_friday\">Jumat</string>\n    <string name=\"days_of_week_item_saturday\">Sabtu</string>\n\n    <string name=\"days_of_week_item_sunday_short\">Min</string>\n    <string name=\"days_of_week_item_monday_short\">Sen</string>\n    <string name=\"days_of_week_item_tuesday_short\">Sel</string>\n    <string name=\"days_of_week_item_wednesday_short\">Rab</string>\n    <string name=\"days_of_week_item_thursday_short\">Kam</string>\n    <string name=\"days_of_week_item_friday_short\">Jum</string>\n    <string name=\"days_of_week_item_saturday_short\">Sab</string>\n\n    <string name=\"weeks_of_month_item_week_1\">Minggu 1</string>\n    <string name=\"weeks_of_month_item_week_2\">Minggu 2</string>\n    <string name=\"weeks_of_month_item_week_3\">Minggu 3</string>\n    <string name=\"weeks_of_month_item_week_4\">Minggu 4</string>\n\n    <string name=\"dialog_assign_subject\">Tetapkan Subjek</string>\n    <string name=\"dialog_pick_start_time\">Pilih Waktu Mulai</string>\n    <string name=\"dialog_pick_end_time\">Pilih Waktu Berakhir</string>\n    <string name=\"dialog_pick_color_tag\">Pilih label warna</string>\n    <string name=\"dialog_select_notification_interval\">Pilih interval pemberitahuan</string>\n    <string name=\"dialog_choose_theme\">Pilih tema</string>\n    <string name=\"dialog_choose_backup\">Pilih file cadangan</string>\n    <string name=\"dialog_confirm_deletion_title\">Apakah Anda ingin menghapus \\\"%1$s\\\"?</string>\n    <string name=\"dialog_confirm_deletion_summary\">Setelah item ini dihapus, item tersebut tidak dapat dipulihkan.</string>\n    <string name=\"dialog_confirm_unarchive_title\">Hapus dari arsip?</string>\n    <string name=\"dialog_confirm_unarchive_summary\">Anda selalu dapat menggeser ke kiri untuk mengarsipkan item ini lagi.</string>\n    <string name=\"dialog_import_attachment_title\">Impor lampiran?</string>\n    <string name=\"dialog_import_attachment_summary\">Aplikasi harus menyalin file ke folder datanya sendiri karena batasan terbaru yang diberlakukan oleh sistem Android. Lanjutkan?</string>\n    <string name=\"dialog_import_attachment_confirm\">Jangan tanya lagi</string>\n    <string name=\"dialog_schedule_details\">Detail Jadwal</string>\n    <string name=\"dialog_discard_changes\">Membuang perubahan?</string>\n    <string name=\"dialog_select_file_import\">Pilih file untuk diimpor</string>\n    <string name=\"dialog_send_to\">Kirim ke</string>\n    <string name=\"dialog_sharing_options\">Opsi berbagi</string>\n    <string name=\"dialog_class_schedules\">Jadwal Kelas</string>\n    <string name=\"dialog_filter_options\">Opsi Filter</string>\n    <string name=\"dialog_new_attachment\">Lampiran Baru</string>\n    <string name=\"dialog_attachment_name\">@string/field_attachment_name</string>\n    <string name=\"dialog_enter_website_url\">Masukkan URL Situs Web</string>\n    <string name=\"dialog_sorting\">Penyortiran</string>\n    <string name=\"dialog_permission_needed_title\">Izin Penyimpanan diperlukan</string>\n    <string name=\"dialog_permission_needed_summary\">Untuk melampirkan file dari perangkat Anda, aplikasi memerlukan izin penyimpanan yang akan diberikan.</string>\n\n    <string name=\"attachment_type_import_file\">Impor file</string>\n    <string name=\"attachment_type_website_url\">URL Situs Web</string>\n\n    <string name=\"sorting_directions_ascending\">Menaik</string>\n    <string name=\"sorting_directions_descending\">Menurun</string>\n\n    <string name=\"filter_options_all\">Semua</string>\n    <string name=\"filter_options_pending_tasks\">Tertunda saja</string>\n    <string name=\"filter_options_finished_tasks\">Selesai saja</string>\n    <string name=\"filter_options_today_classes\">Hari ini saja</string>\n    <string name=\"filter_options_tomorrow_classes\">Besok saja</string>\n\n    <string name=\"field_subject_code\">Kode Subjek</string>\n    <string name=\"field_description\">Deskripsi</string>\n    <string name=\"field_days_of_week\">Hari dalam seminggu</string>\n    <string name=\"field_weeks_of_month\">Minggu dalam sebulan</string>\n    <string name=\"field_start_time\">Waktu Mulai</string>\n    <string name=\"field_end_time\">Waktu Akhir</string>\n    <string name=\"field_task_name\">Nama Tugas</string>\n    <string name=\"field_notes\">Catatan</string>\n    <string name=\"field_subject\">Subjek</string>\n    <string name=\"field_due_date\">Tenggat Waktu</string>\n    <string name=\"field_event_name\">Nama Acara</string>\n    <string name=\"field_schedule\">Jadwal</string>\n    <string name=\"field_location\">Lokasi</string>\n    <string name=\"field_attachments\">Lampiran</string>\n    <string name=\"field_class_time\">Waktu Kelas</string>\n    <string name=\"field_color\">Label Warna</string>\n    <string name=\"field_priority\">Prioritas</string>\n    <string name=\"field_status\">Status</string>\n    <string name=\"field_not_set\">Tidak diatur</string>\n    <string name=\"field_due_in_the_next_meeting\">Dalam pertemuan berikutnya</string>\n    <string name=\"field_due_pick_from_schedule\">Pilih dari jadwal kelas</string>\n    <string name=\"field_due_custom\">Kustom</string>\n    <string name=\"field_attachment_name\">Nama lampiran</string>\n    <string name=\"field_instructor\">Instruktur</string>\n    <string name=\"field_classroom\">Ruang Kelas</string>\n\n    <string name=\"hint_subject_description\">Nama subjek</string>\n    <string name=\"hint_task_notes\">Beberapa ide atau detail kecil tentang tugas</string>\n    <string name=\"hint_event_location\">Masuki ruangan, gedung, atau tempat mana pun</string>\n    <string name=\"hint_event_notes\">Beberapa ide atau detail kecil tentang acara tersebut</string>\n\n    <string name=\"feedback_subject_removed\">Subjek dihapus</string>\n    <string name=\"feedback_log_removed\">Log dihapus</string>\n    <string name=\"feedback_task_removed\">Tugas dihapus</string>\n    <string name=\"feedback_schedule_removed\">Jadwal dihapus</string>\n    <string name=\"feedback_attachment_added\">Lampiran ditambahkan</string>\n    <string name=\"feedback_attachment_removed\">Lampiran dihapus</string>\n    <string name=\"feedback_event_removed\">Acara dihapus</string>\n    <string name=\"feedback_task_marked_as_finished\">Tugas ditandai sebagai selesai</string>\n    <string name=\"feedback_task_marked_as_pending\">Tugas ditandai sebagai tertunda</string>\n    <string name=\"feedback_subject_empty_name\">Anda lupa memasukkan kode subjek</string>\n    <string name=\"feedback_subject_empty_description\">Anda lupa memasukkan deskripsi</string>\n    <string name=\"feedback_subject_no_schedule\">Anda lupa menambahkan jadwal</string>\n    <string name=\"feedback_schedule_empty_days\">Anda lupa menentukan hari</string>\n    <string name=\"feedback_schedule_empty_start_time\">Anda lupa memasukkan waktu mulai</string>\n    <string name=\"feedback_schedule_empty_end_time\">Anda lupa memasukkan waktu akhir</string>\n    <string name=\"feedback_task_empty_name\">Anda lupa memasukkan nama tugas</string>\n    <string name=\"feedback_task_empty_due_date\">Anda lupa menentukan tanggal jatuh tempo</string>\n    <string name=\"feedback_event_empty_name\">Anda lupa memasukkan nama acara</string>\n    <string name=\"feedback_event_empty_location\">Anda lupa memasukkan lokasi</string>\n    <string name=\"feedback_event_empty_schedule\">Anda lupa memasukkan jadwal</string>\n    <string name=\"feedback_restore_invalid\">File cadangan tidak valid</string>\n    <string name=\"feedback_restore_corrupted\">File cadangan rusak atau tidak dapat dibaca</string>\n    <string name=\"feedback_backup_empty\">Tidak ada item untuk dicadangkan</string>\n    <string name=\"feedback_backup_failed\">Proses pencadangan mengalami kesalahan</string>\n    <string name=\"feedback_import_ongoing\">Impor sedang berlangsung</string>\n    <string name=\"feedback_import_completed\">Impor selesai</string>\n    <string name=\"feedback_import_failed\">Impor gagal</string>\n    <string name=\"feedback_export_ongoing\">Ekspor sedang berlangsung</string>\n    <string name=\"feedback_export_completed\">Ekspor berhasil</string>\n    <string name=\"feedback_export_failed\">Ekspor gagal</string>\n    <string name=\"feedback_unable_to_share_title\">Tidak dapat membagikan</string>\n    <string name=\"feedback_unable_to_share_message\">Tidak ada informasi valid yang dapat dibagikan</string>\n\n    <string name=\"settings_group_interface\">Antarmuka</string>\n    <string name=\"settings_group_sound\">Suara</string>\n    <string name=\"settings_group_notification\">Notifikasi</string>\n    <string name=\"settings_group_advanced\">Lanjutan</string>\n    <string name=\"settings_group_debugging\">Debugging</string>\n    <string name=\"settings_group_contribute\">Kontribusi</string>\n\n    <string name=\"settings_theme\">Tema</string>\n    <string name=\"settings_theme_item_system\">Default sistem</string>\n    <string name=\"settings_theme_item_dark\">Gelap</string>\n    <string name=\"settings_theme_item_light\">Terang</string>\n    <string name=\"settings_confetti_title\">Konfeti</string>\n    <string name=\"settings_confetti_summary\">Tunjukkan konfeti ketika tugas ditandai sebagai selesai</string>\n\n    <string name=\"settings_completion_sounds_title\">Suara Penyelesaian</string>\n    <string name=\"settings_completion_sounds_summary\">Putar suara saat Anda menandai tugas sebagai selesai</string>\n\n    <string name=\"settings_reminder_frequency_title\">Frekuensi pengingat</string>\n    <string name=\"settings_reminder_frequency_item_everyday\">Setiap hari</string>\n    <string name=\"settings_reminder_frequency_item_weekends\">Akhir pekan</string>\n    <string name=\"settings_remind_me_in_time_of_day\">Ingatkan saya saat ini</string>\n    <string name=\"settings_when_nearing_due_title\">Saat tugas hampir jatuh tempo</string>\n    <string name=\"settings_when_nearing_due_summary\">Tampilkan pemberitahuan untuk tugas yang mendekati tenggat waktunya</string>\n    <string name=\"settings_task_reminders\">Interval pengingat tugas</string>\n    <string name=\"settings_task_reminders_item_hour\">Sejam sebelumnya</string>\n    <string name=\"settings_task_reminders_item_three_hours\">3 jam sebelumnya</string>\n    <string name=\"settings_task_reminders_item_day\">1 hari sebelumnya</string>\n    <string name=\"settings_incoming_events_title\">Acara yang akan datang</string>\n    <string name=\"settings_incoming_events_summary\">Tampilkan pemberitahuan tentang acara masuk hari ini</string>\n    <string name=\"settings_event_reminders\">Interval pengingat acara</string>\n    <string name=\"settings_event_reminders_item_quarter_hour\">15 menit sebelumnya</string>\n    <string name=\"settings_event_reminders_item_half_hour\">30 menit sebelumnya</string>\n    <string name=\"settings_event_reminders_item_hour\">@string/settings_task_reminders_item_hour</string>\n    <string name=\"settings_classes_for_this_day_title\">Kelas untuk hari ini</string>\n    <string name=\"settings_classes_for_this_day_summary\">Tampilkan pemberitahuan tentang kelas untuk subjek saya hari ini</string>\n    <string name=\"settings_class_reminders\">Interval pengingat kelas</string>\n    <string name=\"settings_class_reminders_item_5_minutes\">5 menit sebelumnya</string>\n    <string name=\"settings_class_reminders_item_15_minutes\">@string/settings_event_reminders_item_quarter_hour</string>\n    <string name=\"settings_class_reminders_item_30_minutes\">@string/settings_event_reminders_item_half_hour</string>\n    <string name=\"settings_more_notification_settings\">Pengaturan Lainnya</string>\n\n    <string name=\"settings_backup_and_restore\">@string/activity_backup</string>\n    <string name=\"settings_backup\">Cadangan</string>\n    <string name=\"settings_backup_summary_no_previous\">Tidak ada cadangan</string>\n    <string name=\"settings_restore\">Pulihkan</string>\n    <string name=\"settings_use_external_browser_title\">Buka tautan di browser eksternal</string>\n    <string name=\"settings_use_external_browser_summary\">Gunakan browser default sistem untuk menangani hyperlink</string>\n\n    <string name=\"settings_not_working_notifications\">@string/button_learn_more</string>\n    <string name=\"settings_not_working_notifications_info\">Terkadang, pemberitahuan Anda mungkin tidak terpicu karena pengoptimalan baterai yang agresif oleh pabrikan ponsel Anda.</string>\n\n    <string name=\"settings_translate\">Terjemahkan</string>\n    <string name=\"settings_report_an_issue\">Laporkan masalah</string>\n    <string name=\"settings_third_party_notices\">@string/activity_notices</string>\n    <string name=\"settings_build_version\">Versi</string>\n\n    <string name=\"color_sky\">Sky</string>\n    <string name=\"color_grass\">Grass</string>\n    <string name=\"color_sunset\">Sunset</string>\n    <string name=\"color_lemon\">Lemon</string>\n    <string name=\"color_sea\">Sea</string>\n    <string name=\"color_grape\">Grape</string>\n    <string name=\"color_cherry\">Cherry</string>\n    <string name=\"color_coral\">Coral</string>\n    <string name=\"color_midnight\">Midnight</string>\n    <string name=\"color_mint\">Mint</string>\n    <string name=\"color_lavender\">Lavender</string>\n    <string name=\"color_graphite\">Grafit</string>\n\n    <string name=\"widget_task_name\">Widget Tugas</string>\n    <string name=\"widget_task_title\">Tugas</string>\n    <string name=\"widget_task_empty\">Anda tidak ada tugas hari ini</string>\n    <string name=\"widget_event_name\">Widget Acara</string>\n    <string name=\"widget_event_title\">Acara</string>\n    <string name=\"widget_event_empty\">Anda tidak ada acara hari ini</string>\n    <string name=\"widget_class_name\">Widget Kelas</string>\n    <string name=\"widget_class_title\">Kelas</string>\n    <string name=\"widget_class_empty\">Anda tidak ada kelas hari ini</string>\n\n    <!-- Helper Text -->\n    <string name=\"helper_this_is_important\">Menandai ini sebagai penting berarti ini akan menampilkan pemberitahuan terus-menerus di bayangan pemberitahuan Anda.</string>\n\n    <!-- Notifications -->\n    <string name=\"notification_channel_group_reminders\">Pengingat</string>\n\n    <string name=\"notification_channel_general\">Umum</string>\n    <string name=\"notification_channel_task_reminders\">Pengingat Tugas</string>\n    <string name=\"notification_channel_event_reminders\">Pengingat Acara</string>\n    <string name=\"notification_channel_class_reminders\">Pengingat Kelas</string>\n\n    <string name=\"notification_pending_tasks_title\">Anda punya %1$d tugas yang tertunda</string>\n    <string name=\"notification_pending_tasks_summary\">Mungkin layak untuk dilihat</string>\n\n    <string name=\"notification_backup_ongoing\">Melakukan pencadangan</string>\n    <string name=\"notification_backup_error\">Pencadangan gagal</string>\n    <string name=\"notification_backup_success\">Pencadangan selesai</string>\n\n    <string name=\"notification_restore_ongoing\">Memulihkan cadangan</string>\n    <string name=\"notification_restore_error\">Pemulihan gagal</string>\n    <string name=\"notification_restore_success\">Pemulihan selesai</string>\n\n    <!-- System -->\n    <string name=\"sharing_attach_to_task\">Lampirkan pada tugas</string>\n\n    <!-- Greetings -->\n    <string name=\"greeting_default\">Semoga harimu menyenangkan!</string>\n    <string name=\"greeting_morning\">Selamat pagi!</string>\n    <string name=\"greeting_afternoon\">Selamat siang!</string>\n    <string name=\"greeting_evening\">Selamat sore!</string>\n\n    <!-- used for concat and formatting -->\n    <string name=\"and\">&#160;dan&#160;</string>\n    <string name=\"yesterday_at\">Kemarin pukul %1$s</string>\n    <string name=\"yesterday\">Kemarin</string>\n    <string name=\"tomorrow_at\">Besok pukul %1$s</string>\n    <string name=\"tomorrow\">Besok</string>\n    <string name=\"today_at\">Hari ini pukul %1$s</string>\n    <string name=\"today\">Hari ini</string>\n    <string name=\"due_today_at\">\" Tenggat hari ini pukul %1$s\"</string>\n    <string name=\"due_tomorrow_at\">\" Tenggat besok pukul %1$s\"</string>\n    <string name=\"due_at\">Jatuh tempo pada %1$s</string>\n\n    <string name=\"open_source_libraries\">Open Source Libraries</string>\n    <string name=\"credit_other_resources\">Bahan Lainnya</string>\n    <string name=\"credit_notification_sound_title\" translatable=\"false\">Zapsplat</string>\n    <string name=\"credit_notification_sound_summary\">Suara Notifikasi</string>\n    <string name=\"credit_launcher_icon_title\" translatable=\"false\">Freepik</string>\n    <string name=\"credit_launcher_icon_summary\">Ikon Launcher</string>\n    <string name=\"credit_user_interface_icons_title\" translatable=\"false\">Tailwind Labs</string>\n    <string name=\"credit_user_interface_icons_summary\">Ikon Antarmuka Pengguna</string>\n    <string name=\"settings_allow_week_numbers_title\">Aktifkan Nomor Minggu</string>\n    <string name=\"settings_allow_week_numbers_summary\">Tampilkan nomor minggu saat mengonfigurasi jadwal.</string>\n    <string name=\"feedback_event_schedule_exists\">Acara dengan jadwal yang sama sudah ada.</string>\n    <string name=\"feedback_event_name_exists\">Acara dengan nama ini sudah ada.</string>\n    <string name=\"feedback_task_name_exists\">Tugas dengan nama ini sudah ada.</string>\n    <string name=\"feedback_schedule_exists\">Jadwal bentrok dengan jadwal lain.</string>\n    <string name=\"feedback_subject_code_exists\">Subjek dengan kode ini sudah ada.</string>\n    <string name=\"days_of_week_item_thursday\">Kamis</string>\n\n</resources>"
  },
  {
    "path": "app/src/main/res/values-night/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n    <color name=\"theme_primary\">#89ceff</color>\r\n    <color name=\"theme_on_primary\">#89ceff</color>\r\n    <color name=\"theme_primary_container\">#004c6e</color>\r\n    <color name=\"theme_on_primary_container\">#c9e6ff</color>\r\n    <color name=\"theme_secondary\">#a1c9ff</color>\r\n    <color name=\"theme_on_secondary\">#a1c9ff</color>\r\n    <color name=\"theme_secondary_container\">#004880</color>\r\n    <color name=\"theme_on_secondary_container\">#d2e4ff</color>\r\n    <color name=\"theme_tertiary\">#c0c1ff</color>\r\n    <color name=\"theme_on_tertiary\">#1000a9</color>\r\n    <color name=\"theme_tertiary_container\">#2f2ebe</color>\r\n    <color name=\"theme_on_tertiary_container\">#e1e0ff</color>\r\n    <color name=\"theme_error\">#ffb4ab</color>\r\n    <color name=\"theme_on_error\">#690005</color>\r\n    <color name=\"theme_error_container\">#93000a</color>\r\n    <color name=\"theme_on_error_container\">#ffdad6</color>\r\n    <color name=\"theme_background\">#191c1e</color>\r\n    <color name=\"theme_on_background\">#e2e2e5</color>\r\n    <color name=\"theme_surface\">#191c1e</color>\r\n    <color name=\"theme_on_surface\">#e2e2e5</color>\r\n    <color name=\"theme_surface_variant\">#41474d</color>\r\n    <color name=\"theme_on_surface_variant\">#c1c7ce</color>\r\n    <color name=\"theme_outline\">#8b9198</color>\r\n    <color name=\"theme_inverse_on_surface\">#191c1e</color>\r\n    <color name=\"theme_inverse_surface\">#e2e2e5</color>\r\n    <color name=\"theme_inverse_primary\">#006591</color>\r\n    <color name=\"theme_shadow\">#000000</color>\r\n    <color name=\"theme_surface_tint\">#89ceff</color>\r\n    <color name=\"theme_surface_tint_color\">#89ceff</color>\r\n\r\n    <color name=\"color_primary_text\">@color/theme_on_surface</color>\r\n    <color name=\"color_secondary_text\">#808080</color>\r\n\r\n</resources>"
  },
  {
    "path": "app/src/main/res/values-night/themes.xml",
    "content": "<resources>\n\n    <style name=\"Fokus.Theme.Base\" parent=\"Fokus.Theme\">\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n        <item name=\"android:navigationBarColor\">@android:color/transparent</item>\n    </style>\n\n    <style name=\"Fokus.Theme.Core\" parent=\"Fokus.Theme.Base\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n    </style>\n\n    <style name=\"Fokus.Theme.Core.Navigation\">\n        <item name=\"android:navigationBarColor\">@android:color/transparent</item>\n    </style>\n\n    <!-- Components -->\n    <style name=\"Fokus.Component.Viewer\" parent=\"Fokus.Component.Viewer.Bridge\">\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n        <item name=\"android:navigationBarColor\">@android:color/transparent</item>\n    </style>\n    <style name=\"Fokus.Component.BottomSheet\" parent=\"Fokus.Component.BottomSheet.Bridge\">\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n        <item name=\"android:navigationBarColor\">@android:color/transparent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values-night-v23/themes.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <style name=\"Fokus.Theme.Base\" parent=\"Fokus.Theme\">\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n        <item name=\"android:navigationBarColor\">@android:color/transparent</item>\n    </style>\n\n    <style name=\"Fokus.Theme.Core\" parent=\"Fokus.Theme.Base\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n    </style>\n\n    <style name=\"Fokus.Theme.Core.Navigation\">\n        <item name=\"android:navigationBarColor\">@android:color/transparent</item>\n    </style>\n\n    <!-- Components -->\n    <style name=\"Fokus.Component.Viewer\" parent=\"Fokus.Component.Viewer.Bridge\">\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n        <item name=\"android:navigationBarColor\">@android:color/transparent</item>\n        <item name=\"android:windowLightStatusBar\">false</item>\n    </style>\n    <style name=\"Fokus.Component.BottomSheet\" parent=\"Fokus.Component.BottomSheet.Bridge\">\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n        <item name=\"android:navigationBarColor\">@android:color/transparent</item>\n    </style>\n\n</resources>"
  },
  {
    "path": "app/src/main/res/values-night-v27/themes.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <style name=\"Fokus.Theme.Core\" parent=\"Fokus.Theme.Base\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n        <item name=\"android:navigationBarColor\">@android:color/transparent</item>\n    </style>\n\n    <style name=\"Fokus.Theme.Core.Navigation\">\n        <item name=\"android:windowTranslucentNavigation\">false</item>\n        <item name=\"android:navigationBarColor\">@android:color/transparent</item>\n    </style>\n\n    <!-- Components -->\n    <style name=\"Fokus.Component.Viewer\" parent=\"Fokus.Component.Viewer.Bridge\">\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n        <item name=\"android:navigationBarColor\">@android:color/transparent</item>\n        <item name=\"android:windowLightStatusBar\">false</item>\n        <item name=\"android:windowLightNavigationBar\">false</item>\n    </style>\n    <style name=\"Fokus.Component.BottomSheet\" parent=\"Fokus.Component.BottomSheet.Bridge\">\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n        <item name=\"android:navigationBarColor\">@android:color/transparent</item>\n        <item name=\"android:windowLightNavigationBar\">false</item>\n    </style>\n\n</resources>"
  },
  {
    "path": "app/src/main/res/values-ru/strings.xml",
    "content": "<resources>\n\n    <string name=\"shortcut_add_task\">@string/button_add_task</string>\n    <string name=\"shortcut_add_event\">@string/button_add_event</string>\n    <string name=\"shortcut_add_subject\">@string/button_add_subject</string>\n\n    <string name=\"activity_tasks\">Твои Задачи</string>\n    <string name=\"activity_tasks_pending\">Твои Отложенные Задачи</string>\n    <string name=\"activity_tasks_finished\">Ваши Готовые Задачи</string>\n    <string name=\"activity_subjects\">Ваши субъекты</string>\n    <string name=\"activity_subjects_today\">Ваши темы сегодня</string>\n    <string name=\"activity_subjects_tomorrow\">Ваши темы Завтра</string>\n    <string name=\"activity_archives\">Ваши заархивированные предметы</string>\n    <string name=\"activity_logs\">Журналы уведомлений</string>\n    <string name=\"activity_settings\">Настройки</string>\n    <string name=\"activity_backup\">Резервное копирование и восстановление</string>\n    <string name=\"activity_notices\">Уведомления третьих лиц</string>\n    <string name=\"activity_open_source_licenses\">Лицензии с открытым исходным кодом</string>\n    <string name=\"activity_about\">о приложении</string>\n\n    <string name=\"menu_add\">@string/button_add</string>\n    <string name=\"menu_more\">Подробнее</string>\n    <string name=\"menu_sort\">Сортировать</string>\n    <string name=\"menu_filter\">Фильтр</string>\n    <string name=\"menu_share\">Поделиться</string>\n    <string name=\"menu_import\">Импорт</string>\n    <string name=\"menu_clear_items\">Чистые журналы</string>\n    <string name=\"menu_export_to_file\">Экспорт в файл</string>\n    <string name=\"menu_share_directly\">Поделиться напрямую</string>\n    <string name=\"menu_archived\">Архивный</string>\n\n    <string name=\"navigation_tasks\">Задачи</string>\n    <string name=\"navigation_events\">События</string>\n    <string name=\"navigation_subjects\">Предметы</string>\n    <string name=\"navigation_home\">Главная страница</string>\n    <string name=\"navigation_logs\">Журналы</string>\n    <string name=\"navigation_settings\">@string/activity_settings</string>\n    <string name=\"navigation_about\">@string/activity_about</string>\n\n    <string name=\"button_add_task\">Добавить задачу</string>\n    <string name=\"button_add_event\">Добавить Событие</string>\n    <string name=\"button_add_subject\">Добавить Предмет</string>\n    <string name=\"button_add\">Добавить</string>\n    <string name=\"button_new\">Новый сайт</string>\n    <string name=\"button_save\">Сохранить</string>\n    <string name=\"button_done\">Готово</string>\n    <string name=\"button_undo\">Отменить</string>\n    <string name=\"button_remove\">Удалить</string>\n    <string name=\"button_continue\">Продолжать</string>\n    <string name=\"button_mark_as_finished\">Отметить как законченный</string>\n    <string name=\"button_mark_as_important\">Отметить как важный</string>\n    <string name=\"button_delete\">Удалить</string>\n    <string name=\"button_cancel\">Отменить</string>\n    <string name=\"button_discard\">Бросить</string>\n    <string name=\"button_dismiss\">Свободен</string>\n    <string name=\"button_learn_more\">Узнать больше</string>\n    <string name=\"button_view_schedules\">Посмотреть Графики</string>\n\n    <string name=\"empty_view_no_subjects_title\">Не добавлены Субъекты</string>\n    <string name=\"empty_view_no_subjects_summary\">Предметы помогают сортировать ваши задачи и события, Если у вас есть, добавьте его, используя кнопку ниже.</string>\n    <string name=\"empty_view_no_classes_today_title\">Классов на сегодня нет</string>\n    <string name=\"empty_view_no_classes_today_summary\">На сегодня у тебя занятия не запланированы.</string>\n    <string name=\"empty_view_no_classes_tomorrow_title\">Занятия завтра не будут</string>\n    <string name=\"empty_view_no_classes_tomorrow_summary\">У тебя нет расписания занятий на завтра.</string>\n    <string name=\"empty_view_no_tasks_title\">Нет Отложенных Задач</string>\n    <string name=\"empty_view_no_tasks_summary\">В настоящее время у вас нет незавершённых дел. Если оно у вас есть, добавьте его с помощью кнопки ниже.</string>\n    <string name=\"empty_view_no_finished_title\">Нет готовых заданий</string>\n    <string name=\"empty_view_no_finished_summary\">В настоящее время у вас нет законченных заданий. Каждая задача, которую вы отметили как Завершенную, будет показана здесь.</string>\n    <string name=\"empty_view_no_logs_title\">Нет записанных журналов</string>\n    <string name=\"empty_view_no_logs_summary\">Как только задание, событие или любое напоминание появится в тени уведомления, оно также появится здесь.</string>\n    <string name=\"empty_view_no_events_title\">Нет Запланированных событий</string>\n    <string name=\"empty_view_no_events_summary\">В настоящее время у вас нет запланированных мероприятий. Если оно у вас есть, добавьте его с помощью кнопки ниже.</string>\n    <string name=\"empty_view_no_previous_title\">Предыдущие события отсутствуют</string>\n    <string name=\"empty_view_no_previous_summary\">В настоящее время у вас нет никаких предыдущих событий. Каждое событие, прошедшее по расписанию, будет отображаться здесь.</string>\n    <string name=\"empty_view_no_archived_tasks\">Архивных задач нет</string>\n    <string name=\"empty_view_no_archived_events\">Нет архивных событий</string>\n    <string name=\"empty_view_no_archived_subjects\">Нет архивных материалов</string>\n\n    <string name=\"days_of_week_item_sunday\">воскресенье</string>\n    <string name=\"days_of_week_item_monday\">Понедельник</string>\n    <string name=\"days_of_week_item_tuesday\">вторник</string>\n    <string name=\"days_of_week_item_wednesday\">среда</string>\n    <string name=\"days_of_week_item_thursday\">четверг</string>\n    <string name=\"days_of_week_item_friday\">пятница</string>\n    <string name=\"days_of_week_item_saturday\">суббота</string>\n\n    <string name=\"days_of_week_item_sunday_short\">Вск</string>\n    <string name=\"days_of_week_item_monday_short\">Пнд</string>\n    <string name=\"days_of_week_item_tuesday_short\">Втр</string>\n    <string name=\"days_of_week_item_wednesday_short\">Срд</string>\n    <string name=\"days_of_week_item_thursday_short\">Чтв</string>\n    <string name=\"days_of_week_item_friday_short\">Птн</string>\n    <string name=\"days_of_week_item_saturday_short\">Сбт</string>\n\n    <string name=\"weeks_of_month_item_week_1\">1 неделя</string>\n    <string name=\"weeks_of_month_item_week_2\">2 неделя</string>\n    <string name=\"weeks_of_month_item_week_3\">3 неделя</string>\n    <string name=\"weeks_of_month_item_week_4\">4 неделя</string>\n\n    <string name=\"dialog_assign_subject\">Назначить Предмет</string>\n    <string name=\"dialog_pick_start_time\">Выберите время начала</string>\n    <string name=\"dialog_pick_end_time\">Выберите время окончания</string>\n    <string name=\"dialog_pick_color_tag\">Выберите цветной тег</string>\n    <string name=\"dialog_select_notification_interval\">Выберите интервал уведомления</string>\n    <string name=\"dialog_choose_theme\">Выберите тему</string>\n    <string name=\"dialog_choose_backup\">Выберите резервный файл</string>\n    <string name=\"dialog_confirm_deletion_title\">Вы хотите удалить \\ \"%1$s\\\"?</string>\n    <string name=\"dialog_confirm_deletion_summary\">После удаления этот пункт не может быть восстановлен.</string>\n    <string name=\"dialog_confirm_unarchive_title\">Удалить из архивов?</string>\n    <string name=\"dialog_confirm_unarchive_summary\">Вы всегда можете пролистать влево, чтобы заново архивировать этот пункт.</string>\n    <string name=\"dialog_import_attachment_title\">Импортное крепление?</string>\n    <string name=\"dialog_import_attachment_summary\">В связи с недавними ограничениями, наложенными системой Android, приложение должно будет скопировать файл в свою собственную папку данных. Продолжить?</string>\n    <string name=\"dialog_import_attachment_confirm\">Никогда больше не спрашивайте.</string>\n    <string name=\"dialog_schedule_details\">Подробная информация о расписании</string>\n    <string name=\"dialog_discard_changes\">Отбрасывать изменения?</string>\n    <string name=\"dialog_select_file_import\">Выберите файл для импорта</string>\n    <string name=\"dialog_send_to\">Отправить</string>\n    <string name=\"dialog_sharing_options\">Совместное использование опционов</string>\n    <string name=\"dialog_class_schedules\">Графики занятий</string>\n    <string name=\"dialog_filter_options\">Опции фильтра</string>\n    <string name=\"dialog_new_attachment\">Новое приложение</string>\n    <string name=\"dialog_attachment_name\">@string/field_attachment_name</string>\n    <string name=\"dialog_enter_website_url\">Введите URL-адрес сайта</string>\n    <string name=\"dialog_sorting\">Сортировка</string>\n    <string name=\"dialog_permission_needed_title\">Разрешение на хранение необходимо</string>\n    <string name=\"dialog_permission_needed_summary\">Чтобы прикрепить файл с устройства, приложению необходимо получить разрешение на хранение.</string>\n\n    <string name=\"attachment_type_import_file\">Файл импорта</string>\n    <string name=\"attachment_type_website_url\">URL-адрес веб-сайта</string>\n\n    <string name=\"sorting_directions_ascending\">По возрастанию</string>\n    <string name=\"sorting_directions_descending\">По убыванию</string>\n\n    <string name=\"filter_options_all\">Все</string>\n    <string name=\"filter_options_pending_tasks\">Только в ожидании</string>\n    <string name=\"filter_options_finished_tasks\">Выполненные</string>\n    <string name=\"filter_options_today_classes\">Сегодня только</string>\n    <string name=\"filter_options_tomorrow_classes\">Только завтра</string>\n\n    <string name=\"field_subject_code\">Предметный код</string>\n    <string name=\"field_description\">Описание</string>\n    <string name=\"field_days_of_week\">Дни недели</string>\n    <string name=\"field_weeks_of_month\">Недели месяца</string>\n    <string name=\"field_start_time\">Время начала</string>\n    <string name=\"field_end_time\">Время окончания</string>\n    <string name=\"field_task_name\">Имя задачи</string>\n    <string name=\"field_notes\">Примечания</string>\n    <string name=\"field_subject\">Предмет</string>\n    <string name=\"field_due_date\">Срок исполнения</string>\n    <string name=\"field_event_name\">Название события</string>\n    <string name=\"field_schedule\">Расписание</string>\n    <string name=\"field_location\">Местоположение</string>\n    <string name=\"field_attachments\">Приложения</string>\n    <string name=\"field_class_time\">Классное время</string>\n    <string name=\"field_color\">Цветная метка</string>\n    <string name=\"field_priority\">Приоритет</string>\n    <string name=\"field_status\">Статус</string>\n    <string name=\"field_not_set\">Не установлен</string>\n    <string name=\"field_due_in_the_next_meeting\">Следующая встреча</string>\n    <string name=\"field_due_pick_from_schedule\">Выберите из расписания занятий</string>\n    <string name=\"field_due_custom\">Пользовательский</string>\n    <string name=\"field_attachment_name\">Имя приложения</string>\n    <string name=\"field_instructor\">Инструктор</string>\n    <string name=\"field_classroom\">Классная комната</string>\n\n    <string name=\"hint_subject_description\">Имя субъекта</string>\n    <string name=\"hint_task_notes\">Некоторые идеи или мелкие детали задачи</string>\n    <string name=\"hint_event_location\">Войти в комнату, здание или любое другое место.</string>\n    <string name=\"hint_event_notes\">Некоторые идеи или мелкие детали мероприятия</string>\n\n    <string name=\"feedback_subject_removed\">Предмет удален</string>\n    <string name=\"feedback_log_removed\">Журнал удален</string>\n    <string name=\"feedback_task_removed\">Задача снята</string>\n    <string name=\"feedback_schedule_removed\">Расписание удалено</string>\n    <string name=\"feedback_attachment_removed\">Крепление удалено</string>\n    <string name=\"feedback_attachment_added\">Добавлено приложение</string>\n    <string name=\"feedback_event_removed\">Событие удалено</string>\n    <string name=\"feedback_task_marked_as_finished\">Задача обозначена как Готово</string>\n    <string name=\"feedback_task_marked_as_pending\">Задача помечена как Ожидающая решения</string>\n    <string name=\"feedback_subject_empty_name\">Вы забыли ввести код Предмет</string>\n    <string name=\"feedback_subject_empty_description\">Вы забыли ввести описание</string>\n    <string name=\"feedback_subject_no_schedule\">Ты забыл добавить расписание</string>\n    <string name=\"feedback_schedule_empty_days\">Вы забыли указать дни</string>\n    <string name=\"feedback_schedule_empty_start_time\">Ты забыл ввести время начала</string>\n    <string name=\"feedback_schedule_empty_end_time\">Ты забыл ввести время окончания</string>\n    <string name=\"feedback_task_empty_name\">Вы забыли ввести имя задачи</string>\n    <string name=\"feedback_task_empty_due_date\">Вы забыли указать срок его исполнения</string>\n    <string name=\"feedback_event_empty_name\">Вы забыли ввести название мероприятия</string>\n    <string name=\"feedback_event_empty_location\">Вы забыли указать место</string>\n    <string name=\"feedback_event_empty_schedule\">Вы забыли войти в расписание</string>\n    <string name=\"feedback_restore_invalid\">Резервный файл недействителен</string>\n    <string name=\"feedback_restore_corrupted\">Резервный файл поврежден или нечитаем.</string>\n    <string name=\"feedback_backup_empty\">Нет пунктов для резервного копирования</string>\n    <string name=\"feedback_backup_failed\">В процессе резервного копирования произошла ошибка</string>\n    <string name=\"feedback_import_ongoing\">Импорт в процессе осуществления</string>\n    <string name=\"feedback_import_completed\">Завершённый импорт</string>\n    <string name=\"feedback_import_failed\">Импорт не состоялся</string>\n    <string name=\"feedback_export_ongoing\">Экспорт продолжается</string>\n    <string name=\"feedback_export_completed\">Экспорт завершен</string>\n    <string name=\"feedback_export_failed\">Экспорт не состоялся</string>\n    <string name=\"feedback_unable_to_share_title\">Невозможно поделиться</string>\n    <string name=\"feedback_unable_to_share_message\">Нет никакой достоверной информации, которой можно было бы поделиться</string>\n    <string name=\"feedback_subject_code_exists\">Объект с таким кодом уже существует.</string>\n    <string name=\"feedback_schedule_exists\">Расписание конфликтует с другим расписанием.</string>\n    <string name=\"feedback_task_name_exists\">Задание с таким именем уже существует.</string>\n    <string name=\"feedback_event_name_exists\">Событие с таким именем уже существует.</string>\n    <string name=\"feedback_event_schedule_exists\">Мероприятие с таким же расписанием уже существует.</string>\n\n    <string name=\"settings_group_interface\">Интерфейс</string>\n    <string name=\"settings_group_sound\">Звуковой</string>\n    <string name=\"settings_group_notification\">Уведомления</string>\n    <string name=\"settings_group_advanced\">Расширенный сайт</string>\n    <string name=\"settings_group_debugging\">Отладка</string>\n    <string name=\"settings_group_contribute\">Делать вклад</string>\n\n    <string name=\"settings_theme\">Тема</string>\n    <string name=\"settings_theme_item_system\">Стандартная система</string>\n    <string name=\"settings_theme_item_dark\">Темный</string>\n    <string name=\"settings_theme_item_light\">Свет</string>\n    <string name=\"settings_confetti_title\">Конфетти</string>\n    <string name=\"settings_confetti_summary\">Показывать конфетти, когда задачи помечены как завершенные</string>\n\n    <string name=\"settings_completion_sounds_title\">Звуки завершения</string>\n    <string name=\"settings_completion_sounds_summary\">Воспроизвести звук, когда вы отмечаете задачу как выполненную</string>\n\n    <string name=\"settings_reminder_frequency_title\">Частота напоминаний</string>\n    <string name=\"settings_reminder_frequency_item_everyday\">Ежедневно</string>\n    <string name=\"settings_reminder_frequency_item_weekends\">Выходные</string>\n    <string name=\"settings_remind_me_in_time_of_day\">Напомни мне сейчас</string>\n    <string name=\"settings_when_nearing_due_title\">Когда задача близка к выполнению.</string>\n    <string name=\"settings_when_nearing_due_summary\">Показывать уведомления о задачах, которые приближаются к своему сроку выполнения</string>\n    <string name=\"settings_task_reminders\">Интервал напоминания о задаче</string>\n    <string name=\"settings_task_reminders_item_hour\">за 1 час до</string>\n    <string name=\"settings_task_reminders_item_three_hours\">за 3 часа до</string>\n    <string name=\"settings_task_reminders_item_day\">за 1 день до</string>\n    <string name=\"settings_incoming_events_title\">Всплывающие события</string>\n    <string name=\"settings_incoming_events_summary\">Показывать уведомления о входящих событиях в этот день</string>\n    <string name=\"settings_event_reminders\">Интервал напоминаний о событиях</string>\n    <string name=\"settings_event_reminders_item_quarter_hour\">за 15 минут до</string>\n    <string name=\"settings_event_reminders_item_half_hour\">за 30 минут до</string>\n    <string name=\"settings_event_reminders_item_hour\">@string/settings_task_reminders_item_hour</string>\n    <string name=\"settings_classes_for_this_day_title\">Занятия по сей день</string>\n    <string name=\"settings_classes_for_this_day_summary\">Показывать уведомления об уроках по моим предметам в этот день</string>\n    <string name=\"settings_class_reminders\">Интервал напоминания класса</string>\n    <string name=\"settings_class_reminders_item_5_minutes\">за 5 минут до</string>\n    <string name=\"settings_class_reminders_item_15_minutes\">@string/settings_event_reminders_item_quarter_hour</string>\n    <string name=\"settings_class_reminders_item_30_minutes\">@string/settings_event_reminders_item_half_hour</string>\n    <string name=\"settings_more_notification_settings\">Дополнительные настройки</string>\n\n    <string name=\"settings_allow_week_numbers_title\">Включить номера недель</string>\n    <string name=\"settings_allow_week_numbers_summary\">Показывать номера недель при настройке расписаний.</string>\n    <string name=\"settings_backup_and_restore\">@string/activity_backup</string>\n    <string name=\"settings_backup\">Резервное копирование</string>\n    <string name=\"settings_backup_summary_no_previous\">Нет предыдущих резервных копий</string>\n    <string name=\"settings_restore\">Восстановление</string>\n    <string name=\"settings_use_external_browser_title\">Открытые ссылки во внешнем браузере</string>\n    <string name=\"settings_use_external_browser_summary\">Используйте системный браузер по умолчанию для работы с гиперссылками.</string>\n\n    <string name=\"settings_not_working_notifications\">@string/button_learn_more</string>\n    <string name=\"settings_not_working_notifications_info\">Иногда ваше уведомление может не сработать из-за агрессивной оптимизации батареи производителем вашего телефона.</string>\n\n    <string name=\"settings_translate\">Перевести</string>\n    <string name=\"settings_report_an_issue\">Сообщить о проблеме</string>\n    <string name=\"settings_third_party_notices\">@string/activity_notices</string>\n    <string name=\"settings_build_version\">Версия для строительства</string>\n\n    <string name=\"color_sky\">Sky</string>\n    <string name=\"color_grass\">Трава</string>\n    <string name=\"color_sunset\">Закат</string>\n    <string name=\"color_lemon\">Lemon</string>\n    <string name=\"color_sea\">Море</string>\n    <string name=\"color_grape\">Виноград</string>\n    <string name=\"color_cherry\">Вишня</string>\n    <string name=\"color_coral\">Коралл</string>\n    <string name=\"color_midnight\">Midnight</string>\n    <string name=\"color_mint\">Мятный двор</string>\n    <string name=\"color_lavender\">Лаванда</string>\n    <string name=\"color_graphite\">Графит</string>\n\n    <string name=\"widget_task_name\">Виджет задач</string>\n    <string name=\"widget_task_title\">Задачи</string>\n    <string name=\"widget_task_empty\">У вас нет задач на сегодня.</string>\n    <string name=\"widget_event_name\">Ивент-виджет</string>\n    <string name=\"widget_event_title\">События</string>\n    <string name=\"widget_event_empty\">У вас нет никаких событий на сегодня.</string>\n    <string name=\"widget_class_name\">Виджет класса</string>\n    <string name=\"widget_class_title\">Занятия</string>\n    <string name=\"widget_class_empty\">У тебя сегодня нет занятий.</string>\n\n    <!-- Helper Text -->\n    <string name=\"helper_this_is_important\">Пометка \"важно\" означает, что он будет показывать постоянное уведомление в тени уведомления.</string>\n\n    <!-- Notifications -->\n    <string name=\"notification_channel_group_reminders\">Напоминания</string>\n\n    <string name=\"notification_channel_general\">Общие сведения</string>\n    <string name=\"notification_channel_task_reminders\">Напоминания о задачах</string>\n    <string name=\"notification_channel_event_reminders\">Напоминания о событиях</string>\n    <string name=\"notification_channel_class_reminders\">Напоминатели класса</string>\n\n    <string name=\"notification_pending_tasks_title\">У вас есть задачи %1$d</string>\n    <string name=\"notification_pending_tasks_summary\">Возможно, стоит взглянуть</string>\n\n    <string name=\"notification_backup_ongoing\">Выполнение резервного копирования</string>\n    <string name=\"notification_backup_error\">Резервное копирование не удалось</string>\n    <string name=\"notification_backup_success\">Резервное копирование Завершено</string>\n\n    <string name=\"notification_restore_ongoing\">Восстановление резервного копирования</string>\n    <string name=\"notification_restore_error\">Восстановить Не удалось</string>\n    <string name=\"notification_restore_success\">Восстановлено Завершено</string>\n\n    <!-- System -->\n    <string name=\"sharing_attach_to_task\">Добавить как Приложение</string>\n\n    <!-- Greetings -->\n    <string name=\"greeting_default\">Добрый день!</string>\n    <string name=\"greeting_morning\">Доброе утро!</string>\n    <string name=\"greeting_afternoon\">Добрый день!</string>\n    <string name=\"greeting_evening\">Добрый вечер!</string>\n\n    <!-- used for concat and formatting -->\n    <string name=\"and\">&#160;и&#160;</string>\n    <string name=\"yesterday_at\">Вчера на %1$s</string>\n    <string name=\"yesterday\">Вчера</string>\n    <string name=\"tomorrow_at\">Завтра на %1$s</string>\n    <string name=\"tomorrow\">Завтра</string>\n    <string name=\"today_at\">Сегодня на %1$s</string>\n    <string name=\"today\">Сегодня</string>\n    <string name=\"due_today_at\">Срок исполнения сегодня %1$s</string>\n    <string name=\"due_tomorrow_at\">Срок исполнения завтрашнего дня %1$s</string>\n    <string name=\"due_at\">В срок %1$s</string>\n\n    <string name=\"open_source_libraries\">Библиотеки с открытым исходным кодом</string>\n    <string name=\"credit_other_resources\">Прочие ресурсы</string>\n    <string name=\"credit_notification_sound_summary\">Звук уведомления</string>\n    <string name=\"credit_launcher_icon_summary\">икона-лаунчер</string>\n    <string name=\"credit_user_interface_icons_summary\">Иконки пользовательского интерфейса</string>\n\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values-tr/strings.xml",
    "content": "<resources>\n    <string translatable=\"false\" name=\"app_name\">Fokus</string>\n\n    <string name=\"shortcut_add_task\">@string/button_add_task</string>\n    <string name=\"shortcut_add_event\">@string/button_add_event</string>\n    <string name=\"shortcut_add_subject\">@string/button_add_subject</string>\n\n    <string name=\"activity_tasks\">Görevler</string>\n    <string name=\"activity_tasks_pending\">Bekleyen Görevler</string>\n    <string name=\"activity_tasks_finished\">Tamamlanmış Görevler</string>\n    <string name=\"activity_subjects\">Konular</string>\n    <string name=\"activity_subjects_today\">Bugünkü Konular</string>\n    <string name=\"activity_subjects_tomorrow\">Yarınki Konular</string>\n    <string name=\"activity_archives\">Arşivlenmiş Kayıtlar</string>\n    <string name=\"activity_logs\">Bildirim Günlüğü</string>\n    <string name=\"activity_settings\">Ayarlar</string>\n    <string name=\"activity_backup\">Yedekle ve Geri Yükle</string>\n    <string name=\"activity_notices\">Third Party Notices</string>\n    <string name=\"activity_open_source_licenses\">Açık Kaynak Lisansları</string>\n    <string name=\"activity_about\">Hakkında</string>\n\n    <string name=\"menu_add\">@string/button_add</string>\n    <string name=\"menu_more\">Daha Çok</string>\n    <string name=\"menu_sort\">Sırala</string>\n    <string name=\"menu_filter\">Filtrele</string>\n    <string name=\"menu_share\">Paylaş</string>\n    <string name=\"menu_import\">İçe Aktar</string>\n    <string name=\"menu_clear_items\">Günlüğü Temizle</string>\n    <string name=\"menu_export_to_file\">Dosya olarak dışa aktar</string>\n    <string name=\"menu_share_directly\">Direkt paylaş</string>\n    <string name=\"menu_archived\">Arşivlenmiş</string>\n\n    <string name=\"navigation_tasks\">Görevler</string>\n    <string name=\"navigation_events\">Etkinlikler</string>\n    <string name=\"navigation_subjects\">Konular</string>\n    <string name=\"navigation_home\">Ana Sayfa</string>\n\n    <string name=\"navigation_logs\">Günlük</string>\n    <string name=\"navigation_settings\">@string/activity_settings</string>\n    <string name=\"navigation_about\">@string/activity_about</string>\n\n    <string name=\"button_add_task\">Görev Oluştur</string>\n    <string name=\"button_add_event\">Etkinlik Oluştur</string>\n    <string name=\"button_add_subject\">Konu Oluştur</string>\n    <string name=\"button_add\">Oluştur</string>\n    <string name=\"button_new\">Yeni</string>\n    <string name=\"button_save\">Kaydet</string>\n    <string name=\"button_done\">Tamamla</string>\n    <string name=\"button_undo\">Geri Al</string>\n    <string name=\"button_remove\">Sil</string>\n    <string name=\"button_continue\">Devam Et</string>\n    <string name=\"button_mark_as_finished\">Tamamlandı Olarak İşaretle</string>\n    <string name=\"button_mark_as_important\">Önemli Olarak İşaretle</string>\n    <string name=\"button_delete\">Sil</string>\n    <string name=\"button_cancel\">İptal</string>\n    <string name=\"button_discard\">Vazgeç</string>\n    <string name=\"button_dismiss\">Reddet</string>\n    <string name=\"button_learn_more\">Daha Fazlası</string>\n    <string name=\"button_view_schedules\">Hatırlatıcıları Görüntüle</string>\n\n    <string name=\"empty_view_no_subjects_title\">Hiç hatırlatıcı yok</string>\n    <string name=\"empty_view_no_subjects_summary\">Konular, görevlerinizi ve etkinliklerinizi filtrelemenize yardımcı olur. Daha önce bir konu oluşturmadıysanız aşağıdaki butonu kullanarak ekleyebilirsiniz.</string>\n    <string name=\"empty_view_no_classes_today_title\">Bugün Ders Yok</string>\n    <string name=\"empty_view_no_classes_today_summary\">Bugün için ayarlanmış herhangi bir ders bulunmuyor.</string>\n    <string name=\"empty_view_no_classes_tomorrow_title\">Yarın Ders Yok</string>\n    <string name=\"empty_view_no_classes_tomorrow_summary\">Yarın için ayarlanmış herhangi bir ders bulunmuyor.</string>\n    <string name=\"empty_view_no_tasks_title\">Bekleyen Görev Yok</string>\n    <string name=\"empty_view_no_tasks_summary\">Bekleyen hiçbir göreviniz bulunmuyor. Yeni bir görev eklemek için aşağıdaki butonu kullanabilirsiniz.</string>\n    <string name=\"empty_view_no_finished_title\">Tamamlanmış Görev Yok</string>\n    <string name=\"empty_view_no_finished_summary\">Tamamlanmış hiçbir göreviniz bulunmuyor. Tamamlandı olarak işaretlediğiniz görevler burada görünür.</string>\n    <string name=\"empty_view_no_logs_title\">Kayıt Günlüğü Boş</string>\n    <string name=\"empty_view_no_logs_summary\">Herhangi bir görev,olay veya hatırlatıcı bildirim çubuğunuzda göründüğünde; burada da görünüyor olacak.</string>\n    <string name=\"empty_view_no_events_title\">Planlanmış Etkinlik Yok</string>\n    <string name=\"empty_view_no_events_summary\">Planlanmış hiçbir etkinlik bulunmuyor. Yeni bir etkinlik eklemek için aşağıdaki butonu kullanabilirsiniz.</string>\n    <string name=\"empty_view_no_previous_title\">Geçmiş Etkinlik Yok</string>\n    <string name=\"empty_view_no_previous_summary\">Tarihi geçmiş hiçbir etkinlik bulunmuyor. Tarihi geçmi etkinlikler burada görünür.</string>\n    <string name=\"empty_view_no_archived_tasks\">Arşivlenmiş Görev Yok</string>\n    <string name=\"empty_view_no_archived_events\">Arşivlenmiş Etkinlik Yok</string>\n    <string name=\"empty_view_no_archived_subjects\">Arşivlenmiş Konu Yok</string>\n\n    <string name=\"days_of_week_item_sunday\">Pazar</string>\n    <string name=\"days_of_week_item_monday\">Pazartesi</string>\n    <string name=\"days_of_week_item_tuesday\">Salı</string>\n    <string name=\"days_of_week_item_wednesday\">Çarşamba</string>\n    <string name=\"days_of_week_item_thursday\">Perşembe</string>\n    <string name=\"days_of_week_item_friday\">Cuma</string>\n    <string name=\"days_of_week_item_saturday\">Cumartesi</string>\n\n    <string name=\"days_of_week_item_sunday_short\">Pzr</string>\n    <string name=\"days_of_week_item_monday_short\">Pzt</string>\n    <string name=\"days_of_week_item_tuesday_short\">Sal</string>\n    <string name=\"days_of_week_item_wednesday_short\">Çrş</string>\n    <string name=\"days_of_week_item_thursday_short\">Prş</string>\n    <string name=\"days_of_week_item_friday_short\">Cum</string>\n    <string name=\"days_of_week_item_saturday_short\">Cts</string>\n\n    <string name=\"weeks_of_month_item_week_1\">1. Hafta</string>\n    <string name=\"weeks_of_month_item_week_2\">2. Hafta</string>\n    <string name=\"weeks_of_month_item_week_3\">3. Hafta</string>\n    <string name=\"weeks_of_month_item_week_4\">4. Hafta</string>\n\n    <string name=\"dialog_assign_subject\">Konu Ata</string>\n    <string name=\"dialog_pick_start_time\">Başlangıç Tarihi Seç</string>\n    <string name=\"dialog_pick_end_time\">Bitiş Tarihi Seç</string>\n    <string name=\"dialog_pick_color_tag\">Etiket rengi seç</string>\n    <string name=\"dialog_select_notification_interval\">Bildirim aralığını seç</string>\n    <string name=\"dialog_choose_theme\">Temayı seç</string>\n    <string name=\"dialog_choose_backup\">Yedekleme dosyası seç</string>\n    <string name=\"dialog_confirm_deletion_title\">\\\"%1$s\\\" silinecek.</string>\n    <string name=\"dialog_confirm_deletion_summary\">Bu işlem geri alınamaz. Devam etmek istiyor musunuz?</string>\n    <string name=\"dialog_confirm_unarchive_title\">Arşivden silinsin mi?</string>\n    <string name=\"dialog_confirm_unarchive_summary\">Sola doğru kaydırarak bu kaydı arşivleyebilirsiniz.</string>\n    <string name=\"dialog_import_attachment_title\">Ek içe aktarılsın mı?</string>\n    <string name=\"dialog_import_attachment_summary\">Android işletim sisteminin getirdiği yeni kısıtlamalardan dolayı, uygulama ek dosyasını kendi alanına kopyalayacak. Devam edilsin mi?</string>\n    <string name=\"dialog_import_attachment_confirm\">Bir daha sorma</string>\n    <string name=\"dialog_schedule_details\">Hatırlatıcı Detayları</string>\n    <string name=\"dialog_discard_changes\">Değişiklerden vazgeçilsin mi?</string>\n    <string name=\"dialog_select_file_import\">İçe aktarılacak dosyayı seçin</string>\n    <string name=\"dialog_send_to\">Şuna gönder</string>\n    <string name=\"dialog_sharing_options\">Paylaşım Ayarları</string>\n    <string name=\"dialog_class_schedules\">Ders Hatırlatıcıları</string>\n    <string name=\"dialog_filter_options\">Filtreleme Ayarları</string>\n    <string name=\"dialog_new_attachment\">Yeni Ek Oluştur</string>\n    <string name=\"dialog_attachment_name\">@string/field_attachment_name</string>\n    <string name=\"dialog_enter_website_url\">Web site adresini girin</string>\n    <string name=\"dialog_sorting\">Sıralama</string>\n    <string name=\"dialog_permission_needed_title\">Kayıt Yeri İzni Gerekiyor</string>\n    <string name=\"dialog_permission_needed_summary\">Cihazınızdan bir dosyayı içe aktarabilmek için kayıt yeri iznine ihtiyacımız var.</string>\n\n    <string name=\"attachment_type_import_file\">Dosyayı İçeri Aktar</string>\n    <string name=\"attachment_type_website_url\">Web Adresi</string>\n\n    <string name=\"sorting_directions_ascending\">Artan</string>\n    <string name=\"sorting_directions_descending\">Azalan</string>\n\n    <string name=\"filter_options_all\">Tümü</string>\n    <string name=\"filter_options_pending_tasks\">Bekleyen</string>\n    <string name=\"filter_options_finished_tasks\">Tamamlanmış</string>\n    <string name=\"filter_options_today_classes\">Bugün</string>\n    <string name=\"filter_options_tomorrow_classes\">Yarın</string>\n\n    <string name=\"field_subject_code\">Konu</string>\n    <string name=\"field_description\">Açıklama</string>\n    <string name=\"field_days_of_week\">Haftanın Günleri</string>\n    <string name=\"field_weeks_of_month\">Ayın Haftaları</string>\n    <string name=\"field_start_time\">Başlangıç Tarihi</string>\n    <string name=\"field_end_time\">Bitiş Tarihi</string>\n    <string name=\"field_task_name\">Görev Adı</string>\n    <string name=\"field_notes\">Notlar</string>\n    <string name=\"field_subject\">Konu</string>\n    <string name=\"field_due_date\">Bitiş Tarihi</string>\n    <string name=\"field_event_name\">Etkinlik Adı</string>\n    <string name=\"field_schedule\">Hatılatıcı</string>\n    <string name=\"field_location\">Konum</string>\n    <string name=\"field_attachments\">Ekler</string>\n    <string name=\"field_class_time\">Ders Saati</string>\n    <string name=\"field_color\">Renk Etiketi</string>\n    <string name=\"field_priority\">Öncelik</string>\n    <string name=\"field_status\">Durum</string>\n    <string name=\"field_not_set\">Ayarlanmamış</string>\n    <string name=\"field_due_in_the_next_meeting\">Bir sonraki toplantıda</string>\n    <string name=\"field_due_pick_from_schedule\">Ders Hatırlatıcılarından seç</string>\n    <string name=\"field_due_custom\">Özel</string>\n    <string name=\"field_attachment_name\">Ek adı</string>\n    <string name=\"field_instructor\">Eğitmen</string>\n    <string name=\"field_classroom\">Sınıf</string>\n\n    <string name=\"hint_subject_description\">Konunun adı</string>\n    <string name=\"hint_task_notes\">Görevle ilgili bazı fikirler veya küçük notlar</string>\n    <string name=\"hint_event_location\">Bir oda, bina veya herhangi bir yer belirtin</string>\n    <string name=\"hint_event_notes\">Etkinlikle ilgili bazı fikirler veya küçük notlar</string>\n\n    <string name=\"feedback_subject_removed\">Konu silindi</string>\n    <string name=\"feedback_log_removed\">Günlük silindi</string>\n    <string name=\"feedback_task_removed\">Görev silindi</string>\n    <string name=\"feedback_schedule_removed\">Hatılatıcı silindi</string>\n    <string name=\"feedback_attachment_added\">Ek eklendi</string>\n    <string name=\"feedback_attachment_removed\">Ek silindi</string>\n    <string name=\"feedback_event_removed\">Etkinlik silindi</string>\n    <string name=\"feedback_task_marked_as_finished\">Görev, tamamlandı olarak işaretlendi</string>\n    <string name=\"feedback_task_marked_as_pending\">Görev, bekleyen olarak işaretlendi</string>\n    <string name=\"feedback_subject_empty_name\">Konu belirtmeyi unuttunuz</string>\n    <string name=\"feedback_subject_empty_description\">Açıklama girmeyi unuttunuz</string>\n    <string name=\"feedback_subject_no_schedule\">Hatırlatıcı eklemeyi unuttunuz</string>\n    <string name=\"feedback_schedule_empty_days\">Gün belirtmeyi unuttunuz</string>\n    <string name=\"feedback_schedule_empty_start_time\">Başlangıç tarihini belirtmeyi unuttunuz</string>\n    <string name=\"feedback_schedule_empty_end_time\">Bitiş tarihini belirtmeyi unuttunuz</string>\n    <string name=\"feedback_task_empty_name\">Görev adını girmeyi unuttunuz</string>\n    <string name=\"feedback_task_empty_due_date\">Bitiş tarihini belirtmeyi unuttunuz</string>\n    <string name=\"feedback_event_empty_name\">Etkinlik adını belirtmeyi unuttunuz</string>\n    <string name=\"feedback_event_empty_location\">Konum bilgisini unuttunuz</string>\n    <string name=\"feedback_event_empty_schedule\">Hatırlatıcı eklemeyi unuttunuz</string>\n    <string name=\"feedback_restore_invalid\">Yedek dosyası geçersiz</string>\n    <string name=\"feedback_restore_corrupted\">Yedek dosyası bozulmuş veya okunamıyor</string>\n    <string name=\"feedback_backup_empty\">Yedeklenecek bir kayıt yok</string>\n    <string name=\"feedback_backup_failed\">Yedekleme işlemi sırasında bir sorunla karşılaşıldı</string>\n    <string name=\"feedback_import_ongoing\">İçe aktarma devam ediyor</string>\n    <string name=\"feedback_import_completed\">İçe aktarma başarılı</string>\n    <string name=\"feedback_import_failed\">İçe aktarma sırasında bir sorunla karşılaşıldı</string>\n    <string name=\"feedback_export_ongoing\">Dışarı aktarma devam ediyor</string>\n    <string name=\"feedback_export_completed\">Dışa aktarma başarılı</string>\n    <string name=\"feedback_export_failed\">Dışa aktarma sırasında bir sorunla karşılaşıldı</string>\n    <string name=\"feedback_unable_to_share_title\">Paylaşılamıyor</string>\n    <string name=\"feedback_unable_to_share_message\">Paylaşılabilecek geçerli bir bilgi yok</string>\n    <string name=\"feedback_subject_code_exists\">Aynı isimde bir konu zaten mevcut.</string>\n    <string name=\"feedback_schedule_exists\">Hatırlatıcı başka bir hatırlatıcı ile çakışıyor.</string>\n    <string name=\"feedback_task_name_exists\">Aynı isimde başka bir görev zaten mevcut.</string>\n    <string name=\"feedback_event_name_exists\">Aynı isimde başka bir etkinlik zaten mevcut.</string>\n    <string name=\"feedback_event_schedule_exists\">Aynı hatırlatıcıya sahip başka bir etkinlik zaten mevcut.</string>\n\n    <string name=\"settings_group_interface\">Arayüz</string>\n    <string name=\"settings_group_sound\">Ses</string>\n    <string name=\"settings_group_notification\">Bildirimler</string>\n    <string name=\"settings_group_advanced\">Gelişmiş</string>\n    <string name=\"settings_group_debugging\">Hata Ayıklama</string>\n    <string name=\"settings_group_contribute\">Katkıda Bulun</string>\n\n    <string name=\"settings_theme\">Tema</string>\n    <string name=\"settings_theme_item_system\">Sistem varsayılanı</string>\n    <string name=\"settings_theme_item_dark\">Karanlık</string>\n    <string name=\"settings_theme_item_light\">Açık</string>\n    <string name=\"settings_confetti_title\">Konfeti</string>\n    <string name=\"settings_confetti_summary\">Görevler tamamlandığında konfeti efekti göster</string>\n\n    <string name=\"settings_completion_sounds_title\">Tamamlanma Sesleri</string>\n    <string name=\"settings_completion_sounds_summary\">Bir görev tamamlandı olarak işaretlendiğinde ses çal</string>\n\n    <string name=\"settings_reminder_frequency_title\">Hatırlatma sıklığı</string>\n    <string name=\"settings_reminder_frequency_item_everyday\">Her Gün</string>\n    <string name=\"settings_reminder_frequency_item_weekends\">Hafta Sonu</string>\n    <string name=\"settings_remind_me_in_time_of_day\">Şu saatte hatırlat</string>\n    <string name=\"settings_when_nearing_due_title\">Bir görevin bitiş tarihi yaklaştığında</string>\n    <string name=\"settings_when_nearing_due_summary\">Son teslim tarihine yaklaşan görevler için bildirimleri göster</string>\n    <string name=\"settings_task_reminders\">Görev hatırlatma aralığı</string>\n    <string name=\"settings_task_reminders_item_hour\">1 saat önce</string>\n    <string name=\"settings_task_reminders_item_three_hours\">3 saat önce</string>\n    <string name=\"settings_task_reminders_item_day\">1 gün önce</string>\n    <string name=\"settings_incoming_events_title\">Yaklaşan etkinlikler</string>\n    <string name=\"settings_incoming_events_summary\">Bugün yaklaşan etkinliklerle ilgili bildirimleri göster</string>\n    <string name=\"settings_event_reminders\">Etkinlik hatırlatma aralığı</string>\n    <string name=\"settings_event_reminders_item_quarter_hour\">15 dakika önce</string>\n    <string name=\"settings_event_reminders_item_half_hour\">30 dakika önce</string>\n    <string name=\"settings_event_reminders_item_hour\">@string/settings_task_reminders_item_hour</string>\n    <string name=\"settings_classes_for_this_day_title\">Bugünkü dersler</string>\n    <string name=\"settings_classes_for_this_day_summary\">Bugünkü derslerimle ilgili bildirimleri göster.</string>\n    <string name=\"settings_class_reminders\">Ders hatırlatma aralığı</string>\n    <string name=\"settings_class_reminders_item_5_minutes\">5 dakika önce</string>\n    <string name=\"settings_class_reminders_item_15_minutes\">@string/settings_event_reminders_item_quarter_hour</string>\n    <string name=\"settings_class_reminders_item_30_minutes\">@string/settings_event_reminders_item_half_hour</string>\n    <string name=\"settings_more_notification_settings\">Daha Çok Ayar</string>\n\n    <string name=\"settings_allow_week_numbers_title\">Hafta Numaralarını Etkinleştir</string>\n    <string name=\"settings_allow_week_numbers_summary\">Hatırlatıcıları ayarlarken hafta numaralarını gösterin.</string>\n    <string name=\"settings_backup_and_restore\">@string/activity_backup</string>\n    <string name=\"settings_backup\">Yedekle</string>\n    <string name=\"settings_backup_summary_no_previous\">Hiç Yedekleme Yapılmamış</string>\n    <string name=\"settings_restore\">Geri Yükle</string>\n    <string name=\"settings_use_external_browser_title\">Bağlantıları harici tarayıcıda aç</string>\n    <string name=\"settings_use_external_browser_summary\">Web site linklerini işlemek için sistem varsayılan tarayıcısını kullanın</string>\n\n    <string name=\"settings_not_working_notifications\">@string/button_learn_more</string>\n    <string name=\"settings_not_working_notifications_info\">Bazen, telefon üreticinizin agresif pil optimizasyonu nedeniyle bildiriminiz tetiklenmeyebilir.</string>\n\n    <string name=\"settings_translate\">Çevir</string>\n    <string name=\"settings_report_an_issue\">Sorun bildir</string>\n    <string name=\"settings_third_party_notices\">@string/activity_notices</string>\n    <string name=\"settings_build_version\">Uygulama Versiyonu</string>\n\n    <string name=\"color_sky\">Gökyüzü</string>\n    <string name=\"color_grass\">Çimen</string>\n    <string name=\"color_sunset\">Gün Batımı</string>\n    <string name=\"color_lemon\">Limon</string>\n    <string name=\"color_sea\">Deniz</string>\n    <string name=\"color_grape\">Üzüm</string>\n    <string name=\"color_cherry\">Kiraz</string>\n    <string name=\"color_coral\">Mercan</string>\n    <string name=\"color_midnight\">Gece Mavisi</string>\n    <string name=\"color_mint\">Nane</string>\n    <string name=\"color_lavender\">Lavanta</string>\n    <string name=\"color_graphite\">Grafit</string>\n\n    <string name=\"widget_task_name\">Görev Widget\\'ı</string>\n    <string name=\"widget_task_title\">Görevler</string>\n    <string name=\"widget_task_empty\">Bugün göreviniz yok</string>\n    <string name=\"widget_event_name\">Etkinlik Widget\\'ı</string>\n    <string name=\"widget_event_title\">Etkinlikler</string>\n    <string name=\"widget_event_empty\">Bugün etkinliğiniz yok</string>\n    <string name=\"widget_class_name\">Ders Widget\\'ı</string>\n    <string name=\"widget_class_title\">Dersler</string>\n    <string name=\"widget_class_empty\">Bugün dersiniz yok</string>\n\n    <!-- Helper Text -->\n    <string name=\"helper_this_is_important\">Bunu önemli olarak işaretlemek, sistem tepsisinde kalıcı bir bildirim olarak gösterileceği anlamına gelir.</string>\n\n    <!-- Notifications -->\n    <string name=\"notification_channel_group_reminders\">Hatırlatıcılar</string>\n\n    <string name=\"notification_channel_general\">Genel</string>\n    <string name=\"notification_channel_task_reminders\">Görev Hatırlatıcıları</string>\n    <string name=\"notification_channel_event_reminders\">Etkinlik Hatırlatıcıları</string>\n    <string name=\"notification_channel_class_reminders\">Ders Hatırlatıcıları</string>\n\n    <string name=\"notification_pending_tasks_title\">Bekleyen %1$d göreviniz var</string>\n    <string name=\"notification_pending_tasks_summary\">Göz atmak isteyebilirsiniz</string>\n\n    <string name=\"notification_backup_ongoing\">Yedekleniyor</string>\n    <string name=\"notification_backup_error\">Yedekleme Başarısız</string>\n    <string name=\"notification_backup_success\">Yedekleme Başarılı</string>\n\n    <string name=\"notification_restore_ongoing\">Geri Yükleniyor</string>\n    <string name=\"notification_restore_error\">Geri Yükleme Başarısız</string>\n    <string name=\"notification_restore_success\">Geri Yükleme Başarılı</string>\n\n    <!-- Sharing -->\n    <string name=\"sharing_attach_to_task\">Göreve Ekle</string>\n\n    <!-- Greetings -->\n    <string name=\"greeting_default\">İyi günler!</string>\n    <string name=\"greeting_morning\">Günaydın!</string>\n    <string name=\"greeting_afternoon\">Tünaydın!</string>\n    <string name=\"greeting_evening\">İyi akşamlar!</string>\n\n    <!-- used for concat and formatting -->\n    <string name=\"and\">&#160;ve&#160;</string>\n    <string name=\"yesterday_at\">Dün şu saatte %1$s</string>\n    <string name=\"yesterday\">Dün</string>\n    <string name=\"tomorrow_at\">Yarın şu saatte %1$s</string>\n    <string name=\"tomorrow\">Yarın</string>\n    <string name=\"today_at\">Bugün şu saatte %1$s</string>\n    <string name=\"today\">Bugün</string>\n    <string name=\"due_today_at\">Bugün şu saatte bitiyor %1$s</string>\n    <string name=\"due_tomorrow_at\">Yarın şu saatte bitiyor %1$s</string>\n\n    <string name=\"open_source_libraries\">Açık Kaynak Kodlu Kütüphaneler</string>\n    <string name=\"credit_other_resources\">Diğer Kaynaklar</string>\n    <string name=\"credit_notification_sound_title\" translatable=\"false\">Zapsplat</string>\n    <string name=\"credit_notification_sound_summary\">Bildirim Sesi</string>\n    <string name=\"credit_launcher_icon_title\" translatable=\"false\">Freepik</string>\n    <string name=\"credit_launcher_icon_summary\">Uygulama Simgesi</string>\n    <string name=\"credit_user_interface_icons_title\" translatable=\"false\">Tailwind Labs</string>\n    <string name=\"credit_user_interface_icons_summary\">Arayüz Simgeleri</string>\n\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values-v23/themes.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <style name=\"Fokus.Theme.Base\" parent=\"Fokus.Theme\">\n        <item name=\"android:windowLightStatusBar\">true</item>\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n        <item name=\"android:navigationBarColor\">@android:color/black</item>\n    </style>\n\n    <style name=\"Fokus.Theme.Core\" parent=\"Fokus.Theme.Base\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n    </style>\n\n    <style name=\"Fokus.Theme.Core.Navigation\"/>\n    <style name=\"Fokus.Theme.Core.Editor\"/>\n\n    <!-- Components -->\n    <style name=\"Fokus.Component.Viewer\" parent=\"Fokus.Component.Viewer.Bridge\">\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n        <item name=\"android:windowLightStatusBar\">true</item>\n    </style>\n\n</resources>"
  },
  {
    "path": "app/src/main/res/values-v27/themes.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <style name=\"Fokus.Theme.Base\" parent=\"Fokus.Theme\">\n        <item name=\"android:windowLightStatusBar\">true</item>\n        <item name=\"android:windowLightNavigationBar\">true</item>\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n        <item name=\"android:navigationBarColor\">@android:color/transparent</item>\n    </style>\n\n    <style name=\"Fokus.Theme.Core\" parent=\"Fokus.Theme.Base\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n    </style>\n\n    <style name=\"Fokus.Theme.Core.Navigation\">\n        <item name=\"android:windowLightNavigationBar\">true</item>\n        <item name=\"android:navigationBarColor\">@android:color/transparent</item>\n    </style>\n\n    <!-- Components -->\n    <style name=\"Fokus.Component.Viewer\" parent=\"Fokus.Component.Viewer.Bridge\">\n        <item name=\"android:statusBarColor\">?attr/colorSurface</item>\n        <item name=\"android:navigationBarColor\">?attr/colorSurface</item>\n        <item name=\"android:windowLightStatusBar\">true</item>\n        <item name=\"android:windowLightNavigationBar\">true</item>\n    </style>\n    <style name=\"Fokus.Component.BottomSheet\" parent=\"Fokus.Component.BottomSheet.Bridge\">\n        <item name=\"android:windowLightNavigationBar\">true</item>\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n        <item name=\"android:navigationBarColor\">?attr/colorSurface</item>\n    </style>\n\n</resources>"
  },
  {
    "path": "app/src/main/res/xml/xml_about_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<PreferenceScreen\r\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\r\n\r\n    <Preference\r\n        app:key=\"KEY_NOTICES\"\r\n        app:title=\"@string/settings_third_party_notices\"\r\n        app:icon=\"@drawable/ic_outline_balance_24\"/>\r\n\r\n    <Preference\r\n        app:key=\"KEY_VERSION\"\r\n        app:title=\"@string/settings_build_version\"\r\n        app:icon=\"@drawable/ic_outline_code_24\"/>\r\n\r\n    <PreferenceCategory\r\n        app:title=\"@string/settings_group_contribute\">\r\n\r\n        <Preference\r\n            app:key=\"KEY_TRANSLATE\"\r\n            app:title=\"@string/settings_translate\"\r\n            app:icon=\"@drawable/ic_outline_translate_24\"/>\r\n\r\n        <Preference\r\n            app:key=\"KEY_REPORT_ISSUE\"\r\n            app:title=\"@string/settings_report_an_issue\"/>\r\n\r\n    </PreferenceCategory>\r\n\r\n</PreferenceScreen>"
  },
  {
    "path": "app/src/main/res/xml/xml_about_notices.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<PreferenceScreen\r\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\r\n\r\n    <Preference\r\n        app:key=\"KEY_LIBRARIES\"\r\n        app:title=\"@string/open_source_libraries\"/>\r\n\r\n    <PreferenceCategory\r\n        app:title=\"@string/credit_other_resources\">\r\n\r\n        <Preference\r\n            app:key=\"KEY_NOTIFICATION_SOUND\"\r\n            app:title=\"@string/credit_notification_sound_title\"\r\n            app:summary=\"@string/credit_notification_sound_summary\"/>\r\n\r\n        <Preference\r\n            app:key=\"KEY_LAUNCHER_ICON\"\r\n            app:title=\"@string/credit_launcher_icon_title\"\r\n            app:summary=\"@string/credit_launcher_icon_summary\"/>\r\n\r\n        <Preference\r\n            app:key=\"KEY_UI_ICONS\"\r\n            app:title=\"@string/credit_user_interface_icons_title\"\r\n            app:summary=\"@string/credit_user_interface_icons_summary\"/>\r\n    </PreferenceCategory>\r\n\r\n</PreferenceScreen>"
  },
  {
    "path": "app/src/main/res/xml/xml_launcher_shortcuts.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<shortcuts\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:tools=\"http://schemas.android.com/tools\"\r\n    tools:targetApi=\"25\">\r\n\r\n    <shortcut\r\n        android:enabled=\"true\"\r\n        android:icon=\"@drawable/shortcut_icon_task\"\r\n        android:shortcutId=\"shortcut:task\"\r\n        android:shortcutShortLabel=\"@string/shortcut_add_task\">\r\n        <intent\r\n            android:action=\"action:shortcut:task\"\r\n            android:targetClass=\"com.isaiahvonrundstedt.fokus.features.task.editor.TaskEditorContainer\"\r\n            android:targetPackage=\"com.isaiahvonrundstedt.fokus\"/>\r\n    </shortcut>\r\n\r\n    <shortcut\r\n        android:enabled=\"true\"\r\n        android:icon=\"@drawable/shortcut_icon_event\"\r\n        android:shortcutId=\"shortcut:event\"\r\n        android:shortcutShortLabel=\"@string/shortcut_add_event\">\r\n        <intent\r\n            android:action=\"action:shortcut:event\"\r\n            android:targetClass=\"com.isaiahvonrundstedt.fokus.features.event.editor.EventEditorContainer\"\r\n            android:targetPackage=\"com.isaiahvonrundstedt.fokus\"/>\r\n    </shortcut>\r\n\r\n    <shortcut\r\n        android:enabled=\"true\"\r\n        android:icon=\"@drawable/shortcut_icon_subject\"\r\n        android:shortcutId=\"shortcut:subject\"\r\n        android:shortcutShortLabel=\"@string/shortcut_add_subject\">\r\n        <intent\r\n            android:action=\"action:shortcut:subject\"\r\n            android:targetClass=\"com.isaiahvonrundstedt.fokus.features.subject.editor.SubjectEditorContainer\"\r\n            android:targetPackage=\"com.isaiahvonrundstedt.fokus\"/>\r\n    </shortcut>\r\n\r\n</shortcuts>"
  },
  {
    "path": "app/src/main/res/xml/xml_provider_paths.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<paths>\n\n    <external-cache-path\n        name=\"temp\" path=\".\"/>\n\n    <!-- Path must be same value with DataImporterService.DIRECTORY_ATTACHMENTS -->\n    <external-files-path\n        name=\"attachments\" path=\".\"/>\n\n    <!-- Path must be same value with DataImporterService.DIRECTORY_ASSETS -->\n    <external-files-path\n        name=\"assets\" path=\".\"/>\n\n</paths>"
  },
  {
    "path": "app/src/main/res/xml/xml_settings_backups.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<PreferenceScreen\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <Preference\n        app:key=\"KEY_BACKUP\"\n        app:title=\"@string/settings_backup\"/>\n\n    <Preference\n        app:key=\"KEY_RESTORE\"\n        app:title=\"@string/settings_restore\"/>\n\n</PreferenceScreen>"
  },
  {
    "path": "app/src/main/res/xml/xml_settings_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<PreferenceScreen\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <PreferenceCategory\n        app:title=\"@string/settings_group_interface\">\n\n        <ListPreference\n            app:key=\"KEY_THEME\"\n            app:title=\"@string/settings_theme\"\n            app:icon=\"@drawable/ic_outline_color_lens_24\"\n            app:dialogTitle=\"@string/dialog_choose_theme\"\n            app:entries=\"@array/settings_dark_theme_items\"\n            app:entryValues=\"@array/settings_dark_theme_values\"\n            app:defaultValue=\"SYSTEM\"\n            app:useSimpleSummaryProvider=\"true\"/>\n\n        <SwitchPreferenceCompat\n            app:key=\"KEY_CONFETTI\"\n            app:title=\"@string/settings_confetti_title\"\n            app:summary=\"@string/settings_confetti_summary\"\n            app:icon=\"@drawable/ic_outline_celebration_24\"\n            app:defaultValue=\"true\"/>\n\n    </PreferenceCategory>\n\n    <PreferenceCategory\n        app:title=\"@string/settings_group_sound\">\n\n        <SwitchPreferenceCompat\n            app:key=\"KEY_SOUND\"\n            app:title=\"@string/settings_completion_sounds_title\"\n            app:summary=\"@string/settings_completion_sounds_summary\"\n            app:defaultValue=\"true\"\n            app:icon=\"@drawable/ic_outline_music_note_24\"/>\n\n    </PreferenceCategory>\n\n    <PreferenceCategory\n        app:title=\"@string/settings_group_notification\">\n\n        <ListPreference\n            app:key=\"KEY_REMINDER_FREQUENCY\"\n            app:title=\"@string/settings_reminder_frequency_title\"\n            app:entries=\"@array/settings_task_reminder_frequency_items\"\n            app:entryValues=\"@array/settings_task_reminder_frequency_values\"\n            app:defaultValue=\"EVERYDAY\"\n            app:icon=\"@drawable/ic_outline_notifications_active_24\"\n            app:useSimpleSummaryProvider=\"true\"/>\n\n        <Preference\n            app:key=\"KEY_REMINDER_TIME\"\n            app:title=\"@string/settings_remind_me_in_time_of_day\"/>\n\n        <SwitchPreferenceCompat\n            app:key=\"KEY_TASK_NOTIFICATION\"\n            app:title=\"@string/settings_when_nearing_due_title\"\n            app:summary=\"@string/settings_when_nearing_due_summary\"\n            app:icon=\"@drawable/ic_outline_access_time_24\"\n            app:defaultValue=\"true\"/>\n\n        <ListPreference\n            app:key=\"KEY_TASK_NOTIFICATION_INTERVAL\"\n            app:title=\"@string/settings_task_reminders\"\n            app:entries=\"@array/settings_task_reminder_interval_items\"\n            app:entryValues=\"@array/settings_task_reminder_interval_values\"\n            app:defaultValue=\"3\"\n            app:dialogTitle=\"@string/dialog_select_notification_interval\"\n            app:dependency=\"KEY_TASK_NOTIFICATION\"\n            app:useSimpleSummaryProvider=\"true\"/>\n\n        <SwitchPreferenceCompat\n            app:key=\"KEY_EVENT_NOTIFICATION\"\n            app:title=\"@string/settings_incoming_events_title\"\n            app:summary=\"@string/settings_incoming_events_summary\"\n            app:icon=\"@drawable/ic_outline_confirmation_number_24\"\n            app:defaultValue=\"true\"/>\n\n        <ListPreference\n            app:key=\"KEY_EVENT_NOTIFICATION_INTERVAL\"\n            app:title=\"@string/settings_event_reminders\"\n            app:entries=\"@array/settings_event_reminder_interval_items\"\n            app:entryValues=\"@array/settings_event_reminder_interval_values\"\n            app:defaultValue=\"30\"\n            app:dialogTitle=\"@string/dialog_select_notification_interval\"\n            app:dependency=\"KEY_EVENT_NOTIFICATION\"\n            app:useSimpleSummaryProvider=\"true\"/>\n\n        <SwitchPreferenceCompat\n            app:key=\"KEY_COURSE_NOTIFICATION\"\n            app:title=\"@string/settings_classes_for_this_day_title\"\n            app:summary=\"@string/settings_classes_for_this_day_summary\"\n            app:icon=\"@drawable/ic_outline_wb_sunny_24\"\n            app:defaultValue=\"true\"/>\n\n        <ListPreference\n            app:key=\"KEY_COURSE_NOTIFICATION_INTERVAL\"\n            app:title=\"@string/settings_class_reminders\"\n            app:entries=\"@array/settings_subject_reminder_interval_items\"\n            app:entryValues=\"@array/settings_subject_reminder_interval_values\"\n            app:defaultValue=\"5\"\n            app:dialogTitle=\"@string/dialog_select_notification_interval\"\n            app:dependency=\"KEY_COURSE_NOTIFICATION\"\n            app:useSimpleSummaryProvider=\"true\"/>\n\n        <Preference\n            app:key=\"KEY_SYSTEM_NOTIFICATION\"\n            app:title=\"@string/settings_more_notification_settings\"/>\n\n    </PreferenceCategory>\n\n    <PreferenceCategory\n        app:title=\"@string/settings_group_advanced\">\n\n        <SwitchPreferenceCompat\n            app:key=\"KEY_ALLOW_WEEK_NUMBERS\"\n            app:title=\"@string/settings_allow_week_numbers_title\"\n            app:summary=\"@string/settings_allow_week_numbers_summary\"/>\n\n        <Preference\n            app:key=\"KEY_BACKUP_RESTORE\"\n            app:title=\"@string/settings_backup_and_restore\"\n            app:icon=\"@drawable/ic_outline_file_open_24\"/>\n\n        <SwitchPreference\n            app:key=\"KEY_USE_EXTERNAL_BROWSER\"\n            app:title=\"@string/settings_use_external_browser_title\"\n            app:summary=\"@string/settings_use_external_browser_summary\"\n            app:icon=\"@drawable/ic_outline_open_in_new_24\"\n            app:defaultValue=\"false\"/>\n\n    </PreferenceCategory>\n\n    <PreferenceCategory\n        app:title=\"@string/settings_group_debugging\">\n\n        <com.isaiahvonrundstedt.fokus.components.preference.InformationHolder\n            app:summary=\"@string/settings_not_working_notifications_info\"\n            tools:layout=\"@layout/layout_preference_info\"/>\n\n        <Preference\n            app:key=\"KEY_BATTERY_OPTIMIZATION\"\n            app:title=\"@string/settings_not_working_notifications\"/>\n\n    </PreferenceCategory>\n\n</PreferenceScreen>"
  },
  {
    "path": "app/src/main/res/xml/xml_widget_events.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<appwidget-provider\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    android:initialLayout=\"@layout/layout_widget_events\"\r\n    android:minWidth=\"180dp\"\r\n    android:minHeight=\"180dp\"\r\n    android:previewImage=\"@mipmap/ic_launcher_round\"\r\n    android:resizeMode=\"horizontal|vertical\"\r\n    android:updatePeriodMillis=\"400\"\r\n    android:widgetCategory=\"home_screen\"/>"
  },
  {
    "path": "app/src/main/res/xml/xml_widget_subjects.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<appwidget-provider\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    android:initialLayout=\"@layout/layout_widget_subjects\"\r\n    android:minWidth=\"180dp\"\r\n    android:minHeight=\"180dp\"\r\n    android:previewImage=\"@mipmap/ic_launcher_round\"\r\n    android:resizeMode=\"horizontal|vertical\"\r\n    android:updatePeriodMillis=\"400\"\r\n    android:widgetCategory=\"home_screen\"/>"
  },
  {
    "path": "app/src/main/res/xml/xml_widget_tasks.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<appwidget-provider\r\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    android:initialLayout=\"@layout/layout_widget_tasks\"\r\n    android:minWidth=\"180dp\"\r\n    android:minHeight=\"180dp\"\r\n    android:previewImage=\"@mipmap/ic_launcher_round\"\r\n    android:resizeMode=\"horizontal|vertical\"\r\n    android:updatePeriodMillis=\"400\"\r\n    android:widgetCategory=\"home_screen\"/>"
  },
  {
    "path": "app/src/test/java/com/isaiahvonrundstedt/fokus/ExampleUnitTest.kt",
    "content": "package com.isaiahvonrundstedt.fokus\r\n\r\nimport org.junit.Test\r\n\r\nimport org.junit.Assert.*\r\n\r\n/**\r\n * Example local unit test, which will execute on the development machine (host).\r\n *\r\n * See [testing documentation](http://d.android.com/tools/testing).\r\n */\r\nclass ExampleUnitTest {\r\n\r\n    @Test\r\n    fun addition_isCorrect() {\r\n        assertEquals(4, 2 + 2)\r\n    }\r\n}\r\n"
  },
  {
    "path": "app/src/test/java/com/isaiahvonrundstedt/fokus/features/attachments/AttachmentTests.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.attachments\n\nimport org.junit.Test\nimport org.junit.Assert.*\n\nclass AttachmentTests {\n\n    private val path = \"/storage/emulated/0/Android/data/com.isaiahvonrundstedt.fokus/files/image.jpg\"\n\n    @Test\n    fun `Get attachment file type and check if it's an image`() {\n        assertTrue(Attachment.isImage(path))\n    }\n\n}"
  },
  {
    "path": "app/src/test/java/com/isaiahvonrundstedt/fokus/features/event/EventUnitTest.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.event\n\nimport org.junit.Test\nimport java.time.ZonedDateTime\n\nclass EventUnitTest {\n\n    @Test\n    fun `should return true if schedule is today`() {\n        val event = Event(schedule = ZonedDateTime.now())\n\n        assert(event.isToday())\n    }\n}"
  },
  {
    "path": "app/src/test/java/com/isaiahvonrundstedt/fokus/features/schedule/ScheduleTests.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.schedule\n\nimport org.junit.Assert.assertTrue\nimport org.junit.Test\nimport java.time.DayOfWeek\n\nclass ScheduleTests {\n\n    @Test\n    fun `Check schedule if it's Monday Wednesday and Thursday`() {\n        val daysOfWeek = Schedule.BIT_VALUE_MONDAY +\n                Schedule.BIT_VALUE_WEDNESDAY + Schedule.BIT_VALUE_THURSDAY\n\n        assertTrue(Schedule.parseDaysOfWeek(daysOfWeek).contains(DayOfWeek.MONDAY.value))\n        assertTrue(Schedule.parseDaysOfWeek(daysOfWeek).contains(DayOfWeek.WEDNESDAY.value))\n        assertTrue(Schedule.parseDaysOfWeek(daysOfWeek).contains(DayOfWeek.THURSDAY.value))\n    }\n\n}"
  },
  {
    "path": "app/src/test/java/com/isaiahvonrundstedt/fokus/features/task/TaskUnitTest.kt",
    "content": "package com.isaiahvonrundstedt.fokus.features.task\n\nimport org.junit.Test\nimport java.time.ZonedDateTime\n\nclass TaskUnitTest {\n\n    @Test\n    fun `should return true when a task has due date`() {\n        val task = Task()\n        task.dueDate = ZonedDateTime.now()\n\n        assert(task.hasDueDate())\n    }\n\n    @Test\n    fun `should return true when the task has due date in the future`() {\n        val task = Task()\n        task.dueDate = ZonedDateTime.now().plusDays(1)\n\n        assert(task.isDueDateInFuture())\n    }\n\n    @Test\n    fun `should return true when task has due date is today`() {\n        val task = Task()\n        task.dueDate = ZonedDateTime.now()\n\n        assert(task.isDueToday())\n    }\n}"
  },
  {
    "path": "build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\r\n\r\nbuildscript {\r\n    ext.kotlin_version = '1.7.10'\r\n    repositories {\r\n        google()\r\n        mavenCentral()\r\n        maven { url 'https://jitpack.io' }\r\n        maven { url \"https://plugins.gradle.org/m2/\" }\r\n    }\r\n    dependencies {\r\n        classpath 'com.android.tools.build:gradle:7.3.1'\r\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\"\r\n        classpath 'com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:8.9.4'\r\n        classpath 'com.google.dagger:hilt-android-gradle-plugin:2.38.1'\r\n\r\n        // NOTE: Do not place your application dependencies here; they belong\r\n        // in the individual module build.gradle files\r\n    }\r\n}\r\n\r\nallprojects {\r\n    repositories {\r\n        google()\r\n        jcenter()\r\n        mavenCentral()\r\n        maven { url 'https://jitpack.io' }\r\n    }\r\n}\r\n\r\ntask clean(type: Delete) {\r\n    delete rootProject.buildDir\r\n}\r\n"
  },
  {
    "path": "fastlane/metadata/android/de/short_description.txt",
    "content": "Aufgaben- und Kalender-App für Studenten"
  },
  {
    "path": "fastlane/metadata/android/en-US/full_description.txt",
    "content": "<p><i>Fokus</i> is an open source application that combines a todo list and a calendar that can help you manage your school related work and events in one place. It’s fast and beautiful yet simple design that can help you focus on what matters most.</p>\n<p><br><b>Features:</b></p><ul>\n<li>Get reminded when a task is nearing its due</li>\n<li>Get reminded about incoming events</li>\n<li>Add attachments to your tasks</li>\n<li>Persistent notifications for important tasks or events</li>\n<li>No ads or any tracking</li>\n<li>Open Source Code</li>\n<li>On-Device Database</li></ul>\n"
  },
  {
    "path": "fastlane/metadata/android/en-US/short_description.txt",
    "content": "To Do app tailored specifically for students"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Wed May 10 13:15:17 IST 2023\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.4-bin.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Project-wide Gradle settings.\r\n# IDE (e.g. Android Studio) users:\r\n# Gradle settings configured through the IDE *will override*\r\n# any settings specified in this file.\r\n# For more details on how to configure your build environment visit\r\n# http://www.gradle.org/docs/current/userguide/build_environment.html\r\n# Specifies the JVM arguments used for the daemon process.\r\n# The setting is particularly useful for tweaking memory settings.\r\norg.gradle.jvmargs=-Xmx1536m\r\n# When configured, Gradle will run in incubating parallel mode.\r\n# This option should only be used with decoupled projects. More details, visit\r\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\r\n# org.gradle.parallel=true\r\n# AndroidX package structure to make it clearer which packages are bundled with the\r\n# Android operating system, and which are packaged with your app's APK\r\n# https://developer.android.com/topic/libraries/support-library/androidx-rn\r\nandroid.useAndroidX=true\r\n# Automatically convert third-party libraries to use AndroidX\r\nandroid.enableJetifier=true\r\n# Kotlin code style for this project: \"official\" or \"obsolete\":\r\nkotlin.code.style=official\r\n"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=$(save \"$@\")\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\n# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong\nif [ \"$(uname)\" = \"Darwin\" ] && [ \"$HOME\" = \"$PWD\" ]; then\n  cd \"$(dirname \"$0\")\"\nfi\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:init\r\n@rem Get command-line arguments, handling Windows variants\r\n\r\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\r\n\r\n:win9xME_args\r\n@rem Slurp the command line arguments.\r\nset CMD_LINE_ARGS=\r\nset _SKIP=2\r\n\r\n:win9xME_args_slurp\r\nif \"x%~1\" == \"x\" goto execute\r\n\r\nset CMD_LINE_ARGS=%*\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "settings.gradle",
    "content": "rootProject.name='Fokus'\r\ninclude ':app'\r\n"
  }
]