diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 733f463f..12871fc6 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -11,6 +11,7 @@ + \ No newline at end of file diff --git a/app/src/main/assets/pl-changelog.html b/app/src/main/assets/pl-changelog.html index c7150a83..50650cdd 100644 --- a/app/src/main/assets/pl-changelog.html +++ b/app/src/main/assets/pl-changelog.html @@ -1,9 +1,8 @@ -

Wersja 4.4.2, 2020-09-05

+

Wersja 4.4.3, 2020-10-16

    -
  • Poprawione komunikaty o aktualizacjach aplikacji.
  • -
  • Mobidziennik: poprawione wyświetlanie przedmiotu w planie lekcji.
  • -
  • Mobidziennik: naprawiony moduł frekwencji.
  • -
  • Naprawione zatrzymanie aplikacji na ekranie logowania.
  • +
  • Mobidziennik: naprawione wysyłanie wiadomości.
  • +
  • Vulcan: naprawione logowanie dla dzienników w Koszalinie.
  • +
  • PPE: opcja wylogowania innych urządzeń przy logowaniu.


diff --git a/app/src/main/cpp/szkolny-signing.cpp b/app/src/main/cpp/szkolny-signing.cpp index 9642f8a9..4861d399 100644 --- a/app/src/main/cpp/szkolny-signing.cpp +++ b/app/src/main/cpp/szkolny-signing.cpp @@ -9,7 +9,7 @@ /*secret password - removed for source code publication*/ static toys AES_IV[16] = { - 0x1a, 0xcd, 0xf0, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + 0xaa, 0x6d, 0x87, 0x46, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat); diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/App.kt b/app/src/main/java/pl/szczodrzynski/edziennik/App.kt index 65836b5e..9a2f84d6 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/App.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/App.kt @@ -57,8 +57,8 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope { val profileId get() = profile.id - var devMode = false var debugMode = false + var devMode = false } val notificationChannelsManager by lazy { NotificationChannelsManager(this) } @@ -107,7 +107,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope { .readTimeout(30, TimeUnit.SECONDS) builder.installHttpsSupport(this) - if (debugMode || BuildConfig.DEBUG) { + if (devMode || BuildConfig.DEBUG) { HyperLog.initialize(this) HyperLog.setLogLevel(Log.VERBOSE) HyperLog.setLogFormat(DebugLogFormat(this)) @@ -162,7 +162,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope { Iconics.registerFont(SzkolnyFont) App.db = AppDb(this) Themes.themeInt = config.ui.theme - debugMode = config.debugMode + devMode = config.debugMode MHttp.instance().customOkHttpClient(http) if (!profileLoadById(config.lastProfileId)) { @@ -173,9 +173,9 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope { setLanguage(it) } - devMode = BuildConfig.DEBUG + debugMode = BuildConfig.DEBUG if (BuildConfig.DEBUG) - debugMode = true + devMode = true Signing.getCert(this) @@ -185,7 +185,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope { if (config.devModePassword != null) checkDevModePassword() - debugMode = devMode || config.debugMode + devMode = debugMode || config.debugMode if (config.sync.enabled) SyncWorker.scheduleNext(this@App, false) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt index 7306109a..d7fb13de 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt @@ -299,7 +299,7 @@ fun colorFromCssName(name: String): Int { "orange" -> 0xffffa500 "black" -> 0xff000000 "white" -> 0xffffffff - else -> -1 + else -> -1L }.toInt() } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt index 28331a75..0bbc77f7 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt @@ -232,7 +232,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope { list += NavTarget(TARGET_MESSAGES_DETAILS, R.string.menu_message, MessageFragment::class).withPopTo(DRAWER_ITEM_MESSAGES) list += NavTarget(TARGET_MESSAGES_COMPOSE, R.string.menu_message_compose, MessagesComposeFragment::class) list += NavTarget(TARGET_WEB_PUSH, R.string.menu_web_push, WebPushFragment::class) - if (App.debugMode) { + if (App.devMode) { list += NavTarget(DRAWER_ITEM_DEBUG, R.string.menu_debug, DebugFragment::class) list += NavTarget(TARGET_LAB, R.string.menu_lab, LabFragment::class) .withIcon(CommunityMaterial.Icon.cmd_flask_outline) @@ -566,7 +566,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope { .withIcon(CommunityMaterial.Icon2.cmd_help_circle_outline) .withOnClickListener(View.OnClickListener { loadTarget(TARGET_FEEDBACK) }) ) - if (App.debugMode) { + if (App.devMode) { bottomSheet += BottomSheetPrimaryItem(false) .withTitle(R.string.menu_debug) .withIcon(CommunityMaterial.Icon.cmd_android_studio) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/config/ProfileConfigGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/config/ProfileConfigGrades.kt index 490fe2dd..6434aac7 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/config/ProfileConfigGrades.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/config/ProfileConfigGrades.kt @@ -49,4 +49,9 @@ class ProfileConfigGrades(private val config: ProfileConfig) { var dontCountGrades: List get() { mDontCountGrades = mDontCountGrades ?: config.values.get("dontCountGrades", listOf()); return mDontCountGrades ?: listOf() } set(value) { config.set("dontCountGrades", value); mDontCountGrades = value } + + private var mHideSticksFromOld: Boolean? = null + var hideSticksFromOld: Boolean + get() { mHideSticksFromOld = mHideSticksFromOld ?: config.values.get("hideSticksFromOld", false); return mHideSticksFromOld ?: false } + set(value) { config.set("hideSticksFromOld", value); mHideSticksFromOld = value } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Constants.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Constants.kt index af006d5a..5bc08159 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Constants.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Constants.kt @@ -119,6 +119,7 @@ const val VULCAN_WEB_ENDPOINT_REGISTER_DEVICE = "RejestracjaUrzadzeniaToken.mvc/ const val EDUDZIENNIK_USER_AGENT = "Szkolny.eu/${BuildConfig.VERSION_NAME}" -const val PODLASIE_API_VERSION = "1.0.31" +const val PODLASIE_API_VERSION = "1.0.62" const val PODLASIE_API_URL = "https://cpdklaser.zeto.bialystok.pl/api" const val PODLASIE_API_USER_ENDPOINT = "/pobierzDaneUcznia" +const val PODLASIE_API_LOGOUT_DEVICES_ENDPOINT = "/wyczyscUrzadzenia" diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Regexes.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Regexes.kt index 894dfe7a..919131f0 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Regexes.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Regexes.kt @@ -12,6 +12,10 @@ object Regexes { """color: (\w+);?""".toRegex() } + val NOT_DIGITS by lazy { + """[^0-9]""".toRegex() + } + val MOBIDZIENNIK_GRADES_SUBJECT_NAME by lazy { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetRecipientList.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetRecipientList.kt index 1118da48..0ed1e4a6 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetRecipientList.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetRecipientList.kt @@ -56,20 +56,21 @@ class MobidziennikWebGetRecipientList(override val data: DataMobidziennik, } private fun processRecipient(listType: Int, listName: String, recipient: JsonObject) { - val id = recipient.getLong("id") ?: -1 + val id = recipient.getString("id") ?: return + val idLong = id.replace(Regexes.NOT_DIGITS, "").toLongOrNull() ?: return // get teacher by ID or create it - val teacher = data.teacherList[id] ?: Teacher(data.profileId, id).apply { + val teacher = data.teacherList[idLong] ?: Teacher(data.profileId, idLong).apply { val fullName = recipient.getString("nazwa")?.fixName() name = fullName ?: "" fullName?.splitName()?.let { name = it.second surname = it.first } - data.teacherList[id] = this + data.teacherList[idLong] = this } teacher.apply { - loginId = id.toString() + loginId = id when (listType) { 1 -> setTeacherType(Teacher.TYPE_PRINCIPAL) 2 -> setTeacherType(Teacher.TYPE_TEACHER) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/firstlogin/PodlasieFirstLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/firstlogin/PodlasieFirstLogin.kt index 9b92d541..a1e9d0eb 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/firstlogin/PodlasieFirstLogin.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/firstlogin/PodlasieFirstLogin.kt @@ -7,6 +7,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.firstlogin import org.greenrobot.eventbus.EventBus import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_PODLASIE +import pl.szczodrzynski.edziennik.data.api.PODLASIE_API_LOGOUT_DEVICES_ENDPOINT import pl.szczodrzynski.edziennik.data.api.PODLASIE_API_USER_ENDPOINT import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.DataPodlasie import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.data.PodlasieApi @@ -22,50 +23,62 @@ class PodlasieFirstLogin(val data: DataPodlasie, val onSuccess: () -> Unit) { private val api = PodlasieApi(data, null) init { + PodlasieLoginApi(data) { + doLogin() + } + } + + private fun doLogin() { val loginStoreId = data.loginStore.id val loginStoreType = LOGIN_TYPE_PODLASIE - PodlasieLoginApi(data) { - api.apiGet(TAG, PODLASIE_API_USER_ENDPOINT) { json -> - val uuid = json.getString("Uuid") - val login = json.getString("Login") - val firstName = json.getString("FirstName") - val lastName = json.getString("LastName") - val studentNameLong = "$firstName $lastName".fixName() - val studentNameShort = studentNameLong.getShortName() - val schoolName = json.getString("SchoolName") - val className = json.getString("SchoolClass") - val schoolYear = json.getString("ActualSchoolYear")?.replace(' ', '/') - val semester = json.getString("ActualTermShortcut")?.length - val apiUrl = json.getString("URL") - - val profile = Profile( - loginStoreId, - loginStoreId, - loginStoreType, - studentNameLong, - login, - studentNameLong, - studentNameShort, - null - ).apply { - studentData["studentId"] = uuid - studentData["studentLogin"] = login - studentData["schoolName"] = schoolName - studentData["className"] = className - studentData["schoolYear"] = schoolYear - studentData["currentSemester"] = semester ?: 1 - studentData["apiUrl"] = apiUrl - - schoolYear?.split('/')?.get(0)?.toInt()?.let { - studentSchoolYearStart = it - } - studentClassName = className - } - - EventBus.getDefault().postSticky(FirstLoginFinishedEvent(listOf(profile), data.loginStore)) - onSuccess() + if (data.loginStore.getLoginData("logoutDevices", false)) { + data.loginStore.removeLoginData("logoutDevices") + api.apiGet(TAG, PODLASIE_API_LOGOUT_DEVICES_ENDPOINT) { + doLogin() } + return + } + + api.apiGet(TAG, PODLASIE_API_USER_ENDPOINT) { json -> + val uuid = json.getString("Uuid") + val login = json.getString("Login") + val firstName = json.getString("FirstName") + val lastName = json.getString("LastName") + val studentNameLong = "$firstName $lastName".fixName() + val studentNameShort = studentNameLong.getShortName() + val schoolName = json.getString("SchoolName") + val className = json.getString("SchoolClass") + val schoolYear = json.getString("ActualSchoolYear")?.replace(' ', '/') + val semester = json.getString("ActualTermShortcut")?.length + val apiUrl = json.getString("URL") + + val profile = Profile( + loginStoreId, + loginStoreId, + loginStoreType, + studentNameLong, + login, + studentNameLong, + studentNameShort, + null + ).apply { + studentData["studentId"] = uuid + studentData["studentLogin"] = login + studentData["schoolName"] = schoolName + studentData["className"] = className + studentData["schoolYear"] = schoolYear + studentData["currentSemester"] = semester ?: 1 + studentData["apiUrl"] = apiUrl + + schoolYear?.split('/')?.get(0)?.toInt()?.let { + studentSchoolYearStart = it + } + studentClassName = className + } + + EventBus.getDefault().postSticky(FirstLoginFinishedEvent(listOf(profile), data.loginStore)) + onSuccess() } } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/DataVulcan.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/DataVulcan.kt index 4b397f5d..882a2fa4 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/DataVulcan.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/DataVulcan.kt @@ -219,6 +219,7 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app "P01" -> "http://efeb-komunikacja.pro-hudson.win.vulcan.pl" "P02" -> "http://efeb-komunikacja.pro-hudsonrc.win.vulcan.pl" "P90" -> "http://efeb-komunikacja-pro-mwujakowska.neo.win.vulcan.pl" + "KO1" -> "https://uonetplus-komunikacja.eduportal.koszalin.pl" "FK1", "FS1" -> "http://api.fakelog.cf" "SZ9" -> "http://hack.szkolny.eu" else -> null diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginWebMain.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginWebMain.kt index 467beea3..896f64e8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginWebMain.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginWebMain.kt @@ -89,7 +89,7 @@ class VulcanLoginWebMain(val data: DataVulcan, val onSuccess: () -> Unit) { return true } - val fsLogin = FSLogin(data.app.http, debug = App.debugMode) + val fsLogin = FSLogin(data.app.http, debug = App.devMode) fsLogin.performLogin( realm = realm, username = data.webUsername ?: data.webEmail ?: return false, diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/Data.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/Data.kt index 6bd9aa83..8dda9543 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/Data.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/Data.kt @@ -136,7 +136,7 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt val db: AppDb by lazy { app.db } init { - if (App.devMode) { + if (App.debugMode) { fakeLogin = loginStore.hasLoginData("fakeLogin") } clear() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing.kt index 4d9f425c..f8ca5090 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing.kt @@ -46,6 +46,6 @@ object Signing { /*fun provideKey(param1: String, param2: Long): ByteArray {*/ fun pleaseStopRightNow(param1: String, param2: Long): ByteArray { - return "$param1.MTIzNDU2Nzg5MDx45DzIF8===.$param2".sha256() + return "$param1.MTIzNDU2Nzg5MDzyYb9Lof===.$param2".sha256() } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt index b1683ac5..b41da04b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt @@ -193,7 +193,7 @@ class EventDetailsDialog( b.goToTimetableButton.attachToastHint(R.string.hint_go_to_timetable) // RE-DOWNLOAD - b.downloadButton.isVisible = App.debugMode + b.downloadButton.isVisible = App.devMode b.downloadButton.onClick { EdziennikTask.eventGet(event.profileId, event).enqueue(activity) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/grade/GradeDetailsDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/grade/GradeDetailsDialog.kt index 20f3ad21..4877413f 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/grade/GradeDetailsDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/grade/GradeDetailsDialog.kt @@ -57,7 +57,7 @@ class GradeDetailsDialog( b.grade = grade b.weightText = manager.getWeightString(app, grade) b.commentVisible = false - b.devMode = App.debugMode + b.devMode = App.devMode b.gradeName.setTextColor(if (ColorUtils.calculateLuminance(gradeColor) > 0.3) 0xaa000000.toInt() else 0xccffffff.toInt()) b.gradeName.background.setTintColor(gradeColor) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/timetable/LessonDetailsDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/timetable/LessonDetailsDialog.kt index 6dc6edb6..5896def0 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/timetable/LessonDetailsDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/timetable/LessonDetailsDialog.kt @@ -78,7 +78,7 @@ class LessonDetailsDialog( ) } - if (App.debugMode) + if (App.devMode) b.lessonId.visibility = View.VISIBLE update() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceDetailsDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceDetailsDialog.kt index ce49efbd..9e6c14d6 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceDetailsDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceDetailsDialog.kt @@ -55,7 +55,7 @@ class AttendanceDetailsDialog( val attendanceColor = manager.getAttendanceColor(attendance) b.attendance = attendance - b.devMode = App.debugMode + b.devMode = App.devMode b.attendanceName.setTextColor(if (ColorUtils.calculateLuminance(attendanceColor) > 0.3) 0xaa000000.toInt() else 0xccffffff.toInt()) b.attendanceName.background.setTintColor(attendanceColor) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/error/ErrorDetailsDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/error/ErrorDetailsDialog.kt index 36a64a3e..32ec46b9 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/error/ErrorDetailsDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/error/ErrorDetailsDialog.kt @@ -45,7 +45,7 @@ class ErrorDetailsDialog( listOf( it.getStringReason(activity).asBoldSpannable().asColoredSpannable(R.attr.colorOnBackground.resolveAttr(activity)), activity.getString(R.string.error_unknown_format, it.errorCode, it.tag), - if (App.debugMode) + if (App.devMode) it.throwable?.stackTraceString ?: it.throwable?.localizedMessage else it.throwable?.localizedMessage diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListFragment.kt index 901ad0cf..33d69c60 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListFragment.kt @@ -71,9 +71,14 @@ class GradesListFragment : Fragment(), CoroutineScope { val adapter = GradesAdapter(activity) var firstRun = true - app.db.gradeDao().getAllOrderBy(App.profileId, app.gradesManager.getOrderByString()).observe(this@GradesListFragment, Observer { items -> this@GradesListFragment.launch { + app.db.gradeDao().getAllOrderBy(App.profileId, app.gradesManager.getOrderByString()).observe(this@GradesListFragment, Observer { grades -> this@GradesListFragment.launch { if (!isAdded) return@launch + val items = when { + app.config.forProfile().grades.hideSticksFromOld && App.devMode -> grades.filter { it.value != 1.0f } + else -> grades + } + // load & configure the adapter adapter.items = withContext(Dispatchers.Default) { processGrades(items) } if (items.isNotNullNorEmpty() && b.list.adapter == null) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt index 1b53e826..8afd7c04 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt @@ -152,13 +152,14 @@ class HomeFragment : Fragment(), CoroutineScope { val items = mutableListOf() cards.mapNotNullTo(items) { + @Suppress("USELESS_CAST") when (it.cardId) { HomeCard.CARD_LUCKY_NUMBER -> HomeLuckyNumberCard(it.cardId, app, activity, this, app.profile) HomeCard.CARD_TIMETABLE -> HomeTimetableCard(it.cardId, app, activity, this, app.profile) HomeCard.CARD_GRADES -> HomeGradesCard(it.cardId, app, activity, this, app.profile) HomeCard.CARD_EVENTS -> HomeEventsCard(it.cardId, app, activity, this, app.profile) else -> null - } + } as HomeCard? } //if (App.devMode) // items += HomeDebugCard(100, app, activity, this, app.profile) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt index d0676105..82e4f895 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt @@ -22,8 +22,9 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import pl.szczodrzynski.edziennik.* +import pl.szczodrzynski.edziennik.databinding.LoginFormCheckboxItemBinding +import pl.szczodrzynski.edziennik.databinding.LoginFormFieldItemBinding import pl.szczodrzynski.edziennik.databinding.LoginFormFragmentBinding -import pl.szczodrzynski.edziennik.databinding.LoginFormItemBinding import pl.szczodrzynski.navlib.colorAttr import java.util.* import kotlin.coroutines.CoroutineContext @@ -75,33 +76,48 @@ class LoginFormFragment : Fragment(), CoroutineScope { b.subTitle.text = platformName ?: app.getString(mode.name) b.text.text = platformGuideText ?: app.getString(mode.guideText) - val credentials = mutableMapOf() + val credentials = mutableMapOf() for (credential in mode.credentials) { if (platformFormFields?.contains(credential.keyName) == false) continue - val b = LoginFormItemBinding.inflate(layoutInflater) - b.textLayout.hint = app.getString(credential.name) - if (credential.hideText) { - b.textEdit.inputType = InputType.TYPE_TEXT_VARIATION_PASSWORD - b.textLayout.endIconMode = TextInputLayout.END_ICON_PASSWORD_TOGGLE + if (credential is LoginInfo.FormField) { + val b = LoginFormFieldItemBinding.inflate(layoutInflater) + b.textLayout.hint = app.getString(credential.name) + if (credential.hideText) { + b.textEdit.inputType = InputType.TYPE_TEXT_VARIATION_PASSWORD + b.textLayout.endIconMode = TextInputLayout.END_ICON_PASSWORD_TOGGLE + } + b.textEdit.addTextChangedListener { + b.textLayout.error = null + } + + b.textEdit.id = credential.name + + b.textEdit.setText(arguments?.getString(credential.keyName) ?: "") + b.textLayout.startIconDrawable = IconicsDrawable(activity) + .icon(credential.icon) + .sizeDp(24) + .paddingDp(2) + .colorAttr(activity, R.attr.colorOnBackground) + + this.b.formContainer.addView(b.root) + credentials[credential] = b } - b.textEdit.addTextChangedListener { - b.textLayout.error = null + if (credential is LoginInfo.FormCheckbox) { + val b = LoginFormCheckboxItemBinding.inflate(layoutInflater) + b.checkbox.text = app.getString(credential.name) + b.checkbox.onChange { _, _ -> + b.errorText.text = null + } + if (arguments?.containsKey(credential.keyName) == true) { + b.checkbox.isChecked = arguments?.getBoolean(credential.keyName) == true + } + + this.b.formContainer.addView(b.root) + credentials[credential] = b } - - b.textEdit.id = credential.name - - b.textEdit.setText(arguments?.getString(credential.keyName) ?: "") - b.textLayout.startIconDrawable = IconicsDrawable(activity) - .icon(credential.icon) - .sizeDp(24) - .paddingDp(2) - .colorAttr(activity, R.attr.colorOnBackground) - - this.b.formContainer.addView(b.root) - credentials[credential] = b } activity.lastError?.let { error -> @@ -109,7 +125,12 @@ class LoginFormFragment : Fragment(), CoroutineScope { startCoroutineTimer(delayMillis = 200L) { for (credential in credentials) { credential.key.errorCodes[error.errorCode]?.let { - credential.value.textLayout.error = app.getString(it) + (credential.value as? LoginFormFieldItemBinding)?.let { b -> + b.textLayout.error = app.getString(it) + } + (credential.value as? LoginFormCheckboxItemBinding)?.let { b -> + b.errorText.text = app.getString(it) + } return@startCoroutineTimer } } @@ -127,7 +148,7 @@ class LoginFormFragment : Fragment(), CoroutineScope { "loginMode" to loginMode ) - if (App.devMode && b.fakeLogin.isChecked) { + if (App.debugMode && b.fakeLogin.isChecked) { payload.putBoolean("fakeLogin", true) } @@ -137,35 +158,42 @@ class LoginFormFragment : Fragment(), CoroutineScope { var hasErrors = false credentials.forEach { (credential, b) -> - var text = b.textEdit.text?.toString() ?: return@forEach - if (!credential.hideText) - text = text.trim() + if (credential is LoginInfo.FormField && b is LoginFormFieldItemBinding) { + var text = b.textEdit.text?.toString() ?: return@forEach + if (!credential.hideText) + text = text.trim() - if (credential.caseMode == LoginInfo.Credential.CaseMode.UPPER_CASE) - text = text.toUpperCase(Locale.getDefault()) - if (credential.caseMode == LoginInfo.Credential.CaseMode.LOWER_CASE) - text = text.toLowerCase(Locale.getDefault()) + if (credential.caseMode == LoginInfo.FormField.CaseMode.UPPER_CASE) + text = text.toUpperCase(Locale.getDefault()) + if (credential.caseMode == LoginInfo.FormField.CaseMode.LOWER_CASE) + text = text.toLowerCase(Locale.getDefault()) - credential.stripTextRegex?.let { - text = text.replace(it.toRegex(), "") + credential.stripTextRegex?.let { + text = text.replace(it.toRegex(), "") + } + + b.textEdit.setText(text) + + if (credential.isRequired && text.isBlank()) { + b.textLayout.error = app.getString(credential.emptyText) + hasErrors = true + return@forEach + } + + if (!text.matches(credential.validationRegex.toRegex())) { + b.textLayout.error = app.getString(credential.invalidText) + hasErrors = true + return@forEach + } + + payload.putString(credential.keyName, text) + arguments?.putString(credential.keyName, text) } - - b.textEdit.setText(text) - - if (credential.isRequired && text.isBlank()) { - b.textLayout.error = app.getString(credential.emptyText) - hasErrors = true - return@forEach + if (credential is LoginInfo.FormCheckbox && b is LoginFormCheckboxItemBinding) { + val checked = b.checkbox.isChecked + payload.putBoolean(credential.keyName, checked) + arguments?.putBoolean(credential.keyName, checked) } - - if (!text.matches(credential.validationRegex.toRegex())) { - b.textLayout.error = app.getString(credential.invalidText) - hasErrors = true - return@forEach - } - - payload.putString(credential.keyName, text) - arguments?.putString(credential.keyName, text) } if (hasErrors) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt index 146fd05b..4ff09d5f 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt @@ -15,7 +15,7 @@ import pl.szczodrzynski.edziennik.ui.modules.grades.models.ExpandableItemModel object LoginInfo { - private fun getEmailCredential(keyName: String) = Credential( + private fun getEmailCredential(keyName: String) = FormField( keyName = keyName, name = R.string.login_hint_email, icon = CommunityMaterial.Icon.cmd_at, @@ -24,9 +24,9 @@ object LoginInfo { errorCodes = mapOf(), isRequired = true, validationRegex = "([\\w.\\-_+]+)?\\w+@[\\w-_]+(\\.\\w+)+", - caseMode = Credential.CaseMode.LOWER_CASE + caseMode = FormField.CaseMode.LOWER_CASE ) - private fun getPasswordCredential(keyName: String) = Credential( + private fun getPasswordCredential(keyName: String) = FormField( keyName = keyName, name = R.string.login_hint_password, icon = CommunityMaterial.Icon2.cmd_lock_outline, @@ -94,7 +94,7 @@ object LoginInfo { hintText = R.string.login_mode_librus_jst_hint, guideText = R.string.login_mode_librus_jst_guide, credentials = listOf( - Credential( + FormField( keyName = "accountCode", name = R.string.login_hint_token, icon = CommunityMaterial.Icon.cmd_code_braces, @@ -103,9 +103,9 @@ object LoginInfo { errorCodes = mapOf(), isRequired = true, validationRegex = "[A-Z0-9_]+", - caseMode = Credential.CaseMode.UPPER_CASE + caseMode = FormField.CaseMode.UPPER_CASE ), - Credential( + FormField( keyName = "accountPin", name = R.string.login_hint_pin, icon = CommunityMaterial.Icon2.cmd_lock, @@ -114,7 +114,7 @@ object LoginInfo { errorCodes = mapOf(), isRequired = true, validationRegex = "[a-z0-9_]+", - caseMode = Credential.CaseMode.LOWER_CASE + caseMode = FormField.CaseMode.LOWER_CASE ) ), errorCodes = mapOf( @@ -138,7 +138,7 @@ object LoginInfo { guideText = R.string.login_mode_vulcan_api_guide, isRecommended = true, credentials = listOf( - Credential( + FormField( keyName = "deviceToken", name = R.string.login_hint_token, icon = CommunityMaterial.Icon.cmd_code_braces, @@ -149,9 +149,9 @@ object LoginInfo { ), isRequired = true, validationRegex = "[A-Z0-9]{5,12}", - caseMode = Credential.CaseMode.UPPER_CASE + caseMode = FormField.CaseMode.UPPER_CASE ), - Credential( + FormField( keyName = "symbol", name = R.string.login_hint_symbol, icon = CommunityMaterial.Icon2.cmd_school, @@ -162,9 +162,9 @@ object LoginInfo { ), isRequired = true, validationRegex = "[a-z0-9_-]+", - caseMode = Credential.CaseMode.LOWER_CASE + caseMode = FormField.CaseMode.LOWER_CASE ), - Credential( + FormField( keyName = "devicePin", name = R.string.login_hint_pin, icon = CommunityMaterial.Icon2.cmd_lock, @@ -175,7 +175,7 @@ object LoginInfo { ), isRequired = true, validationRegex = "[0-9]+", - caseMode = Credential.CaseMode.LOWER_CASE + caseMode = FormField.CaseMode.LOWER_CASE ) ), errorCodes = mapOf( @@ -222,7 +222,7 @@ object LoginInfo { hintText = R.string.login_mode_mobidziennik_web_hint, guideText = R.string.login_mode_mobidziennik_web_guide, credentials = listOf( - Credential( + FormField( keyName = "username", name = R.string.login_hint_login_email, icon = CommunityMaterial.Icon.cmd_account_outline, @@ -231,9 +231,9 @@ object LoginInfo { errorCodes = mapOf(), isRequired = true, validationRegex = "^[a-z0-9_\\-@+.]+$", - caseMode = Credential.CaseMode.LOWER_CASE + caseMode = FormField.CaseMode.LOWER_CASE ), - Credential( + FormField( keyName = "password", name = R.string.login_hint_password, icon = CommunityMaterial.Icon2.cmd_lock_outline, @@ -246,7 +246,7 @@ object LoginInfo { validationRegex = ".*", hideText = true ), - Credential( + FormField( keyName = "serverName", name = R.string.login_hint_address, icon = CommunityMaterial.Icon2.cmd_web, @@ -257,7 +257,7 @@ object LoginInfo { ), isRequired = true, validationRegex = "^[a-z0-9_\\-]+\$", - caseMode = Credential.CaseMode.LOWER_CASE + caseMode = FormField.CaseMode.LOWER_CASE ) ), errorCodes = mapOf( @@ -280,7 +280,7 @@ object LoginInfo { hintText = R.string.login_mode_idziennik_web_hint, guideText = R.string.login_mode_idziennik_web_guide, credentials = listOf( - Credential( + FormField( keyName = "schoolName", name = R.string.login_hint_school_name, icon = CommunityMaterial.Icon2.cmd_school, @@ -291,9 +291,9 @@ object LoginInfo { ), isRequired = true, validationRegex = "^[a-z0-9_\\-.]+$", - caseMode = Credential.CaseMode.LOWER_CASE + caseMode = FormField.CaseMode.LOWER_CASE ), - Credential( + FormField( keyName = "username", name = R.string.login_hint_username, icon = CommunityMaterial.Icon.cmd_account_outline, @@ -302,7 +302,7 @@ object LoginInfo { errorCodes = mapOf(), isRequired = true, validationRegex = "^[a-z0-9_\\-.]+$", - caseMode = Credential.CaseMode.LOWER_CASE + caseMode = FormField.CaseMode.LOWER_CASE ), getPasswordCredential("password") ), @@ -346,7 +346,7 @@ object LoginInfo { icon = R.drawable.login_mode_podlasie_api, guideText = R.string.login_mode_podlasie_api_guide, credentials = listOf( - Credential( + FormField( keyName = "apiToken", name = R.string.login_hint_token, icon = CommunityMaterial.Icon2.cmd_lock_outline, @@ -355,7 +355,15 @@ object LoginInfo { errorCodes = mapOf(), isRequired = true, validationRegex = "[a-zA-Z0-9]{10}", - caseMode = Credential.CaseMode.UNCHANGED + caseMode = FormField.CaseMode.UNCHANGED + ), + FormCheckbox( + keyName = "logoutDevices", + name = R.string.login_podlasie_logout_devices, + checked = false, + errorCodes = mapOf( + ERROR_LOGIN_PODLASIE_API_DEVICE_LIMIT to R.string.error_602_reason + ) ) ), errorCodes = mapOf() @@ -392,7 +400,7 @@ object LoginInfo { val isTesting: Boolean = false, val isPlatformSelection: Boolean = false, - val credentials: List, + val credentials: List, val errorCodes: Map ) @@ -409,11 +417,18 @@ object LoginInfo { val apiData: JsonObject ) - data class Credential( - val keyName: String, + open class BaseCredential( + open val keyName: String, + @StringRes + open val name: Int, + open val errorCodes: Map + ) + + data class FormField( + override val keyName: String, @StringRes - val name: Int, + override val name: Int, val icon: IIcon, @StringRes val placeholder: Int? = null, @@ -421,7 +436,7 @@ object LoginInfo { val emptyText: Int, @StringRes val invalidText: Int, - val errorCodes: Map, + override val errorCodes: Map, @StringRes val hintText: Int? = null, @@ -430,10 +445,18 @@ object LoginInfo { val caseMode: CaseMode = CaseMode.UNCHANGED, val hideText: Boolean = false, val stripTextRegex: String? = null - ) { + ) : BaseCredential(keyName, name, errorCodes) { enum class CaseMode { UNCHANGED, UPPER_CASE, LOWER_CASE } } + data class FormCheckbox( + override val keyName: String, + @StringRes + override val name: Int, + val checked: Boolean = false, + override val errorCodes: Map = mapOf() + ) : BaseCredential(keyName, name, errorCodes) + var chooserList: MutableList? = null var platformList: MutableMap> = mutableMapOf() } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt index e8a4e343..b2623b64 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt @@ -108,7 +108,7 @@ class MessageFragment : Fragment(), CoroutineScope { .setNegativeButton(R.string.cancel, null) .show() } - b.downloadButton.isVisible = App.debugMode + b.downloadButton.isVisible = App.devMode b.downloadButton.onClick { EdziennikTask.messageGet(App.profileId, message).enqueue(activity) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java index 2c84c878..551efd01 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java @@ -581,7 +581,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { syncCardIntervalItem.setChecked(app.getConfig().getSync().getEnabled()); syncCardIntervalItem.setOnClickAction(() -> { List intervalNames = new ArrayList<>(); - if (App.Companion.getDevMode() && false) { + if (App.Companion.getDebugMode() && false) { intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_seconds, 30)); intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_minutes, 2)); } @@ -593,7 +593,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_hours, 3)); intervalNames.add(ExtensionsKt.plural(activity, R.plurals.time_till_hours, 4)); List intervals = new ArrayList<>(); - if (App.Companion.getDevMode() && false) { + if (App.Companion.getDebugMode() && false) { intervals.add(30); intervals.add(2 * 60); } @@ -1059,6 +1059,24 @@ public class SettingsNewFragment extends MaterialAboutFragment { ); } + if (App.Companion.getDevMode()) { + items.add( + new MaterialAboutSwitchItem( + getString(R.string.settings_register_hide_sticks_from_old), + null, + new IconicsDrawable(activity) + .icon(CommunityMaterial.Icon2.cmd_numeric_1_box_outline) + .size(IconicsSize.dp(iconSizeDp)) + .color(IconicsColor.colorInt(iconColor)) + ) + .setChecked(app.getConfig().forProfile().getGrades().getHideSticksFromOld()) + .setOnChangeAction((isChecked, tag) -> { + app.getConfig().forProfile().getGrades().setHideSticksFromOld(isChecked); + return true; + }) + ); + } + } return items; } @@ -1245,7 +1263,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { }) .build());*/ - if (App.Companion.getDebugMode()) { + if (App.Companion.getDevMode()) { items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_crash_text) .subText(R.string.settings_about_crash_subtext) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/Utils.java b/app/src/main/java/pl/szczodrzynski/edziennik/utils/Utils.java index 082d800d..910fc6f0 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/Utils.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/Utils.java @@ -108,7 +108,7 @@ public class Utils { public static List debugLog = new ArrayList<>(); public static void d(String TAG, String message) { - if (App.Companion.getDebugMode()) { + if (App.Companion.getDevMode()) { HyperLog.d("Szkolny/"+TAG, message); //debugLog.add(TAG+": "+message); } diff --git a/app/src/main/res/layout/login_form_checkbox_item.xml b/app/src/main/res/layout/login_form_checkbox_item.xml new file mode 100644 index 00000000..c28e9958 --- /dev/null +++ b/app/src/main/res/layout/login_form_checkbox_item.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/layout/login_form_item.xml b/app/src/main/res/layout/login_form_field_item.xml similarity index 100% rename from app/src/main/res/layout/login_form_item.xml rename to app/src/main/res/layout/login_form_field_item.xml diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 58de31ae..f4a89910 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -1233,4 +1233,5 @@ In order to download the file, you have to grant file storage permission for the application.\n\nClick OK to grant the permission. You denied the required permissions for the application.\n\nIn order to grant the permission, open the Permissions screen for Szkolny.eu in phone settings.\n\nClick OK to open app settings now. Required permissions + Your mother won\'t see your F grades diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7e3498b4..da00018f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1378,4 +1378,6 @@ Zobacz więcej Aktualizuj Dowiedz się więcej + Stara nie zobaczy pał + Wyloguj z pozostałych urządzeń diff --git a/build.gradle b/build.gradle index 43dc3e9f..cfc612be 100644 --- a/build.gradle +++ b/build.gradle @@ -5,8 +5,8 @@ buildscript { kotlin_version = '1.3.61' release = [ - versionName: "4.4.2", - versionCode: 4040299 + versionName: "4.4.3", + versionCode: 4040399 ] setup = [ @@ -53,6 +53,8 @@ buildscript { retrofit : "2.6.4" ] + versions.kotlin = '1.4.0' + versions.kotlin = '1.4.0' } repositories { diff --git a/settings.gradle b/settings.gradle index 3625fac9..b43e4d66 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,5 @@ +include ':wear' +include ':wear' include ':codegen' include ':annotation' rootProject.name='Szkolny.eu' diff --git a/wear/.gitignore b/wear/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/wear/.gitignore @@ -0,0 +1 @@ +/build diff --git a/wear/build.gradle b/wear/build.gradle index 6e4aa162..5b531ae4 100644 --- a/wear/build.gradle +++ b/wear/build.gradle @@ -1,37 +1,53 @@ -apply plugin: 'com.android.application' +/* + * Copyright (c) Kacper Ziubryniewicz 2020-9-17 + */ + +plugins { + id 'com.android.application' + id 'kotlin-android' +} android { - compileSdkVersion 28 - + compileSdkVersion 29 + buildToolsVersion "29.0.3" defaultConfig { applicationId "pl.szczodrzynski.edziennik" minSdkVersion 23 - targetSdkVersion 28 + targetSdkVersion 29 versionCode 1 versionName "1.0" - multiDexEnabled true + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } + buildTypes { release { minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { - sourceCompatibility = '1.8' - targetCompatibility = '1.8' + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' } } dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "org.jetbrains.kotlin:kotlin-stdlib:${versions.kotlin}" + implementation 'androidx.core:core-ktx:1.3.1' + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'com.google.android.material:material:1.2.1' + testImplementation 'junit:junit:4.13' + androidTestImplementation 'androidx.test.ext:junit:1.1.2' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' - implementation 'com.google.android.support:wearable:2.4.0' - implementation 'com.google.android.gms:play-services-wearable:16.0.1' - implementation 'androidx.percentlayout:percentlayout:1.0.0-beta01' - implementation 'androidx.legacy:legacy-support-v4:1.0.0-beta01' - implementation 'androidx.recyclerview:recyclerview:1.0.0-beta01' - implementation 'androidx.wear:wear:1.0.0-beta01' - compileOnly 'com.google.android.wearable:wearable:2.4.0' + implementation 'androidx.wear:wear:1.0.0' + implementation 'com.google.android.support:wearable:2.7.0' + compileOnly 'com.google.android.wearable:wearable:2.7.0' + + implementation "com.google.android.gms:play-services-wearable:${versions.play_services}" } diff --git a/wear/proguard-rules.pro b/wear/proguard-rules.pro new file mode 100644 index 00000000..f1b42451 --- /dev/null +++ b/wear/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/wear/src/androidTest/java/pl/szczodrzynski/edziennik/ExampleInstrumentedTest.kt b/wear/src/androidTest/java/pl/szczodrzynski/edziennik/ExampleInstrumentedTest.kt new file mode 100644 index 00000000..84289796 --- /dev/null +++ b/wear/src/androidTest/java/pl/szczodrzynski/edziennik/ExampleInstrumentedTest.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) Kacper Ziubryniewicz 2020-9-17 + */ + +package pl.szczodrzynski.edziennik + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("pl.szczodrzynski.edziennik", appContext.packageName) + } +} diff --git a/wear/src/main/AndroidManifest.xml b/wear/src/main/AndroidManifest.xml index 8148e132..803bc28d 100644 --- a/wear/src/main/AndroidManifest.xml +++ b/wear/src/main/AndroidManifest.xml @@ -1,44 +1,43 @@ + + - + - - - + - - - + android:theme="@style/Theme.Szkolnyeu"> + + + + android:label="@string/app_name"> - - - - \ No newline at end of file + diff --git a/wear/src/main/java/pl/szczodrzynski/edziennik/MainActivity.java b/wear/src/main/java/pl/szczodrzynski/edziennik/MainActivity.java deleted file mode 100644 index b96fff96..00000000 --- a/wear/src/main/java/pl/szczodrzynski/edziennik/MainActivity.java +++ /dev/null @@ -1,153 +0,0 @@ -package pl.szczodrzynski.edziennik; - -import android.app.Activity; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import androidx.wear.widget.drawer.WearableDrawerLayout; -import androidx.wear.widget.drawer.WearableDrawerView; -import androidx.wear.widget.drawer.WearableNavigationDrawerView; -import android.support.wearable.activity.WearableActivity; -import android.util.Log; -import android.view.View; -import android.widget.ProgressBar; - -import com.google.android.gms.tasks.Task; -import com.google.android.gms.wearable.CapabilityClient; -import com.google.android.gms.wearable.CapabilityInfo; -import com.google.android.gms.wearable.DataEvent; -import com.google.android.gms.wearable.DataItem; -import com.google.android.gms.wearable.Node; -import com.google.android.gms.wearable.PutDataMapRequest; -import com.google.android.gms.wearable.PutDataRequest; -import com.google.android.gms.wearable.Wearable; - -import java.util.Arrays; -import java.util.Set; - -public class MainActivity extends WearableActivity { - - private static final String TAG = "MainActivity"; - private ProgressBar progressBar; - private WearableDrawerLayout wearableDrawerLayout; - private WearableNavigationDrawerView mWearableNavigationDrawer; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - // Enables Always-on - setAmbientEnabled(); - - progressBar = findViewById(R.id.progressBar); - - wearableDrawerLayout = findViewById(R.id.drawer_layout); - wearableDrawerLayout.setDrawerStateCallback(new WearableDrawerLayout.DrawerStateCallback() { - @Override - public void onDrawerOpened(WearableDrawerLayout layout, WearableDrawerView drawerView) { - super.onDrawerOpened(layout, drawerView); - } - - @Override - public void onDrawerClosed(WearableDrawerLayout layout, WearableDrawerView drawerView) { - super.onDrawerClosed(layout, drawerView); - progressBar.setVisibility(View.GONE); - } - }); - - mWearableNavigationDrawer = (WearableNavigationDrawerView) findViewById(R.id.top_navigation_drawer); - WearableNavigationDrawerView.WearableNavigationDrawerAdapter navigationDrawerAdapter = new NavigationDrawerAdapter(this); - mWearableNavigationDrawer.setAdapter(navigationDrawerAdapter); - mWearableNavigationDrawer.addOnItemSelectedListener(new WearableNavigationDrawerView.OnItemSelectedListener() { - @Override - public void onItemSelected(int i) { - //Toast.makeText(MainActivity.this, "Selected item "+i, Toast.LENGTH_SHORT).show(); - progressBar.setVisibility(View.VISIBLE); - } - }); - // Peeks navigation drawer on the top. - mWearableNavigationDrawer.getController().peekDrawer(); - - Wearable.getMessageClient(this).addListener(messageEvent -> { - Log.d(TAG, messageEvent.getPath()+" :: "+ Arrays.toString(messageEvent.getData())); - }); - - Task capabilityInfoTask = - Wearable.getCapabilityClient(this) - .getCapability("edziennik_phone_app", CapabilityClient.FILTER_REACHABLE); - capabilityInfoTask.addOnCompleteListener((task) -> { - if (task.isSuccessful()) { - CapabilityInfo capabilityInfo = task.getResult(); - assert capabilityInfo != null; - Set nodes; - nodes = capabilityInfo.getNodes(); - Log.d(TAG, "Nodes "+nodes); - } else { - Log.d(TAG, "Capability request failed to return any results."); - } - }); - - Wearable.getDataClient(this).addListener(dataEventBuffer -> { - Log.d(TAG, "onDataChanged(): " + dataEventBuffer); - - for (DataEvent event : dataEventBuffer) { - if (event.getType() == DataEvent.TYPE_CHANGED) { - String path = event.getDataItem().getUri().getPath(); - Log.d(TAG, "Data "+path+ " :: "+Arrays.toString(event.getDataItem().getData())); - } - } - }); - - findViewById(R.id.test).setOnClickListener((v -> { - PutDataMapRequest putDataMapRequest = PutDataMapRequest.create("/ping"); - putDataMapRequest.getDataMap().putLong("millis", System.currentTimeMillis()); - - PutDataRequest request = putDataMapRequest.asPutDataRequest(); - request.setData("Hello".getBytes()); - request.setUrgent(); - - Log.d(TAG, "Generating DataItem: " + request); - - Task dataItemTask = - Wearable.getDataClient(getApplicationContext()).putDataItem(request); - dataItemTask.addOnCompleteListener(task -> { - if (task.isSuccessful()) { - - Log.d(TAG, "success"); - } else { - Log.d(TAG, "Capability request failed to return any results."); - } - }); - })); - - - - // Block on a task and get the result synchronously (because this is on a background - // thread). - //DataItem dataItem = dataItemTask.getResult(); - - //Log.d(TAG, "DataItem saved: " + dataItem); - - } - - - private class NavigationDrawerAdapter extends WearableNavigationDrawerView.WearableNavigationDrawerAdapter { - public NavigationDrawerAdapter(Activity activity) { - - } - - @Override - public CharSequence getItemText(int i) { - return "Item "+i; - } - - @Override - public Drawable getItemDrawable(int i) { - return null; - } - - @Override - public int getCount() { - return 5; - } - } -} diff --git a/wear/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt b/wear/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt new file mode 100644 index 00000000..ed694372 --- /dev/null +++ b/wear/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt @@ -0,0 +1,47 @@ +/* + * Copyright (c) Kacper Ziubryniewicz 2020-9-17 + */ + +package pl.szczodrzynski.edziennik + +import android.os.Bundle +import android.support.wearable.activity.WearableActivity +import com.google.android.gms.wearable.* + +class MainActivity : WearableActivity(), DataClient.OnDataChangedListener { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + // Enables Always-on + setAmbientEnabled() + } + + override fun onDataChanged(dataEvents: DataEventBuffer) { + dataEvents.forEach { event -> + if (event.type == DataEvent.TYPE_CHANGED) { + event.dataItem.also { item -> + if (item?.uri?.path?.compareTo("/test") == 0) { + DataMapItem.fromDataItem(item).dataMap.apply { + getInt("test") + } + } + } + } else if (event.type == DataEvent.TYPE_DELETED) { + // DataItem deleted + } + + } + } + + override fun onResume() { + super.onResume() + Wearable.getDataClient(this).addListener(this) + } + + override fun onPause() { + super.onPause() + Wearable.getDataClient(this).removeListener(this) + } +} diff --git a/wear/src/main/res/drawable-v24/ic_launcher_foreground.xml b/wear/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 00000000..d36dec1a --- /dev/null +++ b/wear/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + diff --git a/wear/src/main/res/drawable/ic_launcher_background.xml b/wear/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000..f14b2240 --- /dev/null +++ b/wear/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wear/src/main/res/layout/activity_main.xml b/wear/src/main/res/layout/activity_main.xml index 83b1a1ef..8d270149 100644 --- a/wear/src/main/res/layout/activity_main.xml +++ b/wear/src/main/res/layout/activity_main.xml @@ -1,47 +1,29 @@ - - + + + android:layout_height="match_parent" + android:background="@color/white" + android:padding="@dimen/box_inset_layout_padding" + tools:context=".MainActivity" + tools:deviceIds="wear"> + android:layout_height="match_parent" + android:padding="@dimen/inner_frame_layout_padding" + app:boxedEdges="all" + tools:ignore="MissingPrefix"> - - - -